View Javadoc
1   package org.codehaus.mojo.gwt;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.io.FileInputStream;
24  import java.io.FileNotFoundException;
25  import java.io.InputStream;
26  import java.net.MalformedURLException;
27  import java.net.URL;
28  import java.net.URLClassLoader;
29  import java.util.ArrayList;
30  import java.util.Arrays;
31  import java.util.Collection;
32  import java.util.HashSet;
33  import java.util.List;
34  import java.util.Set;
35  
36  import org.apache.commons.lang.ArrayUtils;
37  import org.apache.maven.artifact.Artifact;
38  import org.apache.maven.model.Resource;
39  import org.apache.maven.plugin.MojoExecutionException;
40  import org.apache.maven.plugins.annotations.Parameter;
41  import org.codehaus.mojo.gwt.utils.DefaultGwtModuleReader;
42  import org.codehaus.mojo.gwt.utils.GwtModuleReaderException;
43  import org.codehaus.plexus.util.DirectoryScanner;
44  import org.codehaus.plexus.util.ReaderFactory;
45  import org.codehaus.plexus.util.xml.Xpp3Dom;
46  import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
47  
48  /**
49   * Add support for GWT Modules.
50   * <p>
51   * Search and read the gwt.xml module files to detect project structure.
52   *
53   * @author <a href="mailto:nicolas@apache.org">Nicolas De Loof</a>
54   * @version $Id$
55   */
56  public abstract class AbstractGwtModuleMojo
57      extends AbstractGwtMojo
58      implements GwtModuleReader
59  {
60      /**
61       * The project GWT modules. If not set, the plugin will scan the project for <code>.gwt.xml</code> files.
62       */
63      @Parameter(alias = "compileTargets")
64      private String[] modules;
65  
66      /**
67       * A single GWT module. Shortcut for &lt;modules&gt; or option to specify a single module from command line
68       */
69      @Parameter(property = "gwt.module")
70      private String module;
71  
72      public List<String> getGwtModules()
73      {
74          String[] modules = getModules();
75          return ArrayUtils.isEmpty( modules )? new ArrayList<String>(0) : Arrays.asList( modules );
76      }
77      
78      /**
79       * Return the configured modules or scan the project source/resources folder to find them
80       *
81       * @return the modules
82       */
83      // FIXME move to DefaultGwtModuleReader !
84      public String[] getModules()
85      {
86          // module has higher priority if set by expression
87          if ( module != null )
88          {
89              return new String[] { module };
90          }
91          if ( modules == null )
92          {
93              //Use a Set to avoid duplicate when user set src/main/java as <resource>
94              Set<String> mods = new HashSet<String>();
95  
96              Collection<String> sourcePaths = getProject().getCompileSourceRoots();
97              for ( String sourcePath : sourcePaths )
98              {
99                  File sourceDirectory = new File( sourcePath );
100                 if ( sourceDirectory.exists() )
101                 {
102                     DirectoryScanner scanner = new DirectoryScanner();
103                     scanner.setBasedir( sourceDirectory.getAbsolutePath() );
104                     scanner.setIncludes( new String[] { "**/*" + DefaultGwtModuleReader.GWT_MODULE_EXTENSION } );
105                     scanner.scan();
106 
107                     mods.addAll( Arrays.asList( scanner.getIncludedFiles() ) );
108                 }
109             }
110 
111             Collection<Resource> resources = getProject().getResources();
112             for ( Resource resource : resources )
113             {
114                 File resourceDirectoryFile = new File( resource.getDirectory() );
115                 if ( !resourceDirectoryFile.exists() )
116                 {
117                     continue;
118                 }
119                 DirectoryScanner scanner = new DirectoryScanner();
120                 scanner.setBasedir( resource.getDirectory() );
121                 scanner.setIncludes( new String[] { "**/*" + DefaultGwtModuleReader.GWT_MODULE_EXTENSION } );
122                 scanner.scan();
123                 mods.addAll( Arrays.asList( scanner.getIncludedFiles() ) );
124             }
125 
126             if ( mods.isEmpty() )
127             {
128                 getLog().warn( "GWT plugin is configured to detect modules, but none were found." );
129             }
130 
131             modules = new String[mods.size()];
132             int i = 0;
133             for ( String fileName : mods )
134             {
135                 String path =
136                     fileName.substring( 0, fileName.length() - DefaultGwtModuleReader.GWT_MODULE_EXTENSION.length() );
137                 modules[i++] = path.replace( File.separatorChar, '.' );
138             }
139             if ( modules.length > 0 )
140             {
141                 getLog().info( "auto discovered modules " + Arrays.asList( modules ) );
142             }
143 
144         }
145         return modules;
146     }
147 
148     public GwtModule readModule( String name )
149         throws GwtModuleReaderException
150     {
151         String modulePath = name.replace( '.', '/' ) + DefaultGwtModuleReader.GWT_MODULE_EXTENSION;
152         Collection<String> sourceRoots = getProject().getCompileSourceRoots();
153         for ( String sourceRoot : sourceRoots )
154         {
155             File root = new File( sourceRoot );
156             File xml = new File( root, modulePath );
157             if ( xml.exists() )
158             {
159                 getLog().debug( "GWT module " + name + " found in " + root );
160                 return readModule( name, xml );
161             }
162         }
163         Collection<Resource> resources = getProject().getResources();
164         for ( Resource resource : resources )
165         {
166             File root = new File( resource.getDirectory() );
167             File xml = new File( root, modulePath );
168             if ( xml.exists() )
169             {
170                 getLog().debug( "GWT module " + name + " found in " + root );
171                 return readModule( name, xml );
172             }
173         }
174 
175         try
176         {
177             Collection<File> classpath = getClasspath( Artifact.SCOPE_COMPILE );
178             URL[] urls = new URL[classpath.size()];
179             int i = 0;
180             for ( File file : classpath )
181             {
182                 urls[i++] = file.toURI().toURL();
183             }
184             InputStream stream = new URLClassLoader( urls ).getResourceAsStream( modulePath );
185             if ( stream != null )
186             {
187                 return readModule( name, stream );
188             }
189         }
190         catch ( MalformedURLException e )
191         {
192             // ignored;
193         } catch (MojoExecutionException e)
194         {
195             throw new GwtModuleReaderException(e.getMessage(), e);
196         }
197 
198         throw new GwtModuleReaderException( "GWT Module " + name + " not found in project sources or resources." );
199     }
200 
201     private GwtModule readModule( String name, File file )
202         throws GwtModuleReaderException
203 
204     {
205         try
206         {
207             GwtModule module = readModule( name, new FileInputStream( file ) );
208             module.setSourceFile(file);
209             return module;
210         }
211         catch ( FileNotFoundException e )
212         {
213             throw new GwtModuleReaderException( "Failed to read module file " + file );
214         }
215     }
216 
217     /**
218      * @param module2
219      * @return
220      */
221     private GwtModule readModule( String name, InputStream xml )
222         throws GwtModuleReaderException
223     {
224         try
225         {
226             Xpp3Dom dom = Xpp3DomBuilder.build( ReaderFactory.newXmlReader( xml ) );
227             return new GwtModule( name, dom, this );
228         }
229         catch ( Exception e )
230         {
231             String error = "Failed to read module XML file " + xml;
232             getLog().error( error );
233             throw new GwtModuleReaderException( error, e );
234         }
235     }
236 
237 }