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