package org.codehaus.mojo.gwt.utils;
/*
* 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.maven.artifact.Artifact;
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.ClasspathBuilderException;
import org.codehaus.mojo.gwt.GwtModule;
import org.codehaus.mojo.gwt.GwtModuleReader;
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;
/**
* @author <a href="mailto:olamy@apache.org">Olivier Lamy</a>
* @since 2.1.0-1
*/
public class DefaultGwtModuleReader
implements GwtModuleReader
{
public static final String GWT_MODULE_EXTENSION = ".gwt.xml";
private MavenProject mavenProject;
private ClasspathBuilder classpathBuilder;
private Log log;
public DefaultGwtModuleReader( MavenProject mavenProject, Log log, ClasspathBuilder classpathBuilder )
{
this.mavenProject = mavenProject;
this.log = log;
this.classpathBuilder = classpathBuilder;
}
@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>) 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[] { "**/*" + GWT_MODULE_EXTENSION } );
scanner.scan();
mods.addAll( Arrays.asList( scanner.getIncludedFiles() ) );
}
}
Collection<Resource> resources = (Collection<Resource>) mavenProject.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[] { "**/*" + GWT_MODULE_EXTENSION } );
scanner.scan();
mods.addAll( Arrays.asList( scanner.getIncludedFiles() ) );
}
if ( mods.isEmpty() )
{
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() - GWT_MODULE_EXTENSION.length() );
modules.add( path.replace( File.separatorChar, '.' ) );
}
if ( modules.size() > 0 )
{
log.info( "auto discovered modules " + modules );
}
return modules;
}
public GwtModule readModule( String name )
throws GwtModuleReaderException
{
String modulePath = name.replace( '.', '/' ) + GWT_MODULE_EXTENSION;
Collection<String> sourceRoots = mavenProject.getCompileSourceRoots();
for ( String sourceRoot : sourceRoots )
{
File root = new File( sourceRoot );
File xml = new File( root, modulePath );
if ( xml.exists() )
{
log.debug( "GWT module " + name + " found in " + root );
return readModule( name, xml );
}
}
Collection<Resource> resources = (Collection<Resource>) mavenProject.getResources();
for ( Resource resource : resources )
{
File root = new File( resource.getDirectory() );
File xml = new File( root, modulePath );
if ( xml.exists() )
{
log.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 ( ClasspathBuilderException 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
{
return readModule( name, new FileInputStream( file ) );
}
catch ( FileNotFoundException e )
{
throw new GwtModuleReaderException( "Failed to read module file " + file );
}
}
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;
log.error( error );
throw new GwtModuleReaderException( error, e );
}
}
public Collection<File> getClasspath( String scope )
throws ClasspathBuilderException
{
Collection<File> files = classpathBuilder.buildClasspathList( mavenProject, scope, mavenProject.getArtifacts(), false );
if ( log.isDebugEnabled() )
{
log.debug( "GWT SDK execution classpath :" );
for ( File f : files )
{
log.debug( " " + f.getAbsolutePath() );
}
}
return files;
}
}