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