package org.spiffyui.maven.plugins.utils; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.io.StringReader; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.maven.model.Resource; import org.apache.maven.plugin.logging.Log; import org.apache.maven.project.MavenProject; import org.codehaus.mojo.gwt.AbstractGwtModuleMojo; import org.codehaus.mojo.gwt.ClasspathBuilder; import org.codehaus.mojo.gwt.GwtModule; import org.codehaus.mojo.gwt.GwtModuleReader; import org.codehaus.mojo.gwt.utils.GwtModuleReaderException; import org.codehaus.plexus.util.DirectoryScanner; import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.xml.Xpp3Dom; import org.codehaus.plexus.util.xml.Xpp3DomBuilder; import org.spiffyui.maven.plugins.InitializeMojo; /** * <p> * The SpiffyGwtModuleReader finds GWT modules in a Maven project and makes them available * for GWT compilation. * </p> * * <p> * This class finds GWT modules and creates a new module which inherits from the existing * module and inserts our build properties, returns the new temporary project file, and * marks the temporary project file for deletion when the build is complete. * </p> */ public class SpiffyGwtModuleReader implements GwtModuleReader { private static final String GWT_MODULE_EXTENSION = ".gwt.xml"; private MavenProject m_mavenProject; private ClasspathBuilder m_classpathBuilder; private Log m_log; private String m_userAgents; private String m_locales; /** * Create a new SpiffyGwtModuleReader. * * @param mavenProject * the maven project * @param log the logging object * @param classpathBuilder * the classpath builder * @param userAgents the user agents for this project or null to leave the default agents * @param locales the locales for this project or null to leave the default locales */ public SpiffyGwtModuleReader(MavenProject mavenProject, Log log, ClasspathBuilder classpathBuilder, String userAgents, String locales) { m_mavenProject = mavenProject; m_log = log; m_classpathBuilder = classpathBuilder; m_userAgents = userAgents; m_locales = locales; } /** * Get the GWT modules for this project. * * @return the list of GWT modules found in this project */ @SuppressWarnings("unchecked") public List<String> getGwtModules() { // Use a Set to avoid duplicate when user set src/main/java as // <resource> Set<String> mods = new HashSet<String>(); Collection<String> sourcePaths = (Collection<String>) m_mavenProject.getCompileSourceRoots(); for (String sourcePath : sourcePaths) { File sourceDirectory = new File(sourcePath); if (sourceDirectory.exists()) { DirectoryScanner scanner = new DirectoryScanner(); scanner.setBasedir(sourceDirectory.getAbsolutePath()); scanner.setIncludes(new String[] { "**/*" + AbstractGwtModuleMojo.GWT_MODULE_EXTENSION }); scanner.scan(); mods.addAll(Arrays.asList(scanner.getIncludedFiles())); } } Collection<Resource> resources = (Collection<Resource>) m_mavenProject.getResources(); for (Resource resource : resources) { File resourceDirectoryFile = new File(resource.getDirectory()); if (!resourceDirectoryFile.exists()) { continue; } mods.addAll(findGwtModuleFiles(resource.getDirectory())); mods.addAll(findGwtModuleFiles(m_mavenProject.getProperties().getProperty("spiffyui.generated-source"))); } if (mods.isEmpty()) { m_log.warn("GWT plugin is configured to detect modules, but none were found."); } List<String> modules = new ArrayList<String>(mods.size()); for (String fileName : mods) { String path = fileName.substring(0, fileName.length() - AbstractGwtModuleMojo.GWT_MODULE_EXTENSION.length()); modules.add(path.replace(File.separatorChar, '.')); } if (modules.size() > 0) { m_log.info("auto discovered modules " + modules); } return modules; } private List<String> findGwtModuleFiles(String baseDir) { if (!new File(baseDir).exists()) { return new ArrayList<String>(); } DirectoryScanner scanner = new DirectoryScanner(); scanner.setBasedir(baseDir); scanner.setIncludes(new String[] { "**/*" + AbstractGwtModuleMojo.GWT_MODULE_EXTENSION }); scanner.scan(); return Arrays.asList(scanner.getIncludedFiles()); } /** * Read a specified GWT module into the project. * * @param name the name of the module to read * * @return the object representing this module * @throws GwtModuleReaderException if there an error reading the module */ public GwtModule readModule(String name) throws GwtModuleReaderException { String modulePath = name.replace('.', '/') + GWT_MODULE_EXTENSION; Collection<String> sourceRoots = m_mavenProject.getCompileSourceRoots(); sourceRoots.add(m_mavenProject.getProperties().getProperty("spiffyui.generated-source")); for (String sourceRoot : sourceRoots) { File root = new File(sourceRoot); File xml = new File(root, modulePath); if (xml.exists()) { m_log.debug("GWT module " + name + " found in " + root); return readModule(name, xml, modulePath); } } Collection<Resource> resources = (Collection<Resource>) m_mavenProject.getResources(); for (Resource resource : resources) { File root = new File(resource.getDirectory()); File xml = new File(root, modulePath); if (xml.exists()) { m_log.debug("GWT module " + name + " found in " + root); return readModule(name, xml, modulePath); } } throw new GwtModuleReaderException("GWT Module " + name + " not found in project sources or resources."); } private GwtModule readModule(String name, File file, String modulePath) throws GwtModuleReaderException { try { return readModule(name, new FileInputStream(file), file, modulePath); } catch (FileNotFoundException e) { throw new GwtModuleReaderException("Failed to read module file " + file); } } private GwtModule readModule(String name, InputStream xml, File file, String modulePath) throws GwtModuleReaderException { try { Xpp3Dom dom = Xpp3DomBuilder.build(ReaderFactory.newXmlReader(xml)); if (name.endsWith(InitializeMojo.SPIFFY_TMP_SUFFIX)) { /* Then we've already created the temporary GWT module and we don't need to create another one. */ return new GwtModule(name, dom, this); } StringBuffer tmp = new StringBuffer(); tmp.append( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>" + "<!DOCTYPE module SYSTEM \"gwt-module.dtd\">" + "<module rename-to=\"" + name + "\">" + "<inherits name=\"" + name + "\"/>"); if (m_userAgents != null) { tmp.append("<set-property name=\"user.agent\" value=\"" + m_userAgents + "\"/>"); } if (m_locales != null) { tmp.append("<extend-property name=\"locale\" values=\"" + m_locales + "\" />"); } tmp.append("</module>"); Xpp3Dom tmpDom = Xpp3DomBuilder.build(new StringReader(tmp.toString())); File out = new File(m_mavenProject.getProperties().getProperty("spiffyui.generated-source"), modulePath.substring(0, modulePath.lastIndexOf('/'))); out.mkdirs(); out = new File(out, name.substring(name.lastIndexOf(".") + 1) + InitializeMojo.SPIFFY_TMP_SUFFIX + ".gwt.xml"); FileUtils.fileWrite(out.getAbsolutePath(), tmpDom.toString()); return new GwtModule(name, tmpDom, this); } catch (Exception e) { String error = "Failed to read module XML file " + xml; m_log.error(error); throw new GwtModuleReaderException(error, e); } } }