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