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