1 package org.apache.maven.archetype.generator;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import groovy.lang.Binding;
23 import groovy.lang.GroovyShell;
24 import org.apache.maven.archetype.ArchetypeGenerationRequest;
25 import org.apache.maven.archetype.common.ArchetypeArtifactManager;
26 import org.apache.maven.archetype.common.ArchetypeFilesResolver;
27 import org.apache.maven.archetype.common.Constants;
28 import org.apache.maven.archetype.common.PomManager;
29 import org.apache.maven.archetype.exception.ArchetypeGenerationFailure;
30 import org.apache.maven.archetype.exception.ArchetypeNotConfigured;
31 import org.apache.maven.archetype.exception.InvalidPackaging;
32 import org.apache.maven.archetype.exception.OutputFileExists;
33 import org.apache.maven.archetype.exception.PomFileExists;
34 import org.apache.maven.archetype.exception.ProjectDirectoryExists;
35 import org.apache.maven.archetype.exception.UnknownArchetype;
36 import org.apache.maven.archetype.metadata.AbstractArchetypeDescriptor;
37 import org.apache.maven.archetype.metadata.ArchetypeDescriptor;
38 import org.apache.maven.archetype.metadata.FileSet;
39 import org.apache.maven.archetype.metadata.ModuleDescriptor;
40 import org.apache.maven.archetype.metadata.RequiredProperty;
41 import org.apache.velocity.VelocityContext;
42 import org.apache.velocity.app.Velocity;
43 import org.apache.velocity.context.Context;
44 import org.codehaus.plexus.component.annotations.Component;
45 import org.codehaus.plexus.component.annotations.Requirement;
46 import org.codehaus.plexus.logging.AbstractLogEnabled;
47 import org.codehaus.plexus.util.FileUtils;
48 import org.codehaus.plexus.util.IOUtil;
49 import org.codehaus.plexus.util.StringUtils;
50 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
51 import org.codehaus.plexus.velocity.VelocityComponent;
52 import org.xml.sax.SAXException;
53
54 import javax.xml.parsers.ParserConfigurationException;
55 import javax.xml.transform.TransformerException;
56 import java.io.File;
57 import java.io.FileNotFoundException;
58 import java.io.FileOutputStream;
59 import java.io.IOException;
60 import java.io.InputStream;
61 import java.io.OutputStream;
62 import java.io.OutputStreamWriter;
63 import java.io.StringWriter;
64 import java.io.Writer;
65 import java.util.ArrayList;
66 import java.util.Iterator;
67 import java.util.List;
68 import java.util.Map;
69 import java.util.Properties;
70 import java.util.regex.Matcher;
71 import java.util.regex.Pattern;
72 import java.util.zip.ZipEntry;
73 import java.util.zip.ZipFile;
74
75 @Component( role = FilesetArchetypeGenerator.class )
76 public class DefaultFilesetArchetypeGenerator
77 extends AbstractLogEnabled
78 implements FilesetArchetypeGenerator
79 {
80 @Requirement
81 private ArchetypeArtifactManager archetypeArtifactManager;
82
83 @Requirement
84 private ArchetypeFilesResolver archetypeFilesResolver;
85
86 @Requirement
87 private PomManager pomManager;
88
89 @Requirement
90 private VelocityComponent velocity;
91
92
93
94
95
96 private static final Pattern TOKEN_PATTERN = Pattern.compile( "__((?:[^_]+_)*[^_]+)__" );
97
98 @Override
99 public void generateArchetype( ArchetypeGenerationRequest request, File archetypeFile )
100 throws UnknownArchetype, ArchetypeNotConfigured, ProjectDirectoryExists, PomFileExists, OutputFileExists,
101 ArchetypeGenerationFailure, InvalidPackaging
102 {
103 ClassLoader old = Thread.currentThread().getContextClassLoader();
104
105 try
106 {
107 ArchetypeDescriptor archetypeDescriptor =
108 archetypeArtifactManager.getFileSetArchetypeDescriptor( archetypeFile );
109
110 if ( !isArchetypeConfigured( archetypeDescriptor, request ) )
111 {
112 if ( request.isInteractiveMode() )
113 {
114 throw new ArchetypeNotConfigured( "No archetype was chosen.", null );
115 }
116
117 StringBuilder exceptionMessage = new StringBuilder(
118 "Archetype " + request.getArchetypeGroupId() + ":" + request.getArchetypeArtifactId() + ":"
119 + request.getArchetypeVersion() + " is not configured" );
120
121 List<String> missingProperties = new ArrayList<>( 0 );
122 for ( RequiredProperty requiredProperty : archetypeDescriptor.getRequiredProperties() )
123 {
124 if ( StringUtils.isEmpty( request.getProperties().getProperty( requiredProperty.getKey() ) ) )
125 {
126 exceptionMessage.append( "\n\tProperty " + requiredProperty.getKey() + " is missing." );
127
128 missingProperties.add( requiredProperty.getKey() );
129 }
130 }
131
132 throw new ArchetypeNotConfigured( exceptionMessage.toString(), missingProperties );
133 }
134
135 Context context = prepareVelocityContext( request );
136
137 String packageName = request.getPackage();
138 String artifactId = request.getArtifactId();
139 File outputDirectoryFile = new File( request.getOutputDirectory(), artifactId );
140 File basedirPom = new File( request.getOutputDirectory(), Constants.ARCHETYPE_POM );
141 File pom = new File( outputDirectoryFile, Constants.ARCHETYPE_POM );
142
143 List<String> archetypeResources = archetypeArtifactManager.getFilesetArchetypeResources( archetypeFile );
144
145 ZipFile archetypeZipFile = archetypeArtifactManager.getArchetypeZipFile( archetypeFile );
146
147 ClassLoader archetypeJarLoader = archetypeArtifactManager.getArchetypeJarLoader( archetypeFile );
148
149 Thread.currentThread().setContextClassLoader( archetypeJarLoader );
150
151 if ( archetypeDescriptor.isPartial() )
152 {
153 getLogger().debug( "Processing partial archetype " + archetypeDescriptor.getName() );
154 if ( outputDirectoryFile.exists() )
155 {
156 if ( !pom.exists() )
157 {
158 throw new PomFileExists( "This is a partial archetype and the pom.xml file doesn't exist." );
159 }
160
161 processPomWithMerge( context, pom, "" );
162
163 processArchetypeTemplatesWithWarning( archetypeDescriptor, archetypeResources, archetypeZipFile, "",
164 context, packageName, outputDirectoryFile );
165 }
166 else
167 {
168 if ( basedirPom.exists() )
169 {
170 processPomWithMerge( context, basedirPom, "" );
171
172 processArchetypeTemplatesWithWarning( archetypeDescriptor, archetypeResources, archetypeZipFile,
173 "", context, packageName,
174 new File( request.getOutputDirectory() ) );
175 }
176 else
177 {
178 processPom( context, pom, "" );
179
180 processArchetypeTemplates( archetypeDescriptor, archetypeResources, archetypeZipFile, "",
181 context, packageName, outputDirectoryFile );
182 }
183 }
184
185 if ( archetypeDescriptor.getModules().size() > 0 )
186 {
187 getLogger().info( "Modules ignored in partial mode" );
188 }
189 }
190 else
191 {
192 getLogger().debug( "Processing complete archetype " + archetypeDescriptor.getName() );
193 if ( outputDirectoryFile.exists() && pom.exists() )
194 {
195 throw new ProjectDirectoryExists(
196 "A Maven project already exists in the directory " + outputDirectoryFile.getPath() );
197 }
198
199 if ( outputDirectoryFile.exists() )
200 {
201 getLogger().warn( "The directory " + outputDirectoryFile.getPath() + " already exists." );
202 }
203
204 context.put( "rootArtifactId", artifactId );
205
206 processFilesetModule( artifactId, artifactId, archetypeResources, pom, archetypeZipFile, "", basedirPom,
207 outputDirectoryFile, packageName, archetypeDescriptor, context );
208 }
209
210 String postGenerationScript = archetypeArtifactManager.getPostGenerationScript( archetypeFile );
211 if ( postGenerationScript != null )
212 {
213 getLogger().info( "Executing " + Constants.ARCHETYPE_POST_GENERATION_SCRIPT
214 + " post-generation script" );
215
216 Binding binding = new Binding();
217
218 final Properties archetypeGeneratorProperties = new Properties();
219 archetypeGeneratorProperties.putAll( System.getProperties() );
220
221 if ( request.getProperties() != null )
222 {
223 archetypeGeneratorProperties.putAll( request.getProperties() );
224 }
225
226 for ( Map.Entry<Object, Object> entry : archetypeGeneratorProperties.entrySet() )
227 {
228 binding.setVariable( entry.getKey().toString(), entry.getValue() );
229 }
230
231 binding.setVariable( "request", request );
232
233 GroovyShell shell = new GroovyShell( binding );
234 shell.evaluate( postGenerationScript );
235 }
236
237
238
239
240 if ( getLogger().isInfoEnabled() )
241 {
242 getLogger().info( "Project created from Archetype in dir: " + outputDirectoryFile.getAbsolutePath() );
243 }
244 }
245 catch ( IOException | XmlPullParserException | ParserConfigurationException | TransformerException
246 | SAXException e )
247 {
248 throw new ArchetypeGenerationFailure( e );
249 }
250 finally
251 {
252 Thread.currentThread().setContextClassLoader( old );
253 }
254 }
255
256 public String getPackageAsDirectory( String packageName )
257 {
258 return StringUtils.replace( packageName, ".", "/" );
259 }
260
261 private boolean copyFile( final File outFile, final String template, final boolean failIfExists,
262 final ZipFile archetypeZipFile )
263 throws OutputFileExists, IOException
264 {
265 getLogger().debug( "Copying file " + template );
266
267 if ( failIfExists && outFile.exists() )
268 {
269 throw new OutputFileExists( "Don't rewrite file " + outFile.getName() );
270 }
271 else if ( outFile.exists() )
272 {
273 getLogger().warn( "CP Don't override file " + outFile );
274
275 return false;
276 }
277
278 ZipEntry input = archetypeZipFile.getEntry( Constants.ARCHETYPE_RESOURCES + "/" + template );
279
280 if ( input.isDirectory() )
281 {
282 outFile.mkdirs();
283 }
284 else
285 {
286 outFile.getParentFile().mkdirs();
287 if ( !outFile.exists() && !outFile.createNewFile() )
288 {
289 getLogger().warn( "Could not create new file \"" + outFile.getPath()
290 + "\" or the file already exists." );
291 }
292
293 try ( InputStream inputStream = archetypeZipFile.getInputStream( input );
294 OutputStream out = new FileOutputStream( outFile ) )
295 {
296 IOUtil.copy( inputStream, out );
297 }
298 }
299
300 return true;
301 }
302
303 private int copyFiles( String directory, List<String> fileSetResources, boolean packaged, String packageName,
304 File outputDirectoryFile, ZipFile archetypeZipFile, String moduleOffset,
305 boolean failIfExists, Context context )
306 throws OutputFileExists, FileNotFoundException, IOException
307 {
308 int count = 0;
309
310 for ( String template : fileSetResources )
311 {
312 File outputFile =
313 getOutputFile( template, directory, outputDirectoryFile, packaged, packageName, moduleOffset, context );
314
315 if ( copyFile( outputFile, template, failIfExists, archetypeZipFile ) )
316 {
317 count++;
318 }
319 }
320
321 return count;
322 }
323
324 private String getEncoding( String archetypeEncoding )
325 {
326 return StringUtils.isEmpty( archetypeEncoding ) ? "UTF-8" : archetypeEncoding;
327 }
328
329 private String getOffsetSeparator( String moduleOffset )
330 {
331 return StringUtils.isEmpty( moduleOffset ) ? "/" : ( "/" + moduleOffset + "/" );
332 }
333
334 private File getOutputFile( String template, String directory, File outputDirectoryFile, boolean packaged,
335 String packageName, String moduleOffset, Context context )
336 {
337 String templateName = StringUtils.replaceOnce( template, directory, "" );
338
339 String outputFileName =
340 directory + "/" + ( packaged ? getPackageAsDirectory( packageName ) : "" ) + "/" + templateName.substring(
341 moduleOffset.length() );
342
343 outputFileName = replaceFilenameTokens( outputFileName, context );
344
345 return new File( outputDirectoryFile, outputFileName );
346 }
347
348
349
350
351
352
353
354
355
356
357 private String replaceFilenameTokens( final String filePath, final Context context )
358 {
359 StringBuffer interpolatedResult = new StringBuffer();
360 Matcher matcher = TOKEN_PATTERN.matcher( filePath );
361
362 while ( matcher.find() )
363 {
364 String propertyToken = matcher.group( 1 );
365 String contextPropertyValue = (String) context.get( propertyToken );
366 if ( contextPropertyValue != null && contextPropertyValue.trim().length() > 0 )
367 {
368 if ( getLogger().isDebugEnabled() )
369 {
370 getLogger().debug( "Replacing property '" + propertyToken + "' in file path '" + filePath
371 + "' with value '" + contextPropertyValue + "'." );
372 }
373 matcher.appendReplacement( interpolatedResult, contextPropertyValue );
374 }
375 else
376 {
377
378 getLogger().warn( "Property '" + propertyToken + "' was not specified, so the token in '" + filePath
379 + "' is not being replaced." );
380 }
381 }
382
383 matcher.appendTail( interpolatedResult );
384
385 if ( getLogger().isDebugEnabled() )
386 {
387 getLogger().debug( "Final interpolated file path: '" + interpolatedResult + "'" );
388 }
389
390 return interpolatedResult.toString();
391 }
392
393 private String getPackageInPathFormat( String aPackage )
394 {
395 return StringUtils.replace( aPackage, ".", "/" );
396 }
397
398 private boolean isArchetypeConfigured( ArchetypeDescriptor archetypeDescriptor, ArchetypeGenerationRequest request )
399 {
400 for ( RequiredProperty requiredProperty : archetypeDescriptor.getRequiredProperties() )
401 {
402 if ( StringUtils.isEmpty( request.getProperties().getProperty( requiredProperty.getKey() ) ) )
403 {
404 return false;
405 }
406 }
407
408 return true;
409 }
410
411 private void setParentArtifactId( Context context, String artifactId )
412 {
413 context.put( Constants.PARENT_ARTIFACT_ID, artifactId );
414 }
415
416 private Context prepareVelocityContext( ArchetypeGenerationRequest request )
417 {
418 Context context = new VelocityContext();
419 context.put( Constants.GROUP_ID, request.getGroupId() );
420 context.put( Constants.ARTIFACT_ID, request.getArtifactId() );
421 context.put( Constants.VERSION, request.getVersion() );
422 context.put( Constants.PACKAGE, request.getPackage() );
423 final String packageInPathFormat = getPackageInPathFormat( request.getPackage() );
424 context.put( Constants.PACKAGE_IN_PATH_FORMAT, packageInPathFormat );
425
426 if ( getLogger().isInfoEnabled() )
427 {
428 getLogger().info( "----------------------------------------------------------------------------" );
429
430 getLogger().info(
431 "Using following parameters for creating project from Archetype: " + request.getArchetypeArtifactId()
432 + ":" + request.getArchetypeVersion() );
433
434 getLogger().info( "----------------------------------------------------------------------------" );
435 getLogger().info( "Parameter: " + Constants.GROUP_ID + ", Value: " + request.getGroupId() );
436 getLogger().info( "Parameter: " + Constants.ARTIFACT_ID + ", Value: " + request.getArtifactId() );
437 getLogger().info( "Parameter: " + Constants.VERSION + ", Value: " + request.getVersion() );
438 getLogger().info( "Parameter: " + Constants.PACKAGE + ", Value: " + request.getPackage() );
439 getLogger().info( "Parameter: " + Constants.PACKAGE_IN_PATH_FORMAT + ", Value: " + packageInPathFormat );
440 }
441
442 for ( Iterator<?> iterator = request.getProperties().keySet().iterator(); iterator.hasNext(); )
443 {
444 String key = (String) iterator.next();
445
446 String value = request.getProperties().getProperty( key );
447
448 if ( maybeVelocityExpression( value ) )
449 {
450 value = evaluateExpression( context, key, value );
451 }
452
453 context.put( key, value );
454
455 if ( getLogger().isInfoEnabled() )
456 {
457 getLogger().info( "Parameter: " + key + ", Value: " + value );
458 }
459 }
460 return context;
461 }
462
463 private boolean maybeVelocityExpression( String value )
464 {
465 return value != null && value.contains( "${" );
466 }
467
468 private String evaluateExpression( Context context, String key, String value )
469 {
470 try ( StringWriter stringWriter = new StringWriter() )
471 {
472 Velocity.evaluate( context, stringWriter, key, value );
473 return stringWriter.toString();
474 }
475 catch ( Exception ex )
476 {
477 return value;
478 }
479 }
480
481 private void processArchetypeTemplates( AbstractArchetypeDescriptor archetypeDescriptor,
482 List<String> archetypeResources, ZipFile archetypeZipFile,
483 String moduleOffset, Context context, String packageName,
484 File outputDirectoryFile )
485 throws OutputFileExists, ArchetypeGenerationFailure, FileNotFoundException, IOException
486 {
487 processTemplates( packageName, outputDirectoryFile, context, archetypeDescriptor, archetypeResources,
488 archetypeZipFile, moduleOffset, false );
489 }
490
491 private void processArchetypeTemplatesWithWarning( ArchetypeDescriptor archetypeDescriptor,
492 List<String> archetypeResources, ZipFile archetypeZipFile,
493 String moduleOffset, Context context, String packageName,
494 File outputDirectoryFile )
495 throws OutputFileExists, ArchetypeGenerationFailure, FileNotFoundException, IOException
496 {
497 processTemplates( packageName, outputDirectoryFile, context, archetypeDescriptor, archetypeResources,
498 archetypeZipFile, moduleOffset, true );
499 }
500
501 private int processFileSet( String directory, List<String> fileSetResources, boolean packaged, String packageName,
502 Context context, File outputDirectoryFile, String moduleOffset,
503 String archetypeEncoding, boolean failIfExists )
504 throws IOException, OutputFileExists, ArchetypeGenerationFailure
505 {
506 int count = 0;
507
508 for ( String template : fileSetResources )
509 {
510 File outputFile =
511 getOutputFile( template, directory, outputDirectoryFile, packaged, packageName, moduleOffset, context );
512
513 if ( processTemplate( outputFile, context, Constants.ARCHETYPE_RESOURCES + "/" + template,
514 archetypeEncoding, failIfExists ) )
515 {
516 count++;
517 }
518 }
519
520 return count;
521 }
522
523 private void processFilesetModule( final String rootArtifactId, final String artifactId,
524 final List<String> archetypeResources, File pom, final ZipFile archetypeZipFile,
525 String moduleOffset, File basedirPom, File outputDirectoryFile,
526 final String packageName, final AbstractArchetypeDescriptor archetypeDescriptor,
527 final Context context ) throws XmlPullParserException, IOException,
528 ParserConfigurationException, SAXException, TransformerException,
529 OutputFileExists, ArchetypeGenerationFailure, InvalidPackaging
530 {
531 outputDirectoryFile.mkdirs();
532 getLogger().debug( "Processing module " + artifactId );
533 getLogger().debug( "Processing module rootArtifactId " + rootArtifactId );
534 getLogger().debug( "Processing module pom " + pom );
535 getLogger().debug( "Processing module moduleOffset " + moduleOffset );
536 getLogger().debug( "Processing module outputDirectoryFile " + outputDirectoryFile );
537
538 processFilesetProject( archetypeDescriptor,
539 StringUtils.replace( artifactId, "${rootArtifactId}", rootArtifactId ),
540 archetypeResources, pom, archetypeZipFile, moduleOffset, context, packageName,
541 outputDirectoryFile, basedirPom );
542
543 String parentArtifactId = (String) context.get( Constants.PARENT_ARTIFACT_ID );
544
545 Iterator<ModuleDescriptor> subprojects = archetypeDescriptor.getModules().iterator();
546
547 if ( subprojects.hasNext() )
548 {
549 getLogger().debug( artifactId + " has modules (" + archetypeDescriptor.getModules() + ")" );
550
551 setParentArtifactId( context, StringUtils.replace( artifactId, "${rootArtifactId}", rootArtifactId ) );
552 }
553
554 while ( subprojects.hasNext() )
555 {
556 ModuleDescriptor project = subprojects.next();
557
558 String modulePath = StringUtils.replace( project.getDir(), "__rootArtifactId__", rootArtifactId );
559 modulePath = replaceFilenameTokens( modulePath, context );
560
561 File moduleOutputDirectoryFile = new File( outputDirectoryFile, modulePath );
562
563 context.put( Constants.ARTIFACT_ID,
564 StringUtils.replace( project.getId(), "${rootArtifactId}", rootArtifactId ) );
565
566 String moduleArtifactId = StringUtils.replace( project.getDir(), "__rootArtifactId__", rootArtifactId );
567 moduleArtifactId = replaceFilenameTokens( moduleArtifactId, context );
568
569 processFilesetModule( rootArtifactId, moduleArtifactId,
570 archetypeResources, new File( moduleOutputDirectoryFile, Constants.ARCHETYPE_POM ),
571 archetypeZipFile,
572 ( StringUtils.isEmpty( moduleOffset ) ? "" : ( moduleOffset + "/" ) )
573 + StringUtils.replace( project.getDir(), "${rootArtifactId}", rootArtifactId ),
574 pom, moduleOutputDirectoryFile, packageName, project, context );
575 }
576
577 restoreParentArtifactId( context, parentArtifactId );
578
579 getLogger().debug( "Processed " + artifactId );
580 }
581
582 private void processFilesetProject( final AbstractArchetypeDescriptor archetypeDescriptor, final String moduleId,
583 final List<String> archetypeResources, final File pom,
584 final ZipFile archetypeZipFile, String moduleOffset, final Context context,
585 final String packageName, final File outputDirectoryFile,
586 final File basedirPom )
587 throws XmlPullParserException, IOException, ParserConfigurationException, SAXException,
588 TransformerException, OutputFileExists, ArchetypeGenerationFailure, InvalidPackaging
589 {
590 getLogger().debug( "Processing fileset project moduleId " + moduleId );
591 getLogger().debug( "Processing fileset project pom " + pom );
592 getLogger().debug( "Processing fileset project moduleOffset " + moduleOffset );
593 getLogger().debug( "Processing fileset project outputDirectoryFile " + outputDirectoryFile );
594 getLogger().debug( "Processing fileset project basedirPom " + basedirPom );
595
596 if ( basedirPom.exists() )
597 {
598 processPomWithParent( context, pom, moduleOffset, basedirPom, moduleId );
599 }
600 else
601 {
602 processPom( context, pom, moduleOffset );
603 }
604
605 processArchetypeTemplates( archetypeDescriptor, archetypeResources, archetypeZipFile, moduleOffset, context,
606 packageName, outputDirectoryFile );
607 }
608
609 private void processPom( Context context, File pom, String moduleOffset )
610 throws IOException, OutputFileExists, ArchetypeGenerationFailure
611 {
612 getLogger().debug( "Processing pom " + pom );
613
614 processTemplate( pom, context,
615 Constants.ARCHETYPE_RESOURCES + getOffsetSeparator( moduleOffset ) + Constants.ARCHETYPE_POM,
616 getEncoding( null ), true );
617 }
618
619 private void processPomWithMerge( Context context, File pom, String moduleOffset )
620 throws OutputFileExists, IOException, XmlPullParserException, ArchetypeGenerationFailure
621 {
622 getLogger().debug( "Processing pom " + pom + " with merge" );
623
624 File temporaryPom = getTemporaryFile( pom );
625
626 processTemplate( temporaryPom, context,
627 Constants.ARCHETYPE_RESOURCES + getOffsetSeparator( moduleOffset ) + Constants.ARCHETYPE_POM,
628 getEncoding( null ), true );
629
630 pomManager.mergePoms( pom, temporaryPom );
631
632
633
634 try
635 {
636 FileUtils.forceDelete( temporaryPom );
637 }
638 catch ( IOException e )
639 {
640 temporaryPom.deleteOnExit();
641 }
642 }
643
644 private void processPomWithParent( Context context, File pom, String moduleOffset, File basedirPom,
645 String moduleId )
646 throws XmlPullParserException, IOException, ParserConfigurationException, SAXException,
647 TransformerException, OutputFileExists, ArchetypeGenerationFailure, InvalidPackaging
648 {
649 getLogger().debug( "Processing pom " + pom + " with parent " + basedirPom );
650
651 processTemplate( pom, context,
652 Constants.ARCHETYPE_RESOURCES + getOffsetSeparator( moduleOffset ) + Constants.ARCHETYPE_POM,
653 getEncoding( null ), true );
654
655 getLogger().debug( "Adding module " + moduleId );
656
657 pomManager.addModule( basedirPom, moduleId );
658
659 pomManager.addParent( pom, basedirPom );
660 }
661
662 @SuppressWarnings( "deprecation" )
663 private boolean processTemplate( File outFile, Context context, String templateFileName, String encoding,
664 boolean failIfExists )
665 throws IOException, OutputFileExists, ArchetypeGenerationFailure
666 {
667 templateFileName = templateFileName.replace( File.separatorChar, '/' );
668
669 String localTemplateFileName = templateFileName.replace( '/', File.separatorChar );
670 if ( !templateFileName.equals( localTemplateFileName ) && !velocity.getEngine().templateExists(
671 templateFileName ) && velocity.getEngine().templateExists( localTemplateFileName ) )
672 {
673 templateFileName = localTemplateFileName;
674 }
675
676 getLogger().debug( "Processing template " + templateFileName );
677
678 if ( outFile.exists() )
679 {
680 if ( failIfExists )
681 {
682 throw new OutputFileExists( "Don't override file " + outFile.getAbsolutePath() );
683 }
684
685 getLogger().warn( "Don't override file " + outFile );
686
687 return false;
688 }
689
690 if ( templateFileName.endsWith( "/" ) )
691 {
692 getLogger().debug( "Creating directory " + outFile );
693
694 outFile.mkdirs();
695
696 return true;
697 }
698
699 if ( !outFile.getParentFile().exists() )
700 {
701 outFile.getParentFile().mkdirs();
702 }
703
704 if ( !outFile.exists() && !outFile.createNewFile() )
705 {
706 getLogger().warn( "Could not create new file \"" + outFile.getPath() + "\" or the file already exists." );
707 }
708
709 getLogger().debug( "Merging into " + outFile );
710
711 try ( Writer writer = new OutputStreamWriter( new FileOutputStream( outFile ), encoding ) )
712 {
713 StringWriter stringWriter = new StringWriter();
714
715 velocity.getEngine().mergeTemplate( templateFileName, encoding, context, stringWriter );
716
717 writer.write( StringUtils.unifyLineSeparators( stringWriter.toString() ) );
718 }
719 catch ( Exception e )
720 {
721 throw new ArchetypeGenerationFailure( "Error merging velocity templates: " + e.getMessage(), e );
722 }
723
724 return true;
725 }
726
727 private void processTemplates( String packageName, File outputDirectoryFile, Context context,
728 AbstractArchetypeDescriptor archetypeDescriptor, List<String> archetypeResources,
729 ZipFile archetypeZipFile, String moduleOffset, boolean failIfExists )
730 throws OutputFileExists, ArchetypeGenerationFailure, IOException
731 {
732 Iterator<FileSet> iterator = archetypeDescriptor.getFileSets().iterator();
733 if ( iterator.hasNext() )
734 {
735 getLogger().debug( "Processing filesets" + "\n " + archetypeResources );
736 }
737
738 int count = 0;
739 while ( iterator.hasNext() )
740 {
741 FileSet fileSet = iterator.next();
742 count++;
743
744 List<String> fileSetResources =
745 archetypeFilesResolver.filterFiles( moduleOffset, fileSet, archetypeResources );
746
747
748
749 getOutputFile( moduleOffset, fileSet.getDirectory(), outputDirectoryFile, fileSet.isPackaged(), packageName,
750 moduleOffset, context ).mkdirs();
751
752 if ( fileSet.isFiltered() )
753 {
754 getLogger().debug( " Processing fileset " + fileSet + " -> " + fileSetResources.size() + ":\n "
755 + fileSetResources );
756
757 int processed =
758 processFileSet( fileSet.getDirectory(), fileSetResources, fileSet.isPackaged(), packageName,
759 context, outputDirectoryFile, moduleOffset, getEncoding( fileSet.getEncoding() ),
760 failIfExists );
761
762 getLogger().debug( " Processed " + processed + " files." );
763 }
764 else
765 {
766 getLogger().debug( " Copying fileset " + fileSet + " -> " + fileSetResources.size() + ":\n "
767 + fileSetResources );
768
769 int copied = copyFiles( fileSet.getDirectory(), fileSetResources, fileSet.isPackaged(), packageName,
770 outputDirectoryFile, archetypeZipFile, moduleOffset, failIfExists, context );
771
772 getLogger().debug( " Copied " + copied + " files." );
773 }
774 }
775
776 getLogger().debug( "Processed " + count + " filesets" );
777 }
778
779 private void restoreParentArtifactId( Context context, String parentArtifactId )
780 {
781 if ( StringUtils.isEmpty( parentArtifactId ) )
782 {
783 context.remove( Constants.PARENT_ARTIFACT_ID );
784 }
785 else
786 {
787 context.put( Constants.PARENT_ARTIFACT_ID, parentArtifactId );
788 }
789 }
790
791 private File getTemporaryFile( File file )
792 {
793 File tmp = FileUtils.createTempFile( file.getName(), Constants.TMP, file.getParentFile() );
794
795 tmp.deleteOnExit();
796
797 return tmp;
798 }
799 }