package org.codehaus.mojo.gwt; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; 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.commons.lang.ArrayUtils; import org.apache.maven.artifact.Artifact; import org.apache.maven.model.Resource; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.Parameter; import org.codehaus.mojo.gwt.utils.DefaultGwtModuleReader; import org.codehaus.mojo.gwt.utils.GwtModuleReaderException; import org.codehaus.plexus.util.DirectoryScanner; import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.xml.Xpp3Dom; import org.codehaus.plexus.util.xml.Xpp3DomBuilder; /** * Add support for GWT Modules. * <p> * Search and read the gwt.xml module files to detect project structure. * * @author <a href="mailto:nicolas@apache.org">Nicolas De Loof</a> * @version $Id$ */ public abstract class AbstractGwtModuleMojo extends AbstractGwtMojo implements GwtModuleReader { /** * The project GWT modules. If not set, the plugin will scan the project for <code>.gwt.xml</code> files. */ @Parameter(alias = "compileTargets") private String[] modules; /** * A single GWT module. Shortcut for <modules> or option to specify a single module from command line */ @Parameter(property = "gwt.module") private String module; public List<String> getGwtModules() { String[] modules = getModules(); return ArrayUtils.isEmpty( modules )? new ArrayList<String>(0) : Arrays.asList( modules ); } /** * Return the configured modules or scan the project source/resources folder to find them * * @return the modules */ // FIXME move to DefaultGwtModuleReader ! public String[] getModules() { // module has higher priority if set by expression if ( module != null ) { return new String[] { module }; } if ( modules == null ) { //Use a Set to avoid duplicate when user set src/main/java as <resource> Set<String> mods = new HashSet<String>(); Collection<String> sourcePaths = getProject().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[] { "**/*" + DefaultGwtModuleReader.GWT_MODULE_EXTENSION } ); scanner.scan(); mods.addAll( Arrays.asList( scanner.getIncludedFiles() ) ); } } Collection<Resource> resources = getProject().getResources(); for ( Resource resource : resources ) { File resourceDirectoryFile = new File( resource.getDirectory() ); if ( !resourceDirectoryFile.exists() ) { continue; } DirectoryScanner scanner = new DirectoryScanner(); scanner.setBasedir( resource.getDirectory() ); scanner.setIncludes( new String[] { "**/*" + DefaultGwtModuleReader.GWT_MODULE_EXTENSION } ); scanner.scan(); mods.addAll( Arrays.asList( scanner.getIncludedFiles() ) ); } if ( mods.isEmpty() ) { getLog().warn( "GWT plugin is configured to detect modules, but none were found." ); } modules = new String[mods.size()]; int i = 0; for ( String fileName : mods ) { String path = fileName.substring( 0, fileName.length() - DefaultGwtModuleReader.GWT_MODULE_EXTENSION.length() ); modules[i++] = path.replace( File.separatorChar, '.' ); } if ( modules.length > 0 ) { getLog().info( "auto discovered modules " + Arrays.asList( modules ) ); } } return modules; } public GwtModule readModule( String name ) throws GwtModuleReaderException { String modulePath = name.replace( '.', '/' ) + DefaultGwtModuleReader.GWT_MODULE_EXTENSION; Collection<String> sourceRoots = getProject().getCompileSourceRoots(); for ( String sourceRoot : sourceRoots ) { File root = new File( sourceRoot ); File xml = new File( root, modulePath ); if ( xml.exists() ) { getLog().debug( "GWT module " + name + " found in " + root ); return readModule( name, xml ); } } Collection<Resource> resources = getProject().getResources(); for ( Resource resource : resources ) { File root = new File( resource.getDirectory() ); File xml = new File( root, modulePath ); if ( xml.exists() ) { getLog().debug( "GWT module " + name + " found in " + root ); return readModule( name, xml ); } } try { Collection<File> classpath = getClasspath( Artifact.SCOPE_COMPILE ); URL[] urls = new URL[classpath.size()]; int i = 0; for ( File file : classpath ) { urls[i++] = file.toURI().toURL(); } InputStream stream = new URLClassLoader( urls ).getResourceAsStream( modulePath ); if ( stream != null ) { return readModule( name, stream ); } } catch ( MalformedURLException e ) { // ignored; } catch (MojoExecutionException e) { throw new GwtModuleReaderException(e.getMessage(), e); } throw new GwtModuleReaderException( "GWT Module " + name + " not found in project sources or resources." ); } private GwtModule readModule( String name, File file ) throws GwtModuleReaderException { try { GwtModule module = readModule( name, new FileInputStream( file ) ); module.setSourceFile(file); return module; } catch ( FileNotFoundException e ) { throw new GwtModuleReaderException( "Failed to read module file " + file ); } } /** * @param module2 * @return */ private GwtModule readModule( String name, InputStream xml ) throws GwtModuleReaderException { try { Xpp3Dom dom = Xpp3DomBuilder.build( ReaderFactory.newXmlReader( xml ) ); return new GwtModule( name, dom, this ); } catch ( Exception e ) { String error = "Failed to read module XML file " + xml; getLog().error( error ); throw new GwtModuleReaderException( error, e ); } } }