1import org.gradle.api.DefaultTask 2import org.gradle.api.tasks.Input 3import org.gradle.api.tasks.OutputFile 4import org.gradle.api.tasks.TaskAction 5import org.w3c.dom.Document 6import org.w3c.dom.Element 7import org.w3c.dom.Node 8import org.w3c.dom.NodeList 9 10import javax.xml.parsers.DocumentBuilder 11import javax.xml.parsers.DocumentBuilderFactory 12import javax.xml.transform.TransformerFactory 13import javax.xml.transform.dom.DOMSource 14import javax.xml.transform.stream.StreamResult 15 16import static org.gradle.api.internal.lambdas.SerializableLambdas.spec; 17 18/** 19 * Gradle task to update sources link in sdk 20 */ 21class SdkSourceUpdaterTask extends DefaultTask { 22 23 private static final JDK_TABLE_PATH = "out/gradle/AndroidStudio/config/options/jdk.table.xml" 24 private static final JAVA_CORE_PATH = "frameworks/base/core/java" 25 private static final JAVA_GRAPHICS_PATH = "frameworks/base/graphics/java" 26 27 @Input 28 String androidRoot 29 30 public SdkSourceUpdaterTask() { 31 setOnlyIf("Sdk file is missing", spec(task -> new File(androidRoot, JDK_TABLE_PATH).exists())) 32 outputs.upToDateWhen { 33 String sdkDefLines = new File(androidRoot, JDK_TABLE_PATH).text 34 String corePath = new File(androidRoot, JAVA_CORE_PATH).getCanonicalPath() 35 String graphicsPath = new File(androidRoot, JAVA_GRAPHICS_PATH).getCanonicalPath() 36 return sdkDefLines.contains(corePath) && sdkDefLines.contains(graphicsPath) 37 } 38 } 39 40 @OutputFile 41 public File getOutputFile() { 42 return new File(androidRoot, JDK_TABLE_PATH) 43 } 44 45 @TaskAction 46 void execute() throws Exception { 47 File sdkDef = new File(androidRoot, JDK_TABLE_PATH) 48 if (!sdkDef.exists()) { 49 throw new IllegalStateException("Sdk config file not found at " + sdkDef); 50 } 51 52 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 53 DocumentBuilder db = dbf.newDocumentBuilder(); 54 Document doc = db.parse(sdkDef); 55 56 NodeList list = doc.getElementsByTagName("jdk"); 57 for (int i = 0; i < list.getLength(); i++) { 58 Node node = list.item(i); 59 if (node.getNodeType() == Node.ELEMENT_NODE) { 60 Element element = (Element) node; 61 Element homePath = findFirstElement(element, "homePath"); 62 if (homePath == null) { 63 continue; 64 } 65 66 String pathValue = homePath.getAttribute("value"); 67 if (pathValue == null || pathValue.isBlank()) { 68 continue; 69 } 70 71 72 if (!pathValue.contains("out/gradle/MockSdk")) { 73 continue; 74 } 75 76 // Found the right SDK 77 Element sourcePath = findFirstElement(element, "sourcePath"); 78 if (sourcePath == null) { 79 // TODO: Add source path 80 continue; 81 } 82 83 while (sourcePath.hasChildNodes()) 84 sourcePath.removeChild(sourcePath.getFirstChild()); 85 86 // Create root 87 Element el = createRoot(doc, "type", "composite"); 88 sourcePath.appendChild(el); 89 90 // Create paths 91 el.appendChild(createRoot(doc, "type", "simple", "url", "file://" + new File(androidRoot, JAVA_CORE_PATH).getCanonicalPath())); 92 el.appendChild(createRoot(doc, "type", "simple", "url", "file://" + new File(androidRoot, JAVA_GRAPHICS_PATH).getCanonicalPath())); 93 } 94 } 95 96 // Write the xml 97 TransformerFactory.newInstance().newTransformer() 98 .transform(new DOMSource(doc), new StreamResult(sdkDef)) 99 100 System.out.println("======================================") 101 System.out.println("======================================") 102 System.out.println(" Android sources linked") 103 System.out.println("Restart IDE for changes to take effect") 104 System.out.println("======================================") 105 System.out.println("======================================") 106 } 107 108 private Element createRoot(Document doc, String... attrs) { 109 Element el = doc.createElement("root"); 110 for (int i = 0; i < attrs.length; i += 2) { 111 el.setAttribute(attrs[i], attrs[i + 1]); 112 } 113 return el; 114 } 115 116 private Element findFirstElement(Element node, String tag) { 117 NodeList paths = node.getElementsByTagName(tag); 118 if (paths.getLength() < 1) { 119 return null; 120 } 121 Node n = paths.item(0); 122 if (n.getNodeType() != Node.ELEMENT_NODE) { 123 return null; 124 } 125 return (Element) n; 126 } 127}