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 2 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
288 try ( InputStream inputStream = archetypeZipFile.getInputStream( input );
289 OutputStream out = new FileOutputStream( outFile ) )
290 {
291 IOUtil.copy( inputStream, out );
292 }
293 }
294
295 return true;
296 }
297
298 private int copyFiles( String directory, List<String> fileSetResources, boolean packaged, String packageName,
299 File outputDirectoryFile, ZipFile archetypeZipFile, String moduleOffset,
300 boolean failIfExists, Context context )
301 throws OutputFileExists, FileNotFoundException, IOException
302 {
303 int count = 0;
304
305 for ( String template : fileSetResources )
306 {
307 File outputFile =
308 getOutputFile( template, directory, outputDirectoryFile, packaged, packageName, moduleOffset, context );
309
310 if ( copyFile( outputFile, template, failIfExists, archetypeZipFile ) )
311 {
312 count++;
313 }
314 }
315
316 return count;
317 }
318
319 private String getEncoding( String archetypeEncoding )
320 {
321 return StringUtils.isEmpty( archetypeEncoding ) ? "UTF-8" : archetypeEncoding;
322 }
323
324 private String getOffsetSeparator( String moduleOffset )
325 {
326 return StringUtils.isEmpty( moduleOffset ) ? "/" : ( "/" + moduleOffset + "/" );
327 }
328
329 private File getOutputFile( String template, String directory, File outputDirectoryFile, boolean packaged,
330 String packageName, String moduleOffset, Context context )
331 {
332 String templateName = StringUtils.replaceOnce( template, directory, "" );
333
334 String outputFileName =
335 directory + "/" + ( packaged ? getPackageAsDirectory( packageName ) : "" ) + "/" + templateName.substring(
336 moduleOffset.length() );
337
338 outputFileName = replaceFilenameTokens( outputFileName, context );
339
340 return new File( outputDirectoryFile, outputFileName );
341 }
342
343
344
345
346
347
348
349
350
351
352 private String replaceFilenameTokens( final String filePath, final Context context )
353 {
354 StringBuffer interpolatedResult = new StringBuffer();
355 Matcher matcher = TOKEN_PATTERN.matcher( filePath );
356
357 while ( matcher.find() )
358 {
359 String propertyToken = matcher.group( 1 );
360 String contextPropertyValue = (String) context.get( propertyToken );
361 if ( contextPropertyValue != null && contextPropertyValue.trim().length() > 0 )
362 {
363 if ( getLogger().isDebugEnabled() )
364 {
365 getLogger().debug( "Replacing property '" + propertyToken + "' in file path '" + filePath
366 + "' with value '" + contextPropertyValue + "'." );
367 }
368 matcher.appendReplacement( interpolatedResult, contextPropertyValue );
369 }
370 else
371 {
372
373 getLogger().warn( "Property '" + propertyToken + "' was not specified, so the token in '" + filePath
374 + "' is not being replaced." );
375 }
376 }
377
378 matcher.appendTail( interpolatedResult );
379
380 if ( getLogger().isDebugEnabled() )
381 {
382 getLogger().debug( "Final interpolated file path: '" + interpolatedResult + "'" );
383 }
384
385 return interpolatedResult.toString();
386 }
387
388 private String getPackageInPathFormat( String aPackage )
389 {
390 return StringUtils.replace( aPackage, ".", "/" );
391 }
392
393 private boolean isArchetypeConfigured( ArchetypeDescriptor archetypeDescriptor, ArchetypeGenerationRequest request )
394 {
395 for ( RequiredProperty requiredProperty : archetypeDescriptor.getRequiredProperties() )
396 {
397 if ( StringUtils.isEmpty( request.getProperties().getProperty( requiredProperty.getKey() ) ) )
398 {
399 return false;
400 }
401 }
402
403 return true;
404 }
405
406 private void setParentArtifactId( Context context, String artifactId )
407 {
408 context.put( Constants.PARENT_ARTIFACT_ID, artifactId );
409 }
410
411 private Context prepareVelocityContext( ArchetypeGenerationRequest request )
412 {
413 Context context = new VelocityContext();
414 context.put( Constants.GROUP_ID, request.getGroupId() );
415 context.put( Constants.ARTIFACT_ID, request.getArtifactId() );
416 context.put( Constants.VERSION, request.getVersion() );
417 context.put( Constants.PACKAGE, request.getPackage() );
418 final String packageInPathFormat = getPackageInPathFormat( request.getPackage() );
419 context.put( Constants.PACKAGE_IN_PATH_FORMAT, packageInPathFormat );
420
421 if ( getLogger().isInfoEnabled() )
422 {
423 getLogger().info( "----------------------------------------------------------------------------" );
424
425 getLogger().info(
426 "Using following parameters for creating project from Archetype: " + request.getArchetypeArtifactId()
427 + ":" + request.getArchetypeVersion() );
428
429 getLogger().info( "----------------------------------------------------------------------------" );
430 getLogger().info( "Parameter: " + Constants.GROUP_ID + ", Value: " + request.getGroupId() );
431 getLogger().info( "Parameter: " + Constants.ARTIFACT_ID + ", Value: " + request.getArtifactId() );
432 getLogger().info( "Parameter: " + Constants.VERSION + ", Value: " + request.getVersion() );
433 getLogger().info( "Parameter: " + Constants.PACKAGE + ", Value: " + request.getPackage() );
434 getLogger().info( "Parameter: " + Constants.PACKAGE_IN_PATH_FORMAT + ", Value: " + packageInPathFormat );
435 }
436
437 for ( Iterator<?> iterator = request.getProperties().keySet().iterator(); iterator.hasNext(); )
438 {
439 String key = (String) iterator.next();
440
441 String value = request.getProperties().getProperty( key );
442
443 if ( maybeVelocityExpression( value ) )
444 {
445 value = evaluateExpression( context, key, value );
446 }
447
448 context.put( key, value );
449
450 if ( getLogger().isInfoEnabled() )
451 {
452 getLogger().info( "Parameter: " + key + ", Value: " + value );
453 }
454 }
455 return context;
456 }
457
458 private boolean maybeVelocityExpression( String value )
459 {
460 return value != null && value.contains( "${" );
461 }
462
463 private String evaluateExpression( Context context, String key, String value )
464 {
465 try ( StringWriter stringWriter = new StringWriter() )
466 {
467 Velocity.evaluate( context, stringWriter, key, value );
468 return stringWriter.toString();
469 }
470 catch ( Exception ex )
471 {
472 return value;
473 }
474 }
475
476 private void processArchetypeTemplates( AbstractArchetypeDescriptor archetypeDescriptor,
477 List<String> archetypeResources, ZipFile archetypeZipFile,
478 String moduleOffset, Context context, String packageName,
479 File outputDirectoryFile )
480 throws OutputFileExists, ArchetypeGenerationFailure, FileNotFoundException, IOException
481 {
482 processTemplates( packageName, outputDirectoryFile, context, archetypeDescriptor, archetypeResources,
483 archetypeZipFile, moduleOffset, false );
484 }
485
486 private void processArchetypeTemplatesWithWarning( ArchetypeDescriptor archetypeDescriptor,
487 List<String> archetypeResources, ZipFile archetypeZipFile,
488 String moduleOffset, Context context, String packageName,
489 File outputDirectoryFile )
490 throws OutputFileExists, ArchetypeGenerationFailure, FileNotFoundException, IOException
491 {
492 processTemplates( packageName, outputDirectoryFile, context, archetypeDescriptor, archetypeResources,
493 archetypeZipFile, moduleOffset, true );
494 }
495
496 private int processFileSet( String directory, List<String> fileSetResources, boolean packaged, String packageName,
497 Context context, File outputDirectoryFile, String moduleOffset,
498 String archetypeEncoding, boolean failIfExists )
499 throws OutputFileExists, ArchetypeGenerationFailure
500 {
501 int count = 0;
502
503 for ( String template : fileSetResources )
504 {
505 File outputFile =
506 getOutputFile( template, directory, outputDirectoryFile, packaged, packageName, moduleOffset, context );
507
508 if ( processTemplate( outputFile, context, Constants.ARCHETYPE_RESOURCES + "/" + template,
509 archetypeEncoding, failIfExists ) )
510 {
511 count++;
512 }
513 }
514
515 return count;
516 }
517
518 private void processFilesetModule( final String rootArtifactId, final String artifactId,
519 final List<String> archetypeResources, File pom, final ZipFile archetypeZipFile,
520 String moduleOffset, File basedirPom, File outputDirectoryFile,
521 final String packageName, final AbstractArchetypeDescriptor archetypeDescriptor,
522 final Context context ) throws XmlPullParserException, IOException,
523 ParserConfigurationException, SAXException, TransformerException,
524 OutputFileExists, ArchetypeGenerationFailure, InvalidPackaging
525 {
526 outputDirectoryFile.mkdirs();
527 getLogger().debug( "Processing module " + artifactId );
528 getLogger().debug( "Processing module rootArtifactId " + rootArtifactId );
529 getLogger().debug( "Processing module pom " + pom );
530 getLogger().debug( "Processing module moduleOffset " + moduleOffset );
531 getLogger().debug( "Processing module outputDirectoryFile " + outputDirectoryFile );
532
533 processFilesetProject( archetypeDescriptor,
534 StringUtils.replace( artifactId, "${rootArtifactId}", rootArtifactId ),
535 archetypeResources, pom, archetypeZipFile, moduleOffset, context, packageName,
536 outputDirectoryFile, basedirPom );
537
538 String parentArtifactId = (String) context.get( Constants.PARENT_ARTIFACT_ID );
539
540 Iterator<ModuleDescriptor> subprojects = archetypeDescriptor.getModules().iterator();
541
542 if ( subprojects.hasNext() )
543 {
544 getLogger().debug( artifactId + " has modules (" + archetypeDescriptor.getModules() + ")" );
545
546 setParentArtifactId( context, StringUtils.replace( artifactId, "${rootArtifactId}", rootArtifactId ) );
547 }
548
549 while ( subprojects.hasNext() )
550 {
551 ModuleDescriptor project = subprojects.next();
552
553 String modulePath = StringUtils.replace( project.getDir(), "__rootArtifactId__", rootArtifactId );
554 modulePath = replaceFilenameTokens( modulePath, context );
555
556 File moduleOutputDirectoryFile = new File( outputDirectoryFile, modulePath );
557
558 context.put( Constants.ARTIFACT_ID,
559 StringUtils.replace( project.getId(), "${rootArtifactId}", rootArtifactId ) );
560
561 String moduleArtifactId = StringUtils.replace( project.getDir(), "__rootArtifactId__", rootArtifactId );
562 moduleArtifactId = replaceFilenameTokens( moduleArtifactId, context );
563
564 processFilesetModule( rootArtifactId, moduleArtifactId,
565 archetypeResources, new File( moduleOutputDirectoryFile, Constants.ARCHETYPE_POM ),
566 archetypeZipFile,
567 ( StringUtils.isEmpty( moduleOffset ) ? "" : ( moduleOffset + "/" ) )
568 + StringUtils.replace( project.getDir(), "${rootArtifactId}", rootArtifactId ),
569 pom, moduleOutputDirectoryFile, packageName, project, context );
570 }
571
572 restoreParentArtifactId( context, parentArtifactId );
573
574 getLogger().debug( "Processed " + artifactId );
575 }
576
577 private void processFilesetProject( final AbstractArchetypeDescriptor archetypeDescriptor, final String moduleId,
578 final List<String> archetypeResources, final File pom,
579 final ZipFile archetypeZipFile, String moduleOffset, final Context context,
580 final String packageName, final File outputDirectoryFile,
581 final File basedirPom )
582 throws XmlPullParserException, IOException, ParserConfigurationException, SAXException,
583 TransformerException, OutputFileExists, ArchetypeGenerationFailure, InvalidPackaging
584 {
585 getLogger().debug( "Processing fileset project moduleId " + moduleId );
586 getLogger().debug( "Processing fileset project pom " + pom );
587 getLogger().debug( "Processing fileset project moduleOffset " + moduleOffset );
588 getLogger().debug( "Processing fileset project outputDirectoryFile " + outputDirectoryFile );
589 getLogger().debug( "Processing fileset project basedirPom " + basedirPom );
590
591 if ( basedirPom.exists() )
592 {
593 processPomWithParent( context, pom, moduleOffset, basedirPom, moduleId );
594 }
595 else
596 {
597 processPom( context, pom, moduleOffset );
598 }
599
600 processArchetypeTemplates( archetypeDescriptor, archetypeResources, archetypeZipFile, moduleOffset, context,
601 packageName, outputDirectoryFile );
602 }
603
604 private void processPom( Context context, File pom, String moduleOffset )
605 throws OutputFileExists, ArchetypeGenerationFailure
606 {
607 getLogger().debug( "Processing pom " + pom );
608
609 processTemplate( pom, context,
610 Constants.ARCHETYPE_RESOURCES + getOffsetSeparator( moduleOffset ) + Constants.ARCHETYPE_POM,
611 getEncoding( null ), true );
612 }
613
614 private void processPomWithMerge( Context context, File pom, String moduleOffset )
615 throws OutputFileExists, IOException, XmlPullParserException, ArchetypeGenerationFailure
616 {
617 getLogger().debug( "Processing pom " + pom + " with merge" );
618
619 File temporaryPom = getTemporaryFile( pom );
620
621 processTemplate( temporaryPom, context,
622 Constants.ARCHETYPE_RESOURCES + getOffsetSeparator( moduleOffset ) + Constants.ARCHETYPE_POM,
623 getEncoding( null ), true );
624
625 pomManager.mergePoms( pom, temporaryPom );
626
627
628
629 try
630 {
631 FileUtils.forceDelete( temporaryPom );
632 }
633 catch ( IOException e )
634 {
635 temporaryPom.deleteOnExit();
636 }
637 }
638
639 private void processPomWithParent( Context context, File pom, String moduleOffset, File basedirPom,
640 String moduleId )
641 throws XmlPullParserException, IOException, ParserConfigurationException, SAXException,
642 TransformerException, OutputFileExists, ArchetypeGenerationFailure, InvalidPackaging
643 {
644 getLogger().debug( "Processing pom " + pom + " with parent " + basedirPom );
645
646 processTemplate( pom, context,
647 Constants.ARCHETYPE_RESOURCES + getOffsetSeparator( moduleOffset ) + Constants.ARCHETYPE_POM,
648 getEncoding( null ), true );
649
650 getLogger().debug( "Adding module " + moduleId );
651
652 pomManager.addModule( basedirPom, moduleId );
653
654 pomManager.addParent( pom, basedirPom );
655 }
656
657 @SuppressWarnings( "deprecation" )
658 private boolean processTemplate( File outFile, Context context, String templateFileName, String encoding,
659 boolean failIfExists )
660 throws OutputFileExists, ArchetypeGenerationFailure
661 {
662 templateFileName = templateFileName.replace( File.separatorChar, '/' );
663
664 String localTemplateFileName = templateFileName.replace( '/', File.separatorChar );
665 if ( !templateFileName.equals( localTemplateFileName ) && !velocity.getEngine().templateExists(
666 templateFileName ) && velocity.getEngine().templateExists( localTemplateFileName ) )
667 {
668 templateFileName = localTemplateFileName;
669 }
670
671 getLogger().debug( "Processing template " + templateFileName );
672
673 if ( outFile.exists() )
674 {
675 if ( failIfExists )
676 {
677 throw new OutputFileExists( "Don't override file " + outFile.getAbsolutePath() );
678 }
679
680 getLogger().warn( "Don't override file " + outFile );
681
682 return false;
683 }
684
685 if ( templateFileName.endsWith( "/" ) )
686 {
687 getLogger().debug( "Creating directory " + outFile );
688
689 outFile.mkdirs();
690
691 return true;
692 }
693
694 if ( !outFile.getParentFile().exists() )
695 {
696 outFile.getParentFile().mkdirs();
697 }
698
699 getLogger().debug( "Merging into " + outFile );
700
701 try ( Writer writer = new OutputStreamWriter( new FileOutputStream( outFile ), encoding ) )
702 {
703 StringWriter stringWriter = new StringWriter();
704
705 velocity.getEngine().mergeTemplate( templateFileName, encoding, context, stringWriter );
706
707 writer.write( StringUtils.unifyLineSeparators( stringWriter.toString() ) );
708
709 writer.flush();
710 }
711 catch ( Exception e )
712 {
713 throw new ArchetypeGenerationFailure( "Error merging velocity templates: " + e.getMessage(), e );
714 }
715
716 return true;
717 }
718
719 private void processTemplates( String packageName, File outputDirectoryFile, Context context,
720 AbstractArchetypeDescriptor archetypeDescriptor, List<String> archetypeResources,
721 ZipFile archetypeZipFile, String moduleOffset, boolean failIfExists )
722 throws OutputFileExists, ArchetypeGenerationFailure, IOException
723 {
724 Iterator<FileSet> iterator = archetypeDescriptor.getFileSets().iterator();
725 if ( iterator.hasNext() )
726 {
727 getLogger().debug( "Processing filesets" + "\n " + archetypeResources );
728 }
729
730 int count = 0;
731 while ( iterator.hasNext() )
732 {
733 FileSet fileSet = iterator.next();
734 count++;
735
736 List<String> fileSetResources =
737 archetypeFilesResolver.filterFiles( moduleOffset, fileSet, archetypeResources );
738
739
740
741 getOutputFile( moduleOffset, fileSet.getDirectory(), outputDirectoryFile, fileSet.isPackaged(), packageName,
742 moduleOffset, context ).mkdirs();
743
744 if ( fileSet.isFiltered() )
745 {
746 getLogger().debug( " Processing fileset " + fileSet + " -> " + fileSetResources.size() + ":\n "
747 + fileSetResources );
748
749 int processed =
750 processFileSet( fileSet.getDirectory(), fileSetResources, fileSet.isPackaged(), packageName,
751 context, outputDirectoryFile, moduleOffset, getEncoding( fileSet.getEncoding() ),
752 failIfExists );
753
754 getLogger().debug( " Processed " + processed + " files." );
755 }
756 else
757 {
758 getLogger().debug( " Copying fileset " + fileSet + " -> " + fileSetResources.size() + ":\n "
759 + fileSetResources );
760
761 int copied = copyFiles( fileSet.getDirectory(), fileSetResources, fileSet.isPackaged(), packageName,
762 outputDirectoryFile, archetypeZipFile, moduleOffset, failIfExists, context );
763
764 getLogger().debug( " Copied " + copied + " files." );
765 }
766 }
767
768 getLogger().debug( "Processed " + count + " filesets" );
769 }
770
771 private void restoreParentArtifactId( Context context, String parentArtifactId )
772 {
773 if ( StringUtils.isEmpty( parentArtifactId ) )
774 {
775 context.remove( Constants.PARENT_ARTIFACT_ID );
776 }
777 else
778 {
779 context.put( Constants.PARENT_ARTIFACT_ID, parentArtifactId );
780 }
781 }
782
783 private File getTemporaryFile( File file )
784 {
785 File tmp = FileUtils.createTempFile( file.getName(), Constants.TMP, file.getParentFile() );
786
787 tmp.deleteOnExit();
788
789 return tmp;
790 }
791 }