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