blob: a430d2ca28bf5e09c49ccdbef85a0b929c628616 [file] [log] [blame]
package org.apache.maven.archetype.creator;
/*
* 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 org.apache.commons.collections.CollectionUtils;
import org.apache.maven.archetype.ArchetypeCreationRequest;
import org.apache.maven.archetype.ArchetypeCreationResult;
import org.apache.maven.archetype.common.ArchetypeFilesResolver;
import org.apache.maven.archetype.common.Constants;
import org.apache.maven.archetype.common.PomManager;
import org.apache.maven.archetype.common.util.FileCharsetDetector;
import org.apache.maven.archetype.common.util.ListScanner;
import org.apache.maven.archetype.common.util.PathUtils;
import org.apache.maven.archetype.exception.TemplateCreationException;
import org.apache.maven.archetype.metadata.ArchetypeDescriptor;
import org.apache.maven.archetype.metadata.FileSet;
import org.apache.maven.archetype.metadata.ModuleDescriptor;
import org.apache.maven.archetype.metadata.RequiredProperty;
import org.apache.maven.archetype.metadata.io.xpp3.ArchetypeDescriptorXpp3Writer;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.model.Build;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Extension;
import org.apache.maven.model.Model;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginManagement;
import org.apache.maven.model.Profile;
import org.apache.maven.model.Resource;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectBuilder;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.shared.invoker.DefaultInvocationRequest;
import org.apache.maven.shared.invoker.DefaultInvoker;
import org.apache.maven.shared.invoker.InvocationRequest;
import org.apache.maven.shared.invoker.Invoker;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.WriterFactory;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
/**
* Create a 2.x Archetype project from a project. Since 2.0-alpha-5, an integration-test named "basic" is created along
* the archetype itself to provide immediate test when building the archetype.
*/
@Component( role = ArchetypeCreator.class, hint = "fileset" )
public class FilesetArchetypeCreator
extends AbstractLogEnabled
implements ArchetypeCreator
{
private static final String DEFAULT_OUTPUT_DIRECTORY =
"target" + File.separator + "generated-sources" + File.separator + "archetype";
@Requirement
private ArchetypeFilesResolver archetypeFilesResolver;
@Requirement
private PomManager pomManager;
@Requirement
private MavenProjectBuilder projectBuilder;
public void createArchetype( ArchetypeCreationRequest request, ArchetypeCreationResult result )
{
MavenProject project = request.getProject();
List<String> languages = request.getLanguages();
List<String> filtereds = request.getFiltereds();
String defaultEncoding = request.getDefaultEncoding();
boolean preserveCData = request.isPreserveCData();
boolean keepParent = request.isKeepParent();
boolean partialArchetype = request.isPartialArchetype();
ArtifactRepository localRepository = request.getLocalRepository();
File outputDirectory = request.getOutputDirectory();
File basedir = project.getBasedir();
Properties properties = new Properties();
Properties configurationProperties = new Properties();
if ( request.getProperties() != null )
{
properties.putAll( request.getProperties() );
configurationProperties.putAll( request.getProperties() );
}
extractPropertiesFromProject( project, properties, configurationProperties, request.getPackageName() );
if ( outputDirectory == null )
{
getLogger().debug( "No output directory defined, using default: " + DEFAULT_OUTPUT_DIRECTORY );
outputDirectory = FileUtils.resolveFile( basedir, DEFAULT_OUTPUT_DIRECTORY );
}
outputDirectory.mkdirs();
getLogger().debug( "Creating archetype in " + outputDirectory );
try
{
File archetypePomFile =
createArchetypeProjectPom( project, localRepository, configurationProperties, outputDirectory );
File archetypeResourcesDirectory = new File( outputDirectory, getTemplateOutputDirectory() );
File archetypeFilesDirectory = new File( archetypeResourcesDirectory, Constants.ARCHETYPE_RESOURCES );
getLogger().debug( "Archetype's files output directory " + archetypeFilesDirectory );
File archetypeDescriptorFile = new File( archetypeResourcesDirectory, Constants.ARCHETYPE_DESCRIPTOR );
archetypeDescriptorFile.getParentFile().mkdirs();
File archetypePostGenerationScript =
new File( archetypeResourcesDirectory, Constants.ARCHETYPE_POST_GENERATION_SCRIPT );
archetypePostGenerationScript.getParentFile().mkdirs();
if ( request.getProject().getBuild() != null && CollectionUtils.isNotEmpty(
request.getProject().getBuild().getResources() ) )
{
for ( Resource resource : request.getProject().getBuild().getResources() )
{
File inputFile = new File(
resource.getDirectory() + File.separator + Constants.ARCHETYPE_POST_GENERATION_SCRIPT );
if ( inputFile.exists() )
{
FileUtils.copyFile( inputFile, archetypePostGenerationScript );
}
}
}
getLogger().debug( "Starting archetype's descriptor " + project.getArtifactId() );
ArchetypeDescriptor archetypeDescriptor = new ArchetypeDescriptor();
archetypeDescriptor.setName( project.getArtifactId() );
archetypeDescriptor.setPartial( partialArchetype );
addRequiredProperties( archetypeDescriptor, properties );
// TODO ensure reverseProperties contains NO dotted properties
Properties reverseProperties = getReversedProperties( archetypeDescriptor, properties );
// reverseProperties.remove( Constants.GROUP_ID );
// TODO ensure pomReversedProperties contains NO dotted properties
Properties pomReversedProperties = getReversedProperties( archetypeDescriptor, properties );
// pomReversedProperties.remove( Constants.PACKAGE );
String packageName = configurationProperties.getProperty( Constants.PACKAGE );
Model pom = pomManager.readPom( FileUtils.resolveFile( basedir, Constants.ARCHETYPE_POM ) );
List<String> excludePatterns =
configurationProperties.getProperty( Constants.EXCLUDE_PATTERNS ) != null
? Arrays.asList(
StringUtils.split( configurationProperties.getProperty( Constants.EXCLUDE_PATTERNS ), "," ) )
: Collections.<String>emptyList();
List<String> fileNames = resolveFileNames( pom, basedir, excludePatterns );
if ( getLogger().isDebugEnabled() )
{
getLogger().debug( "Scanned for files " + fileNames.size() );
for ( String name : fileNames )
{
getLogger().debug( "- " + name );
}
}
List<FileSet> filesets = resolveFileSets( packageName, fileNames, languages, filtereds, defaultEncoding );
getLogger().debug( "Resolved filesets for " + archetypeDescriptor.getName() );
archetypeDescriptor.setFileSets( filesets );
createArchetypeFiles( reverseProperties, filesets, packageName, basedir, archetypeFilesDirectory,
defaultEncoding );
getLogger().debug( "Created files for " + archetypeDescriptor.getName() );
setParentArtifactId( reverseProperties, configurationProperties.getProperty( Constants.ARTIFACT_ID ) );
for ( Iterator<String> modules = pom.getModules().iterator(); modules.hasNext(); )
{
String moduleId = (String) modules.next();
String rootArtifactId = configurationProperties.getProperty( Constants.ARTIFACT_ID );
String moduleIdDirectory = moduleId;
if ( moduleId.indexOf( rootArtifactId ) >= 0 )
{
moduleIdDirectory = StringUtils.replace( moduleId, rootArtifactId, "__rootArtifactId__" );
}
getLogger().debug( "Creating module " + moduleId );
ModuleDescriptor moduleDescriptor =
createModule( reverseProperties, rootArtifactId, moduleId, packageName,
FileUtils.resolveFile( basedir, moduleId ),
new File( archetypeFilesDirectory, moduleIdDirectory ), languages, filtereds,
defaultEncoding, preserveCData, keepParent );
archetypeDescriptor.addModule( moduleDescriptor );
getLogger().debug(
"Added module " + moduleDescriptor.getName() + " in " + archetypeDescriptor.getName() );
}
restoreParentArtifactId( reverseProperties, null );
restoreArtifactId( reverseProperties, configurationProperties.getProperty( Constants.ARTIFACT_ID ) );
createPoms( pom, configurationProperties.getProperty( Constants.ARTIFACT_ID ),
configurationProperties.getProperty( Constants.ARTIFACT_ID ), archetypeFilesDirectory, basedir,
pomReversedProperties, preserveCData, keepParent );
getLogger().debug( "Created Archetype " + archetypeDescriptor.getName() + " template pom(s)" );
Writer out = null;
try
{
out = WriterFactory.newXmlWriter( archetypeDescriptorFile );
ArchetypeDescriptorXpp3Writer writer = new ArchetypeDescriptorXpp3Writer();
writer.write( out, archetypeDescriptor );
getLogger().debug( "Archetype " + archetypeDescriptor.getName() + " descriptor written" );
}
finally
{
IOUtil.close( out );
}
createArchetypeBasicIt( archetypeDescriptor, outputDirectory );
// Copy archetype integration tests.
File archetypeIntegrationTestInputFolder =
new File( basedir, Constants.SRC + File.separator + "it" + File.separator + "projects" );
File archetypeIntegrationTestOutputFolder = new File( outputDirectory,
Constants.SRC + File.separator + Constants.TEST
+ File.separator + Constants.RESOURCES
+ File.separator + "projects" );
if ( archetypeIntegrationTestInputFolder.exists() )
{
getLogger().info( "Copying: " + archetypeIntegrationTestInputFolder.getAbsolutePath() + " into "
+ archetypeIntegrationTestOutputFolder.getAbsolutePath() );
FileUtils.copyDirectoryStructure( archetypeIntegrationTestInputFolder,
archetypeIntegrationTestOutputFolder );
}
InvocationRequest internalRequest = new DefaultInvocationRequest();
internalRequest.setPomFile( archetypePomFile );
internalRequest.setGoals( Collections.singletonList( request.getPostPhase() ) );
Invoker invoker = new DefaultInvoker();
invoker.execute( internalRequest );
}
catch ( Exception e )
{
result.setCause( e );
}
}
/**
* Create an archetype IT, ie goals.txt and archetype.properties in src/test/resources/projects/basic.
*
* @param archetypeDescriptor
* @param generatedSourcesDirectory
* @throws IOException
* @since 2.0-alpha-5
*/
private void createArchetypeBasicIt( ArchetypeDescriptor archetypeDescriptor, File generatedSourcesDirectory )
throws IOException
{
String basic =
Constants.SRC + File.separator + Constants.TEST + File.separator + Constants.RESOURCES + File.separator
+ "projects" + File.separator + "basic";
File basicItDirectory = new File( generatedSourcesDirectory, basic );
basicItDirectory.mkdirs();
InputStream in = null;
OutputStream out = null;
try
{
in = FilesetArchetypeCreator.class.getResourceAsStream( "archetype.properties" );
Properties archetypeProperties = new Properties();
archetypeProperties.load( in );
for ( RequiredProperty req : archetypeDescriptor.getRequiredProperties() )
{
archetypeProperties.put( req.getKey(), req.getDefaultValue() );
}
out = new FileOutputStream( new File( basicItDirectory, "archetype.properties" ) );
archetypeProperties.store( out, null );
}
finally
{
IOUtil.close( in );
IOUtil.close( out );
}
copyResource( "goal.txt", new File( basicItDirectory, "goal.txt" ) );
getLogger().debug( "Added basic integration test" );
}
private void extractPropertiesFromProject( MavenProject project, Properties properties,
Properties configurationProperties, String packageName )
{
if ( !properties.containsKey( Constants.GROUP_ID ) )
{
properties.setProperty( Constants.GROUP_ID, project.getGroupId() );
}
configurationProperties.setProperty( Constants.GROUP_ID, properties.getProperty( Constants.GROUP_ID ) );
if ( !properties.containsKey( Constants.ARTIFACT_ID ) )
{
properties.setProperty( Constants.ARTIFACT_ID, project.getArtifactId() );
}
configurationProperties.setProperty( Constants.ARTIFACT_ID, properties.getProperty( Constants.ARTIFACT_ID ) );
if ( !properties.containsKey( Constants.VERSION ) )
{
properties.setProperty( Constants.VERSION, project.getVersion() );
}
configurationProperties.setProperty( Constants.VERSION, properties.getProperty( Constants.VERSION ) );
if ( packageName != null )
{
properties.setProperty( Constants.PACKAGE, packageName );
}
else if ( !properties.containsKey( Constants.PACKAGE ) )
{
properties.setProperty( Constants.PACKAGE, project.getGroupId() );
}
configurationProperties.setProperty( Constants.PACKAGE, properties.getProperty( Constants.PACKAGE ) );
}
/**
* Create the archetype project pom.xml file, that will be used to build the archetype.
*/
private File createArchetypeProjectPom( MavenProject project, ArtifactRepository localRepository,
Properties configurationProperties, File projectDir )
throws TemplateCreationException, IOException
{
Model model = new Model();
model.setModelVersion( "4.0.0" );
// these values should be retrieved from the request with sensible defaults
model.setGroupId( configurationProperties.getProperty( Constants.ARCHETYPE_GROUP_ID, project.getGroupId() ) );
model.setArtifactId(
configurationProperties.getProperty( Constants.ARCHETYPE_ARTIFACT_ID, project.getArtifactId() ) );
model.setVersion( configurationProperties.getProperty( Constants.ARCHETYPE_VERSION, project.getVersion() ) );
model.setPackaging( "maven-archetype" );
model.setName(
configurationProperties.getProperty( Constants.ARCHETYPE_ARTIFACT_ID, project.getArtifactId() ) );
model.setUrl( configurationProperties.getProperty( Constants.ARCHETYPE_URL, project.getUrl() ) );
model.setDescription(
configurationProperties.getProperty( Constants.ARCHETYPE_DESCRIPTION, project.getDescription() ) );
model.setLicenses( project.getLicenses() );
model.setDevelopers( project.getDevelopers() );
model.setScm( project.getScm() );
Build build = new Build();
model.setBuild( build );
// In many cases where we are behind a firewall making Archetypes for work mates we want
// to simply be able to deploy the archetypes once we have created them. In order to do
// this we want to utilize information from the project we are creating the archetype from.
// This will be a fully working project that has been testing and inherits from a POM
// that contains deployment information, along with any extensions required for deployment.
// We don't want to create archetypes that cannot be deployed after we create them. People
// might want to edit the archetype POM but they should not have too.
if ( project.getParent() != null )
{
Artifact pa = project.getParentArtifact();
try
{
MavenProject p =
projectBuilder.buildFromRepository( pa, project.getRemoteArtifactRepositories(), localRepository );
if ( p.getDistributionManagement() != null )
{
model.setDistributionManagement( p.getDistributionManagement() );
}
if ( p.getBuildExtensions() != null )
{
for ( Iterator<Extension> i = p.getBuildExtensions().iterator(); i.hasNext(); )
{
Extension be = i.next();
model.getBuild().addExtension( be );
}
}
}
catch ( ProjectBuildingException e )
{
throw new TemplateCreationException(
"Error reading parent POM of project: " + pa.getGroupId() + ":" + pa.getArtifactId() + ":"
+ pa.getVersion() );
}
}
Extension extension = new Extension();
extension.setGroupId( "org.apache.maven.archetype" );
extension.setArtifactId( "archetype-packaging" );
extension.setVersion( getArchetypeVersion() );
model.getBuild().addExtension( extension );
Plugin plugin = new Plugin();
plugin.setGroupId( "org.apache.maven.plugins" );
plugin.setArtifactId( "maven-archetype-plugin" );
plugin.setVersion( getArchetypeVersion() );
PluginManagement pluginManagement = new PluginManagement();
pluginManagement.addPlugin( plugin );
model.getBuild().setPluginManagement( pluginManagement );
getLogger().debug( "Creating archetype's pom" );
File archetypePomFile = new File( projectDir, Constants.ARCHETYPE_POM );
archetypePomFile.getParentFile().mkdirs();
copyResource( "pom-prototype.xml", archetypePomFile );
pomManager.writePom( model, archetypePomFile, archetypePomFile );
return archetypePomFile;
}
private void copyResource( String name, File destination )
throws IOException
{
InputStream in = null;
OutputStream out = null;
try
{
in = FilesetArchetypeCreator.class.getResourceAsStream( name );
out = new FileOutputStream( destination );
IOUtil.copy( in, out );
}
finally
{
IOUtil.close( in );
IOUtil.close( out );
}
}
private void addRequiredProperties( ArchetypeDescriptor archetypeDescriptor, Properties properties )
{
Properties requiredProperties = new Properties();
requiredProperties.putAll( properties );
requiredProperties.remove( Constants.ARCHETYPE_GROUP_ID );
requiredProperties.remove( Constants.ARCHETYPE_ARTIFACT_ID );
requiredProperties.remove( Constants.ARCHETYPE_VERSION );
requiredProperties.remove( Constants.GROUP_ID );
requiredProperties.remove( Constants.ARTIFACT_ID );
requiredProperties.remove( Constants.VERSION );
requiredProperties.remove( Constants.PACKAGE );
for ( Iterator<?> propertiesIterator = requiredProperties.keySet().iterator(); propertiesIterator.hasNext(); )
{
String propertyKey = (String) propertiesIterator.next();
RequiredProperty requiredProperty = new RequiredProperty();
requiredProperty.setKey( propertyKey );
requiredProperty.setDefaultValue( requiredProperties.getProperty( propertyKey ) );
archetypeDescriptor.addRequiredProperty( requiredProperty );
getLogger().debug(
"Adding requiredProperty " + propertyKey + "=" + requiredProperties.getProperty( propertyKey )
+ " to archetype's descriptor" );
}
}
private void createModulePoms( Properties pomReversedProperties, String rootArtifactId, String packageName,
File basedir, File archetypeFilesDirectory, boolean preserveCData,
boolean keepParent )
throws FileNotFoundException, IOException, XmlPullParserException
{
Model pom = pomManager.readPom( FileUtils.resolveFile( basedir, Constants.ARCHETYPE_POM ) );
String parentArtifactId = pomReversedProperties.getProperty( Constants.PARENT_ARTIFACT_ID );
String artifactId = pom.getArtifactId();
setParentArtifactId( pomReversedProperties, pomReversedProperties.getProperty( Constants.ARTIFACT_ID ) );
setArtifactId( pomReversedProperties, pom.getArtifactId() );
for ( Iterator<String> modules = pom.getModules().iterator(); modules.hasNext(); )
{
String subModuleId = modules.next();
String subModuleIdDirectory = subModuleId;
if ( subModuleId.indexOf( rootArtifactId ) >= 0 )
{
subModuleIdDirectory = StringUtils.replace( subModuleId, rootArtifactId, "__rootArtifactId__" );
}
createModulePoms( pomReversedProperties, rootArtifactId, packageName,
FileUtils.resolveFile( basedir, subModuleId ),
FileUtils.resolveFile( archetypeFilesDirectory, subModuleIdDirectory ), preserveCData,
keepParent );
}
createModulePom( pom, rootArtifactId, archetypeFilesDirectory, pomReversedProperties,
FileUtils.resolveFile( basedir, Constants.ARCHETYPE_POM ), preserveCData, keepParent );
restoreParentArtifactId( pomReversedProperties, parentArtifactId );
restoreArtifactId( pomReversedProperties, artifactId );
}
private void createPoms( Model pom, String rootArtifactId, String artifactId, File archetypeFilesDirectory,
File basedir, Properties pomReversedProperties, boolean preserveCData, boolean keepParent )
throws IOException, FileNotFoundException, XmlPullParserException
{
setArtifactId( pomReversedProperties, pom.getArtifactId() );
for ( Iterator<String> modules = pom.getModules().iterator(); modules.hasNext(); )
{
String moduleId = modules.next();
String moduleIdDirectory = moduleId;
if ( moduleId.indexOf( rootArtifactId ) >= 0 )
{
moduleIdDirectory = StringUtils.replace( moduleId, rootArtifactId, "__rootArtifactId__" );
}
createModulePoms( pomReversedProperties, rootArtifactId, moduleId,
FileUtils.resolveFile( basedir, moduleId ),
new File( archetypeFilesDirectory, moduleIdDirectory ), preserveCData, keepParent );
}
restoreParentArtifactId( pomReversedProperties, null );
restoreArtifactId( pomReversedProperties, artifactId );
createArchetypePom( pom, archetypeFilesDirectory, pomReversedProperties,
FileUtils.resolveFile( basedir, Constants.ARCHETYPE_POM ), preserveCData, keepParent );
}
private String getPackageInPathFormat( String aPackage )
{
return StringUtils.replace( aPackage, ".", "/" );
}
private void rewriteReferences( Model pom, String rootArtifactId, String groupId )
{
// rewrite Dependencies
if ( pom.getDependencies() != null && !pom.getDependencies().isEmpty() )
{
for ( Iterator<Dependency> dependencies = pom.getDependencies().iterator(); dependencies.hasNext(); )
{
rewriteDependencyReferences( dependencies.next(), rootArtifactId, groupId );
}
}
// rewrite DependencyManagement
if ( pom.getDependencyManagement() != null && pom.getDependencyManagement().getDependencies() != null
&& !pom.getDependencyManagement().getDependencies().isEmpty() )
{
for ( Iterator<Dependency> dependencies = pom.getDependencyManagement().getDependencies().iterator();
dependencies.hasNext(); )
{
rewriteDependencyReferences( dependencies.next(), rootArtifactId, groupId );
}
}
// rewrite Plugins
if ( pom.getBuild() != null && pom.getBuild().getPlugins() != null && !pom.getBuild().getPlugins().isEmpty() )
{
for ( Iterator<Plugin> plugins = pom.getBuild().getPlugins().iterator(); plugins.hasNext(); )
{
rewritePluginReferences( plugins.next(), rootArtifactId, groupId );
}
}
// rewrite PluginManagement
if ( pom.getBuild() != null && pom.getBuild().getPluginManagement() != null
&& pom.getBuild().getPluginManagement().getPlugins() != null
&& !pom.getBuild().getPluginManagement().getPlugins().isEmpty() )
{
for ( Iterator<Plugin> plugins = pom.getBuild().getPluginManagement().getPlugins().iterator();
plugins.hasNext(); )
{
rewritePluginReferences( plugins.next(), rootArtifactId, groupId );
}
}
// rewrite Profiles
if ( pom.getProfiles() != null )
{
for ( Iterator<Profile> profiles = pom.getProfiles().iterator(); profiles.hasNext(); )
{
Profile profile = profiles.next();
// rewrite Dependencies
if ( profile.getDependencies() != null && !profile.getDependencies().isEmpty() )
{
for ( Iterator<Dependency> dependencies = profile.getDependencies().iterator();
dependencies.hasNext(); )
{
rewriteDependencyReferences( dependencies.next(), rootArtifactId, groupId );
}
}
// rewrite DependencyManagement
if ( profile.getDependencyManagement() != null
&& profile.getDependencyManagement().getDependencies() != null
&& !profile.getDependencyManagement().getDependencies().isEmpty() )
{
for ( Iterator<Dependency> dependencies =
profile.getDependencyManagement().getDependencies().iterator(); dependencies.hasNext(); )
{
rewriteDependencyReferences( dependencies.next(), rootArtifactId, groupId );
}
}
// rewrite Plugins
if ( profile.getBuild() != null && profile.getBuild().getPlugins() != null
&& !profile.getBuild().getPlugins().isEmpty() )
{
for ( Iterator<Plugin> plugins = profile.getBuild().getPlugins().iterator(); plugins.hasNext(); )
{
rewritePluginReferences( plugins.next(), rootArtifactId, groupId );
}
}
// rewrite PluginManagement
if ( profile.getBuild() != null && profile.getBuild().getPluginManagement() != null
&& profile.getBuild().getPluginManagement().getPlugins() != null
&& !profile.getBuild().getPluginManagement().getPlugins().isEmpty() )
{
for ( Iterator<Plugin> plugins = profile.getBuild().getPluginManagement().getPlugins().iterator();
plugins.hasNext(); )
{
rewritePluginReferences( plugins.next(), rootArtifactId, groupId );
}
}
}
}
}
private void rewriteDependencyReferences( Dependency dependency, String rootArtifactId, String groupId )
{
if ( dependency.getArtifactId() != null && dependency.getArtifactId().indexOf( rootArtifactId ) >= 0 )
{
if ( dependency.getGroupId() != null )
{
dependency.setGroupId(
StringUtils.replace( dependency.getGroupId(), groupId, "${" + Constants.GROUP_ID + "}" ) );
}
dependency.setArtifactId(
StringUtils.replace( dependency.getArtifactId(), rootArtifactId, "${rootArtifactId}" ) );
if ( dependency.getVersion() != null )
{
dependency.setVersion( "${" + Constants.VERSION + "}" );
}
}
}
private void rewritePluginReferences( Plugin plugin, String rootArtifactId, String groupId )
{
if ( plugin.getArtifactId() != null && plugin.getArtifactId().indexOf( rootArtifactId ) >= 0 )
{
if ( plugin.getGroupId() != null )
{
String g = StringUtils.replace( plugin.getGroupId(), groupId, "${" + Constants.GROUP_ID + "}" );
plugin.setGroupId( g );
}
plugin.setArtifactId( StringUtils.replace( plugin.getArtifactId(), rootArtifactId, "${rootArtifactId}" ) );
if ( plugin.getVersion() != null )
{
plugin.setVersion( "${" + Constants.VERSION + "}" );
}
}
if ( plugin.getArtifactId() != null && "maven-ear-plugin".equals( plugin.getArtifactId() ) )
{
rewriteEARPluginReferences( plugin, rootArtifactId, groupId );
}
}
private void rewriteEARPluginReferences( Plugin plugin, String rootArtifactId, String groupId )
{
Xpp3Dom configuration = (Xpp3Dom) plugin.getConfiguration();
if ( configuration != null )
{
Xpp3Dom[] modules = configuration.getChild( "modules" ).getChildren();
for ( int i = 0; i < modules.length; i++ )
{
Xpp3Dom module = modules[i];
Xpp3Dom moduleGroupId = module.getChild( "groupId" );
Xpp3Dom moduleArtifactId = module.getChild( "artifactId" );
Xpp3Dom moduleBundleFileName = module.getChild( "bundleFileName" );
Xpp3Dom moduleModuleId = module.getChild( "moduleId" );
Xpp3Dom moduleContextRoot = module.getChild( "contextRoot" );
if ( moduleGroupId != null )
{
moduleGroupId.setValue(
StringUtils.replace( moduleGroupId.getValue(), groupId, "${" + Constants.GROUP_ID + "}" ) );
}
if ( moduleArtifactId != null )
{
moduleArtifactId.setValue(
StringUtils.replace( moduleArtifactId.getValue(), rootArtifactId, "${rootArtifactId}" ) );
}
if ( moduleBundleFileName != null )
{
moduleBundleFileName.setValue(
StringUtils.replace( moduleBundleFileName.getValue(), rootArtifactId, "${rootArtifactId}" ) );
}
if ( moduleModuleId != null )
{
moduleModuleId.setValue(
StringUtils.replace( moduleModuleId.getValue(), rootArtifactId, "${rootArtifactId}" ) );
}
if ( moduleContextRoot != null )
{
moduleContextRoot.setValue(
StringUtils.replace( moduleContextRoot.getValue(), rootArtifactId, "${rootArtifactId}" ) );
}
}
}
}
private void setArtifactId( Properties properties, String artifactId )
{
properties.setProperty( Constants.ARTIFACT_ID, artifactId );
}
private List<String> concatenateToList( List<String> toConcatenate, String with )
{
List<String> result = new ArrayList<String>( toConcatenate.size() );
for ( String concatenate : toConcatenate )
{
result.add( ( ( with.length() > 0 ) ? ( with + "/" + concatenate ) : concatenate ) );
}
return result;
}
private void copyFiles( File basedir, File archetypeFilesDirectory, String directory, List<String> fileSetResources,
boolean packaged, String packageName )
throws IOException
{
String packageAsDirectory = StringUtils.replace( packageName, ".", File.separator );
getLogger().debug( "Package as Directory: Package:" + packageName + "->" + packageAsDirectory );
for ( String inputFileName : fileSetResources )
{
String outputFileName = packaged
? StringUtils.replace( inputFileName, packageAsDirectory + File.separator, "" )
: inputFileName;
getLogger().debug( "InputFileName:" + inputFileName );
getLogger().debug( "OutputFileName:" + outputFileName );
File outputFile = new File( archetypeFilesDirectory, outputFileName );
File inputFile = new File( basedir, inputFileName );
outputFile.getParentFile().mkdirs();
FileUtils.copyFile( inputFile, outputFile );
}
}
private void createArchetypeFiles( Properties reverseProperties, List<FileSet> fileSets, String packageName,
File basedir, File archetypeFilesDirectory, String defaultEncoding )
throws IOException
{
getLogger().debug( "Creating Archetype/Module files from " + basedir + " to " + archetypeFilesDirectory );
for ( FileSet fileSet : fileSets )
{
DirectoryScanner scanner = new DirectoryScanner();
scanner.setBasedir( basedir );
scanner.setIncludes( (String[]) concatenateToList( fileSet.getIncludes(), fileSet.getDirectory() ).toArray(
new String[fileSet.getIncludes().size()] ) );
scanner.setExcludes( (String[]) fileSet.getExcludes().toArray( new String[fileSet.getExcludes().size()] ) );
scanner.addDefaultExcludes();
getLogger().debug( "Using fileset " + fileSet );
scanner.scan();
List<String> fileSetResources = Arrays.asList( scanner.getIncludedFiles() );
getLogger().debug( "Scanned " + fileSetResources.size() + " resources" );
if ( fileSet.isFiltered() )
{
processFileSet( basedir, archetypeFilesDirectory, fileSet.getDirectory(), fileSetResources,
fileSet.isPackaged(), packageName, reverseProperties, defaultEncoding );
getLogger().debug( "Processed " + fileSet.getDirectory() + " files" );
}
else
{
copyFiles( basedir, archetypeFilesDirectory, fileSet.getDirectory(), fileSetResources,
fileSet.isPackaged(), packageName );
getLogger().debug( "Copied " + fileSet.getDirectory() + " files" );
}
}
}
private void createArchetypePom( Model pom, File archetypeFilesDirectory, Properties pomReversedProperties,
File initialPomFile, boolean preserveCData, boolean keepParent )
throws IOException
{
File outputFile = FileUtils.resolveFile( archetypeFilesDirectory, Constants.ARCHETYPE_POM );
if ( preserveCData )
{
getLogger().debug( "Preserving CDATA parts of pom" );
File inputFile = FileUtils.resolveFile( archetypeFilesDirectory, Constants.ARCHETYPE_POM + ".tmp" );
FileUtils.copyFile( initialPomFile, inputFile );
Reader in = null;
Writer out = null;
try
{
in = ReaderFactory.newXmlReader( inputFile );
String initialcontent = IOUtil.toString( in );
String content = getReversedContent( initialcontent, pomReversedProperties );
outputFile.getParentFile().mkdirs();
out = WriterFactory.newXmlWriter( outputFile );
IOUtil.copy( content, out );
}
finally
{
IOUtil.close( in );
IOUtil.close( out );
}
inputFile.delete();
}
else
{
if ( !keepParent )
{
pom.setParent( null );
}
pom.setModules( null );
pom.setGroupId( "${" + Constants.GROUP_ID + "}" );
pom.setArtifactId( "${" + Constants.ARTIFACT_ID + "}" );
pom.setVersion( "${" + Constants.VERSION + "}" );
pom.setName( getReversedPlainContent( pom.getName(), pomReversedProperties ) );
pom.setDescription( getReversedPlainContent( pom.getDescription(), pomReversedProperties ) );
pom.setUrl( getReversedPlainContent( pom.getUrl(), pomReversedProperties ) );
rewriteReferences( pom, pomReversedProperties.getProperty( Constants.ARTIFACT_ID ),
pomReversedProperties.getProperty( Constants.GROUP_ID ) );
pomManager.writePom( pom, outputFile, initialPomFile );
}
Reader in = null;
try
{
in = ReaderFactory.newXmlReader( initialPomFile );
String initialcontent = IOUtil.toString( in );
Iterator<?> properties = pomReversedProperties.keySet().iterator();
while ( properties.hasNext() )
{
String property = (String) properties.next();
if ( initialcontent.indexOf( "${" + property + "}" ) > 0 )
{
getLogger().warn(
"Archetype uses ${" + property + "} for internal processing, but file " + initialPomFile
+ " contains this property already" );
}
}
}
finally
{
IOUtil.close( in );
}
}
private FileSet createFileSet( final List<String> excludes, final boolean packaged, final boolean filtered,
final String group, final List<String> includes, String defaultEncoding )
{
FileSet fileSet = new FileSet();
fileSet.setDirectory( group );
fileSet.setPackaged( packaged );
fileSet.setFiltered( filtered );
fileSet.setIncludes( includes );
fileSet.setExcludes( excludes );
fileSet.setEncoding( defaultEncoding );
getLogger().debug( "Created Fileset " + fileSet );
return fileSet;
}
private List<FileSet> createFileSets( List<String> files, int level, boolean packaged, String packageName,
boolean filtered, String defaultEncoding )
{
List<FileSet> fileSets = new ArrayList<FileSet>();
if ( !files.isEmpty() )
{
getLogger().debug( "Creating filesets" + ( packaged ? ( " packaged (" + packageName + ")" ) : "" ) + (
filtered
? " filtered"
: "" ) + " at level " + level );
if ( level == 0 )
{
List<String> includes = new ArrayList<String>( files );
List<String> excludes = new ArrayList<String>();
if ( !includes.isEmpty() )
{
fileSets.add( createFileSet( excludes, packaged, filtered, "", includes, defaultEncoding ) );
}
}
else
{
Map<String, List<String>> groups = getGroupsMap( files, level );
for ( String group : groups.keySet() )
{
getLogger().debug( "Creating filesets for group " + group );
if ( !packaged )
{
fileSets.add( getUnpackagedFileSet( filtered, group, groups.get( group ), defaultEncoding ) );
}
else
{
fileSets.addAll(
getPackagedFileSets( filtered, group, groups.get( group ), packageName, defaultEncoding ) );
}
}
} // end if
getLogger().debug( "Resolved fileSets " + fileSets );
} // end if
return fileSets;
}
private ModuleDescriptor createModule( Properties reverseProperties, String rootArtifactId, String moduleId,
String packageName, File basedir, File archetypeFilesDirectory,
List<String> languages, List<String> filtereds, String defaultEncoding,
boolean preserveCData, boolean keepParent )
throws IOException, XmlPullParserException
{
ModuleDescriptor archetypeDescriptor = new ModuleDescriptor();
getLogger().debug( "Starting module's descriptor " + moduleId );
archetypeFilesDirectory.mkdirs();
getLogger().debug( "Module's files output directory " + archetypeFilesDirectory );
Model pom = pomManager.readPom( FileUtils.resolveFile( basedir, Constants.ARCHETYPE_POM ) );
String replacementId = pom.getArtifactId();
String moduleDirectory = pom.getArtifactId();
if ( replacementId.indexOf( rootArtifactId ) >= 0 )
{
replacementId = StringUtils.replace( replacementId, rootArtifactId, "${rootArtifactId}" );
moduleDirectory = StringUtils.replace( moduleId, rootArtifactId, "__rootArtifactId__" );
}
if ( moduleId.indexOf( rootArtifactId ) >= 0 )
{
moduleDirectory = StringUtils.replace( moduleId, rootArtifactId, "__rootArtifactId__" );
}
archetypeDescriptor.setName( replacementId );
archetypeDescriptor.setId( replacementId );
archetypeDescriptor.setDir( moduleDirectory );
setArtifactId( reverseProperties, pom.getArtifactId() );
List<String> excludePatterns =
reverseProperties.getProperty( Constants.EXCLUDE_PATTERNS ) != null
? Arrays.asList( StringUtils.split( reverseProperties.getProperty( Constants.EXCLUDE_PATTERNS ), "," ) )
: Collections.<String>emptyList();
List<String> fileNames = resolveFileNames( pom, basedir, excludePatterns );
List<FileSet> filesets = resolveFileSets( packageName, fileNames, languages, filtereds, defaultEncoding );
getLogger().debug( "Resolved filesets for module " + archetypeDescriptor.getName() );
archetypeDescriptor.setFileSets( filesets );
createArchetypeFiles( reverseProperties, filesets, packageName, basedir, archetypeFilesDirectory,
defaultEncoding );
getLogger().debug( "Created files for module " + archetypeDescriptor.getName() );
String parentArtifactId = reverseProperties.getProperty( Constants.PARENT_ARTIFACT_ID );
setParentArtifactId( reverseProperties, pom.getArtifactId() );
for ( Iterator<String> modules = pom.getModules().iterator(); modules.hasNext(); )
{
String subModuleId = modules.next();
String subModuleIdDirectory = subModuleId;
if ( subModuleId.indexOf( rootArtifactId ) >= 0 )
{
subModuleIdDirectory = StringUtils.replace( subModuleId, rootArtifactId, "__rootArtifactId__" );
}
getLogger().debug( "Creating module " + subModuleId );
ModuleDescriptor moduleDescriptor =
createModule( reverseProperties, rootArtifactId, subModuleId, packageName,
FileUtils.resolveFile( basedir, subModuleId ),
FileUtils.resolveFile( archetypeFilesDirectory, subModuleIdDirectory ), languages,
filtereds, defaultEncoding, preserveCData, keepParent );
archetypeDescriptor.addModule( moduleDescriptor );
getLogger().debug( "Added module " + moduleDescriptor.getName() + " in " + archetypeDescriptor.getName() );
}
restoreParentArtifactId( reverseProperties, parentArtifactId );
restoreArtifactId( reverseProperties, pom.getArtifactId() );
getLogger().debug( "Created Module " + archetypeDescriptor.getName() + " pom" );
return archetypeDescriptor;
}
private void createModulePom( Model pom, String rootArtifactId, File archetypeFilesDirectory,
Properties pomReversedProperties, File initialPomFile, boolean preserveCData,
boolean keepParent )
throws IOException
{
File outputFile = FileUtils.resolveFile( archetypeFilesDirectory, Constants.ARCHETYPE_POM );
if ( preserveCData )
{
getLogger().debug( "Preserving CDATA parts of pom" );
File inputFile = FileUtils.resolveFile( archetypeFilesDirectory, Constants.ARCHETYPE_POM + ".tmp" );
FileUtils.copyFile( initialPomFile, inputFile );
Reader in = null;
Writer out = null;
try
{
in = ReaderFactory.newXmlReader( inputFile );
String initialcontent = IOUtil.toString( in );
String content = getReversedContent( initialcontent, pomReversedProperties );
outputFile.getParentFile().mkdirs();
out = WriterFactory.newXmlWriter( outputFile );
IOUtil.copy( content, out );
}
finally
{
IOUtil.close( in );
IOUtil.close( out );
}
inputFile.delete();
}
else
{
if ( pom.getParent() != null )
{
pom.getParent().setGroupId( StringUtils.replace( pom.getParent().getGroupId(),
pomReversedProperties.getProperty(
Constants.GROUP_ID ),
"${" + Constants.GROUP_ID + "}" ) );
if ( pom.getParent().getArtifactId() != null
&& pom.getParent().getArtifactId().indexOf( rootArtifactId ) >= 0 )
{
pom.getParent().setArtifactId(
StringUtils.replace( pom.getParent().getArtifactId(), rootArtifactId, "${rootArtifactId}" ) );
}
if ( pom.getParent().getVersion() != null )
{
pom.getParent().setVersion( "${" + Constants.VERSION + "}" );
}
}
pom.setModules( null );
if ( pom.getGroupId() != null )
{
pom.setGroupId(
StringUtils.replace( pom.getGroupId(), pomReversedProperties.getProperty( Constants.GROUP_ID ),
"${" + Constants.GROUP_ID + "}" ) );
}
pom.setArtifactId( "${" + Constants.ARTIFACT_ID + "}" );
if ( pom.getVersion() != null )
{
pom.setVersion( "${" + Constants.VERSION + "}" );
}
pom.setName( getReversedPlainContent( pom.getName(), pomReversedProperties ) );
pom.setDescription( getReversedPlainContent( pom.getDescription(), pomReversedProperties ) );
pom.setUrl( getReversedPlainContent( pom.getUrl(), pomReversedProperties ) );
rewriteReferences( pom, rootArtifactId, pomReversedProperties.getProperty( Constants.GROUP_ID ) );
pomManager.writePom( pom, outputFile, initialPomFile );
}
Reader in = null;
try
{
in = ReaderFactory.newXmlReader( initialPomFile );
String initialcontent = IOUtil.toString( in );
for ( Iterator<?> properties = pomReversedProperties.keySet().iterator(); properties.hasNext(); )
{
String property = (String) properties.next();
if ( initialcontent.indexOf( "${" + property + "}" ) > 0 )
{
getLogger().warn(
"OldArchetype uses ${" + property + "} for internal processing, but file " + initialPomFile
+ " contains this property already" );
}
}
}
finally
{
IOUtil.close( in );
}
}
private Set<String> getExtensions( List<String> files )
{
Set<String> extensions = new HashSet<String>();
for ( String file : files )
{
extensions.add( FileUtils.extension( file ) );
}
return extensions;
}
private Map<String, List<String>> getGroupsMap( final List<String> files, final int level )
{
Map<String, List<String>> groups = new HashMap<String, List<String>>();
for ( String file : files )
{
String directory = PathUtils.getDirectory( file, level );
// make all groups have unix style
directory = StringUtils.replace( directory, File.separator, "/" );
if ( !groups.containsKey( directory ) )
{
groups.put( directory, new ArrayList<String>() );
}
List<String> group = groups.get( directory );
String innerPath = file.substring( directory.length() + 1 );
// make all groups have unix style
innerPath = StringUtils.replace( innerPath, File.separator, "/" );
group.add( innerPath );
}
getLogger().debug( "Sorted " + groups.size() + " groups in " + files.size() + " files" );
getLogger().debug( "Sorted Files: " + files );
return groups;
}
private FileSet getPackagedFileSet( final boolean filtered, final Set<String> packagedExtensions,
final String group, final Set<String> unpackagedExtensions,
final List<String> unpackagedFiles, String defaultEncoding )
{
List<String> includes = new ArrayList<String>();
List<String> excludes = new ArrayList<String>();
for ( String extension : packagedExtensions )
{
includes.add( "**/*." + extension );
if ( unpackagedExtensions.contains( extension ) )
{
excludes.addAll( archetypeFilesResolver.getFilesWithExtension( unpackagedFiles, extension ) );
}
}
return createFileSet( excludes, true, filtered, group, includes, defaultEncoding );
}
private List<FileSet> getPackagedFileSets( final boolean filtered, final String group,
final List<String> groupFiles, final String packageName,
String defaultEncoding )
{
String packageAsDir = StringUtils.replace( packageName, ".", "/" );
List<FileSet> packagedFileSets = new ArrayList<FileSet>();
List<String> packagedFiles = archetypeFilesResolver.getPackagedFiles( groupFiles, packageAsDir );
getLogger().debug( "Found packaged Files:" + packagedFiles );
List<String> unpackagedFiles = archetypeFilesResolver.getUnpackagedFiles( groupFiles, packageAsDir );
getLogger().debug( "Found unpackaged Files:" + unpackagedFiles );
Set<String> packagedExtensions = getExtensions( packagedFiles );
getLogger().debug( "Found packaged extensions " + packagedExtensions );
Set<String> unpackagedExtensions = getExtensions( unpackagedFiles );
if ( !packagedExtensions.isEmpty() )
{
packagedFileSets.add(
getPackagedFileSet( filtered, packagedExtensions, group, unpackagedExtensions, unpackagedFiles,
defaultEncoding ) );
}
if ( !unpackagedExtensions.isEmpty() )
{
getLogger().debug( "Found unpackaged extensions " + unpackagedExtensions );
packagedFileSets.add(
getUnpackagedFileSet( filtered, unpackagedExtensions, unpackagedFiles, group, packagedExtensions,
defaultEncoding ) );
}
return packagedFileSets;
}
private void setParentArtifactId( Properties properties, String parentArtifactId )
{
properties.setProperty( Constants.PARENT_ARTIFACT_ID, parentArtifactId );
}
private void processFileSet( File basedir, File archetypeFilesDirectory, String directory,
List<String> fileSetResources, boolean packaged, String packageName,
Properties reverseProperties, String defaultEncoding )
throws IOException
{
String packageAsDirectory = StringUtils.replace( packageName, ".", File.separator );
getLogger().debug( "Package as Directory: Package:" + packageName + "->" + packageAsDirectory );
for ( String inputFileName : fileSetResources )
{
String initialFilename = packaged
? StringUtils.replace( inputFileName, packageAsDirectory + File.separator, "" )
: inputFileName;
getLogger().debug( "InputFileName:" + inputFileName );
File inputFile = new File( basedir, inputFileName );
FileCharsetDetector detector = new FileCharsetDetector( inputFile );
String fileEncoding = detector.isFound() ? detector.getCharset() : defaultEncoding;
String initialcontent = IOUtil.toString( new FileInputStream( inputFile ), fileEncoding );
for ( Iterator<?> properties = reverseProperties.keySet().iterator(); properties.hasNext(); )
{
String property = (String) properties.next();
if ( initialcontent.indexOf( "${" + property + "}" ) > 0 )
{
getLogger().warn(
"Archetype uses ${" + property + "} for internal processing, but file " + inputFile
+ " contains this property already" );
}
}
String content = getReversedContent( initialcontent, reverseProperties );
String outputFilename = getReversedFilename( initialFilename, reverseProperties );
getLogger().debug( "OutputFileName:" + outputFilename );
File outputFile = new File( archetypeFilesDirectory, outputFilename );
outputFile.getParentFile().mkdirs();
org.apache.commons.io.IOUtils.write( content, new FileOutputStream( outputFile ), fileEncoding );
}
}
private List<String> removePackage( List<String> sources, String packageAsDirectory )
{
if ( sources == null )
{
return null;
}
List<String> unpackagedSources = new ArrayList<String>( sources.size() );
for ( String source : sources )
{
String unpackagedSource = StringUtils.replace( source, packageAsDirectory, "" );
unpackagedSources.add( unpackagedSource );
}
return unpackagedSources;
}
private Properties getReversedProperties( ArchetypeDescriptor archetypeDescriptor, Properties properties )
{
Properties reversedProperties = new Properties();
reversedProperties.putAll( properties );
reversedProperties.remove( Constants.ARCHETYPE_GROUP_ID );
reversedProperties.remove( Constants.ARCHETYPE_ARTIFACT_ID );
reversedProperties.remove( Constants.ARCHETYPE_VERSION );
String packageName = properties.getProperty( Constants.PACKAGE );
String packageInPathFormat = getPackageInPathFormat( packageName );
if ( !packageInPathFormat.equals( packageName ) )
{
reversedProperties.setProperty( Constants.PACKAGE_IN_PATH_FORMAT, packageInPathFormat );
}
// TODO check that reversed properties are all different and no one is a substring of another?
// to avoid wrong variable replacements
return reversedProperties;
}
private List<String> resolveFileNames( final Model pom, final File basedir, List<String> excludePatterns )
throws IOException
{
getLogger().debug( "Resolving files for " + pom.getId() + " in " + basedir );
StringBuffer buff = new StringBuffer( "pom.xml*,archetype.properties*,target/**," );
for ( Iterator<String> modules = pom.getModules().iterator(); modules.hasNext(); )
{
buff.append( ',' ).append( modules.next() ).append( "/**" );
}
for ( String defaultExclude : ListScanner.DEFAULTEXCLUDES )
{
buff.append( ',' ).append( defaultExclude ).append( "/**" );
}
for ( String excludePattern : excludePatterns )
{
buff.append( ',' ).append( excludePattern );
}
String excludes = PathUtils.convertPathForOS( buff.toString() );
List<String> fileNames = FileUtils.getFileNames( basedir, "**,.*,**/.*", excludes, false );
getLogger().debug( "Resolved " + fileNames.size() + " files" );
getLogger().debug( "Resolved Files:" + fileNames );
return fileNames;
}
private List<FileSet> resolveFileSets( String packageName, List<String> fileNames, List<String> languages,
List<String> filtereds, String defaultEncoding )
{
List<FileSet> resolvedFileSets = new ArrayList<FileSet>();
getLogger().debug(
"Resolving filesets with package=" + packageName + ", languages=" + languages + " and extentions="
+ filtereds );
List<String> files = new ArrayList<String>( fileNames );
StringBuilder languageIncludes = new StringBuilder();
for ( String language : languages )
{
languageIncludes.append( ( ( languageIncludes.length() == 0 ) ? "" : "," ) + language + "/**" );
}
getLogger().debug( "Using languages includes " + languageIncludes );
StringBuilder filteredIncludes = new StringBuilder();
for ( String filtered : filtereds )
{
filteredIncludes.append(
( ( filteredIncludes.length() == 0 ) ? "" : "," ) + "**/" + ( filtered.startsWith( "." ) ? "" : "*." )
+ filtered );
}
getLogger().debug( "Using filtered includes " + filteredIncludes );
/* sourcesMainFiles */
List<String> sourcesMainFiles =
archetypeFilesResolver.findSourcesMainFiles( files, languageIncludes.toString() );
if ( !sourcesMainFiles.isEmpty() )
{
files.removeAll( sourcesMainFiles );
List<String> filteredFiles =
archetypeFilesResolver.getFilteredFiles( sourcesMainFiles, filteredIncludes.toString() );
sourcesMainFiles.removeAll( filteredFiles );
List<String> unfilteredFiles = sourcesMainFiles;
if ( !filteredFiles.isEmpty() )
{
resolvedFileSets.addAll( createFileSets( filteredFiles, 3, true, packageName, true, defaultEncoding ) );
}
if ( !unfilteredFiles.isEmpty() )
{
resolvedFileSets.addAll(
createFileSets( unfilteredFiles, 3, true, packageName, false, defaultEncoding ) );
}
}
/* resourcesMainFiles */
List<String> resourcesMainFiles =
archetypeFilesResolver.findResourcesMainFiles( files, languageIncludes.toString() );
if ( !resourcesMainFiles.isEmpty() )
{
files.removeAll( resourcesMainFiles );
List<String> filteredFiles =
archetypeFilesResolver.getFilteredFiles( resourcesMainFiles, filteredIncludes.toString() );
resourcesMainFiles.removeAll( filteredFiles );
List<String> unfilteredFiles = resourcesMainFiles;
if ( !filteredFiles.isEmpty() )
{
resolvedFileSets.addAll(
createFileSets( filteredFiles, 3, false, packageName, true, defaultEncoding ) );
}
if ( !unfilteredFiles.isEmpty() )
{
resolvedFileSets.addAll(
createFileSets( unfilteredFiles, 3, false, packageName, false, defaultEncoding ) );
}
}
/* sourcesTestFiles */
List<String> sourcesTestFiles =
archetypeFilesResolver.findSourcesTestFiles( files, languageIncludes.toString() );
if ( !sourcesTestFiles.isEmpty() )
{
files.removeAll( sourcesTestFiles );
List<String> filteredFiles =
archetypeFilesResolver.getFilteredFiles( sourcesTestFiles, filteredIncludes.toString() );
sourcesTestFiles.removeAll( filteredFiles );
List<String> unfilteredFiles = sourcesTestFiles;
if ( !filteredFiles.isEmpty() )
{
resolvedFileSets.addAll( createFileSets( filteredFiles, 3, true, packageName, true, defaultEncoding ) );
}
if ( !unfilteredFiles.isEmpty() )
{
resolvedFileSets.addAll(
createFileSets( unfilteredFiles, 3, true, packageName, false, defaultEncoding ) );
}
}
/* ressourcesTestFiles */
List<String> resourcesTestFiles =
archetypeFilesResolver.findResourcesTestFiles( files, languageIncludes.toString() );
if ( !resourcesTestFiles.isEmpty() )
{
files.removeAll( resourcesTestFiles );
List<String> filteredFiles =
archetypeFilesResolver.getFilteredFiles( resourcesTestFiles, filteredIncludes.toString() );
resourcesTestFiles.removeAll( filteredFiles );
List<String> unfilteredFiles = resourcesTestFiles;
if ( !filteredFiles.isEmpty() )
{
resolvedFileSets.addAll(
createFileSets( filteredFiles, 3, false, packageName, true, defaultEncoding ) );
}
if ( !unfilteredFiles.isEmpty() )
{
resolvedFileSets.addAll(
createFileSets( unfilteredFiles, 3, false, packageName, false, defaultEncoding ) );
}
}
/* siteFiles */
List<String> siteFiles = archetypeFilesResolver.findSiteFiles( files, languageIncludes.toString() );
if ( !siteFiles.isEmpty() )
{
files.removeAll( siteFiles );
List<String> filteredFiles =
archetypeFilesResolver.getFilteredFiles( siteFiles, filteredIncludes.toString() );
siteFiles.removeAll( filteredFiles );
List<String> unfilteredFiles = siteFiles;
if ( !filteredFiles.isEmpty() )
{
resolvedFileSets.addAll(
createFileSets( filteredFiles, 2, false, packageName, true, defaultEncoding ) );
}
if ( !unfilteredFiles.isEmpty() )
{
resolvedFileSets.addAll(
createFileSets( unfilteredFiles, 2, false, packageName, false, defaultEncoding ) );
}
}
/* thirdLevelSourcesfiles */
List<String> thirdLevelSourcesfiles =
archetypeFilesResolver.findOtherSources( 3, files, languageIncludes.toString() );
if ( !thirdLevelSourcesfiles.isEmpty() )
{
files.removeAll( thirdLevelSourcesfiles );
List<String> filteredFiles =
archetypeFilesResolver.getFilteredFiles( thirdLevelSourcesfiles, filteredIncludes.toString() );
thirdLevelSourcesfiles.removeAll( filteredFiles );
List<String> unfilteredFiles = thirdLevelSourcesfiles;
if ( !filteredFiles.isEmpty() )
{
resolvedFileSets.addAll( createFileSets( filteredFiles, 3, true, packageName, true, defaultEncoding ) );
}
if ( !unfilteredFiles.isEmpty() )
{
resolvedFileSets.addAll(
createFileSets( unfilteredFiles, 3, true, packageName, false, defaultEncoding ) );
}
/* thirdLevelResourcesfiles */
List<String> thirdLevelResourcesfiles =
archetypeFilesResolver.findOtherResources( 3, files, thirdLevelSourcesfiles,
languageIncludes.toString() );
if ( !thirdLevelResourcesfiles.isEmpty() )
{
files.removeAll( thirdLevelResourcesfiles );
filteredFiles =
archetypeFilesResolver.getFilteredFiles( thirdLevelResourcesfiles, filteredIncludes.toString() );
thirdLevelResourcesfiles.removeAll( filteredFiles );
unfilteredFiles = thirdLevelResourcesfiles;
if ( !filteredFiles.isEmpty() )
{
resolvedFileSets.addAll(
createFileSets( filteredFiles, 3, false, packageName, true, defaultEncoding ) );
}
if ( !unfilteredFiles.isEmpty() )
{
resolvedFileSets.addAll(
createFileSets( unfilteredFiles, 3, false, packageName, false, defaultEncoding ) );
}
}
} // end if
/* secondLevelSourcesfiles */
List<String> secondLevelSourcesfiles =
archetypeFilesResolver.findOtherSources( 2, files, languageIncludes.toString() );
if ( !secondLevelSourcesfiles.isEmpty() )
{
files.removeAll( secondLevelSourcesfiles );
List<String> filteredFiles =
archetypeFilesResolver.getFilteredFiles( secondLevelSourcesfiles, filteredIncludes.toString() );
secondLevelSourcesfiles.removeAll( filteredFiles );
List<String> unfilteredFiles = secondLevelSourcesfiles;
if ( !filteredFiles.isEmpty() )
{
resolvedFileSets.addAll( createFileSets( filteredFiles, 2, true, packageName, true, defaultEncoding ) );
}
if ( !unfilteredFiles.isEmpty() )
{
resolvedFileSets.addAll(
createFileSets( unfilteredFiles, 2, true, packageName, false, defaultEncoding ) );
}
}
/* secondLevelResourcesfiles */
List<String> secondLevelResourcesfiles =
archetypeFilesResolver.findOtherResources( 2, files, languageIncludes.toString() );
if ( !secondLevelResourcesfiles.isEmpty() )
{
files.removeAll( secondLevelResourcesfiles );
List<String> filteredFiles =
archetypeFilesResolver.getFilteredFiles( secondLevelResourcesfiles, filteredIncludes.toString() );
secondLevelResourcesfiles.removeAll( filteredFiles );
List<String> unfilteredFiles = secondLevelResourcesfiles;
if ( !filteredFiles.isEmpty() )
{
resolvedFileSets.addAll(
createFileSets( filteredFiles, 2, false, packageName, true, defaultEncoding ) );
}
if ( !unfilteredFiles.isEmpty() )
{
resolvedFileSets.addAll(
createFileSets( unfilteredFiles, 2, false, packageName, false, defaultEncoding ) );
}
}
/* rootResourcesfiles */
List<String> rootResourcesfiles =
archetypeFilesResolver.findOtherResources( 0, files, languageIncludes.toString() );
if ( !rootResourcesfiles.isEmpty() )
{
files.removeAll( rootResourcesfiles );
List<String> filteredFiles =
archetypeFilesResolver.getFilteredFiles( rootResourcesfiles, filteredIncludes.toString() );
rootResourcesfiles.removeAll( filteredFiles );
List<String> unfilteredFiles = rootResourcesfiles;
if ( !filteredFiles.isEmpty() )
{
resolvedFileSets.addAll(
createFileSets( filteredFiles, 0, false, packageName, true, defaultEncoding ) );
}
if ( !unfilteredFiles.isEmpty() )
{
resolvedFileSets.addAll(
createFileSets( unfilteredFiles, 0, false, packageName, false, defaultEncoding ) );
}
}
/**/
if ( !files.isEmpty() )
{
getLogger().info( "Ignored files: " + files );
}
return resolvedFileSets;
}
private void restoreArtifactId( Properties properties, String artifactId )
{
if ( StringUtils.isEmpty( artifactId ) )
{
properties.remove( Constants.ARTIFACT_ID );
}
else
{
properties.setProperty( Constants.ARTIFACT_ID, artifactId );
}
}
private void restoreParentArtifactId( Properties properties, String parentArtifactId )
{
if ( StringUtils.isEmpty( parentArtifactId ) )
{
properties.remove( Constants.PARENT_ARTIFACT_ID );
}
else
{
properties.setProperty( Constants.PARENT_ARTIFACT_ID, parentArtifactId );
}
}
private String getReversedContent( String content, Properties properties )
{
String result =
StringUtils.replace( StringUtils.replace( content, "$", "${symbol_dollar}" ), "\\", "${symbol_escape}" );
result = getReversedPlainContent( result, properties );
// TODO: Replace velocity to a better engine...
return "#set( $symbol_pound = '#' )\n" + "#set( $symbol_dollar = '$' )\n" + "#set( $symbol_escape = '\\' )\n"
+ StringUtils.replace( result, "#", "${symbol_pound}" );
}
private String getReversedPlainContent( String content, Properties properties )
{
String result = content;
for ( Iterator<?> propertyIterator = properties.keySet().iterator(); propertyIterator.hasNext(); )
{
String propertyKey = (String) propertyIterator.next();
result = StringUtils.replace( result, properties.getProperty( propertyKey ), "${" + propertyKey + "}" );
}
return result;
}
private String getReversedFilename( String filename, Properties properties )
{
String result = filename;
for ( Iterator<?> propertyIterator = properties.keySet().iterator(); propertyIterator.hasNext(); )
{
String propertyKey = (String) propertyIterator.next();
result = StringUtils.replace( result, properties.getProperty( propertyKey ), "__" + propertyKey + "__" );
}
return result;
}
private String getTemplateOutputDirectory()
{
return Constants.SRC + File.separator + Constants.MAIN + File.separator + Constants.RESOURCES;
}
private FileSet getUnpackagedFileSet( final boolean filtered, final String group, final List<String> groupFiles,
String defaultEncoding )
{
Set<String> extensions = getExtensions( groupFiles );
List<String> includes = new ArrayList<String>();
List<String> excludes = new ArrayList<String>();
for ( String extension : extensions )
{
includes.add( "**/*." + extension );
}
return createFileSet( excludes, false, filtered, group, includes, defaultEncoding );
}
private FileSet getUnpackagedFileSet( final boolean filtered, final Set<String> unpackagedExtensions,
final List<String> unpackagedFiles, final String group,
final Set<String> packagedExtensions, String defaultEncoding )
{
List<String> includes = new ArrayList<String>();
List<String> excludes = new ArrayList<String>();
for ( String extension : unpackagedExtensions )
{
if ( packagedExtensions.contains( extension ) )
{
includes.addAll( archetypeFilesResolver.getFilesWithExtension( unpackagedFiles, extension ) );
}
else
{
if ( StringUtils.isEmpty( extension ) )
{
includes.add( "**/*" );
}
else
{
includes.add( "**/*." + extension );
}
}
}
return createFileSet( excludes, false, filtered, group, includes, defaultEncoding );
}
private static final String MAVEN_PROPERTIES =
"META-INF/maven/org.apache.maven.archetype/archetype-common/pom.properties";
public String getArchetypeVersion()
{
InputStream is = null;
// This should actually come from the pom.properties at testing but it's not generated and put into the JAR, it
// happens as part of the JAR plugin which is crap as it makes testing inconsistent.
String version = "version";
try
{
Properties properties = new Properties();
is = getClass().getClassLoader().getResourceAsStream( MAVEN_PROPERTIES );
if ( is != null )
{
properties.load( is );
String property = properties.getProperty( "version" );
if ( property != null )
{
return property;
}
}
return version;
}
catch ( IOException e )
{
return version;
}
finally
{
IOUtil.close( is );
}
}
}