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 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
90
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
184 Properties reverseProperties = getReversedProperties( archetypeDescriptor, properties );
185
186
187
188 Properties pomReversedProperties = getReversedProperties( archetypeDescriptor, properties );
189
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
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
320
321
322
323
324
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
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
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
422
423
424
425
426
427
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
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
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
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
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
647 if ( pom.getProfiles() != null )
648 {
649 for ( Profile profile : pom.getProfiles() )
650 {
651
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
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
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
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 }
1015
1016 getLogger().debug( "Resolved fileSets " + fileSets );
1017 }
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
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
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
1379
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
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
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
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
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
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
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
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 }
1607
1608
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
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
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
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
1808
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 }