package au.gov.ga.earthsci.verifier; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Properties; import java.util.Set; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathFactory; import org.apache.commons.io.filefilter.WildcardFileFilter; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; /** * Custom Ant task for EarthSci that checks each plugin in the plugins directory * for correct configuration. Each plugin must: * <ul> * <li>Contain a Maven pom.xml file</li> * <li>Be listed in the pom.xml file in the plugins/ directory</li> * <li>Include sensible files in the bin.includes property in its * build.properties file</li> * </ul> * * @author Michael de Hoog (michael.dehoog@ga.gov.au) */ public class VerifyPlugins extends Task { private String pluginsdir; public void setPluginsdir(String pluginsdir) { this.pluginsdir = pluginsdir; } @Override public void execute() throws BuildException { File directory = new File(pluginsdir); File pomFile = new File(directory, "pom.xml"); Set<String> modules = new HashSet<String>(); Set<String> plugins = new HashSet<String>(); List<File> pluginDirectories = new ArrayList<File>(); File[] files = directory.listFiles(); for (File file : files) { if (file.isDirectory() && new File(file, ".project").exists()) { plugins.add(file.getName()); pluginDirectories.add(file); File pluginPom = new File(file, "pom.xml"); if (!pluginPom.exists()) { throw new BuildException(pluginPom + " not found"); } } } try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(false); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(pomFile); XPath xpath = XPathFactory.newInstance().newXPath(); XPathExpression expression = xpath.compile("//modules/module"); NodeList moduleElements = (NodeList) expression.evaluate(document, XPathConstants.NODESET); for (int i = 0; i < moduleElements.getLength(); i++) { Element moduleElement = (Element) moduleElements.item(i); String module = moduleElement.getTextContent(); if (modules.contains(module)) { throw new BuildException("Module defined more than once: " + module); } modules.add(module); } } catch (Exception e) { throw new BuildException("Error parsing plugins POM file", e); } Set<String> missingModules = new HashSet<String>(plugins); missingModules.removeAll(modules); if (!missingModules.isEmpty()) { StringBuilder sb = new StringBuilder(pomFile + " is missing the following plugin modules:"); for (String missingModule : missingModules) { sb.append("\n\t" + missingModule); } throw new BuildException(sb.toString()); } for (File pluginDirectory : pluginDirectories) { File buildFile = new File(pluginDirectory, "build.properties"); if (!buildFile.exists()) { throw new BuildException(buildFile + " not found"); } Properties properties = new Properties(); try { FileInputStream fis = new FileInputStream(buildFile); try { properties.load(fis); } finally { fis.close(); } } catch (IOException e) { throw new BuildException("Error reading " + buildFile, e); } String binIncludes = properties.getProperty("bin.includes"); String[] split = binIncludes.split(","); Set<String> includes = new HashSet<String>(Arrays.asList(split)); String[] patterns = new String[] { "META-INF", "icons", "css", "OSGI-INF", "schema", "*.e4xmi" }; FileFilter filter = new WildcardFileFilter(patterns); File[] matchingFiles = pluginDirectory.listFiles(filter); for (File matchingFile : matchingFiles) { String match = matchingFile.getName(); if (matchingFile.isDirectory()) { match += "/"; } if (!includes.contains(match)) { throw new BuildException(buildFile + " missing '" + match + "' from it's bin.includes property"); } } } } }