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