1 package org.apache.maven.plugin.resources.remote;
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.ProjectDependenciesResolver;
23 import org.apache.maven.artifact.Artifact;
24 import org.apache.maven.artifact.factory.ArtifactFactory;
25 import org.apache.maven.artifact.repository.ArtifactRepository;
26 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
27 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
28 import org.apache.maven.artifact.versioning.VersionRange;
29 import org.apache.maven.execution.MavenSession;
30 import org.apache.maven.model.Model;
31 import org.apache.maven.model.Organization;
32 import org.apache.maven.model.Resource;
33 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
34 import org.apache.maven.plugin.AbstractMojo;
35 import org.apache.maven.plugin.MojoExecutionException;
36 import org.apache.maven.plugin.logging.Log;
37 import org.apache.maven.plugin.resources.remote.io.xpp3.RemoteResourcesBundleXpp3Reader;
38 import org.apache.maven.plugin.resources.remote.io.xpp3.SupplementalDataModelXpp3Reader;
39 import org.apache.maven.project.InvalidProjectModelException;
40 import org.apache.maven.project.MavenProject;
41 import org.apache.maven.project.MavenProjectBuilder;
42 import org.apache.maven.project.ProjectBuildingException;
43 import org.apache.maven.project.artifact.InvalidDependencyVersionException;
44 import org.apache.maven.project.inheritance.ModelInheritanceAssembler;
45 import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException;
46 import org.apache.maven.shared.artifact.filter.collection.ArtifactIdFilter;
47 import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts;
48 import org.apache.maven.shared.artifact.filter.collection.GroupIdFilter;
49 import org.apache.maven.shared.artifact.filter.collection.ScopeFilter;
50 import org.apache.maven.shared.artifact.filter.collection.TransitivityFilter;
51 import org.apache.maven.shared.downloader.DownloadException;
52 import org.apache.maven.shared.downloader.DownloadNotFoundException;
53 import org.apache.maven.shared.downloader.Downloader;
54 import org.apache.maven.shared.filtering.MavenFileFilter;
55 import org.apache.maven.shared.filtering.MavenFileFilterRequest;
56 import org.apache.maven.shared.filtering.MavenFilteringException;
57 import org.apache.velocity.VelocityContext;
58 import org.apache.velocity.app.Velocity;
59 import org.apache.velocity.exception.MethodInvocationException;
60 import org.apache.velocity.exception.ParseErrorException;
61 import org.apache.velocity.exception.ResourceNotFoundException;
62 import org.codehaus.plexus.resource.ResourceManager;
63 import org.codehaus.plexus.resource.loader.FileResourceLoader;
64 import org.codehaus.plexus.util.FileUtils;
65 import org.codehaus.plexus.util.IOUtil;
66 import org.codehaus.plexus.util.ReaderFactory;
67 import org.codehaus.plexus.util.StringUtils;
68 import org.codehaus.plexus.util.WriterFactory;
69 import org.codehaus.plexus.util.xml.Xpp3Dom;
70 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
71 import org.codehaus.plexus.velocity.VelocityComponent;
72
73 import java.io.File;
74 import java.io.FileInputStream;
75 import java.io.FileOutputStream;
76 import java.io.FileReader;
77 import java.io.FileWriter;
78 import java.io.IOException;
79 import java.io.InputStream;
80 import java.io.InputStreamReader;
81 import java.io.OutputStream;
82 import java.io.OutputStreamWriter;
83 import java.io.PrintWriter;
84 import java.io.Reader;
85 import java.io.StringReader;
86 import java.io.Writer;
87 import java.net.MalformedURLException;
88 import java.net.URL;
89 import java.text.SimpleDateFormat;
90 import java.util.ArrayList;
91 import java.util.Collections;
92 import java.util.Comparator;
93 import java.util.Date;
94 import java.util.Enumeration;
95 import java.util.HashMap;
96 import java.util.LinkedHashSet;
97 import java.util.List;
98 import java.util.Map;
99 import java.util.Set;
100 import java.util.TreeMap;
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126 public class ProcessRemoteResourcesMojo
127 extends AbstractMojo
128 {
129
130 private static final String TEMPLATE_SUFFIX = ".vm";
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154 protected List<String> filterDelimiters;
155
156
157
158
159
160 protected boolean useDefaultFilterDelimiters;
161
162
163
164
165
166
167
168
169 protected boolean runOnlyAtExecutionRoot;
170
171
172
173
174
175
176
177
178 protected File basedir;
179
180
181
182
183
184
185 protected String encoding;
186
187
188
189
190
191
192
193
194 private ArtifactRepository localRepository;
195
196
197
198
199
200
201
202
203 private List<ArtifactRepository> remoteArtifactRepositories;
204
205
206
207
208
209
210
211
212 private MavenProject project;
213
214
215
216
217
218
219 private File outputDirectory;
220
221
222
223
224
225
226 private File appendedResourcesDirectory;
227
228
229
230
231
232
233
234
235
236
237
238 private String[] supplementalModels;
239
240
241
242
243
244
245
246 private List<String> supplementalModelArtifacts;
247
248
249
250
251 private Map<String, Model> supplementModels;
252
253
254
255
256
257
258
259
260
261
262 private ModelInheritanceAssembler inheritanceAssembler;
263
264
265
266
267
268
269
270 private List<String> resourceBundles;
271
272
273
274
275
276
277
278 private boolean skip;
279
280
281
282
283
284
285
286 private boolean attached = true;
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301 private Map<String, String> properties = new HashMap<String, String>();
302
303
304
305
306
307
308
309
310 private List<Resource> resources;
311
312
313
314
315
316
317
318
319 private Downloader downloader;
320
321
322
323
324
325
326
327
328 private VelocityComponent velocity;
329
330
331
332
333
334
335 private MavenFileFilter fileFilter;
336
337
338
339
340
341
342
343
344 private ArtifactFactory artifactFactory;
345
346
347
348
349
350
351
352
353 private MavenSession mavenSession;
354
355
356
357
358
359
360
361
362 private MavenProjectBuilder mavenProjectBuilder;
363
364
365
366
367
368
369 private ResourceManager locator;
370
371
372
373
374
375
376
377
378
379 protected String includeScope;
380
381
382
383
384
385
386
387
388 protected String excludeScope;
389
390
391
392
393
394
395
396
397 protected String excludeArtifactIds;
398
399
400
401
402
403
404
405
406 protected String includeArtifactIds;
407
408
409
410
411
412
413
414
415 protected String excludeGroupIds;
416
417
418
419
420
421
422
423
424 protected String includeGroupIds;
425
426
427
428
429
430
431
432
433 protected boolean excludeTransitive;
434
435
436
437
438 protected ProjectDependenciesResolver dependencyResolver;
439
440 @SuppressWarnings( "unchecked" )
441 public void execute()
442 throws MojoExecutionException
443 {
444 if ( skip )
445 {
446 return;
447 }
448
449 if ( runOnlyAtExecutionRoot && !isExecutionRoot() )
450 {
451 getLog().info( "Skipping remote-resource generation in this project because it's not the Execution Root" );
452 return;
453 }
454
455 if ( supplementalModels == null )
456 {
457 File sups = new File( appendedResourcesDirectory, "supplemental-models.xml" );
458 if ( sups.exists() )
459 {
460 try
461 {
462 supplementalModels = new String[]{sups.toURL().toString()};
463 }
464 catch ( MalformedURLException e )
465 {
466
467 getLog().debug( "URL issue with supplemental-models.xml: " + e.toString() );
468 }
469 }
470 }
471
472 addSupplementalModelArtifacts();
473 locator.addSearchPath( FileResourceLoader.ID, project.getFile().getParentFile().getAbsolutePath() );
474 if ( appendedResourcesDirectory != null )
475 {
476 locator.addSearchPath( FileResourceLoader.ID, appendedResourcesDirectory.getAbsolutePath() );
477 }
478 locator.addSearchPath( "url", "" );
479 locator.setOutputDirectory( new File( project.getBuild().getDirectory() ) );
480
481 ClassLoader origLoader = Thread.currentThread().getContextClassLoader();
482 try
483 {
484 Thread.currentThread().setContextClassLoader( this.getClass().getClassLoader() );
485
486 validate();
487
488 List<File> resourceBundleArtifacts = downloadBundles( resourceBundles );
489 supplementModels = loadSupplements( supplementalModels );
490
491 VelocityContext context = new VelocityContext( properties );
492 configureVelocityContext( context );
493
494 RemoteResourcesClassLoader classLoader
495 = new RemoteResourcesClassLoader( null );
496
497 initalizeClassloader( classLoader, resourceBundleArtifacts );
498 Thread.currentThread().setContextClassLoader( classLoader );
499
500 processResourceBundles( classLoader, context );
501
502 try
503 {
504 if ( outputDirectory.exists() )
505 {
506
507
508
509
510 if ( attached )
511 {
512 Resource resource = new Resource();
513 resource.setDirectory( outputDirectory.getAbsolutePath() );
514
515 project.getResources().add( resource );
516 project.getTestResources().add( resource );
517 }
518
519
520
521
522 File dotFile = new File( project.getBuild().getDirectory(), ".plxarc" );
523 FileUtils.mkdir( dotFile.getParentFile().getAbsolutePath() );
524 FileUtils.fileWrite( dotFile.getAbsolutePath(), outputDirectory.getName() );
525 }
526 }
527 catch ( IOException e )
528 {
529 throw new MojoExecutionException( "Error creating dot file for archiving instructions.", e );
530 }
531 }
532 finally
533 {
534 Thread.currentThread().setContextClassLoader( origLoader );
535 }
536 }
537
538 private boolean isExecutionRoot()
539 {
540 Log log = this.getLog();
541
542 boolean result = mavenSession.getExecutionRootDirectory().equalsIgnoreCase( basedir.toString() );
543
544 if ( log.isDebugEnabled() )
545 {
546 log.debug("Root Folder:" + mavenSession.getExecutionRootDirectory());
547 log.debug("Current Folder:"+ basedir );
548
549 if ( result )
550 {
551 log.debug( "This is the execution root." );
552 }
553 else
554 {
555 log.debug( "This is NOT the execution root." );
556 }
557 }
558
559 return result;
560 }
561
562 private void addSupplementalModelArtifacts() throws MojoExecutionException
563 {
564 if ( supplementalModelArtifacts != null && !supplementalModelArtifacts.isEmpty() )
565 {
566 List<File> artifacts = downloadBundles( supplementalModelArtifacts );
567
568 for ( File artifact : artifacts )
569 {
570 if ( artifact.isDirectory() )
571 {
572 locator.addSearchPath( FileResourceLoader.ID, artifact.getAbsolutePath() );
573 }
574 else
575 {
576 try
577 {
578 locator.addSearchPath( "jar", "jar:" + artifact.toURL().toExternalForm() );
579 }
580 catch (MalformedURLException e)
581 {
582 throw new MojoExecutionException( "Could not use jar "
583 + artifact.getAbsolutePath(), e );
584 }
585 }
586 }
587
588
589 }
590 }
591
592 @SuppressWarnings( "unchecked" )
593 protected List<MavenProject> getProjects()
594 throws MojoExecutionException
595 {
596 List<MavenProject> projects = new ArrayList<MavenProject>();
597
598
599 FilterArtifacts filter = new FilterArtifacts();
600
601 Set<Artifact> depArtifacts;
602 Set<Artifact> artifacts = resolveProjectArtifacts();
603 if ( runOnlyAtExecutionRoot )
604 {
605 depArtifacts = aggregateProjectDependencyArtifacts();
606 }
607 else
608 {
609 depArtifacts = project.getDependencyArtifacts();
610 }
611
612 filter.addFilter( new TransitivityFilter( depArtifacts, this.excludeTransitive ) );
613 filter.addFilter( new ScopeFilter( this.includeScope, this.excludeScope ) );
614 filter.addFilter( new GroupIdFilter( this.includeGroupIds, this.excludeGroupIds ) );
615 filter.addFilter( new ArtifactIdFilter( this.includeArtifactIds, this.excludeArtifactIds ) );
616
617
618 try
619 {
620 artifacts = filter.filter( artifacts );
621 }
622 catch ( ArtifactFilterException e )
623 {
624 throw new MojoExecutionException(e.getMessage(),e);
625 }
626
627
628 for ( Artifact artifact : artifacts )
629 {
630 try
631 {
632 List<ArtifactRepository> remoteRepo = remoteArtifactRepositories;
633 if ( artifact.isSnapshot() )
634 {
635 VersionRange rng = VersionRange.createFromVersion( artifact.getBaseVersion() );
636 artifact = artifactFactory.createDependencyArtifact( artifact.getGroupId(),
637 artifact.getArtifactId(), rng,
638 artifact.getType(), artifact.getClassifier(),
639 artifact.getScope(), null,
640 artifact.isOptional() );
641 }
642
643 getLog().debug( "Building project for " + artifact );
644 MavenProject p = null;
645 try
646 {
647 p = mavenProjectBuilder.buildFromRepository( artifact, remoteRepo, localRepository );
648 }
649 catch ( InvalidProjectModelException e )
650 {
651 getLog().warn( "Invalid project model for artifact [" + artifact.getArtifactId() + ":" +
652 artifact.getGroupId() + ":" + artifact.getVersion() + "]. " +
653 "It will be ignored by the remote resources Mojo." );
654 continue;
655 }
656
657 String supplementKey =
658 generateSupplementMapKey( p.getModel().getGroupId(), p.getModel().getArtifactId() );
659
660 if ( supplementModels.containsKey( supplementKey ) )
661 {
662 Model mergedModel = mergeModels( p.getModel(), (Model) supplementModels.get( supplementKey ) );
663 MavenProject mergedProject = new MavenProject( mergedModel );
664 projects.add( mergedProject );
665 mergedProject.setArtifact( artifact );
666 mergedProject.setVersion( artifact.getVersion() );
667 getLog().debug( "Adding project with groupId [" + mergedProject.getGroupId() + "] (supplemented)" );
668 }
669 else
670 {
671 projects.add( p );
672 getLog().debug( "Adding project with groupId [" + p.getGroupId() + "]" );
673 }
674 }
675 catch ( ProjectBuildingException e )
676 {
677 throw new MojoExecutionException( e.getMessage(), e );
678 }
679 }
680 Collections.sort( projects, new ProjectComparator() );
681 return projects;
682 }
683
684 @SuppressWarnings( "unchecked" )
685 private Set<Artifact> resolveProjectArtifacts()
686 throws MojoExecutionException
687 {
688 try
689 {
690 if ( runOnlyAtExecutionRoot )
691 {
692 List<MavenProject> projects = mavenSession.getSortedProjects();
693 return dependencyResolver.resolve( projects, Collections.singleton( Artifact.SCOPE_TEST ), mavenSession );
694 }
695 else
696 {
697 return dependencyResolver.resolve( project, Collections.singleton( Artifact.SCOPE_TEST ), mavenSession );
698 }
699 }
700 catch ( ArtifactResolutionException e )
701 {
702 throw new MojoExecutionException( "Failed to resolve dependencies for one or more projects in the reactor. Reason: "
703 + e.getMessage(), e );
704 }
705 catch ( ArtifactNotFoundException e )
706 {
707 throw new MojoExecutionException( "Failed to resolve dependencies for one or more projects in the reactor. Reason: "
708 + e.getMessage(), e );
709 }
710 }
711
712 @SuppressWarnings( "unchecked" )
713 private Set<Artifact> aggregateProjectDependencyArtifacts()
714 throws MojoExecutionException
715 {
716 Set<Artifact> artifacts = new LinkedHashSet<Artifact>();
717
718 List<MavenProject> projects = mavenSession.getSortedProjects();
719 for ( MavenProject p : projects )
720 {
721 if ( p.getDependencyArtifacts() == null )
722 {
723 try
724 {
725 Set<Artifact> depArtifacts = p.createArtifacts( artifactFactory, null, null );
726 p.setDependencyArtifacts( depArtifacts );
727
728 if ( depArtifacts != null && !depArtifacts.isEmpty() )
729 {
730 artifacts.addAll( depArtifacts );
731 }
732 }
733 catch ( InvalidDependencyVersionException e )
734 {
735 throw new MojoExecutionException( "Failed to create dependency artifacts for: " + p.getId() + ". Reason: "
736 + e.getMessage(), e );
737 }
738 }
739 }
740
741 return artifacts;
742 }
743
744 protected Map<Organization, List<MavenProject>> getProjectsSortedByOrganization( List<MavenProject> projects )
745 throws MojoExecutionException
746 {
747 Map<Organization, List<MavenProject>> organizations = new TreeMap<Organization, List<MavenProject>>( new OrganizationComparator() );
748 List<MavenProject> unknownOrganization = new ArrayList<MavenProject>();
749
750 for ( MavenProject p : projects )
751 {
752 if ( p.getOrganization() != null && StringUtils.isNotEmpty( p.getOrganization().getName() ) )
753 {
754 List<MavenProject> sortedProjects = (List<MavenProject>) organizations.get( p.getOrganization() );
755 if ( sortedProjects == null )
756 {
757 sortedProjects = new ArrayList<MavenProject>();
758 }
759 sortedProjects.add( p );
760
761 organizations.put( p.getOrganization(), sortedProjects );
762 }
763 else
764 {
765 unknownOrganization.add( p );
766 }
767 }
768 if ( !unknownOrganization.isEmpty() )
769 {
770 Organization unknownOrg = new Organization();
771 unknownOrg.setName( "an unknown organization" );
772 organizations.put( unknownOrg, unknownOrganization );
773 }
774
775 return organizations;
776 }
777
778 protected boolean copyResourceIfExists( File file, String relFileName, VelocityContext context )
779 throws IOException, MojoExecutionException
780 {
781 for ( Resource resource : resources )
782 {
783 File resourceDirectory = new File( resource.getDirectory() );
784
785 if ( !resourceDirectory.exists() )
786 {
787 continue;
788 }
789
790
791 File source = new File( resourceDirectory, relFileName );
792 File templateSource = new File( resourceDirectory, relFileName + TEMPLATE_SUFFIX );
793
794 if ( !source.exists() && templateSource.exists() )
795 {
796 source = templateSource;
797 }
798
799 if ( source.exists() && !source.equals( file ) )
800 {
801 if ( source == templateSource )
802 {
803 Reader reader = null;
804 Writer writer = null;
805 try
806 {
807 if ( encoding != null )
808 {
809 reader = new InputStreamReader( new FileInputStream( source ), encoding );
810 writer = new OutputStreamWriter( new FileOutputStream( file ), encoding );
811 }
812 else
813 {
814 reader = ReaderFactory.newPlatformReader( source );
815 writer = WriterFactory.newPlatformWriter( file );
816 }
817
818 velocity.getEngine().evaluate( context, writer, "", reader );
819 velocity.getEngine().evaluate( context, writer, "", reader );
820 }
821 catch ( ParseErrorException e )
822 {
823 throw new MojoExecutionException( "Error rendering velocity resource.", e );
824 }
825 catch ( MethodInvocationException e )
826 {
827 throw new MojoExecutionException( "Error rendering velocity resource.", e );
828 }
829 catch ( ResourceNotFoundException e )
830 {
831 throw new MojoExecutionException( "Error rendering velocity resource.", e );
832 }
833 finally
834 {
835 IOUtil.close( writer );
836 IOUtil.close( reader );
837 }
838 }
839 else if ( resource.isFiltering() )
840 {
841
842 MavenFileFilterRequest req = setupRequest( resource, source, file );
843
844 try
845 {
846 fileFilter.copyFile( req );
847 }
848 catch ( MavenFilteringException e )
849 {
850 throw new MojoExecutionException( "Error filtering resource: " + source, e );
851 }
852 }
853 else
854 {
855 FileUtils.copyFile( source, file );
856 }
857
858
859 resource.addExclude( relFileName );
860
861 return true;
862 }
863
864 }
865 return false;
866 }
867
868 @SuppressWarnings( "unchecked" )
869 private MavenFileFilterRequest setupRequest( Resource resource, File source, File file )
870 {
871 MavenFileFilterRequest req = new MavenFileFilterRequest();
872 req.setFrom( source );
873 req.setTo( file );
874 req.setFiltering( resource.isFiltering() );
875
876 req.setMavenProject( project );
877 req.setMavenSession( mavenSession );
878 req.setInjectProjectBuildFilters( true );
879
880 if ( encoding != null )
881 {
882 req.setEncoding( encoding );
883 }
884
885 if ( filterDelimiters != null && !filterDelimiters.isEmpty() )
886 {
887 LinkedHashSet<String> delims = new LinkedHashSet<String>();
888 if ( useDefaultFilterDelimiters )
889 {
890 delims.addAll( req.getDelimiters() );
891 }
892
893 for ( String delim : filterDelimiters )
894 {
895 if ( delim == null )
896 {
897 delims.add( "${*}" );
898 }
899 else
900 {
901 delims.add( delim );
902 }
903 }
904
905 req.setDelimiters( delims );
906 }
907
908 return req;
909 }
910
911 protected void validate()
912 throws MojoExecutionException
913 {
914 int bundleCount = 1;
915
916 for ( String artifactDescriptor : resourceBundles )
917 {
918
919 String[] s = StringUtils.split( artifactDescriptor, ":" );
920
921 if ( s.length != 3 )
922 {
923 String position;
924
925 if ( bundleCount == 1 )
926 {
927 position = "1st";
928 }
929 else if ( bundleCount == 2 )
930 {
931 position = "2nd";
932 }
933 else if ( bundleCount == 3 )
934 {
935 position = "3rd";
936 }
937 else
938 {
939 position = bundleCount + "th";
940 }
941
942 throw new MojoExecutionException( "The " + position +
943 " resource bundle configured must specify a groupId, artifactId, and" +
944 " version for a remote resource bundle. " +
945 "Must be of the form <resourceBundle>groupId:artifactId:version</resourceBundle>" );
946 }
947
948 bundleCount++;
949 }
950
951 }
952
953 protected void configureVelocityContext( VelocityContext context )
954 throws MojoExecutionException
955 {
956 String inceptionYear = project.getInceptionYear();
957 String year = new SimpleDateFormat( "yyyy" ).format( new Date() );
958
959 if ( StringUtils.isEmpty( inceptionYear ) )
960 {
961 if ( getLog().isDebugEnabled() )
962 {
963 getLog().debug( "inceptionYear not specified, defaulting to " + year );
964 }
965
966 inceptionYear = year;
967 }
968 context.put( "project", project );
969 List<MavenProject> projects = getProjects();
970 context.put( "projects", projects );
971 context.put( "projectsSortedByOrganization", getProjectsSortedByOrganization( projects ) );
972
973 context.put( "presentYear", year );
974
975 if ( inceptionYear.equals( year ) )
976 {
977 context.put( "projectTimespan", year );
978 }
979 else
980 {
981 context.put( "projectTimespan", inceptionYear + "-" + year );
982 }
983 }
984
985 @SuppressWarnings( "unchecked" )
986 private List<File> downloadBundles( List<String> bundles )
987 throws MojoExecutionException
988 {
989 List<File> bundleArtifacts = new ArrayList<File>();
990
991 try
992 {
993 for ( String artifactDescriptor : bundles )
994 {
995
996 String[] s = artifactDescriptor.split( ":" );
997 File artifact = null;
998
999 if ( mavenSession != null )
1000 {
1001 List<MavenProject> list = mavenSession.getSortedProjects();
1002 for ( MavenProject p : list )
1003 {
1004 if ( s[0].equals( p.getGroupId() )
1005 && s[1].equals( p.getArtifactId() )
1006 && s[2].equals( p.getVersion() ) )
1007 {
1008 artifact = new File( p.getBuild().getOutputDirectory() );
1009 }
1010 }
1011 }
1012 if ( artifact == null || !artifact.exists() )
1013 {
1014 artifact = downloader.download( s[0], s[1], s[2], localRepository, remoteArtifactRepositories );
1015 }
1016
1017 bundleArtifacts.add( artifact );
1018 }
1019 }
1020 catch ( DownloadException e )
1021 {
1022 throw new MojoExecutionException( "Error downloading resources JAR.", e );
1023 }
1024 catch ( DownloadNotFoundException e )
1025 {
1026 throw new MojoExecutionException( "Resources JAR cannot be found.", e );
1027 }
1028
1029 return bundleArtifacts;
1030 }
1031
1032 private void initalizeClassloader( RemoteResourcesClassLoader cl, List<File> artifacts )
1033 throws MojoExecutionException
1034 {
1035 try
1036 {
1037 for ( File artifact : artifacts )
1038 {
1039 cl.addURL( artifact.toURI().toURL() );
1040 }
1041 }
1042 catch ( MalformedURLException e )
1043 {
1044 throw new MojoExecutionException( "Unable to configure resources classloader: " + e.getMessage(), e );
1045 }
1046 }
1047
1048 protected void processResourceBundles( RemoteResourcesClassLoader classLoader, VelocityContext context )
1049 throws MojoExecutionException
1050 {
1051 InputStreamReader reader = null;
1052
1053 try
1054 {
1055
1056 for ( Enumeration<URL> e = classLoader.getResources( BundleRemoteResourcesMojo.RESOURCES_MANIFEST );
1057 e.hasMoreElements(); )
1058 {
1059 URL url = (URL) e.nextElement();
1060
1061 try
1062 {
1063 reader = new InputStreamReader( url.openStream() );
1064
1065 RemoteResourcesBundleXpp3Reader bundleReader = new RemoteResourcesBundleXpp3Reader();
1066
1067 RemoteResourcesBundle bundle = bundleReader.read( reader );
1068
1069 for ( String bundleResource : (List<String>) bundle.getRemoteResources() )
1070 {
1071 String projectResource = bundleResource;
1072
1073 boolean doVelocity = false;
1074 if ( projectResource.endsWith( TEMPLATE_SUFFIX ) )
1075 {
1076 projectResource = projectResource.substring( 0, projectResource.length() - 3 );
1077 doVelocity = true;
1078 }
1079
1080
1081
1082 File f = new File( outputDirectory, projectResource );
1083
1084 FileUtils.mkdir( f.getParentFile().getAbsolutePath() );
1085
1086 if ( !copyResourceIfExists( f, projectResource, context ) )
1087 {
1088 if ( doVelocity )
1089 {
1090 PrintWriter writer;
1091 if ( bundle.getSourceEncoding() == null )
1092 {
1093 writer = new PrintWriter( new FileWriter( f ) );
1094 }
1095 else
1096 {
1097 writer = new PrintWriter( new OutputStreamWriter( new FileOutputStream( f ),
1098 bundle.getSourceEncoding() ) );
1099
1100 }
1101
1102 try
1103 {
1104 if ( bundle.getSourceEncoding() == null )
1105 {
1106 velocity.getEngine().mergeTemplate( bundleResource, context, writer );
1107 }
1108 else
1109 {
1110 velocity.getEngine().mergeTemplate( bundleResource, bundle.getSourceEncoding(),
1111 context, writer );
1112
1113 }
1114 }
1115 finally
1116 {
1117 IOUtil.close(writer);
1118 }
1119 }
1120 else
1121 {
1122 URL resUrl = classLoader.getResource( bundleResource );
1123 if ( resUrl != null )
1124 {
1125 FileUtils.copyURLToFile( resUrl, f );
1126 }
1127 }
1128 File appendedResourceFile = new File( appendedResourcesDirectory, projectResource );
1129 File appendedVmResourceFile = new File( appendedResourcesDirectory,
1130 projectResource + ".vm" );
1131 if ( appendedResourceFile.exists() )
1132 {
1133 final InputStream in = new FileInputStream( appendedResourceFile );
1134 final OutputStream append = new FileOutputStream( f, true );
1135
1136 try
1137 {
1138 IOUtil.copy( in, append );
1139 }
1140 finally
1141 {
1142 IOUtil.close( in );
1143 IOUtil.close( append );
1144 }
1145 }
1146 else if ( appendedVmResourceFile.exists() )
1147 {
1148 PrintWriter writer;
1149 FileReader freader = new FileReader( appendedVmResourceFile );
1150
1151 if ( bundle.getSourceEncoding() == null )
1152 {
1153 writer = new PrintWriter( new FileWriter( f, true ) );
1154 }
1155 else
1156 {
1157 writer = new PrintWriter( new OutputStreamWriter( new FileOutputStream( f, true ),
1158 bundle.getSourceEncoding() ) );
1159
1160 }
1161
1162 try
1163 {
1164 Velocity.init();
1165 Velocity.evaluate( context, writer, "remote-resources", freader );
1166 }
1167 finally
1168 {
1169 IOUtil.close(writer);
1170 IOUtil.close(freader);
1171 }
1172 }
1173
1174 }
1175 }
1176 }
1177 finally
1178 {
1179 reader.close();
1180 }
1181 }
1182 }
1183 catch ( IOException e )
1184 {
1185 throw new MojoExecutionException( "Error finding remote resources manifests", e );
1186 }
1187 catch ( XmlPullParserException e )
1188 {
1189 throw new MojoExecutionException( "Error parsing remote resource bundle descriptor.", e );
1190 }
1191 catch ( Exception e )
1192 {
1193 throw new MojoExecutionException( "Error rendering velocity resource.", e );
1194 }
1195 }
1196
1197 protected Model getSupplement( Xpp3Dom supplementModelXml )
1198 throws MojoExecutionException
1199 {
1200 MavenXpp3Reader modelReader = new MavenXpp3Reader();
1201 Model model = null;
1202
1203 try
1204 {
1205 model = modelReader.read( new StringReader( supplementModelXml.toString() ) );
1206 String groupId = model.getGroupId();
1207 String artifactId = model.getArtifactId();
1208
1209 if ( groupId == null || groupId.trim().equals( "" ) )
1210 {
1211 throw new MojoExecutionException(
1212 "Supplemental project XML " + "requires that a <groupId> element be present." );
1213 }
1214
1215 if ( artifactId == null || artifactId.trim().equals( "" ) )
1216 {
1217 throw new MojoExecutionException(
1218 "Supplemental project XML " + "requires that a <artifactId> element be present." );
1219 }
1220 }
1221 catch ( IOException e )
1222 {
1223 getLog().warn( "Unable to read supplemental XML: " + e.getMessage(), e );
1224 }
1225 catch ( XmlPullParserException e )
1226 {
1227 getLog().warn( "Unable to parse supplemental XML: " + e.getMessage(), e );
1228 }
1229
1230 return model;
1231 }
1232
1233 protected Model mergeModels( Model parent, Model child )
1234 {
1235 inheritanceAssembler.assembleModelInheritance( child, parent );
1236 return child;
1237 }
1238
1239 private static String generateSupplementMapKey( String groupId, String artifactId )
1240 {
1241 return groupId.trim() + ":" + artifactId.trim();
1242 }
1243
1244 private Map<String, Model> loadSupplements( String models[] )
1245 throws MojoExecutionException
1246 {
1247 if ( models == null )
1248 {
1249 getLog().debug( "Supplemental data models won't be loaded. " + "No models specified." );
1250 return Collections.emptyMap();
1251 }
1252
1253 List<Supplement> supplements = new ArrayList<Supplement>();
1254 for ( int idx = 0; idx < models.length; idx++ )
1255 {
1256 String set = models[idx];
1257 getLog().debug( "Preparing ruleset: " + set );
1258 try
1259 {
1260 File f = locator.getResourceAsFile( set, getLocationTemp( set ) );
1261
1262 if ( null == f || !f.exists() )
1263 {
1264 throw new MojoExecutionException( "Cold not resolve " + set );
1265 }
1266 if ( !f.canRead() )
1267 {
1268 throw new MojoExecutionException( "Supplemental data models won't be loaded. " + "File " +
1269 f.getAbsolutePath() + " cannot be read, check permissions on the file." );
1270 }
1271
1272 getLog().debug( "Loading supplemental models from " + f.getAbsolutePath() );
1273
1274 SupplementalDataModelXpp3Reader reader = new SupplementalDataModelXpp3Reader();
1275 SupplementalDataModel supplementalModel = reader.read( new FileReader( f ) );
1276 supplements.addAll( supplementalModel.getSupplement() );
1277 }
1278 catch ( Exception e )
1279 {
1280 String msg = "Error loading supplemental data models: " + e.getMessage();
1281 getLog().error( msg, e );
1282 throw new MojoExecutionException( msg, e );
1283 }
1284 }
1285
1286 getLog().debug( "Loading supplements complete." );
1287
1288 Map<String, Model> supplementMap = new HashMap<String, Model>();
1289 for ( Supplement sd : supplements )
1290 {
1291 Xpp3Dom dom = (Xpp3Dom) sd.getProject();
1292
1293 Model m = getSupplement( dom );
1294 supplementMap.put( generateSupplementMapKey( m.getGroupId(), m.getArtifactId() ), m );
1295 }
1296
1297 return supplementMap;
1298 }
1299
1300
1301
1302
1303
1304
1305
1306 private String getLocationTemp( String name )
1307 {
1308 String loc = name;
1309 if ( loc.indexOf( '/' ) != -1 )
1310 {
1311 loc = loc.substring( loc.lastIndexOf( '/' ) + 1 );
1312 }
1313 if ( loc.indexOf( '\\' ) != -1 )
1314 {
1315 loc = loc.substring( loc.lastIndexOf( '\\' ) + 1 );
1316 }
1317 getLog().debug( "Before: " + name + " After: " + loc );
1318 return loc;
1319 }
1320
1321 class OrganizationComparator
1322 implements Comparator<Organization>
1323 {
1324 public int compare( Organization org1, Organization org2 )
1325 {
1326 int i = compareStrings( org1.getName(), org2.getName() );
1327 if (i == 0)
1328 {
1329 i = compareStrings( org1.getUrl(), org2.getUrl() );
1330 }
1331 return i;
1332 }
1333
1334 public boolean equals( Organization o1, Organization o2 )
1335 {
1336 return compare(o1, o2) == 0;
1337 }
1338
1339 private int compareStrings( String s1, String s2 ) {
1340 if ( s1 == null && s2 == null )
1341 {
1342 return 0;
1343 }
1344 else if ( s1 == null && s2 != null )
1345 {
1346 return 1;
1347 }
1348 else if ( s1 != null && s2 == null )
1349 {
1350 return -1;
1351 }
1352
1353 return s1.compareToIgnoreCase( s2 );
1354 }
1355 }
1356
1357 class ProjectComparator
1358 implements Comparator<MavenProject>
1359 {
1360 @SuppressWarnings( "unchecked" )
1361 public int compare( MavenProject p1, MavenProject p2 )
1362 {
1363 return p1.getArtifact().compareTo( p2.getArtifact() );
1364 }
1365
1366 public boolean equals( MavenProject p1, MavenProject p2 )
1367 {
1368 return p1.getArtifact().equals( p2.getArtifact() );
1369 }
1370 }
1371
1372 }