Based on the description of the import task, it is very similar to an object that includes two additional functions:
- target redirection
- special properties
To view an “efficient build”, I don’t think that special handling of the properties is required (although it can be added by iterating the inserted targets). Thus, the processing to achieve this becomes.
- Parse the build.xml file in the DOM
- For each top level tag found (only the top level is available), find the reference source file.
- Parse the build.xml reference file
- insert any content from the build.xml reference file that does not interfere with the files in the current file.
- Repeat step 2 for the build.xml referenced files until you find more
- Print Resulting DOM
You can define a custom Ant task so that this processing can be defined in a task running from your assembly. See the tutorial for more details.
Here is a basic implementation that recursively imports and inserts DOM elements from referenced files. There are almost certainly some errors there when I reset them, but it should do basically what you need:
/** * Reads the build.xml and outputs the resolved build to stdout */ public static void main(String[] args) { try { Element root = new EffectiveBuild().parse(new File(args[0])); XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat()); outputter.output(root, System.out); } catch (Exception e) { // TODO handle errors e.printStackTrace(); } } /** * Get the DOM for the passed file and iterate all imports, replacing with * non-duplicate referenced content */ private Element parse(File buildFile) throws JDOMException, IOException { Element root = getRootElement(buildFile); List<Element> imports = root.getChildren("import"); for (int i = 0; i < imports.size(); i++) { Element element = imports.get(i); List<Content> importContent = parseImport(element, root, buildFile); int replaceIndex = root.indexOf(element); root.addContent(replaceIndex, importContent); root.removeContent(element); } root.removeChildren("import"); return root; } /** * Get the imported file and merge it into the parent. */ private List<Content> parseImport(Element element, Element currentRoot, File buildFile) throws JDOMException, IOException { String importFileName = element.getAttributeValue("file"); File importFile = new File(buildFile.getParentFile(), importFileName) .getAbsoluteFile(); if (importFileName != null) { Element importRoot = getRootElement(importFile); return getImportContent(element, currentRoot, importRoot, importFile); } return Collections.emptyList(); } /** * Replace the passed element with the content of the importRoot * (not the project tag) */ private List<Content> getImportContent(Element element, Element currentRoot, Element importRoot, File buildFile) throws JDOMException, IOException { if (currentRoot != null) { // copy all the reference import elements to the parent if needed List<Content> childNodes = importRoot.cloneContent(); List<Content> importContent = new ArrayList<Content>(); for (Content content : childNodes) { if (content instanceof Element && ((Element) content).getName().equals("import")) { importContent.addAll(parseImport((Element) content, currentRoot, buildFile)); } if (!existsInParent(currentRoot, content)) { importContent.add(content); } else { // TODO note the element was skipped } } return importContent; } return Collections.emptyList(); } /** * Return true if the content already defined in the parent */ private boolean existsInParent(Element parent, Content content) { if (content instanceof Text) { if (((Text) content).getText().trim().length() == 0) { // let the pretty printer deal with the whitespace return false; } return true; } if (content instanceof Element) { String id = ((Element) content).getAttributeValue("name"); String name = ((Element) content).getName(); List<Content> parentContent = parent.getChildren(); if (id != null) { for (Content content2 : parentContent) { if (content2 instanceof Element && ((Element) content2).getName().equals(name)) { String parentId = ((Element) content2) .getAttributeValue("name"); if (parentId != null && parentId.equals(id)) { return true; } } } } } return false; } /** * Parse the passed file. */ private Element getRootElement(File buildFile) throws JDOMException, IOException { SAXBuilder builder = new SAXBuilder(); builder.setValidation(false); builder.setIgnoringElementContentWhitespace(true); Document doc = builder.build(buildFile); Element root = doc.getRootElement(); return root; }
source share