View Javadoc
1   package org.apache.maven.archetype.creator;
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.FileOutputStream;
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.io.OutputStream;
29  import java.io.Reader;
30  import java.io.Writer;
31  import java.util.ArrayList;
32  import java.util.Arrays;
33  import java.util.Collections;
34  import java.util.HashMap;
35  import java.util.HashSet;
36  import java.util.Iterator;
37  import java.util.List;
38  import java.util.Map;
39  import java.util.Properties;
40  import java.util.Set;
41  
42  import org.apache.commons.collections.CollectionUtils;
43  import org.apache.maven.archetype.ArchetypeCreationRequest;
44  import org.apache.maven.archetype.ArchetypeCreationResult;
45  import org.apache.maven.archetype.common.ArchetypeFilesResolver;
46  import org.apache.maven.archetype.common.Constants;
47  import org.apache.maven.archetype.common.PomManager;
48  import org.apache.maven.archetype.common.util.FileCharsetDetector;
49  import org.apache.maven.archetype.common.util.ListScanner;
50  import org.apache.maven.archetype.common.util.PathUtils;
51  import org.apache.maven.archetype.exception.TemplateCreationException;
52  import org.apache.maven.archetype.metadata.ArchetypeDescriptor;
53  import org.apache.maven.archetype.metadata.FileSet;
54  import org.apache.maven.archetype.metadata.ModuleDescriptor;
55  import org.apache.maven.archetype.metadata.RequiredProperty;
56  import org.apache.maven.archetype.metadata.io.xpp3.ArchetypeDescriptorXpp3Writer;
57  import org.apache.maven.artifact.Artifact;
58  import org.apache.maven.artifact.repository.ArtifactRepository;
59  import org.apache.maven.model.Build;
60  import org.apache.maven.model.Dependency;
61  import org.apache.maven.model.Extension;
62  import org.apache.maven.model.Model;
63  import org.apache.maven.model.Plugin;
64  import org.apache.maven.model.PluginManagement;
65  import org.apache.maven.model.Profile;
66  import org.apache.maven.model.Resource;
67  import org.apache.maven.project.DefaultProjectBuildingRequest;
68  import org.apache.maven.project.MavenProject;
69  import org.apache.maven.project.ProjectBuilder;
70  import org.apache.maven.project.ProjectBuildingException;
71  import org.apache.maven.project.ProjectBuildingRequest;
72  import org.apache.maven.shared.invoker.DefaultInvocationRequest;
73  import org.apache.maven.shared.invoker.InvocationRequest;
74  import org.apache.maven.shared.invoker.InvocationResult;
75  import org.apache.maven.shared.invoker.Invoker;
76  import org.codehaus.plexus.component.annotations.Component;
77  import org.codehaus.plexus.component.annotations.Requirement;
78  import org.codehaus.plexus.logging.AbstractLogEnabled;
79  import org.codehaus.plexus.util.DirectoryScanner;
80  import org.codehaus.plexus.util.FileUtils;
81  import org.codehaus.plexus.util.IOUtil;
82  import org.codehaus.plexus.util.ReaderFactory;
83  import org.codehaus.plexus.util.StringUtils;
84  import org.codehaus.plexus.util.WriterFactory;
85  import org.codehaus.plexus.util.xml.Xpp3Dom;
86  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
87  
88  /**
89   * Create a 2.x Archetype project from a project. Since 2.0-alpha-5, an integration-test named "basic" is created along
90   * the archetype itself to provide immediate test when building the archetype.
91   */
92  @Component( role = ArchetypeCreator.class, hint = "fileset" )
93  public class FilesetArchetypeCreator
94      extends AbstractLogEnabled
95      implements ArchetypeCreator
96  {
97      private static final String DEFAULT_OUTPUT_DIRECTORY =
98          "target" + File.separator + "generated-sources" + File.separator + "archetype";
99  
100     @Requirement
101     private ArchetypeFilesResolver archetypeFilesResolver;
102 
103     @Requirement
104     private PomManager pomManager;
105 
106     @Requirement
107     private ProjectBuilder projectBuilder;
108     
109     @Requirement
110     private Invoker invoker;
111 
112     public void createArchetype( ArchetypeCreationRequest request, ArchetypeCreationResult result )
113     {
114         MavenProject project = request.getProject();
115         List<String> languages = request.getLanguages();
116         List<String> filtereds = request.getFiltereds();
117         String defaultEncoding = request.getDefaultEncoding();
118         boolean preserveCData = request.isPreserveCData();
119         boolean keepParent = request.isKeepParent();
120         boolean partialArchetype = request.isPartialArchetype();
121         ArtifactRepository localRepository = request.getLocalRepository();
122         File outputDirectory = request.getOutputDirectory();
123         File basedir = project.getBasedir();
124 
125         Properties properties = new Properties();
126         Properties configurationProperties = new Properties();
127         if ( request.getProperties() != null )
128         {
129             properties.putAll( request.getProperties() );
130             configurationProperties.putAll( request.getProperties() );
131         }
132 
133         extractPropertiesFromProject( project, properties, configurationProperties, request.getPackageName() );
134 
135         if ( outputDirectory == null )
136         {
137             getLogger().debug( "No output directory defined, using default: " + DEFAULT_OUTPUT_DIRECTORY );
138             outputDirectory = FileUtils.resolveFile( basedir, DEFAULT_OUTPUT_DIRECTORY );
139         }
140         outputDirectory.mkdirs();
141 
142         getLogger().debug( "Creating archetype in " + outputDirectory );
143 
144         try
145         {
146             File archetypePomFile =
147                 createArchetypeProjectPom( project, localRepository, configurationProperties, outputDirectory );
148 
149             File archetypeResourcesDirectory = new File( outputDirectory, getTemplateOutputDirectory() );
150 
151             File archetypeFilesDirectory = new File( archetypeResourcesDirectory, Constants.ARCHETYPE_RESOURCES );
152             getLogger().debug( "Archetype's files output directory " + archetypeFilesDirectory );
153 
154             File archetypeDescriptorFile = new File( archetypeResourcesDirectory, Constants.ARCHETYPE_DESCRIPTOR );
155             archetypeDescriptorFile.getParentFile().mkdirs();
156 
157             File archetypePostGenerationScript =
158                 new File( archetypeResourcesDirectory, Constants.ARCHETYPE_POST_GENERATION_SCRIPT );
159             archetypePostGenerationScript.getParentFile().mkdirs();
160 
161             if ( request.getProject().getBuild() != null && CollectionUtils.isNotEmpty(
162                 request.getProject().getBuild().getResources() ) )
163             {
164                 for ( Resource resource : request.getProject().getBuild().getResources() )
165                 {
166                     File inputFile = new File(
167                         resource.getDirectory() + File.separator + Constants.ARCHETYPE_POST_GENERATION_SCRIPT );
168                     if ( inputFile.exists() )
169                     {
170                         FileUtils.copyFile( inputFile, archetypePostGenerationScript );
171                     }
172                 }
173             }
174 
175             getLogger().debug( "Starting archetype's descriptor " + project.getArtifactId() );
176             ArchetypeDescriptor archetypeDescriptor = new ArchetypeDescriptor();
177 
178             archetypeDescriptor.setName( project.getArtifactId() );
179             archetypeDescriptor.setPartial( partialArchetype );
180 
181             addRequiredProperties( archetypeDescriptor, properties );
182 
183             // TODO ensure reverseProperties contains NO dotted properties
184             Properties reverseProperties = getReversedProperties( archetypeDescriptor, properties );
185             // reverseProperties.remove( Constants.GROUP_ID );
186 
187             // TODO ensure pomReversedProperties contains NO dotted properties
188             Properties pomReversedProperties = getReversedProperties( archetypeDescriptor, properties );
189             // pomReversedProperties.remove( Constants.PACKAGE );
190 
191             String packageName = configurationProperties.getProperty( Constants.PACKAGE );
192 
193             Model pom = pomManager.readPom( FileUtils.resolveFile( basedir, Constants.ARCHETYPE_POM ) );
194 
195             List<String> excludePatterns =
196                 configurationProperties.getProperty( Constants.EXCLUDE_PATTERNS ) != null
197                     ? Arrays.asList(
198                     StringUtils.split( configurationProperties.getProperty( Constants.EXCLUDE_PATTERNS ), "," ) )
199                     : Collections.<String>emptyList();
200 
201             List<String> fileNames = resolveFileNames( pom, basedir, excludePatterns );
202             if ( getLogger().isDebugEnabled() )
203             {
204                 getLogger().debug( "Scanned for files " + fileNames.size() );
205 
206                 for ( String name : fileNames )
207                 {
208                     getLogger().debug( "- " + name );
209                 }
210             }
211 
212             List<FileSet> filesets = resolveFileSets( packageName, fileNames, languages, filtereds, defaultEncoding );
213             getLogger().debug( "Resolved filesets for " + archetypeDescriptor.getName() );
214 
215             archetypeDescriptor.setFileSets( filesets );
216 
217             createArchetypeFiles( reverseProperties, filesets, packageName, basedir, archetypeFilesDirectory,
218                                   defaultEncoding, excludePatterns );
219             getLogger().debug( "Created files for " + archetypeDescriptor.getName() );
220 
221             setParentArtifactId( reverseProperties, configurationProperties.getProperty( Constants.ARTIFACT_ID ) );
222 
223             for ( String moduleId : pom.getModules() )
224             {
225                 String rootArtifactId = configurationProperties.getProperty( Constants.ARTIFACT_ID );
226                 String moduleIdDirectory = moduleId;
227 
228                 if ( moduleId.indexOf( rootArtifactId ) >= 0 )
229                 {
230                     moduleIdDirectory = StringUtils.replace( moduleId, rootArtifactId, "__rootArtifactId__" );
231                 }
232 
233                 getLogger().debug( "Creating module " + moduleId );
234 
235                 ModuleDescriptor moduleDescriptor =
236                     createModule( reverseProperties, rootArtifactId, moduleId, packageName,
237                                   FileUtils.resolveFile( basedir, moduleId ),
238                                   new File( archetypeFilesDirectory, moduleIdDirectory ), languages, filtereds,
239                                   defaultEncoding, preserveCData, keepParent );
240 
241                 archetypeDescriptor.addModule( moduleDescriptor );
242 
243                 getLogger().debug(
244                     "Added module " + moduleDescriptor.getName() + " in " + archetypeDescriptor.getName() );
245             }
246 
247             restoreParentArtifactId( reverseProperties, null );
248             restoreArtifactId( reverseProperties, configurationProperties.getProperty( Constants.ARTIFACT_ID ) );
249 
250             createPoms( pom, configurationProperties.getProperty( Constants.ARTIFACT_ID ),
251                         configurationProperties.getProperty( Constants.ARTIFACT_ID ), archetypeFilesDirectory, basedir,
252                         pomReversedProperties, preserveCData, keepParent );
253             getLogger().debug( "Created Archetype " + archetypeDescriptor.getName() + " template pom(s)" );
254 
255             Writer out = null;
256             try
257             {
258                 out = WriterFactory.newXmlWriter( archetypeDescriptorFile );
259 
260                 ArchetypeDescriptorXpp3Writer writer = new ArchetypeDescriptorXpp3Writer();
261 
262                 writer.write( out, archetypeDescriptor );
263 
264                 getLogger().debug( "Archetype " + archetypeDescriptor.getName() + " descriptor written" );
265             }
266             finally
267             {
268                 IOUtil.close( out );
269             }
270 
271             createArchetypeBasicIt( archetypeDescriptor, outputDirectory );
272 
273             // Copy archetype integration tests.
274             File archetypeIntegrationTestInputFolder =
275                 new File( basedir, Constants.SRC + File.separator + "it" + File.separator + "projects" );
276             File archetypeIntegrationTestOutputFolder = new File( outputDirectory,
277                                                                   Constants.SRC + File.separator + Constants.TEST
278                                                                       + File.separator + Constants.RESOURCES
279                                                                       + File.separator + "projects" );
280 
281             if ( archetypeIntegrationTestInputFolder.exists() )
282             {
283                 getLogger().info( "Copying: " + archetypeIntegrationTestInputFolder.getAbsolutePath() + " into "
284                                       + archetypeIntegrationTestOutputFolder.getAbsolutePath() );
285 
286                 FileUtils.copyDirectoryStructure( archetypeIntegrationTestInputFolder,
287                                                   archetypeIntegrationTestOutputFolder );
288 
289             }
290             InvocationRequest internalRequest = new DefaultInvocationRequest();
291             internalRequest.setPomFile( archetypePomFile );
292             internalRequest.setGoals( Collections.singletonList( request.getPostPhase() ) );
293             if ( request.getLocalRepository() != null )
294             {
295                 internalRequest.setLocalRepositoryDirectory( new File( request.getLocalRepository().getBasedir() ) );
296             }
297 
298             InvocationResult invokerResult = invoker.execute( internalRequest );
299             if ( invokerResult.getExitCode() != 0 )
300             {
301                 if ( invokerResult.getExecutionException() != null )
302                 {
303                     throw invokerResult.getExecutionException();
304                 }
305                 else
306                 {
307                     throw new Exception( "Invoker process ended with result different than 0!" );
308                 }
309             }
310 
311         }
312         catch ( Exception e )
313         {
314             result.setCause( e );
315         }
316     }
317 
318     /**
319      * Create an archetype IT, ie goals.txt and archetype.properties in src/test/resources/projects/basic.
320      *
321      * @param archetypeDescriptor
322      * @param generatedSourcesDirectory
323      * @throws IOException
324      * @since 2.0-alpha-5
325      */
326     private void createArchetypeBasicIt( ArchetypeDescriptor archetypeDescriptor, File generatedSourcesDirectory )
327         throws IOException
328     {
329         String basic =
330             Constants.SRC + File.separator + Constants.TEST + File.separator + Constants.RESOURCES + File.separator
331                 + "projects" + File.separator + "basic";
332         File basicItDirectory = new File( generatedSourcesDirectory, basic );
333         basicItDirectory.mkdirs();
334 
335         InputStream in = null;
336         OutputStream out = null;
337 
338         try
339         {
340             in = FilesetArchetypeCreator.class.getResourceAsStream( "archetype.properties" );
341 
342             Properties archetypeProperties = new Properties();
343             archetypeProperties.load( in );
344 
345             for ( RequiredProperty req : archetypeDescriptor.getRequiredProperties() )
346             {
347                 archetypeProperties.put( req.getKey(), req.getDefaultValue() );
348             }
349 
350             out = new FileOutputStream( new File( basicItDirectory, "archetype.properties" ) );
351             archetypeProperties.store( out, null );
352         }
353         finally
354         {
355             IOUtil.close( in );
356             IOUtil.close( out );
357         }
358         copyResource( "goal.txt", new File( basicItDirectory, "goal.txt" ) );
359 
360         getLogger().debug( "Added basic integration test" );
361     }
362 
363     private void extractPropertiesFromProject( MavenProject project, Properties properties,
364                                                Properties configurationProperties, String packageName )
365     {
366         if ( !properties.containsKey( Constants.GROUP_ID ) )
367         {
368             properties.setProperty( Constants.GROUP_ID, project.getGroupId() );
369         }
370         configurationProperties.setProperty( Constants.GROUP_ID, properties.getProperty( Constants.GROUP_ID ) );
371 
372         if ( !properties.containsKey( Constants.ARTIFACT_ID ) )
373         {
374             properties.setProperty( Constants.ARTIFACT_ID, project.getArtifactId() );
375         }
376         configurationProperties.setProperty( Constants.ARTIFACT_ID, properties.getProperty( Constants.ARTIFACT_ID ) );
377 
378         if ( !properties.containsKey( Constants.VERSION ) )
379         {
380             properties.setProperty( Constants.VERSION, project.getVersion() );
381         }
382         configurationProperties.setProperty( Constants.VERSION, properties.getProperty( Constants.VERSION ) );
383 
384         if ( packageName != null )
385         {
386             properties.setProperty( Constants.PACKAGE, packageName );
387         }
388         else if ( !properties.containsKey( Constants.PACKAGE ) )
389         {
390             properties.setProperty( Constants.PACKAGE, project.getGroupId() );
391         }
392         configurationProperties.setProperty( Constants.PACKAGE, properties.getProperty( Constants.PACKAGE ) );
393     }
394 
395     /**
396      * Create the archetype project pom.xml file, that will be used to build the archetype.
397      */
398     private File createArchetypeProjectPom( MavenProject project, ArtifactRepository localRepository,
399                                             Properties configurationProperties, File projectDir )
400         throws TemplateCreationException, IOException
401     {
402         Model model = new Model();
403         model.setModelVersion( "4.0.0" );
404         // these values should be retrieved from the request with sensible defaults
405         model.setGroupId( configurationProperties.getProperty( Constants.ARCHETYPE_GROUP_ID, project.getGroupId() ) );
406         model.setArtifactId(
407             configurationProperties.getProperty( Constants.ARCHETYPE_ARTIFACT_ID, project.getArtifactId() ) );
408         model.setVersion( configurationProperties.getProperty( Constants.ARCHETYPE_VERSION, project.getVersion() ) );
409         model.setPackaging( "maven-archetype" );
410         model.setName(
411             configurationProperties.getProperty( Constants.ARCHETYPE_ARTIFACT_ID, project.getArtifactId() ) );
412         model.setUrl( configurationProperties.getProperty( Constants.ARCHETYPE_URL, project.getUrl() ) );
413         model.setDescription(
414             configurationProperties.getProperty( Constants.ARCHETYPE_DESCRIPTION, project.getDescription() ) );
415         model.setLicenses( project.getLicenses() );
416         model.setDevelopers( project.getDevelopers() );
417         model.setScm( project.getScm() );
418         Build build = new Build();
419         model.setBuild( build );
420 
421         // In many cases where we are behind a firewall making Archetypes for work mates we want
422         // to simply be able to deploy the archetypes once we have created them. In order to do
423         // this we want to utilize information from the project we are creating the archetype from.
424         // This will be a fully working project that has been testing and inherits from a POM
425         // that contains deployment information, along with any extensions required for deployment.
426         // We don't want to create archetypes that cannot be deployed after we create them. People
427         // might want to edit the archetype POM but they should not have too.
428 
429         if ( project.getParent() != null )
430         {
431             Artifact pa = project.getParentArtifact();
432 
433             try
434             {
435                 ProjectBuildingRequest buildingRequest = new DefaultProjectBuildingRequest();
436                 buildingRequest.setLocalRepository( localRepository );
437                 buildingRequest.setRemoteRepositories( project.getRemoteArtifactRepositories() );
438                 
439                 MavenProject p = projectBuilder.build( pa, buildingRequest ).getProject();
440 
441                 if ( p.getDistributionManagement() != null )
442                 {
443                     model.setDistributionManagement( p.getDistributionManagement() );
444                 }
445 
446                 if ( p.getBuildExtensions() != null )
447                 {
448                     for ( Extension be : p.getBuildExtensions() )
449                     {
450                         model.getBuild().addExtension( be );
451                     }
452                 }
453             }
454             catch ( ProjectBuildingException e )
455             {
456                 throw new TemplateCreationException(
457                     "Error reading parent POM of project: " + pa.getGroupId() + ":" + pa.getArtifactId() + ":"
458                         + pa.getVersion() );
459             }
460         }
461 
462         Extension extension = new Extension();
463         extension.setGroupId( "org.apache.maven.archetype" );
464         extension.setArtifactId( "archetype-packaging" );
465         extension.setVersion( getArchetypeVersion() );
466         model.getBuild().addExtension( extension );
467 
468         Plugin plugin = new Plugin();
469         plugin.setGroupId( "org.apache.maven.plugins" );
470         plugin.setArtifactId( "maven-archetype-plugin" );
471         plugin.setVersion( getArchetypeVersion() );
472 
473         PluginManagement pluginManagement = new PluginManagement();
474         pluginManagement.addPlugin( plugin );
475         model.getBuild().setPluginManagement( pluginManagement );
476 
477         getLogger().debug( "Creating archetype's pom" );
478 
479         File archetypePomFile = new File( projectDir, Constants.ARCHETYPE_POM );
480 
481         archetypePomFile.getParentFile().mkdirs();
482 
483         copyResource( "pom-prototype.xml", archetypePomFile );
484 
485         pomManager.writePom( model, archetypePomFile, archetypePomFile );
486 
487         return archetypePomFile;
488     }
489 
490     private void copyResource( String name, File destination )
491         throws IOException
492     {
493         InputStream in = null;
494         OutputStream out = null;
495 
496         try
497         {
498             in = FilesetArchetypeCreator.class.getResourceAsStream( name );
499             out = new FileOutputStream( destination );
500 
501             IOUtil.copy( in, out );
502         }
503         finally
504         {
505             IOUtil.close( in );
506             IOUtil.close( out );
507         }
508     }
509 
510     private void addRequiredProperties( ArchetypeDescriptor archetypeDescriptor, Properties properties )
511     {
512         Properties requiredProperties = new Properties();
513         requiredProperties.putAll( properties );
514         requiredProperties.remove( Constants.ARCHETYPE_GROUP_ID );
515         requiredProperties.remove( Constants.ARCHETYPE_ARTIFACT_ID );
516         requiredProperties.remove( Constants.ARCHETYPE_VERSION );
517         requiredProperties.remove( Constants.GROUP_ID );
518         requiredProperties.remove( Constants.ARTIFACT_ID );
519         requiredProperties.remove( Constants.VERSION );
520         requiredProperties.remove( Constants.PACKAGE );
521         requiredProperties.remove( Constants.EXCLUDE_PATTERNS );
522 
523         for ( Iterator<?> propertiesIterator = requiredProperties.keySet().iterator(); propertiesIterator.hasNext(); )
524         {
525             String propertyKey = (String) propertiesIterator.next();
526 
527             RequiredProperty requiredProperty = new RequiredProperty();
528             requiredProperty.setKey( propertyKey );
529             requiredProperty.setDefaultValue( requiredProperties.getProperty( propertyKey ) );
530 
531             archetypeDescriptor.addRequiredProperty( requiredProperty );
532 
533             getLogger().debug(
534                 "Adding requiredProperty " + propertyKey + "=" + requiredProperties.getProperty( propertyKey )
535                     + " to archetype's descriptor" );
536         }
537     }
538 
539     private void createModulePoms( Properties pomReversedProperties, String rootArtifactId, String packageName,
540                                    File basedir, File archetypeFilesDirectory, boolean preserveCData,
541                                    boolean keepParent )
542         throws FileNotFoundException, IOException, XmlPullParserException
543     {
544         Model pom = pomManager.readPom( FileUtils.resolveFile( basedir, Constants.ARCHETYPE_POM ) );
545 
546         String parentArtifactId = pomReversedProperties.getProperty( Constants.PARENT_ARTIFACT_ID );
547         String artifactId = pom.getArtifactId();
548         setParentArtifactId( pomReversedProperties, pomReversedProperties.getProperty( Constants.ARTIFACT_ID ) );
549         setArtifactId( pomReversedProperties, pom.getArtifactId() );
550 
551         for ( String subModuleId : pom.getModules() )
552         {
553             String subModuleIdDirectory = subModuleId;
554 
555             if ( subModuleId.indexOf( rootArtifactId ) >= 0 )
556             {
557                 subModuleIdDirectory = StringUtils.replace( subModuleId, rootArtifactId, "__rootArtifactId__" );
558             }
559 
560             createModulePoms( pomReversedProperties, rootArtifactId, packageName,
561                               FileUtils.resolveFile( basedir, subModuleId ),
562                               FileUtils.resolveFile( archetypeFilesDirectory, subModuleIdDirectory ), preserveCData,
563                               keepParent );
564         }
565 
566         createModulePom( pom, rootArtifactId, archetypeFilesDirectory, pomReversedProperties,
567                          FileUtils.resolveFile( basedir, Constants.ARCHETYPE_POM ), preserveCData, keepParent );
568 
569         restoreParentArtifactId( pomReversedProperties, parentArtifactId );
570         restoreArtifactId( pomReversedProperties, artifactId );
571     }
572 
573     private void createPoms( Model pom, String rootArtifactId, String artifactId, File archetypeFilesDirectory,
574                              File basedir, Properties pomReversedProperties, boolean preserveCData, boolean keepParent )
575         throws IOException, FileNotFoundException, XmlPullParserException
576     {
577         setArtifactId( pomReversedProperties, pom.getArtifactId() );
578 
579         for ( String moduleId : pom.getModules() )
580         {
581             String moduleIdDirectory = moduleId;
582 
583             if ( moduleId.indexOf( rootArtifactId ) >= 0 )
584             {
585                 moduleIdDirectory = StringUtils.replace( moduleId, rootArtifactId, "__rootArtifactId__" );
586             }
587 
588             createModulePoms( pomReversedProperties, rootArtifactId, moduleId,
589                               FileUtils.resolveFile( basedir, moduleId ),
590                               new File( archetypeFilesDirectory, moduleIdDirectory ), preserveCData, keepParent );
591         }
592 
593         restoreParentArtifactId( pomReversedProperties, null );
594         restoreArtifactId( pomReversedProperties, artifactId );
595 
596         createArchetypePom( pom, archetypeFilesDirectory, pomReversedProperties,
597                             FileUtils.resolveFile( basedir, Constants.ARCHETYPE_POM ), preserveCData, keepParent );
598     }
599 
600     private String getPackageInPathFormat( String aPackage )
601     {
602         return StringUtils.replace( aPackage, ".", "/" );
603     }
604 
605     private void rewriteReferences( Model pom, String rootArtifactId, String groupId )
606     {
607         // rewrite Dependencies
608         if ( pom.getDependencies() != null && !pom.getDependencies().isEmpty() )
609         {
610             for ( Dependency dependency : pom.getDependencies() )
611             {
612                 rewriteDependencyReferences( dependency, rootArtifactId, groupId );
613             }
614         }
615 
616         // rewrite DependencyManagement
617         if ( pom.getDependencyManagement() != null && pom.getDependencyManagement().getDependencies() != null
618             && !pom.getDependencyManagement().getDependencies().isEmpty() )
619         {
620             for ( Dependency dependency : pom.getDependencyManagement().getDependencies() )
621             {
622                 rewriteDependencyReferences( dependency, rootArtifactId, groupId );
623             }
624         }
625 
626         // rewrite Plugins
627         if ( pom.getBuild() != null && pom.getBuild().getPlugins() != null && !pom.getBuild().getPlugins().isEmpty() )
628         {
629             for ( Plugin plugin : pom.getBuild().getPlugins() )
630             {
631                 rewritePluginReferences( plugin, rootArtifactId, groupId );
632             }
633         }
634 
635         // rewrite PluginManagement
636         if ( pom.getBuild() != null && pom.getBuild().getPluginManagement() != null
637             && pom.getBuild().getPluginManagement().getPlugins() != null
638             && !pom.getBuild().getPluginManagement().getPlugins().isEmpty() )
639         {
640             for ( Plugin plugin : pom.getBuild().getPluginManagement().getPlugins() )
641             {
642                 rewritePluginReferences( plugin, rootArtifactId, groupId );
643             }
644         }
645 
646         // rewrite Profiles
647         if ( pom.getProfiles() != null )
648         {
649             for ( Profile profile : pom.getProfiles() )
650             {
651                 // rewrite Dependencies
652                 if ( profile.getDependencies() != null && !profile.getDependencies().isEmpty() )
653                 {
654                     for ( Dependency dependency : profile.getDependencies() )
655                     {
656                         rewriteDependencyReferences( dependency, rootArtifactId, groupId );
657                     }
658                 }
659 
660                 // rewrite DependencyManagement
661                 if ( profile.getDependencyManagement() != null
662                     && profile.getDependencyManagement().getDependencies() != null
663                     && !profile.getDependencyManagement().getDependencies().isEmpty() )
664                 {
665                     for ( Dependency dependency : profile.getDependencyManagement().getDependencies() )
666                     {
667                         rewriteDependencyReferences( dependency, rootArtifactId, groupId );
668                     }
669                 }
670 
671                 // rewrite Plugins
672                 if ( profile.getBuild() != null && profile.getBuild().getPlugins() != null
673                     && !profile.getBuild().getPlugins().isEmpty() )
674                 {
675                     for ( Plugin plugin : profile.getBuild().getPlugins() )
676                     {
677                         rewritePluginReferences( plugin, rootArtifactId, groupId );
678                     }
679                 }
680 
681                 // rewrite PluginManagement
682                 if ( profile.getBuild() != null && profile.getBuild().getPluginManagement() != null
683                     && profile.getBuild().getPluginManagement().getPlugins() != null
684                     && !profile.getBuild().getPluginManagement().getPlugins().isEmpty() )
685                 {
686                     for ( Plugin plugin : profile.getBuild().getPluginManagement().getPlugins() )
687                     {
688                         rewritePluginReferences( plugin, rootArtifactId, groupId );
689                     }
690                 }
691             }
692         }
693     }
694 
695     private void rewriteDependencyReferences( Dependency dependency, String rootArtifactId, String groupId )
696     {
697         if ( dependency.getArtifactId() != null && dependency.getArtifactId().indexOf( rootArtifactId ) >= 0 )
698         {
699             if ( dependency.getGroupId() != null )
700             {
701                 dependency.setGroupId(
702                     StringUtils.replace( dependency.getGroupId(), groupId, "${" + Constants.GROUP_ID + "}" ) );
703             }
704 
705             dependency.setArtifactId(
706                 StringUtils.replace( dependency.getArtifactId(), rootArtifactId, "${rootArtifactId}" ) );
707 
708             if ( dependency.getVersion() != null )
709             {
710                 dependency.setVersion( "${" + Constants.VERSION + "}" );
711             }
712         }
713     }
714 
715     private void rewritePluginReferences( Plugin plugin, String rootArtifactId, String groupId )
716     {
717         if ( plugin.getArtifactId() != null && plugin.getArtifactId().indexOf( rootArtifactId ) >= 0 )
718         {
719             if ( plugin.getGroupId() != null )
720             {
721                 String g = StringUtils.replace( plugin.getGroupId(), groupId, "${" + Constants.GROUP_ID + "}" );
722                 plugin.setGroupId( g );
723             }
724 
725             plugin.setArtifactId( StringUtils.replace( plugin.getArtifactId(), rootArtifactId, "${rootArtifactId}" ) );
726 
727             if ( plugin.getVersion() != null )
728             {
729                 plugin.setVersion( "${" + Constants.VERSION + "}" );
730             }
731         }
732 
733         if ( plugin.getArtifactId() != null && "maven-ear-plugin".equals( plugin.getArtifactId() ) )
734         {
735             rewriteEARPluginReferences( plugin, rootArtifactId, groupId );
736         }
737     }
738 
739     private void rewriteEARPluginReferences( Plugin plugin, String rootArtifactId, String groupId )
740     {
741         Xpp3Dom configuration = (Xpp3Dom) plugin.getConfiguration();
742         if ( configuration != null )
743         {
744             Xpp3Dom[] modules = configuration.getChild( "modules" ).getChildren();
745             for ( int i = 0; i < modules.length; i++ )
746             {
747                 Xpp3Dom module = modules[i];
748                 Xpp3Dom moduleGroupId = module.getChild( "groupId" );
749                 Xpp3Dom moduleArtifactId = module.getChild( "artifactId" );
750                 Xpp3Dom moduleBundleFileName = module.getChild( "bundleFileName" );
751                 Xpp3Dom moduleModuleId = module.getChild( "moduleId" );
752                 Xpp3Dom moduleContextRoot = module.getChild( "contextRoot" );
753 
754                 if ( moduleGroupId != null )
755                 {
756                     moduleGroupId.setValue(
757                         StringUtils.replace( moduleGroupId.getValue(), groupId, "${" + Constants.GROUP_ID + "}" ) );
758                 }
759 
760                 if ( moduleArtifactId != null )
761                 {
762                     moduleArtifactId.setValue(
763                         StringUtils.replace( moduleArtifactId.getValue(), rootArtifactId, "${rootArtifactId}" ) );
764                 }
765 
766                 if ( moduleBundleFileName != null )
767                 {
768                     moduleBundleFileName.setValue(
769                         StringUtils.replace( moduleBundleFileName.getValue(), rootArtifactId, "${rootArtifactId}" ) );
770                 }
771 
772                 if ( moduleModuleId != null )
773                 {
774                     moduleModuleId.setValue(
775                         StringUtils.replace( moduleModuleId.getValue(), rootArtifactId, "${rootArtifactId}" ) );
776                 }
777 
778                 if ( moduleContextRoot != null )
779                 {
780                     moduleContextRoot.setValue(
781                         StringUtils.replace( moduleContextRoot.getValue(), rootArtifactId, "${rootArtifactId}" ) );
782                 }
783             }
784         }
785     }
786 
787     private void setArtifactId( Properties properties, String artifactId )
788     {
789         properties.setProperty( Constants.ARTIFACT_ID, artifactId );
790     }
791 
792     private List<String> concatenateToList( List<String> toConcatenate, String with )
793     {
794         List<String> result = new ArrayList<String>( toConcatenate.size() );
795 
796         for ( String concatenate : toConcatenate )
797         {
798             result.add( ( ( with.length() > 0 ) ? ( with + "/" + concatenate ) : concatenate ) );
799         }
800 
801         return result;
802     }
803 
804     private List<String> addLists( List<String> list, List<String> other )
805     {
806         List<String> result = new ArrayList<String>( list.size() + other.size() );
807         result.addAll( list );
808         result.addAll( other );
809         return result;
810     }
811 
812     private void copyFiles( File basedir, File archetypeFilesDirectory, String directory, List<String> fileSetResources,
813                             boolean packaged, String packageName )
814         throws IOException
815     {
816         String packageAsDirectory = StringUtils.replace( packageName, ".", File.separator );
817 
818         getLogger().debug( "Package as Directory: Package:" + packageName + "->" + packageAsDirectory );
819 
820         for ( String inputFileName : fileSetResources )
821         {
822             String outputFileName = packaged
823                 ? StringUtils.replace( inputFileName, packageAsDirectory + File.separator, "" )
824                 : inputFileName;
825             getLogger().debug( "InputFileName:" + inputFileName );
826             getLogger().debug( "OutputFileName:" + outputFileName );
827 
828             File outputFile = new File( archetypeFilesDirectory, outputFileName );
829 
830             File inputFile = new File( basedir, inputFileName );
831 
832             outputFile.getParentFile().mkdirs();
833 
834             FileUtils.copyFile( inputFile, outputFile );
835         }
836     }
837 
838     private void createArchetypeFiles( Properties reverseProperties, List<FileSet> fileSets, String packageName,
839                                        File basedir, File archetypeFilesDirectory, String defaultEncoding,
840                                        List<String> excludePatterns )
841         throws IOException
842     {
843         getLogger().debug( "Creating Archetype/Module files from " + basedir + " to " + archetypeFilesDirectory );
844 
845         for ( FileSet fileSet : fileSets )
846         {
847             DirectoryScanner scanner = new DirectoryScanner();
848             scanner.setBasedir( basedir );
849             scanner.setIncludes( (String[]) concatenateToList( fileSet.getIncludes(), fileSet.getDirectory() ).toArray(
850                 new String[fileSet.getIncludes().size()] ) );
851             scanner.setExcludes( (String[]) addLists( fileSet.getExcludes(), excludePatterns ).toArray(
852                 new String[fileSet.getExcludes().size()] ) );
853             scanner.addDefaultExcludes();
854             getLogger().debug( "Using fileset " + fileSet );
855             scanner.scan();
856 
857             List<String> fileSetResources = Arrays.asList( scanner.getIncludedFiles() );
858             getLogger().debug( "Scanned " + fileSetResources.size() + " resources" );
859 
860             if ( fileSet.isFiltered() )
861             {
862                 processFileSet( basedir, archetypeFilesDirectory, fileSet.getDirectory(), fileSetResources,
863                                 fileSet.isPackaged(), packageName, reverseProperties, defaultEncoding );
864                 getLogger().debug( "Processed " + fileSet.getDirectory() + " files" );
865             }
866             else
867             {
868                 copyFiles( basedir, archetypeFilesDirectory, fileSet.getDirectory(), fileSetResources,
869                            fileSet.isPackaged(), packageName );
870                 getLogger().debug( "Copied " + fileSet.getDirectory() + " files" );
871             }
872         }
873     }
874 
875     private void createArchetypePom( Model pom, File archetypeFilesDirectory, Properties pomReversedProperties,
876                                      File initialPomFile, boolean preserveCData, boolean keepParent )
877         throws IOException
878     {
879         File outputFile = FileUtils.resolveFile( archetypeFilesDirectory, Constants.ARCHETYPE_POM );
880 
881         if ( preserveCData )
882         {
883             getLogger().debug( "Preserving CDATA parts of pom" );
884             File inputFile = FileUtils.resolveFile( archetypeFilesDirectory, Constants.ARCHETYPE_POM + ".tmp" );
885 
886             FileUtils.copyFile( initialPomFile, inputFile );
887 
888             Reader in = null;
889             Writer out = null;
890             try
891             {
892                 in = ReaderFactory.newXmlReader( inputFile );
893 
894                 String initialcontent = IOUtil.toString( in );
895 
896                 String content = getReversedContent( initialcontent, pomReversedProperties );
897 
898                 outputFile.getParentFile().mkdirs();
899 
900                 out = WriterFactory.newXmlWriter( outputFile );
901 
902                 IOUtil.copy( content, out );
903             }
904             finally
905             {
906                 IOUtil.close( in );
907                 IOUtil.close( out );
908             }
909 
910             inputFile.delete();
911         }
912         else
913         {
914             if ( !keepParent )
915             {
916                 pom.setParent( null );
917             }
918 
919             pom.setModules( null );
920             pom.setGroupId( "${" + Constants.GROUP_ID + "}" );
921             pom.setArtifactId( "${" + Constants.ARTIFACT_ID + "}" );
922             pom.setVersion( "${" + Constants.VERSION + "}" );
923             pom.setName( getReversedPlainContent( pom.getName(), pomReversedProperties ) );
924             pom.setDescription( getReversedPlainContent( pom.getDescription(), pomReversedProperties ) );
925             pom.setUrl( getReversedPlainContent( pom.getUrl(), pomReversedProperties ) );
926 
927             rewriteReferences( pom, pomReversedProperties.getProperty( Constants.ARTIFACT_ID ),
928                                pomReversedProperties.getProperty( Constants.GROUP_ID ) );
929 
930             pomManager.writePom( pom, outputFile, initialPomFile );
931         }
932 
933         Reader in = null;
934         try
935         {
936             in = ReaderFactory.newXmlReader( initialPomFile );
937             String initialcontent = IOUtil.toString( in );
938 
939             Iterator<?> properties = pomReversedProperties.keySet().iterator();
940             while ( properties.hasNext() )
941             {
942                 String property = (String) properties.next();
943 
944                 if ( initialcontent.indexOf( "${" + property + "}" ) > 0 )
945                 {
946                     getLogger().warn(
947                         "Archetype uses ${" + property + "} for internal processing, but file " + initialPomFile
948                             + " contains this property already" );
949                 }
950             }
951         }
952         finally
953         {
954             IOUtil.close( in );
955         }
956     }
957 
958     private FileSet createFileSet( final List<String> excludes, final boolean packaged, final boolean filtered,
959                                    final String group, final List<String> includes, String defaultEncoding )
960     {
961         FileSet fileSet = new FileSet();
962 
963         fileSet.setDirectory( group );
964         fileSet.setPackaged( packaged );
965         fileSet.setFiltered( filtered );
966         fileSet.setIncludes( includes );
967         fileSet.setExcludes( excludes );
968         fileSet.setEncoding( defaultEncoding );
969 
970         getLogger().debug( "Created Fileset " + fileSet );
971 
972         return fileSet;
973     }
974 
975     private List<FileSet> createFileSets( List<String> files, int level, boolean packaged, String packageName,
976                                           boolean filtered, String defaultEncoding )
977     {
978         List<FileSet> fileSets = new ArrayList<FileSet>();
979 
980         if ( !files.isEmpty() )
981         {
982             getLogger().debug( "Creating filesets" + ( packaged ? ( " packaged (" + packageName + ")" ) : "" ) + (
983                 filtered
984                     ? " filtered"
985                     : "" ) + " at level " + level );
986             if ( level == 0 )
987             {
988                 List<String> includes = new ArrayList<String>( files );
989                 List<String> excludes = new ArrayList<String>();
990 
991                 if ( !includes.isEmpty() )
992                 {
993                     fileSets.add( createFileSet( excludes, packaged, filtered, "", includes, defaultEncoding ) );
994                 }
995             }
996             else
997             {
998                 Map<String, List<String>> groups = getGroupsMap( files, level );
999 
1000                 for ( String group : groups.keySet() )
1001                 {
1002                     getLogger().debug( "Creating filesets for group " + group );
1003 
1004                     if ( !packaged )
1005                     {
1006                         fileSets.add( getUnpackagedFileSet( filtered, group, groups.get( group ), defaultEncoding ) );
1007                     }
1008                     else
1009                     {
1010                         fileSets.addAll(
1011                             getPackagedFileSets( filtered, group, groups.get( group ), packageName, defaultEncoding ) );
1012                     }
1013                 }
1014             } // end if
1015 
1016             getLogger().debug( "Resolved fileSets " + fileSets );
1017         } // end if
1018 
1019         return fileSets;
1020     }
1021 
1022     private ModuleDescriptor createModule( Properties reverseProperties, String rootArtifactId, String moduleId,
1023                                            String packageName, File basedir, File archetypeFilesDirectory,
1024                                            List<String> languages, List<String> filtereds, String defaultEncoding,
1025                                            boolean preserveCData, boolean keepParent )
1026         throws IOException, XmlPullParserException
1027     {
1028         ModuleDescriptor archetypeDescriptor = new ModuleDescriptor();
1029         getLogger().debug( "Starting module's descriptor " + moduleId );
1030 
1031         archetypeFilesDirectory.mkdirs();
1032         getLogger().debug( "Module's files output directory " + archetypeFilesDirectory );
1033 
1034         Model pom = pomManager.readPom( FileUtils.resolveFile( basedir, Constants.ARCHETYPE_POM ) );
1035         String replacementId = pom.getArtifactId();
1036         String moduleDirectory = pom.getArtifactId();
1037 
1038         if ( replacementId.indexOf( rootArtifactId ) >= 0 )
1039         {
1040             replacementId = StringUtils.replace( replacementId, rootArtifactId, "${rootArtifactId}" );
1041             moduleDirectory = StringUtils.replace( moduleId, rootArtifactId, "__rootArtifactId__" );
1042         }
1043 
1044         if ( moduleId.indexOf( rootArtifactId ) >= 0 )
1045         {
1046             moduleDirectory = StringUtils.replace( moduleId, rootArtifactId, "__rootArtifactId__" );
1047         }
1048 
1049         archetypeDescriptor.setName( replacementId );
1050         archetypeDescriptor.setId( replacementId );
1051         archetypeDescriptor.setDir( moduleDirectory );
1052 
1053         setArtifactId( reverseProperties, pom.getArtifactId() );
1054 
1055         List<String> excludePatterns =
1056             reverseProperties.getProperty( Constants.EXCLUDE_PATTERNS ) != null
1057                 ? Arrays.asList( StringUtils.split( reverseProperties.getProperty( Constants.EXCLUDE_PATTERNS ), "," ) )
1058                 : Collections.<String>emptyList();
1059 
1060         List<String> fileNames = resolveFileNames( pom, basedir, excludePatterns );
1061 
1062         List<FileSet> filesets = resolveFileSets( packageName, fileNames, languages, filtereds, defaultEncoding );
1063         getLogger().debug( "Resolved filesets for module " + archetypeDescriptor.getName() );
1064 
1065         archetypeDescriptor.setFileSets( filesets );
1066 
1067         createArchetypeFiles( reverseProperties, filesets, packageName, basedir, archetypeFilesDirectory,
1068                               defaultEncoding, excludePatterns );
1069         getLogger().debug( "Created files for module " + archetypeDescriptor.getName() );
1070 
1071         String parentArtifactId = reverseProperties.getProperty( Constants.PARENT_ARTIFACT_ID );
1072         setParentArtifactId( reverseProperties, pom.getArtifactId() );
1073 
1074         for ( String subModuleId : pom.getModules() )
1075         {
1076             String subModuleIdDirectory = subModuleId;
1077             if ( subModuleId.indexOf( rootArtifactId ) >= 0 )
1078             {
1079                 subModuleIdDirectory = StringUtils.replace( subModuleId, rootArtifactId, "__rootArtifactId__" );
1080             }
1081 
1082             getLogger().debug( "Creating module " + subModuleId );
1083 
1084             ModuleDescriptor moduleDescriptor =
1085                 createModule( reverseProperties, rootArtifactId, subModuleId, packageName,
1086                               FileUtils.resolveFile( basedir, subModuleId ),
1087                               FileUtils.resolveFile( archetypeFilesDirectory, subModuleIdDirectory ), languages,
1088                               filtereds, defaultEncoding, preserveCData, keepParent );
1089 
1090             archetypeDescriptor.addModule( moduleDescriptor );
1091 
1092             getLogger().debug( "Added module " + moduleDescriptor.getName() + " in " + archetypeDescriptor.getName() );
1093         }
1094 
1095         restoreParentArtifactId( reverseProperties, parentArtifactId );
1096         restoreArtifactId( reverseProperties, pom.getArtifactId() );
1097 
1098         getLogger().debug( "Created Module " + archetypeDescriptor.getName() + " pom" );
1099 
1100         return archetypeDescriptor;
1101     }
1102 
1103     private void createModulePom( Model pom, String rootArtifactId, File archetypeFilesDirectory,
1104                                   Properties pomReversedProperties, File initialPomFile, boolean preserveCData,
1105                                   boolean keepParent )
1106         throws IOException
1107     {
1108         File outputFile = FileUtils.resolveFile( archetypeFilesDirectory, Constants.ARCHETYPE_POM );
1109 
1110         if ( preserveCData )
1111         {
1112             getLogger().debug( "Preserving CDATA parts of pom" );
1113             File inputFile = FileUtils.resolveFile( archetypeFilesDirectory, Constants.ARCHETYPE_POM + ".tmp" );
1114 
1115             FileUtils.copyFile( initialPomFile, inputFile );
1116 
1117             Reader in = null;
1118             Writer out = null;
1119             try
1120             {
1121                 in = ReaderFactory.newXmlReader( inputFile );
1122 
1123                 String initialcontent = IOUtil.toString( in );
1124 
1125                 String content = getReversedContent( initialcontent, pomReversedProperties );
1126 
1127                 outputFile.getParentFile().mkdirs();
1128 
1129                 out = WriterFactory.newXmlWriter( outputFile );
1130 
1131                 IOUtil.copy( content, out );
1132             }
1133             finally
1134             {
1135                 IOUtil.close( in );
1136                 IOUtil.close( out );
1137             }
1138 
1139             inputFile.delete();
1140         }
1141         else
1142         {
1143             if ( pom.getParent() != null )
1144             {
1145                 pom.getParent().setGroupId( StringUtils.replace( pom.getParent().getGroupId(),
1146                                                                  pomReversedProperties.getProperty(
1147                                                                      Constants.GROUP_ID ),
1148                                                                  "${" + Constants.GROUP_ID + "}" ) );
1149                 if ( pom.getParent().getArtifactId() != null
1150                     && pom.getParent().getArtifactId().indexOf( rootArtifactId ) >= 0 )
1151                 {
1152                     pom.getParent().setArtifactId(
1153                         StringUtils.replace( pom.getParent().getArtifactId(), rootArtifactId, "${rootArtifactId}" ) );
1154                 }
1155                 if ( pom.getParent().getVersion() != null )
1156                 {
1157                     pom.getParent().setVersion( "${" + Constants.VERSION + "}" );
1158                 }
1159             }
1160             pom.setModules( null );
1161 
1162             if ( pom.getGroupId() != null )
1163             {
1164                 pom.setGroupId(
1165                     StringUtils.replace( pom.getGroupId(), pomReversedProperties.getProperty( Constants.GROUP_ID ),
1166                                          "${" + Constants.GROUP_ID + "}" ) );
1167             }
1168 
1169             pom.setArtifactId( "${" + Constants.ARTIFACT_ID + "}" );
1170 
1171             if ( pom.getVersion() != null )
1172             {
1173                 pom.setVersion( "${" + Constants.VERSION + "}" );
1174             }
1175 
1176             pom.setName( getReversedPlainContent( pom.getName(), pomReversedProperties ) );
1177             pom.setDescription( getReversedPlainContent( pom.getDescription(), pomReversedProperties ) );
1178             pom.setUrl( getReversedPlainContent( pom.getUrl(), pomReversedProperties ) );
1179 
1180             rewriteReferences( pom, rootArtifactId, pomReversedProperties.getProperty( Constants.GROUP_ID ) );
1181 
1182             pomManager.writePom( pom, outputFile, initialPomFile );
1183         }
1184 
1185         Reader in = null;
1186         try
1187         {
1188             in = ReaderFactory.newXmlReader( initialPomFile );
1189             String initialcontent = IOUtil.toString( in );
1190 
1191             for ( Iterator<?> properties = pomReversedProperties.keySet().iterator(); properties.hasNext(); )
1192             {
1193                 String property = (String) properties.next();
1194 
1195                 if ( initialcontent.indexOf( "${" + property + "}" ) > 0 )
1196                 {
1197                     getLogger().warn(
1198                         "OldArchetype uses ${" + property + "} for internal processing, but file " + initialPomFile
1199                             + " contains this property already" );
1200                 }
1201             }
1202         }
1203         finally
1204         {
1205             IOUtil.close( in );
1206         }
1207     }
1208 
1209     private Set<String> getExtensions( List<String> files )
1210     {
1211         Set<String> extensions = new HashSet<String>();
1212 
1213         for ( String file : files )
1214         {
1215             extensions.add( FileUtils.extension( file ) );
1216         }
1217 
1218         return extensions;
1219     }
1220 
1221     private Map<String, List<String>> getGroupsMap( final List<String> files, final int level )
1222     {
1223         Map<String, List<String>> groups = new HashMap<String, List<String>>();
1224 
1225         for ( String file : files )
1226         {
1227             String directory = PathUtils.getDirectory( file, level );
1228             // make all groups have unix style
1229             directory = StringUtils.replace( directory, File.separator, "/" );
1230 
1231             if ( !groups.containsKey( directory ) )
1232             {
1233                 groups.put( directory, new ArrayList<String>() );
1234             }
1235 
1236             List<String> group = groups.get( directory );
1237 
1238             String innerPath = file.substring( directory.length() + 1 );
1239             // make all groups have unix style
1240             innerPath = StringUtils.replace( innerPath, File.separator, "/" );
1241 
1242             group.add( innerPath );
1243         }
1244 
1245         getLogger().debug( "Sorted " + groups.size() + " groups in " + files.size() + " files" );
1246         getLogger().debug( "Sorted Files: " + files );
1247 
1248         return groups;
1249     }
1250 
1251     private FileSet getPackagedFileSet( final boolean filtered, final Set<String> packagedExtensions,
1252                                         final String group, final Set<String> unpackagedExtensions,
1253                                         final List<String> unpackagedFiles, String defaultEncoding )
1254     {
1255         List<String> includes = new ArrayList<String>();
1256         List<String> excludes = new ArrayList<String>();
1257 
1258         for ( String extension : packagedExtensions )
1259         {
1260             includes.add( "**/*." + extension );
1261 
1262             if ( unpackagedExtensions.contains( extension ) )
1263             {
1264                 excludes.addAll( archetypeFilesResolver.getFilesWithExtension( unpackagedFiles, extension ) );
1265             }
1266         }
1267 
1268         return createFileSet( excludes, true, filtered, group, includes, defaultEncoding );
1269     }
1270 
1271     private List<FileSet> getPackagedFileSets( final boolean filtered, final String group,
1272                                                final List<String> groupFiles, final String packageName,
1273                                                String defaultEncoding )
1274     {
1275         String packageAsDir = StringUtils.replace( packageName, ".", "/" );
1276 
1277         List<FileSet> packagedFileSets = new ArrayList<FileSet>();
1278         List<String> packagedFiles = archetypeFilesResolver.getPackagedFiles( groupFiles, packageAsDir );
1279         getLogger().debug( "Found packaged Files:" + packagedFiles );
1280 
1281         List<String> unpackagedFiles = archetypeFilesResolver.getUnpackagedFiles( groupFiles, packageAsDir );
1282         getLogger().debug( "Found unpackaged Files:" + unpackagedFiles );
1283 
1284         Set<String> packagedExtensions = getExtensions( packagedFiles );
1285         getLogger().debug( "Found packaged extensions " + packagedExtensions );
1286 
1287         Set<String> unpackagedExtensions = getExtensions( unpackagedFiles );
1288 
1289         if ( !packagedExtensions.isEmpty() )
1290         {
1291             packagedFileSets.add(
1292                 getPackagedFileSet( filtered, packagedExtensions, group, unpackagedExtensions, unpackagedFiles,
1293                                     defaultEncoding ) );
1294         }
1295 
1296         if ( !unpackagedExtensions.isEmpty() )
1297         {
1298             getLogger().debug( "Found unpackaged extensions " + unpackagedExtensions );
1299 
1300             packagedFileSets.add(
1301                 getUnpackagedFileSet( filtered, unpackagedExtensions, unpackagedFiles, group, packagedExtensions,
1302                                       defaultEncoding ) );
1303         }
1304 
1305         return packagedFileSets;
1306     }
1307 
1308     private void setParentArtifactId( Properties properties, String parentArtifactId )
1309     {
1310         properties.setProperty( Constants.PARENT_ARTIFACT_ID, parentArtifactId );
1311     }
1312 
1313     private void processFileSet( File basedir, File archetypeFilesDirectory, String directory,
1314                                  List<String> fileSetResources, boolean packaged, String packageName,
1315                                  Properties reverseProperties, String defaultEncoding )
1316         throws IOException
1317     {
1318         String packageAsDirectory = StringUtils.replace( packageName, ".", File.separator );
1319 
1320         getLogger().debug( "Package as Directory: Package:" + packageName + "->" + packageAsDirectory );
1321 
1322         for ( String inputFileName : fileSetResources )
1323         {
1324             String initialFilename = packaged
1325                 ? StringUtils.replace( inputFileName, packageAsDirectory + File.separator, "" )
1326                 : inputFileName;
1327 
1328             getLogger().debug( "InputFileName:" + inputFileName );
1329 
1330             File inputFile = new File( basedir, inputFileName );
1331 
1332             FileCharsetDetector detector = new FileCharsetDetector( inputFile );
1333 
1334             String fileEncoding = detector.isFound() ? detector.getCharset() : defaultEncoding;
1335 
1336             String initialcontent = IOUtil.toString( new FileInputStream( inputFile ), fileEncoding );
1337 
1338             for ( Iterator<?> properties = reverseProperties.keySet().iterator(); properties.hasNext(); )
1339             {
1340                 String property = (String) properties.next();
1341 
1342                 if ( initialcontent.indexOf( "${" + property + "}" ) > 0 )
1343                 {
1344                     getLogger().warn(
1345                         "Archetype uses ${" + property + "} for internal processing, but file " + inputFile
1346                             + " contains this property already" );
1347                 }
1348             }
1349 
1350             String content = getReversedContent( initialcontent, reverseProperties );
1351             String outputFilename = getReversedFilename( initialFilename, reverseProperties );
1352 
1353             getLogger().debug( "OutputFileName:" + outputFilename );
1354 
1355             File outputFile = new File( archetypeFilesDirectory, outputFilename );
1356             outputFile.getParentFile().mkdirs();
1357 
1358             org.apache.commons.io.IOUtils.write( content, new FileOutputStream( outputFile ), fileEncoding );
1359         }
1360     }
1361 
1362     private Properties getReversedProperties( ArchetypeDescriptor archetypeDescriptor, Properties properties )
1363     {
1364         Properties reversedProperties = new Properties();
1365 
1366         reversedProperties.putAll( properties );
1367         reversedProperties.remove( Constants.ARCHETYPE_GROUP_ID );
1368         reversedProperties.remove( Constants.ARCHETYPE_ARTIFACT_ID );
1369         reversedProperties.remove( Constants.ARCHETYPE_VERSION );
1370 
1371         String packageName = properties.getProperty( Constants.PACKAGE );
1372         String packageInPathFormat = getPackageInPathFormat( packageName );
1373         if ( !packageInPathFormat.equals( packageName ) )
1374         {
1375             reversedProperties.setProperty( Constants.PACKAGE_IN_PATH_FORMAT, packageInPathFormat );
1376         }
1377 
1378         // TODO check that reversed properties are all different and no one is a substring of another?
1379         // to avoid wrong variable replacements
1380 
1381         return reversedProperties;
1382     }
1383 
1384     private List<String> resolveFileNames( final Model pom, final File basedir, List<String> excludePatterns )
1385         throws IOException
1386     {
1387         getLogger().debug( "Resolving files for " + pom.getId() + " in " + basedir );
1388 
1389         StringBuffer buff = new StringBuffer( "pom.xml*,archetype.properties*,target/**," );
1390         for ( String module : pom.getModules() )
1391         {
1392             buff.append( ',' ).append( module ).append( "/**" );
1393         }
1394 
1395         for ( String defaultExclude : ListScanner.DEFAULTEXCLUDES )
1396         {
1397             buff.append( ',' ).append( defaultExclude ).append( "/**" );
1398         }
1399 
1400         for ( String excludePattern : excludePatterns )
1401         {
1402             buff.append( ',' ).append( excludePattern );
1403         }
1404 
1405         String excludes = PathUtils.convertPathForOS( buff.toString() );
1406 
1407         List<String> fileNames = FileUtils.getFileNames( basedir, "**,.*,**/.*", excludes, false );
1408 
1409         getLogger().debug( "Resolved " + fileNames.size() + " files" );
1410         getLogger().debug( "Resolved Files:" + fileNames );
1411 
1412         return fileNames;
1413     }
1414 
1415     private List<FileSet> resolveFileSets( String packageName, List<String> fileNames, List<String> languages,
1416                                            List<String> filtereds, String defaultEncoding )
1417     {
1418         List<FileSet> resolvedFileSets = new ArrayList<FileSet>();
1419         getLogger().debug(
1420             "Resolving filesets with package=" + packageName + ", languages=" + languages + " and extentions="
1421                 + filtereds );
1422 
1423         List<String> files = new ArrayList<String>( fileNames );
1424 
1425         StringBuilder languageIncludes = new StringBuilder();
1426 
1427         for ( String language : languages )
1428         {
1429             languageIncludes.append( ( ( languageIncludes.length() == 0 ) ? "" : "," ) + language + "/**" );
1430         }
1431 
1432         getLogger().debug( "Using languages includes " + languageIncludes );
1433 
1434         StringBuilder filteredIncludes = new StringBuilder();
1435         for ( String filtered : filtereds )
1436         {
1437             filteredIncludes.append(
1438                 ( ( filteredIncludes.length() == 0 ) ? "" : "," ) + "**/" + ( filtered.startsWith( "." ) ? "" : "*." )
1439                     + filtered );
1440         }
1441 
1442         getLogger().debug( "Using filtered includes " + filteredIncludes );
1443 
1444         /* sourcesMainFiles */
1445         List<String> sourcesMainFiles =
1446             archetypeFilesResolver.findSourcesMainFiles( files, languageIncludes.toString() );
1447         if ( !sourcesMainFiles.isEmpty() )
1448         {
1449             files.removeAll( sourcesMainFiles );
1450 
1451             List<String> filteredFiles =
1452                 archetypeFilesResolver.getFilteredFiles( sourcesMainFiles, filteredIncludes.toString() );
1453             sourcesMainFiles.removeAll( filteredFiles );
1454 
1455             List<String> unfilteredFiles = sourcesMainFiles;
1456             if ( !filteredFiles.isEmpty() )
1457             {
1458                 resolvedFileSets.addAll( createFileSets( filteredFiles, 3, true, packageName, true, defaultEncoding ) );
1459             }
1460 
1461             if ( !unfilteredFiles.isEmpty() )
1462             {
1463                 resolvedFileSets.addAll(
1464                     createFileSets( unfilteredFiles, 3, true, packageName, false, defaultEncoding ) );
1465             }
1466         }
1467 
1468         /* resourcesMainFiles */
1469         List<String> resourcesMainFiles =
1470             archetypeFilesResolver.findResourcesMainFiles( files, languageIncludes.toString() );
1471         if ( !resourcesMainFiles.isEmpty() )
1472         {
1473             files.removeAll( resourcesMainFiles );
1474 
1475             List<String> filteredFiles =
1476                 archetypeFilesResolver.getFilteredFiles( resourcesMainFiles, filteredIncludes.toString() );
1477             resourcesMainFiles.removeAll( filteredFiles );
1478 
1479             List<String> unfilteredFiles = resourcesMainFiles;
1480             if ( !filteredFiles.isEmpty() )
1481             {
1482                 resolvedFileSets.addAll(
1483                     createFileSets( filteredFiles, 3, false, packageName, true, defaultEncoding ) );
1484             }
1485             if ( !unfilteredFiles.isEmpty() )
1486             {
1487                 resolvedFileSets.addAll(
1488                     createFileSets( unfilteredFiles, 3, false, packageName, false, defaultEncoding ) );
1489             }
1490         }
1491 
1492         /* sourcesTestFiles */
1493         List<String> sourcesTestFiles =
1494             archetypeFilesResolver.findSourcesTestFiles( files, languageIncludes.toString() );
1495         if ( !sourcesTestFiles.isEmpty() )
1496         {
1497             files.removeAll( sourcesTestFiles );
1498 
1499             List<String> filteredFiles =
1500                 archetypeFilesResolver.getFilteredFiles( sourcesTestFiles, filteredIncludes.toString() );
1501             sourcesTestFiles.removeAll( filteredFiles );
1502 
1503             List<String> unfilteredFiles = sourcesTestFiles;
1504             if ( !filteredFiles.isEmpty() )
1505             {
1506                 resolvedFileSets.addAll( createFileSets( filteredFiles, 3, true, packageName, true, defaultEncoding ) );
1507             }
1508             if ( !unfilteredFiles.isEmpty() )
1509             {
1510                 resolvedFileSets.addAll(
1511                     createFileSets( unfilteredFiles, 3, true, packageName, false, defaultEncoding ) );
1512             }
1513         }
1514 
1515         /* ressourcesTestFiles */
1516         List<String> resourcesTestFiles =
1517             archetypeFilesResolver.findResourcesTestFiles( files, languageIncludes.toString() );
1518         if ( !resourcesTestFiles.isEmpty() )
1519         {
1520             files.removeAll( resourcesTestFiles );
1521 
1522             List<String> filteredFiles =
1523                 archetypeFilesResolver.getFilteredFiles( resourcesTestFiles, filteredIncludes.toString() );
1524             resourcesTestFiles.removeAll( filteredFiles );
1525 
1526             List<String> unfilteredFiles = resourcesTestFiles;
1527             if ( !filteredFiles.isEmpty() )
1528             {
1529                 resolvedFileSets.addAll(
1530                     createFileSets( filteredFiles, 3, false, packageName, true, defaultEncoding ) );
1531             }
1532             if ( !unfilteredFiles.isEmpty() )
1533             {
1534                 resolvedFileSets.addAll(
1535                     createFileSets( unfilteredFiles, 3, false, packageName, false, defaultEncoding ) );
1536             }
1537         }
1538 
1539         /* siteFiles */
1540         List<String> siteFiles = archetypeFilesResolver.findSiteFiles( files, languageIncludes.toString() );
1541         if ( !siteFiles.isEmpty() )
1542         {
1543             files.removeAll( siteFiles );
1544 
1545             List<String> filteredFiles =
1546                 archetypeFilesResolver.getFilteredFiles( siteFiles, filteredIncludes.toString() );
1547             siteFiles.removeAll( filteredFiles );
1548 
1549             List<String> unfilteredFiles = siteFiles;
1550             if ( !filteredFiles.isEmpty() )
1551             {
1552                 resolvedFileSets.addAll(
1553                     createFileSets( filteredFiles, 2, false, packageName, true, defaultEncoding ) );
1554             }
1555             if ( !unfilteredFiles.isEmpty() )
1556             {
1557                 resolvedFileSets.addAll(
1558                     createFileSets( unfilteredFiles, 2, false, packageName, false, defaultEncoding ) );
1559             }
1560         }
1561 
1562         /* thirdLevelSourcesfiles */
1563         List<String> thirdLevelSourcesfiles =
1564             archetypeFilesResolver.findOtherSources( 3, files, languageIncludes.toString() );
1565         if ( !thirdLevelSourcesfiles.isEmpty() )
1566         {
1567             files.removeAll( thirdLevelSourcesfiles );
1568 
1569             List<String> filteredFiles =
1570                 archetypeFilesResolver.getFilteredFiles( thirdLevelSourcesfiles, filteredIncludes.toString() );
1571             thirdLevelSourcesfiles.removeAll( filteredFiles );
1572 
1573             List<String> unfilteredFiles = thirdLevelSourcesfiles;
1574             if ( !filteredFiles.isEmpty() )
1575             {
1576                 resolvedFileSets.addAll( createFileSets( filteredFiles, 3, true, packageName, true, defaultEncoding ) );
1577             }
1578             if ( !unfilteredFiles.isEmpty() )
1579             {
1580                 resolvedFileSets.addAll(
1581                     createFileSets( unfilteredFiles, 3, true, packageName, false, defaultEncoding ) );
1582             }
1583 
1584             /* thirdLevelResourcesfiles */
1585             List<String> thirdLevelResourcesfiles =
1586                 archetypeFilesResolver.findOtherResources( 3, files, thirdLevelSourcesfiles,
1587                                                            languageIncludes.toString() );
1588             if ( !thirdLevelResourcesfiles.isEmpty() )
1589             {
1590                 files.removeAll( thirdLevelResourcesfiles );
1591                 filteredFiles =
1592                     archetypeFilesResolver.getFilteredFiles( thirdLevelResourcesfiles, filteredIncludes.toString() );
1593                 thirdLevelResourcesfiles.removeAll( filteredFiles );
1594                 unfilteredFiles = thirdLevelResourcesfiles;
1595                 if ( !filteredFiles.isEmpty() )
1596                 {
1597                     resolvedFileSets.addAll(
1598                         createFileSets( filteredFiles, 3, false, packageName, true, defaultEncoding ) );
1599                 }
1600                 if ( !unfilteredFiles.isEmpty() )
1601                 {
1602                     resolvedFileSets.addAll(
1603                         createFileSets( unfilteredFiles, 3, false, packageName, false, defaultEncoding ) );
1604                 }
1605             }
1606         } // end if
1607 
1608         /* secondLevelSourcesfiles */
1609         List<String> secondLevelSourcesfiles =
1610             archetypeFilesResolver.findOtherSources( 2, files, languageIncludes.toString() );
1611         if ( !secondLevelSourcesfiles.isEmpty() )
1612         {
1613             files.removeAll( secondLevelSourcesfiles );
1614 
1615             List<String> filteredFiles =
1616                 archetypeFilesResolver.getFilteredFiles( secondLevelSourcesfiles, filteredIncludes.toString() );
1617             secondLevelSourcesfiles.removeAll( filteredFiles );
1618 
1619             List<String> unfilteredFiles = secondLevelSourcesfiles;
1620             if ( !filteredFiles.isEmpty() )
1621             {
1622                 resolvedFileSets.addAll( createFileSets( filteredFiles, 2, true, packageName, true, defaultEncoding ) );
1623             }
1624             if ( !unfilteredFiles.isEmpty() )
1625             {
1626                 resolvedFileSets.addAll(
1627                     createFileSets( unfilteredFiles, 2, true, packageName, false, defaultEncoding ) );
1628             }
1629         }
1630 
1631         /* secondLevelResourcesfiles */
1632         List<String> secondLevelResourcesfiles =
1633             archetypeFilesResolver.findOtherResources( 2, files, languageIncludes.toString() );
1634         if ( !secondLevelResourcesfiles.isEmpty() )
1635         {
1636             files.removeAll( secondLevelResourcesfiles );
1637 
1638             List<String> filteredFiles =
1639                 archetypeFilesResolver.getFilteredFiles( secondLevelResourcesfiles, filteredIncludes.toString() );
1640             secondLevelResourcesfiles.removeAll( filteredFiles );
1641 
1642             List<String> unfilteredFiles = secondLevelResourcesfiles;
1643             if ( !filteredFiles.isEmpty() )
1644             {
1645                 resolvedFileSets.addAll(
1646                     createFileSets( filteredFiles, 2, false, packageName, true, defaultEncoding ) );
1647             }
1648             if ( !unfilteredFiles.isEmpty() )
1649             {
1650                 resolvedFileSets.addAll(
1651                     createFileSets( unfilteredFiles, 2, false, packageName, false, defaultEncoding ) );
1652             }
1653         }
1654 
1655         /* rootResourcesfiles */
1656         List<String> rootResourcesfiles =
1657             archetypeFilesResolver.findOtherResources( 0, files, languageIncludes.toString() );
1658         if ( !rootResourcesfiles.isEmpty() )
1659         {
1660             files.removeAll( rootResourcesfiles );
1661 
1662             List<String> filteredFiles =
1663                 archetypeFilesResolver.getFilteredFiles( rootResourcesfiles, filteredIncludes.toString() );
1664             rootResourcesfiles.removeAll( filteredFiles );
1665 
1666             List<String> unfilteredFiles = rootResourcesfiles;
1667             if ( !filteredFiles.isEmpty() )
1668             {
1669                 resolvedFileSets.addAll(
1670                     createFileSets( filteredFiles, 0, false, packageName, true, defaultEncoding ) );
1671             }
1672             if ( !unfilteredFiles.isEmpty() )
1673             {
1674                 resolvedFileSets.addAll(
1675                     createFileSets( unfilteredFiles, 0, false, packageName, false, defaultEncoding ) );
1676             }
1677         }
1678 
1679         /**/
1680         if ( !files.isEmpty() )
1681         {
1682             getLogger().info( "Ignored files: " + files );
1683         }
1684 
1685         return resolvedFileSets;
1686     }
1687 
1688     private void restoreArtifactId( Properties properties, String artifactId )
1689     {
1690         if ( StringUtils.isEmpty( artifactId ) )
1691         {
1692             properties.remove( Constants.ARTIFACT_ID );
1693         }
1694         else
1695         {
1696             properties.setProperty( Constants.ARTIFACT_ID, artifactId );
1697         }
1698     }
1699 
1700     private void restoreParentArtifactId( Properties properties, String parentArtifactId )
1701     {
1702         if ( StringUtils.isEmpty( parentArtifactId ) )
1703         {
1704             properties.remove( Constants.PARENT_ARTIFACT_ID );
1705         }
1706         else
1707         {
1708             properties.setProperty( Constants.PARENT_ARTIFACT_ID, parentArtifactId );
1709         }
1710     }
1711 
1712     private String getReversedContent( String content, Properties properties )
1713     {
1714         String result =
1715             StringUtils.replace( StringUtils.replace( content, "$", "${symbol_dollar}" ), "\\", "${symbol_escape}" );
1716         result = getReversedPlainContent( result, properties );
1717 
1718         // TODO: Replace velocity to a better engine...
1719         return "#set( $symbol_pound = '#' )\n" + "#set( $symbol_dollar = '$' )\n" + "#set( $symbol_escape = '\\' )\n"
1720             + StringUtils.replace( result, "#", "${symbol_pound}" );
1721     }
1722 
1723     private String getReversedPlainContent( String content, Properties properties )
1724     {
1725         String result = content;
1726 
1727         for ( Iterator<?> propertyIterator = properties.keySet().iterator(); propertyIterator.hasNext(); )
1728         {
1729             String propertyKey = (String) propertyIterator.next();
1730 
1731             result = StringUtils.replace( result, properties.getProperty( propertyKey ), "${" + propertyKey + "}" );
1732         }
1733         return result;
1734     }
1735 
1736     private String getReversedFilename( String filename, Properties properties )
1737     {
1738         String result = filename;
1739 
1740         for ( Iterator<?> propertyIterator = properties.keySet().iterator(); propertyIterator.hasNext(); )
1741         {
1742             String propertyKey = (String) propertyIterator.next();
1743 
1744             result = StringUtils.replace( result, properties.getProperty( propertyKey ), "__" + propertyKey + "__" );
1745         }
1746 
1747         return result;
1748     }
1749 
1750     private String getTemplateOutputDirectory()
1751     {
1752         return Constants.SRC + File.separator + Constants.MAIN + File.separator + Constants.RESOURCES;
1753     }
1754 
1755     private FileSet getUnpackagedFileSet( final boolean filtered, final String group, final List<String> groupFiles,
1756                                           String defaultEncoding )
1757     {
1758         Set<String> extensions = getExtensions( groupFiles );
1759 
1760         List<String> includes = new ArrayList<String>();
1761         List<String> excludes = new ArrayList<String>();
1762 
1763         for ( String extension : extensions )
1764         {
1765             includes.add( "**/*." + extension );
1766         }
1767 
1768         return createFileSet( excludes, false, filtered, group, includes, defaultEncoding );
1769     }
1770 
1771     private FileSet getUnpackagedFileSet( final boolean filtered, final Set<String> unpackagedExtensions,
1772                                           final List<String> unpackagedFiles, final String group,
1773                                           final Set<String> packagedExtensions, String defaultEncoding )
1774     {
1775         List<String> includes = new ArrayList<String>();
1776         List<String> excludes = new ArrayList<String>();
1777 
1778         for ( String extension : unpackagedExtensions )
1779         {
1780             if ( packagedExtensions.contains( extension ) )
1781             {
1782                 includes.addAll( archetypeFilesResolver.getFilesWithExtension( unpackagedFiles, extension ) );
1783             }
1784             else
1785             {
1786                 if ( StringUtils.isEmpty( extension ) )
1787                 {
1788                     includes.add( "**/*" );
1789                 }
1790                 else
1791                 {
1792                     includes.add( "**/*." + extension );
1793                 }
1794             }
1795         }
1796 
1797         return createFileSet( excludes, false, filtered, group, includes, defaultEncoding );
1798     }
1799 
1800     private static final String MAVEN_PROPERTIES =
1801         "META-INF/maven/org.apache.maven.archetype/archetype-common/pom.properties";
1802 
1803     public String getArchetypeVersion()
1804     {
1805         InputStream is = null;
1806 
1807         // This should actually come from the pom.properties at testing but it's not generated and put into the JAR, it
1808         // happens as part of the JAR plugin which is crap as it makes testing inconsistent.
1809         String version = "version";
1810 
1811         try
1812         {
1813             Properties properties = new Properties();
1814 
1815             is = getClass().getClassLoader().getResourceAsStream( MAVEN_PROPERTIES );
1816 
1817             if ( is != null )
1818             {
1819                 properties.load( is );
1820 
1821                 String property = properties.getProperty( "version" );
1822 
1823                 if ( property != null )
1824                 {
1825                     return property;
1826                 }
1827             }
1828 
1829             return version;
1830         }
1831         catch ( IOException e )
1832         {
1833             return version;
1834         }
1835         finally
1836         {
1837             IOUtil.close( is );
1838         }
1839     }
1840 }