1 package org.apache.maven.archetype.mojos;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.BufferedReader;
23 import java.io.File;
24 import java.io.FileInputStream;
25 import java.io.FileReader;
26 import java.io.FileWriter;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.Reader;
30 import java.io.StringWriter;
31 import java.io.Writer;
32 import java.util.Arrays;
33 import java.util.Collection;
34 import java.util.HashMap;
35 import java.util.LinkedHashMap;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Objects;
39 import java.util.Properties;
40 import java.util.Set;
41
42 import org.apache.commons.collections.CollectionUtils;
43 import org.apache.maven.archetype.ArchetypeGenerationRequest;
44 import org.apache.maven.archetype.ArchetypeGenerationResult;
45 import org.apache.maven.archetype.common.Constants;
46 import org.apache.maven.archetype.exception.ArchetypeNotConfigured;
47 import org.apache.maven.archetype.generator.ArchetypeGenerator;
48 import org.apache.maven.artifact.repository.ArtifactRepository;
49 import org.apache.maven.execution.MavenSession;
50 import org.apache.maven.plugin.AbstractMojo;
51 import org.apache.maven.plugin.MojoExecutionException;
52 import org.apache.maven.plugin.MojoFailureException;
53 import org.apache.maven.plugins.annotations.Component;
54 import org.apache.maven.plugins.annotations.Mojo;
55 import org.apache.maven.plugins.annotations.Parameter;
56 import org.apache.maven.project.DefaultProjectBuildingRequest;
57 import org.apache.maven.project.MavenProject;
58 import org.apache.maven.project.ProjectBuildingRequest;
59 import org.apache.maven.settings.Settings;
60 import org.apache.maven.settings.io.xpp3.SettingsXpp3Writer;
61 import org.apache.maven.shared.transfer.artifact.DefaultArtifactCoordinate;
62 import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResolver;
63 import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResolverException;
64 import org.apache.maven.shared.invoker.DefaultInvocationRequest;
65 import org.apache.maven.shared.invoker.InvocationRequest;
66 import org.apache.maven.shared.invoker.InvocationResult;
67 import org.apache.maven.shared.invoker.Invoker;
68 import org.apache.maven.shared.invoker.MavenInvocationException;
69 import org.apache.maven.shared.scriptinterpreter.RunFailureException;
70 import org.apache.maven.shared.scriptinterpreter.ScriptRunner;
71 import org.codehaus.plexus.util.FileUtils;
72 import org.codehaus.plexus.util.IOUtil;
73 import org.codehaus.plexus.util.InterpolationFilterReader;
74 import org.codehaus.plexus.util.ReaderFactory;
75 import org.codehaus.plexus.util.StringUtils;
76 import org.codehaus.plexus.util.WriterFactory;
77 import org.codehaus.plexus.util.introspection.ReflectionValueExtractor;
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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
127
128
129
130
131
132
133
134
135
136 @Mojo( name = "integration-test", requiresProject = true )
137 public class IntegrationTestMojo
138 extends AbstractMojo
139 {
140
141 @Component
142 private ArchetypeGenerator archetypeGenerator;
143
144 @Component
145 private Invoker invoker;
146
147 @Component
148 private ArtifactResolver artifactResolver;
149
150 @Parameter( defaultValue = "${project.remoteArtifactRepositories}", readonly = true, required = true )
151 protected List<ArtifactRepository> remoteRepositories;
152
153 @Parameter( defaultValue = "${localRepository}", readonly = true, required = true )
154 protected ArtifactRepository localRepository;
155
156
157
158
159 @Parameter( defaultValue = "${project}", readonly = true, required = true )
160 private MavenProject project;
161
162 @Parameter( defaultValue = "${session}", readonly = true, required = true )
163 private MavenSession session;
164
165
166
167
168 @Parameter( property = "archetype.test.skip" )
169 private boolean skip = false;
170
171
172
173
174
175
176 @Parameter( property = "archetype.test.projectsDirectory", defaultValue = "${project.build.testOutputDirectory}/projects", required = true )
177 private File testProjectsDirectory;
178
179
180
181
182
183
184
185
186
187
188 @Parameter( property = "archetype.test.verifyScript", defaultValue = "verify" )
189 private String postBuildHookScript;
190
191
192
193
194
195
196 @Parameter( property = "archetype.test.noLog", defaultValue = "false" )
197 private boolean noLog;
198
199
200
201
202
203
204 @Parameter( property = "archetype.test.streamLogs", defaultValue = "true" )
205 private boolean streamLogs;
206
207
208
209
210
211
212 @Parameter( property = "encoding", defaultValue = "${project.build.sourceEncoding}" )
213 private String encoding;
214
215
216
217
218
219
220 @Parameter( property = "archetype.test.localRepositoryPath", defaultValue = "${settings.localRepository}", required = true )
221 private File localRepositoryPath;
222
223
224
225
226
227
228 @Parameter( property = "archetype.test.showVersion", defaultValue = "false" )
229 private boolean showVersion;
230
231
232
233
234
235
236 @Parameter( property = "archetype.test.ignoreEOLStyle", defaultValue = "false" )
237 private boolean ignoreEOLStyle;
238
239
240
241
242
243
244 @Parameter( property = "archetype.test.debug", defaultValue = "false" )
245 private boolean debug;
246
247
248
249
250
251
252 @Parameter
253 private Map<String, String> filterProperties;
254
255
256
257
258
259
260 @Parameter( defaultValue = "${settings}", required = true, readonly = true )
261 private Settings settings;
262
263
264
265
266
267
268
269
270 @Parameter( property = "archetype.test.settingsFile" )
271 private File settingsFile;
272
273
274
275
276
277
278 @Parameter
279 private Map<String, String> properties = new HashMap<>();
280
281 @Override
282 public void execute()
283 throws MojoExecutionException, MojoFailureException
284 {
285 if ( skip )
286 {
287 return;
288 }
289
290 if ( !testProjectsDirectory.exists() )
291 {
292 getLog().warn( "No Archetype IT projects: root 'projects' directory not found." );
293
294 return;
295 }
296
297 File archetypeFile = project.getArtifact().getFile();
298
299 if ( archetypeFile == null )
300 {
301 throw new MojoFailureException( "Unable to get the archetypes' artifact which should have just been built:"
302 + " you probably launched 'mvn archetype:integration-test' instead of"
303 + " 'mvn integration-test'." );
304 }
305
306 try
307 {
308 List<File> projectsGoalFiles = FileUtils.getFiles( testProjectsDirectory, "**/goal.txt", "" );
309
310 if ( projectsGoalFiles.size() == 0 )
311 {
312 getLog().warn( "No Archetype IT projects: no directory with goal.txt found." );
313
314 return;
315 }
316
317 StringWriter errorWriter = new StringWriter();
318 for ( File goalFile : projectsGoalFiles )
319 {
320 try
321 {
322 processIntegrationTest( goalFile, archetypeFile );
323 }
324 catch ( IntegrationTestFailure ex )
325 {
326 errorWriter.write( "\nArchetype IT '" + goalFile.getParentFile().getName() + "' failed: " );
327 errorWriter.write( ex.getMessage() );
328 }
329 }
330
331 String errors = errorWriter.toString();
332 if ( !StringUtils.isEmpty( errors ) )
333 {
334 throw new MojoExecutionException( errors );
335 }
336 }
337 catch ( IOException ex )
338 {
339 throw new MojoFailureException( ex, ex.getMessage(), ex.getMessage() );
340 }
341 }
342
343
344
345
346
347
348
349
350 private void assertDirectoryEquals( File reference, File actual )
351 throws IntegrationTestFailure, IOException
352 {
353 List<String> referenceFiles =
354 FileUtils.getFileAndDirectoryNames( reference, "**", null, false, true, true, true );
355 getLog().debug( "reference content: " + referenceFiles );
356
357 List<String> actualFiles = FileUtils.getFileAndDirectoryNames( actual, "**", null, false, true, true, true );
358 getLog().debug( "actual content: " + referenceFiles );
359
360 boolean fileNamesEquals = CollectionUtils.isEqualCollection( referenceFiles, actualFiles );
361
362 if ( !fileNamesEquals )
363 {
364 getLog().debug( "Actual list of files is not the same as reference:" );
365 int missing = 0;
366 for ( String ref : referenceFiles )
367 {
368 if ( actualFiles.contains( ref ) )
369 {
370 actualFiles.remove( ref );
371 getLog().debug( "Contained " + ref );
372 }
373 else
374 {
375 missing++;
376 getLog().error( "Not contained " + ref );
377 }
378 }
379 getLog().error( "Remains " + actualFiles );
380
381 throw new IntegrationTestFailure(
382 "Reference and generated project differs (missing: " + missing + ", unexpected: " + actualFiles.size()
383 + ")" );
384 }
385
386 boolean contentEquals = true;
387
388 for ( String file : referenceFiles )
389 {
390 File referenceFile = new File( reference, file );
391 File actualFile = new File( actual, file );
392
393 if ( referenceFile.isDirectory() )
394 {
395 if ( actualFile.isFile() )
396 {
397 getLog().warn( "File " + file + " is a directory in the reference but a file in actual" );
398 contentEquals = false;
399 }
400 }
401 else if ( actualFile.isDirectory() )
402 {
403 if ( referenceFile.isFile() )
404 {
405 getLog().warn( "File " + file + " is a file in the reference but a directory in actual" );
406 contentEquals = false;
407 }
408 }
409 else if ( !contentEquals( referenceFile, actualFile ) )
410 {
411 getLog().warn( "Contents of file " + file + " are not equal" );
412 contentEquals = false;
413 }
414 }
415 if ( !contentEquals )
416 {
417 throw new IntegrationTestFailure( "Some content are not equals" );
418 }
419 }
420
421
422
423
424
425 private boolean contentEquals( File referenceFile, File actualFile )
426 throws IOException
427 {
428
429 if ( !ignoreEOLStyle )
430 {
431 getLog().warn( "Property ignoreEOLStyle was not set - files will be compared considering their EOL style!" );
432 return FileUtils.contentEquals( referenceFile, actualFile );
433 }
434
435 getLog().debug( "Comparing files with EOL style ignored." );
436
437 try ( BufferedReader referenceFileReader = new BufferedReader( new FileReader( referenceFile ) );
438 BufferedReader actualFileReader = new BufferedReader( new FileReader( actualFile ) ) )
439 {
440 String refLine = null;
441 String actualLine = null;
442
443 do
444 {
445 refLine = referenceFileReader.readLine();
446 actualLine = actualFileReader.readLine();
447 if ( !Objects.equals( refLine, actualLine ) )
448 {
449 return false;
450 }
451 }
452 while ( refLine != null || actualLine != null );
453
454 return true;
455 }
456 }
457
458 private Properties loadProperties( final File propertiesFile )
459 throws IOException
460 {
461 Properties properties = new Properties();
462
463 try ( InputStream in = new FileInputStream( propertiesFile ) )
464 {
465 properties.load( in );
466 }
467
468 return properties;
469 }
470
471 private void processIntegrationTest( File goalFile, File archetypeFile )
472 throws IntegrationTestFailure, MojoExecutionException
473 {
474 getLog().info( "Processing Archetype IT project: " + goalFile.getParentFile().getName() );
475
476 try
477 {
478 Properties properties = getProperties( goalFile );
479
480 File basedir = new File( goalFile.getParentFile(), "project" );
481
482 FileUtils.deleteDirectory( basedir );
483
484 FileUtils.mkdir( basedir.toString() );
485
486 basedir = setupParentProjects( goalFile.getParentFile().getParentFile(), basedir );
487
488 ArchetypeGenerationRequest request = generate( project.getGroupId(), project.getArtifactId(), project.getVersion(), archetypeFile, properties, basedir.toString() );
489
490 File reference = new File( goalFile.getParentFile(), "reference" );
491
492 if ( reference.exists() )
493 {
494
495 getLog().info( "Comparing generated project with reference content: " + reference );
496
497 assertDirectoryEquals( reference, new File( basedir, request.getArtifactId() ) );
498 }
499
500 String goals = FileUtils.fileRead( goalFile );
501
502 if ( StringUtils.isNotEmpty( goals ) )
503 {
504 invokePostArchetypeGenerationGoals( goals.trim(), new File( basedir, request.getArtifactId() ),
505 goalFile );
506 }
507 }
508 catch ( IOException ioe )
509 {
510 throw new IntegrationTestFailure( ioe );
511 }
512 }
513
514 private ArchetypeGenerationRequest generate( String archetypeGroupId, String archetypeArtifactId, String archetypeVersion, File archetypeFile, Properties properties, String basedir ) throws IntegrationTestFailure
515 {
516
517 ArchetypeGenerationRequest request =
518 new ArchetypeGenerationRequest().setArchetypeGroupId( archetypeGroupId ).setArchetypeArtifactId(
519 archetypeArtifactId ).setArchetypeVersion( archetypeVersion ).setGroupId(
520 properties.getProperty( Constants.GROUP_ID ) ).setArtifactId(
521 properties.getProperty( Constants.ARTIFACT_ID ) ).setVersion(
522 properties.getProperty( Constants.VERSION ) ).setPackage(
523 properties.getProperty( Constants.PACKAGE ) ).setOutputDirectory( basedir ).setProperties(
524 properties );
525
526
527 ArchetypeGenerationResult result = new ArchetypeGenerationResult();
528
529 archetypeGenerator.generateArchetype( request, archetypeFile, result );
530
531 if ( result.getCause() != null )
532 {
533 if ( result.getCause() instanceof ArchetypeNotConfigured )
534 {
535 ArchetypeNotConfigured anc = (ArchetypeNotConfigured) result.getCause();
536
537 throw new IntegrationTestFailure(
538 "Missing required properties in archetype.properties: " + StringUtils.join(
539 anc.getMissingProperties().iterator(), ", " ), anc );
540 }
541
542 throw new IntegrationTestFailure( result.getCause().getMessage(), result.getCause() );
543 }
544 return request;
545 }
546
547 private File setupParentProjects( File configFolder, File buildFolder )
548 throws IOException, MojoExecutionException, IntegrationTestFailure
549 {
550
551 File archetypePomPropertiesFile = new File( configFolder, "archetype.pom.properties" );
552 if ( !archetypePomPropertiesFile.exists() )
553 {
554 getLog().debug( "No 'archetype.pom.properties' file found in " + configFolder );
555 return buildFolder;
556 }
557
558
559 buildFolder = setupParentProjects( configFolder.getParentFile(), buildFolder );
560
561 Properties archetypePomProperties = loadProperties( archetypePomPropertiesFile );
562 String groupId = archetypePomProperties.getProperty( Constants.GROUP_ID );
563 if ( StringUtils.isEmpty( groupId ) )
564 {
565 throw new MojoExecutionException( "Property " + Constants.GROUP_ID + " not set in " + archetypePomPropertiesFile );
566 }
567 String artifactId = archetypePomProperties.getProperty( Constants.ARTIFACT_ID );
568 if ( StringUtils.isEmpty( artifactId ) )
569 {
570 throw new MojoExecutionException( "Property " + Constants.ARTIFACT_ID + " not set in " + archetypePomPropertiesFile );
571 }
572 String version = archetypePomProperties.getProperty( Constants.VERSION );
573 if ( StringUtils.isEmpty( version ) )
574 {
575 throw new MojoExecutionException( "Property " + Constants.VERSION + " not set in " + archetypePomPropertiesFile );
576 }
577
578 File archetypeFile;
579 try
580 {
581 archetypeFile = getArchetypeFile( groupId, artifactId, version );
582 }
583 catch ( ArtifactResolverException e )
584 {
585 throw new MojoExecutionException( "Could not resolve archetype artifact " , e );
586 }
587 Properties archetypeProperties = getProperties( archetypePomPropertiesFile );
588 getLog().info( "Setting up parent project in " + buildFolder );
589 ArchetypeGenerationRequest request = generate( groupId, artifactId, version, archetypeFile, archetypeProperties, buildFolder.toString() );
590 return new File( buildFolder, request.getArtifactId() );
591 }
592
593 private File getArchetypeFile( String groupId, String artifactId, String version )
594 throws ArtifactResolverException
595 {
596 ProjectBuildingRequest buildingRequest = new DefaultProjectBuildingRequest( session.getProjectBuildingRequest() );
597 if ( localRepository != null )
598 {
599 buildingRequest = buildingRequest.setLocalRepository( localRepository );
600 }
601 if ( remoteRepositories != null && !remoteRepositories.isEmpty() )
602 {
603 buildingRequest = buildingRequest.setRemoteRepositories( remoteRepositories );
604 }
605
606 DefaultArtifactCoordinate coordinate = new DefaultArtifactCoordinate();
607 coordinate.setGroupId( groupId );
608 coordinate.setArtifactId( artifactId );
609 coordinate.setVersion( version );
610
611 return artifactResolver.resolveArtifact( buildingRequest, coordinate ).getArtifact().getFile();
612 }
613
614 private Properties getProperties( File goalFile )
615 throws IOException
616 {
617 File propertiesFile = new File( goalFile.getParentFile(), "archetype.properties" );
618
619 return loadProperties( propertiesFile );
620 }
621
622 private void invokePostArchetypeGenerationGoals( String goals, File basedir, File goalFile )
623 throws IntegrationTestFailure, IOException, MojoExecutionException
624 {
625 FileLogger logger = setupLogger( basedir );
626
627 if ( !StringUtils.isBlank( goals ) )
628 {
629
630 getLog().info( "Invoking post-archetype-generation goals: " + goals );
631
632 if ( !localRepositoryPath.exists() )
633 {
634 localRepositoryPath.mkdirs();
635 }
636
637
638 InvocationRequest request = new DefaultInvocationRequest().setBaseDirectory( basedir ).setGoals(
639 Arrays.asList( StringUtils.split( goals, "," ) ) ).setLocalRepositoryDirectory(
640 localRepositoryPath ).setBatchMode( true ).setShowErrors( true );
641
642
643 request.setDebug( debug );
644
645 request.setShowVersion( showVersion );
646
647 if ( logger != null )
648 {
649 request.setErrorHandler( logger );
650
651 request.setOutputHandler( logger );
652 }
653
654 if ( !properties.isEmpty() )
655 {
656 Properties props = new Properties();
657 for ( Map.Entry<String, String> entry : properties.entrySet() )
658 {
659 if ( entry.getValue() != null )
660 {
661 props.setProperty( entry.getKey(), entry.getValue() );
662 }
663 }
664 request.setProperties( props );
665 }
666
667 if ( settingsFile != null )
668 {
669 File interpolatedSettingsDirectory =
670 new File( project.getBuild().getOutputDirectory(), "archetype-it" );
671 if ( interpolatedSettingsDirectory.exists() )
672 {
673 FileUtils.deleteDirectory( interpolatedSettingsDirectory );
674 }
675 interpolatedSettingsDirectory.mkdir();
676 File interpolatedSettingsFile =
677 new File( interpolatedSettingsDirectory, "interpolated-" + settingsFile.getName() );
678
679 buildInterpolatedFile( settingsFile, interpolatedSettingsFile );
680
681 request.setUserSettingsFile( interpolatedSettingsFile );
682 }
683 else
684 {
685 File mainBuildSettingsDirectory =
686 new File( project.getBuild().getOutputDirectory(), "archetype-it" );
687 mainBuildSettingsDirectory.mkdir();
688 File mainBuildSettingsFile = new File( mainBuildSettingsDirectory, "archetype-settings.xml" );
689
690 SettingsXpp3Writer settingsWriter = new SettingsXpp3Writer();
691
692 try ( FileWriter fileWriter = new FileWriter( mainBuildSettingsFile ) )
693 {
694 settingsWriter.write( fileWriter, settings );
695 }
696
697 if ( getLog().isDebugEnabled() )
698 {
699 getLog().debug( "Created archetype-settings.xml with settings from the main Maven build: "
700 + mainBuildSettingsFile.getAbsolutePath() );
701 }
702
703 request.setUserSettingsFile( mainBuildSettingsFile );
704 }
705
706 try
707 {
708 InvocationResult result = invoker.execute( request );
709
710 getLog().info( "Post-archetype-generation invoker exit code: " + result.getExitCode() );
711
712 if ( result.getExitCode() != 0 )
713 {
714 throw new IntegrationTestFailure( "Execution failure: exit code = " + result.getExitCode(),
715 result.getExecutionException() );
716 }
717 }
718 catch ( MavenInvocationException e )
719 {
720 throw new IntegrationTestFailure( "Cannot run additions goals.", e );
721 }
722 }
723 else
724 {
725 getLog().info( "No post-archetype-generation goals to invoke." );
726 }
727
728 ScriptRunner scriptRunner = new ScriptRunner( getLog() );
729 scriptRunner.setScriptEncoding( encoding );
730
731 Map<String, Object> context = new LinkedHashMap<>();
732 context.put( "projectDir", basedir );
733
734 try
735 {
736 scriptRunner.run( "post-build script", goalFile.getParentFile(), postBuildHookScript, context, logger,
737 "failure post script", true );
738 }
739 catch ( RunFailureException e )
740 {
741 throw new IntegrationTestFailure( "post build script failure failure: " + e.getMessage(), e );
742 }
743 }
744
745 private FileLogger setupLogger( File basedir )
746 throws IOException
747 {
748 FileLogger logger = null;
749
750 if ( !noLog )
751 {
752 File outputLog = new File( basedir, "build.log" );
753
754 if ( streamLogs )
755 {
756 logger = new FileLogger( outputLog, getLog() );
757 }
758 else
759 {
760 logger = new FileLogger( outputLog );
761 }
762
763 getLog().debug( "build log initialized in: " + outputLog );
764
765 }
766
767 return logger;
768 }
769
770 class IntegrationTestFailure
771 extends Exception
772 {
773 IntegrationTestFailure()
774 {
775 super();
776 }
777
778 IntegrationTestFailure( String message )
779 {
780 super( message );
781 }
782
783 IntegrationTestFailure( Throwable cause )
784 {
785 super( cause );
786 }
787
788 IntegrationTestFailure( String message, Throwable cause )
789 {
790 super( message, cause );
791 }
792 }
793
794
795
796
797
798
799 private Map<String, Object> getInterpolationValueSource()
800 {
801 Map<String, Object> props = new HashMap<>();
802 if ( filterProperties != null )
803 {
804 props.putAll( filterProperties );
805 }
806 if ( filterProperties != null )
807 {
808 props.putAll( filterProperties );
809 }
810 props.put( "basedir", this.project.getBasedir().getAbsolutePath() );
811 props.put( "baseurl", toUrl( this.project.getBasedir().getAbsolutePath() ) );
812 if ( settings.getLocalRepository() != null )
813 {
814 props.put( "localRepository", settings.getLocalRepository() );
815 props.put( "localRepositoryUrl", toUrl( settings.getLocalRepository() ) );
816 }
817 return new CompositeMap( this.project, props );
818 }
819
820 protected void buildInterpolatedFile( File originalFile, File interpolatedFile )
821 throws MojoExecutionException
822 {
823 getLog().debug( "Interpolate " + originalFile.getPath() + " to " + interpolatedFile.getPath() );
824
825 try
826 {
827 String xml;
828
829
830 Map<String, Object> composite = getInterpolationValueSource();
831
832 try ( Reader xmlStreamReader = ReaderFactory.newXmlReader( originalFile );
833 Reader reader = new InterpolationFilterReader( xmlStreamReader, composite, "@", "@" ) )
834 {
835 xml = IOUtil.toString( reader );
836 }
837
838
839 try ( Writer writer = WriterFactory.newXmlWriter( interpolatedFile ) )
840 {
841 interpolatedFile.getParentFile().mkdirs();
842
843 writer.write( xml );
844 }
845 }
846 catch ( IOException e )
847 {
848 throw new MojoExecutionException( "Failed to interpolate file " + originalFile.getPath(), e );
849 }
850 }
851
852 private static class CompositeMap
853 implements Map<String, Object>
854 {
855
856
857
858
859 private MavenProject mavenProject;
860
861
862
863
864 private Map<String, Object> properties;
865
866
867
868
869
870
871
872
873
874 protected CompositeMap( MavenProject mavenProject, Map<String, Object> properties )
875 {
876 if ( mavenProject == null )
877 {
878 throw new IllegalArgumentException( "no project specified" );
879 }
880 this.mavenProject = mavenProject;
881 this.properties = properties == null ? (Map) new Properties() : properties;
882 }
883
884
885
886
887
888
889 @Override
890 public void clear()
891 {
892
893 }
894
895
896
897
898
899
900 @Override
901 public boolean containsKey( Object key )
902 {
903 if ( !( key instanceof String ) )
904 {
905 return false;
906 }
907
908 String expression = (String) key;
909 if ( expression.startsWith( "project." ) || expression.startsWith( "pom." ) )
910 {
911 try
912 {
913 Object evaluated = ReflectionValueExtractor.evaluate( expression, this.mavenProject );
914 if ( evaluated != null )
915 {
916 return true;
917 }
918 }
919 catch ( Exception e )
920 {
921
922 }
923 }
924
925 return properties.containsKey( key ) || mavenProject.getProperties().containsKey( key );
926 }
927
928
929
930
931
932
933 @Override
934 public boolean containsValue( Object value )
935 {
936 throw new UnsupportedOperationException();
937 }
938
939
940
941
942
943
944 @Override
945 public Set<Entry<String, Object>> entrySet()
946 {
947 throw new UnsupportedOperationException();
948 }
949
950
951
952
953
954
955 @Override
956 public Object get( Object key )
957 {
958 if ( !( key instanceof String ) )
959 {
960 return null;
961 }
962
963 String expression = (String) key;
964 if ( expression.startsWith( "project." ) || expression.startsWith( "pom." ) )
965 {
966 try
967 {
968 Object evaluated = ReflectionValueExtractor.evaluate( expression, this.mavenProject );
969 if ( evaluated != null )
970 {
971 return evaluated;
972 }
973 }
974 catch ( Exception e )
975 {
976
977 }
978 }
979
980 Object value = properties.get( key );
981
982 return ( value != null ? value : this.mavenProject.getProperties().get( key ) );
983
984 }
985
986
987
988
989
990
991 @Override
992 public boolean isEmpty()
993 {
994 return this.mavenProject == null && this.mavenProject.getProperties().isEmpty()
995 && this.properties.isEmpty();
996 }
997
998
999
1000
1001
1002
1003 @Override
1004 public Set<String> keySet()
1005 {
1006 throw new UnsupportedOperationException();
1007 }
1008
1009
1010
1011
1012
1013
1014 @Override
1015 public Object put( String key, Object value )
1016 {
1017 throw new UnsupportedOperationException();
1018 }
1019
1020
1021
1022
1023
1024
1025 @Override
1026 public void putAll( Map<? extends String, ? extends Object> t )
1027 {
1028 throw new UnsupportedOperationException();
1029 }
1030
1031
1032
1033
1034
1035
1036 @Override
1037 public Object remove( Object key )
1038 {
1039 throw new UnsupportedOperationException();
1040 }
1041
1042
1043
1044
1045
1046
1047 @Override
1048 public int size()
1049 {
1050 throw new UnsupportedOperationException();
1051 }
1052
1053
1054
1055
1056
1057
1058 @Override
1059 public Collection<Object> values()
1060 {
1061 throw new UnsupportedOperationException();
1062 }
1063 }
1064
1065
1066
1067
1068
1069
1070
1071
1072 private static String toUrl( String filename )
1073 {
1074
1075
1076
1077
1078 String url = "file://" + new File( filename ).toURI().getPath();
1079 if ( url.endsWith( "/" ) )
1080 {
1081 url = url.substring( 0, url.length() - 1 );
1082 }
1083 return url;
1084 }
1085 }