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