Author: khmarbaise Date: Mon Nov 3 20:52:32 2014 New Revision: 1636439 URL: http://svn.apache.org/r1636439 Log: [MEAR-180] - Checking the list of modules if we have duplicate artifacts and produce a warnging optionally fail the build to keep backward compatibility.
Added: maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugin/ear/util/ModuleIdentifierValidator.java maven/plugins/trunk/maven-ear-plugin/src/test/java/org/apache/maven/plugin/ear/util/ModuleIdentifierValidatorTest.java Modified: maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugin/ear/EarMojo.java Modified: maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugin/ear/EarMojo.java URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugin/ear/EarMojo.java?rev=1636439&r1=1636438&r2=1636439&view=diff ============================================================================== --- maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugin/ear/EarMojo.java (original) +++ maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugin/ear/EarMojo.java Mon Nov 3 20:52:32 2014 @@ -26,6 +26,7 @@ import org.apache.maven.plugin.MojoExecu import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugin.ear.util.EarMavenArchiver; import org.apache.maven.plugin.ear.util.JavaEEVersion; +import org.apache.maven.plugin.ear.util.ModuleIdentifierValidator; import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; @@ -58,6 +59,9 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; import java.util.zip.ZipException; /** @@ -254,6 +258,45 @@ public class EarMojo @Parameter( property = "maven.ear.useJvmChmod", defaultValue = "true" ) private boolean useJvmChmod = true; + /** + * The list of artifacts is checked and if you set this to {@code true} + * the build will fail if duplicate artifacts have been found within + * the build configuration. + * + * @since 2.10 + */ + //TODO: This can be removed if we change to full unique identifiers in EAR (next major version!) + @Parameter( defaultValue = "false", property = "maven.ear.duplicateArtifactsBreakTheBuild" ) + private boolean duplicateArtifactsBreakTheBuild; + + private void checkModuleUniqueness() + throws MojoExecutionException + { + ModuleIdentifierValidator miv = new ModuleIdentifierValidator( getModules() ); + miv.checkForDuplicateArtifacts(); + if ( miv.existDuplicateArtifacts() ) + { + Map<String, List<EarModule>> duplicateArtifacts = miv.getDuplicateArtifacts(); + for ( Entry<String, List<EarModule>> entry : duplicateArtifacts.entrySet() ) + { + getLog().warn( "The artifactId " + entry.getKey() + " exists more than once in the modules list." ); + for ( EarModule earModule : entry.getValue() ) + { + getLog().warn( " --> " + earModule.getArtifact().getId() + " (" + earModule.getType() + ")" ); + } + } + + getLog().warn("HINT: This can be simply solved by using the <fileNameMapping>full</fileNameMapping>"); + + if ( duplicateArtifactsBreakTheBuild ) + { + throw new MojoExecutionException( + "The build contains duplicate artifacts which result in unpredictable ear content." ); + } + } + + } + public void execute() throws MojoExecutionException, MojoFailureException { @@ -284,6 +327,12 @@ public class EarMojo // Copy modules try { + // TODO: With the next major release the modules + // should be identified by a unique id instead of the + // the artifactId's only which means this + // check can be removed. + checkModuleUniqueness(); + for ( EarModule module : getModules() ) { if ( module instanceof JavaModule ) @@ -707,10 +756,10 @@ public class EarMojo if ( module.getLibDir() != null ) { - //MEAR-189: - //We use the original name, cause in case of fileNameMapping to no-version/full - //we could not not delete it and it will end up in the resulting EAR and the WAR - //will not be cleaned up. + // MEAR-189: + // We use the original name, cause in case of fileNameMapping to no-version/full + // we could not not delete it and it will end up in the resulting EAR and the WAR + // will not be cleaned up. File artifact = new File( new File( workDirectory, module.getLibDir() ), jm.getOriginalBundleFileName() ); Added: maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugin/ear/util/ModuleIdentifierValidator.java URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugin/ear/util/ModuleIdentifierValidator.java?rev=1636439&view=auto ============================================================================== --- maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugin/ear/util/ModuleIdentifierValidator.java (added) +++ maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugin/ear/util/ModuleIdentifierValidator.java Mon Nov 3 20:52:32 2014 @@ -0,0 +1,107 @@ +package org.apache.maven.plugin.ear.util; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.maven.plugin.ear.EarModule; + +/** + * This class will check the list of modules if there exist a duplicate artifactId. If we have such case it's necessary + * to create a warning to the user otherwise it can happen to overwrite existing artifacts during the EAR creation + * process. This is a temporary solution to keep backward compatibility with previous versions. For the next major + * release 3.X the creation of the EAR archive should be done based on unique identifiers like + * {@code groupId:artifactId:version}. + * + * @author Karl Heinz Marbaise <khmarba...@apache.org> + */ +public class ModuleIdentifierValidator +{ + + private List<EarModule> earModules; + + private Map<String, List<EarModule>> result; + + public ModuleIdentifierValidator( List<EarModule> earModules ) + { + if ( earModules == null ) + { + throw new IllegalArgumentException( "Not allowed to give null for earModules." ); + } + this.earModules = earModules; + this.result = new HashMap<String, List<EarModule>>(); + } + + /** + * You have to call {@link #checkForDuplicateArtifacts()} before + * otherwise you will get always {@code false}. + * @return true in case of existing duplicates false otherwise. + */ + public boolean existDuplicateArtifacts() + { + return !result.isEmpty(); + } + + /** + * Trigger the module list check. + * + * @return this for fluent usage. + */ + public ModuleIdentifierValidator checkForDuplicateArtifacts() + { + analyze(); + return this; + } + + private void analyze() + { + final Map<String, List<EarModule>> newList = new HashMap<String, List<EarModule>>(); + + for ( EarModule earModule : earModules ) + { + String earId = earModule.getArtifact().getArtifactId() + ":" + earModule.getArtifact().getVersion(); + + if ( newList.containsKey( earId ) ) + { + newList.get( earId ).add( earModule ); + } + else + { + List<EarModule> list = new ArrayList<EarModule>(); + list.add( earModule ); + newList.put( earId, list ); + } + } + + result.clear(); + for ( Map.Entry<String, List<EarModule>> item : newList.entrySet() ) + { + if ( item.getValue().size() > 1 ) + { + result.put( item.getKey(), item.getValue() ); + } + } + + } + + public Map<String, List<EarModule>> getDuplicateArtifacts() + { + return result; + } + + public List<EarModule> getEarModules() + { + return earModules; + } + + public ModuleIdentifierValidator setEarModules( List<EarModule> earModules ) + { + if ( earModules == null ) + { + throw new IllegalArgumentException( "Not allowed to give null for earModules." ); + } + this.earModules = earModules; + return this; + } +} \ No newline at end of file Added: maven/plugins/trunk/maven-ear-plugin/src/test/java/org/apache/maven/plugin/ear/util/ModuleIdentifierValidatorTest.java URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-ear-plugin/src/test/java/org/apache/maven/plugin/ear/util/ModuleIdentifierValidatorTest.java?rev=1636439&view=auto ============================================================================== --- maven/plugins/trunk/maven-ear-plugin/src/test/java/org/apache/maven/plugin/ear/util/ModuleIdentifierValidatorTest.java (added) +++ maven/plugins/trunk/maven-ear-plugin/src/test/java/org/apache/maven/plugin/ear/util/ModuleIdentifierValidatorTest.java Mon Nov 3 20:52:32 2014 @@ -0,0 +1,144 @@ +package org.apache.maven.plugin.ear.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.ear.EarModule; +import org.junit.Before; +import org.junit.Test; + +public class ModuleIdentifierValidatorTest +{ + private List<EarModule> earModules; + + private ModuleIdentifierValidator miv; + + @Before + public void before() + { + this.earModules = new ArrayList<EarModule>(); + this.miv = new ModuleIdentifierValidator( this.earModules ); + } + + private EarModule createMockEarModule( String groupId, String artifactId, String version ) + { + EarModule earModule = mock( EarModule.class ); + Artifact artifact = mock( Artifact.class ); + when( earModule.getArtifact() ).thenReturn( artifact ); + when( earModule.getArtifact().getGroupId() ).thenReturn( groupId ); + when( earModule.getArtifact().getArtifactId() ).thenReturn( artifactId ); + when( earModule.getArtifact().getVersion() ).thenReturn( version ); + when( earModule.getArtifact().getId() ).thenReturn( groupId + ":" + artifactId + ":" + version ); + return earModule; + } + + @Test + public void existDuplicateShouldResultFalseWithEmptyList() + { + miv.checkForDuplicateArtifacts(); + + assertFalse( miv.existDuplicateArtifacts() ); + } + + @Test + public void shouldNotFailCauseTheArtifactIdsAreDifferentWithSameGroupId() + { + earModules.add( createMockEarModule( "org.apache.maven.test", "result-artifact", "1.0.0" ) ); + earModules.add( createMockEarModule( "org.apache.maven.test", "result-artifact-a", "1.0.0" ) ); + earModules.add( createMockEarModule( "org.apache.maven.test", "result-artifact-b", "1.0.0" ) ); + + assertFalse( miv.checkForDuplicateArtifacts().existDuplicateArtifacts() ); + + Map<String, List<EarModule>> result = miv.getDuplicateArtifacts(); + + assertTrue( result.isEmpty() ); + } + + @Test + public void shouldNotFailCauseTheArtifactIdsAreDifferent() + { + earModules.add( createMockEarModule( "org.apache", "artifact-1", "1.0.0" ) ); + earModules.add( createMockEarModule( "org.apache", "artifact-2", "1.0.0" ) ); + earModules.add( createMockEarModule( "org.apache.maven", "aid-1", "1.0.0" ) ); + earModules.add( createMockEarModule( "org.apache.maven", "aid-2", "1.0.0" ) ); + earModules.add( createMockEarModule( "org.apache.maven.test", "result-artifact-a", "1.0.0" ) ); + earModules.add( createMockEarModule( "org.apache.maven.test", "result-artifact-b", "1.0.0" ) ); + + assertFalse( miv.checkForDuplicateArtifacts().existDuplicateArtifacts() ); + + Map<String, List<EarModule>> result = miv.getDuplicateArtifacts(); + + assertTrue( result.isEmpty() ); + } + + @Test + public void shouldFailCauseTheArtifactIdsAreIdenticalWithDifferentGroupIds() + { + EarModule earModule1 = createMockEarModule( "org.apache.maven.test", "result-artifact", "1.0.0" ); + EarModule earModule2 = createMockEarModule( "org.apache.maven", "result-artifact", "1.0.0" ); + earModules.add( earModule1 ); + earModules.add( earModule2 ); + + miv.checkForDuplicateArtifacts(); + Map<String, List<EarModule>> result = miv.getDuplicateArtifacts(); + + assertFalse( result.isEmpty() ); + assertEquals( 1, result.size() ); + assertTrue( result.containsKey( "result-artifact:1.0.0" ) ); + assertEquals( 2, result.get( "result-artifact:1.0.0" ).size() ); + } + + @Test + public void shouldFailCauseTheArtifactIdsAreIdentical() + { + earModules.add( createMockEarModule( "org.apache", "artifact-1", "1.0.0" ) ); + earModules.add( createMockEarModule( "org.apache", "artifact-2", "1.0.0" ) ); + earModules.add( createMockEarModule( "org.apache.maven", "aid-1", "1.0.0" ) ); + earModules.add( createMockEarModule( "org.apache.maven", "artifact-2", "1.0.0" ) ); + earModules.add( createMockEarModule( "org.apache.maven.test", "result-artifact-a", "1.0.0" ) ); + earModules.add( createMockEarModule( "org.apache.maven.test", "result-artifact-b", "1.0.0" ) ); + + miv.checkForDuplicateArtifacts(); + Map<String, List<EarModule>> result = miv.getDuplicateArtifacts(); + + assertFalse( result.isEmpty() ); + } + + @Test + public void shouldFailWithAppropriateInformationAboutTheIdenticalArtifactIds() + { + EarModule earModule_1 = createMockEarModule( "org.apache", "artifact-2", "1.0.0" ); + EarModule earModule_2 = createMockEarModule( "org.apache.maven", "artifact-2", "1.0.0" ); + + earModules.add( createMockEarModule( "org.apache", "artifact-1", "1.0.0" ) ); + earModules.add( earModule_1 ); + earModules.add( createMockEarModule( "org.apache.maven", "aid-1", "1.0.0" ) ); + earModules.add( earModule_2 ); + earModules.add( createMockEarModule( "org.apache.maven.test", "result-artifact-a", "1.0.0" ) ); + earModules.add( createMockEarModule( "org.apache.maven.test", "result-artifact-b", "1.0.0" ) ); + + miv.checkForDuplicateArtifacts(); + Map<String, List<EarModule>> result = miv.getDuplicateArtifacts(); + + assertFalse( result.isEmpty() ); + assertEquals( 1, result.size() ); + + assertTrue( result.containsKey( "artifact-2:1.0.0" ) ); + + List<EarModule> list = result.get( "artifact-2:1.0.0" ); + + assertEquals( 2, list.size() ); + assertTrue( list.contains( earModule_1 ) ); + assertTrue( list.contains( earModule_2 ) ); + + } + +}