You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by eo...@apache.org on 2018/12/19 13:47:43 UTC

[maven-shade-plugin] 01/01: MSHADE-307 defaults for transformers and filters

This is an automated email from the ASF dual-hosted git repository.

eolivelli pushed a commit to branch MSHADE-307
in repository https://gitbox.apache.org/repos/asf/maven-shade-plugin.git

commit fb89fe25e965d1188e83625ec6fad9ca8e7bf345
Author: Romain Manni-Bucau <rm...@gmail.com>
AuthorDate: Wed Dec 19 10:18:10 2018 +0100

    MSHADE-307 defaults for transformers and filters
---
 .../apache/maven/plugins/shade/mojo/ShadeMojo.java | 115 ++++++++++----
 src/site/apt/examples/includes-excludes.apt.vm     |  13 ++
 src/site/apt/examples/resource-transformers.apt.vm |   7 +
 .../maven/plugins/shade/mojo/ShadeMojoTest.java    | 174 +++++++++++++--------
 4 files changed, 219 insertions(+), 90 deletions(-)

diff --git a/src/main/java/org/apache/maven/plugins/shade/mojo/ShadeMojo.java b/src/main/java/org/apache/maven/plugins/shade/mojo/ShadeMojo.java
index 6b8d24a..69cad48 100644
--- a/src/main/java/org/apache/maven/plugins/shade/mojo/ShadeMojo.java
+++ b/src/main/java/org/apache/maven/plugins/shade/mojo/ShadeMojo.java
@@ -40,7 +40,9 @@ import org.apache.maven.plugins.shade.filter.SimpleFilter;
 import org.apache.maven.plugins.shade.pom.PomWriter;
 import org.apache.maven.plugins.shade.relocation.Relocator;
 import org.apache.maven.plugins.shade.relocation.SimpleRelocator;
+import org.apache.maven.plugins.shade.resource.ManifestResourceTransformer;
 import org.apache.maven.plugins.shade.resource.ResourceTransformer;
+import org.apache.maven.plugins.shade.resource.ServicesResourceTransformer;
 import org.apache.maven.project.DefaultProjectBuildingRequest;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.project.MavenProjectHelper;
@@ -76,6 +78,7 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -764,12 +767,44 @@ public class ShadeMojo
     {
         if ( transformers == null )
         {
-            return Collections.emptyList();
+            return getDefaultResourceTransformers();
         }
 
         return Arrays.asList( transformers );
     }
 
+    private List<ResourceTransformer> getDefaultResourceTransformers()
+    {
+        final List<ResourceTransformer> transformers = new LinkedList<>();
+        if ( missTransformer( ServicesResourceTransformer.class ) )
+        {
+            getLog().debug( "Adding ServicesResourceTransformer transformer" );
+            transformers.add( new ServicesResourceTransformer() );
+        }
+        if ( missTransformer( ManifestResourceTransformer.class ) )
+        {
+            getLog().debug( "Adding ManifestResourceTransformer transformer" );
+            transformers.add( new ManifestResourceTransformer() );
+        }
+        return transformers;
+    }
+
+    private boolean missTransformer( final Class<?> type )
+    {
+        if ( transformers == null )
+        {
+            return true;
+        }
+        for ( final ResourceTransformer transformer : transformers )
+        {
+            if ( type.isInstance( transformer ) )
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
     private List<Filter> getFilters()
         throws MojoExecutionException
     {
@@ -778,39 +813,13 @@ public class ShadeMojo
 
         if ( this.filters != null && this.filters.length > 0 )
         {
-            Map<Artifact, ArtifactId> artifacts = new HashMap<Artifact, ArtifactId>();
-
-            artifacts.put( project.getArtifact(), new ArtifactId( project.getArtifact() ) );
-
-            for ( Artifact artifact : project.getArtifacts() )
-            {
-                artifacts.put( artifact, new ArtifactId( artifact ) );
-            }
+            Map<Artifact, ArtifactId> artifacts = getArtifactIds();
 
             for ( ArchiveFilter filter : this.filters )
             {
                 ArtifactId pattern = new ArtifactId( filter.getArtifact() );
 
-                Set<File> jars = new HashSet<File>();
-
-                for ( Map.Entry<Artifact, ArtifactId> entry : artifacts.entrySet() )
-                {
-                    if ( entry.getValue().matches( pattern ) )
-                    {
-                        Artifact artifact = entry.getKey();
-
-                        jars.add( artifact.getFile() );
-
-                        if ( createSourcesJar )
-                        {
-                            File file = resolveArtifactSources( artifact );
-                            if ( file != null )
-                            {
-                                jars.add( file );
-                            }
-                        }
-                    }
-                }
+                Set<File> jars = getMatchingJars( artifacts, pattern );
 
                 if ( jars.isEmpty() )
                 {
@@ -822,6 +831,16 @@ public class ShadeMojo
                 simpleFilters.add( new SimpleFilter( jars, filter.getIncludes(), filter.getExcludes() ) );
             }
         }
+        else if ( this.filters == null )
+        {
+            getLog().debug( "Adding META-INF/*.SF, META-INF/*.DSA and META-INF/*.RSA exclusions" );
+
+            Map<Artifact, ArtifactId> artifacts = getArtifactIds();
+            simpleFilters.add( new SimpleFilter(
+                    getMatchingJars( artifacts , new ArtifactId( "*:*" ) ),
+                    Collections.<String>emptySet(),
+                    new HashSet<>( Arrays.asList( "META-INF/*.SF", "META-INF/*.DSA", "META-INF/*.RSA" ) ) ) );
+        }
 
         filters.addAll( simpleFilters );
 
@@ -842,6 +861,44 @@ public class ShadeMojo
         return filters;
     }
 
+    private Set<File> getMatchingJars( final Map<Artifact, ArtifactId> artifacts, final ArtifactId pattern )
+    {
+        final Set<File> jars = new HashSet<File>();
+
+        for ( final Map.Entry<Artifact, ArtifactId> entry : artifacts.entrySet() )
+        {
+            if ( entry.getValue().matches( pattern ) )
+            {
+                final Artifact artifact = entry.getKey();
+
+                jars.add( artifact.getFile() );
+
+                if ( createSourcesJar )
+                {
+                    final File file = resolveArtifactSources( artifact );
+                    if ( file != null )
+                    {
+                        jars.add( file );
+                    }
+                }
+            }
+        }
+        return jars;
+    }
+
+    private Map<Artifact, ArtifactId> getArtifactIds()
+    {
+        final Map<Artifact, ArtifactId> artifacts = new HashMap<Artifact, ArtifactId>();
+
+        artifacts.put( project.getArtifact(), new ArtifactId( project.getArtifact() ) );
+
+        for ( final Artifact artifact : project.getArtifacts() )
+        {
+            artifacts.put( artifact, new ArtifactId( artifact ) );
+        }
+        return artifacts;
+    }
+
     private File shadedArtifactFileWithClassifier()
     {
         Artifact artifact = project.getArtifact();
diff --git a/src/site/apt/examples/includes-excludes.apt.vm b/src/site/apt/examples/includes-excludes.apt.vm
index e83126f..f6a7b9a 100644
--- a/src/site/apt/examples/includes-excludes.apt.vm
+++ b/src/site/apt/examples/includes-excludes.apt.vm
@@ -122,6 +122,19 @@ Selecting Contents for Uber JAR
   was introduced in plugin version 1.3. It excludes all signature related files from every artifact, regardless of its
   group or artifact id.
 
+  Note that if you didn't specify a not null <<<filters>>> value then the following setup will be done:
+
++----
+<filter>
+  <artifact>*:*</artifact>
+  <excludes>
+    <exclude>META-INF/*.SF</exclude>
+    <exclude>META-INF/*.DSA</exclude>
+    <exclude>META-INF/*.RSA</exclude>
+  </excludes>
+</filter>
++----
+
   Besides user-specified filters, the plugin can also be configured to automatically remove all classes of dependencies
   that are not used by the project, thereby minimizing the resulting uber JAR:
 
diff --git a/src/site/apt/examples/resource-transformers.apt.vm b/src/site/apt/examples/resource-transformers.apt.vm
index 1a09833..9f1d4ec 100644
--- a/src/site/apt/examples/resource-transformers.apt.vm
+++ b/src/site/apt/examples/resource-transformers.apt.vm
@@ -538,3 +538,10 @@ Transformers in <<<org.apache.maven.plugins.shade.resource>>>
  ...
 </project>
 +-----
+
+* Default transformers
+
+    If no transformer is configured (which means you didn't opened/closed <<<transformers>>>
+    because an empty list is considered valid) then a default setup is done. It adds <<<ServicesResourceTransformer>>>
+    and <<<ManifestResourceTransformer>>>.
+
diff --git a/src/test/java/org/apache/maven/plugins/shade/mojo/ShadeMojoTest.java b/src/test/java/org/apache/maven/plugins/shade/mojo/ShadeMojoTest.java
index fa869c8..e47180b 100644
--- a/src/test/java/org/apache/maven/plugins/shade/mojo/ShadeMojoTest.java
+++ b/src/test/java/org/apache/maven/plugins/shade/mojo/ShadeMojoTest.java
@@ -29,6 +29,7 @@ import java.net.URL;
 import java.net.URLClassLoader;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
@@ -41,10 +42,13 @@ import org.apache.maven.execution.MavenSession;
 import org.apache.maven.plugins.shade.ShadeRequest;
 import org.apache.maven.plugins.shade.Shader;
 import org.apache.maven.plugins.shade.filter.Filter;
+import org.apache.maven.plugins.shade.filter.SimpleFilter;
 import org.apache.maven.plugins.shade.relocation.Relocator;
 import org.apache.maven.plugins.shade.relocation.SimpleRelocator;
 import org.apache.maven.plugins.shade.resource.ComponentsXmlResourceTransformer;
+import org.apache.maven.plugins.shade.resource.ManifestResourceTransformer;
 import org.apache.maven.plugins.shade.resource.ResourceTransformer;
+import org.apache.maven.plugins.shade.resource.ServicesResourceTransformer;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.project.ProjectBuildingRequest;
 import org.apache.maven.shared.transfer.artifact.ArtifactCoordinate;
@@ -60,6 +64,48 @@ import org.codehaus.plexus.PlexusTestCase;
 public class ShadeMojoTest
     extends PlexusTestCase
 {
+    public void testDefaultConfiguration() throws Exception
+    {
+        final ShadeMojo shadeMojo = new ShadeMojo();
+        setProject(shadeMojo);
+
+        // default transformers are present
+        final Method getResourceTransformers = ShadeMojo.class.getDeclaredMethod("getResourceTransformers");
+        getResourceTransformers.setAccessible(true);
+        final List<ResourceTransformer> transformers =
+                List.class.cast(getResourceTransformers.invoke(shadeMojo));
+        assertEquals(2, transformers.size());
+        assertTrue(ServicesResourceTransformer.class.isInstance(transformers.get(0)));
+        assertTrue(ManifestResourceTransformer.class.isInstance(transformers.get(1)));
+
+        // default exclusion is present
+        final Method getFilters = ShadeMojo.class.getDeclaredMethod("getFilters");
+        getFilters.setAccessible(true);
+        final List<Filter> filters =
+                List.class.cast(getFilters.invoke(shadeMojo));
+        assertEquals(1, filters.size());
+
+        final Filter filter = filters.iterator().next();
+        assertTrue(SimpleFilter.class.isInstance(filter));
+
+        final Field jars = filter.getClass().getDeclaredField("jars");
+        jars.setAccessible(true);
+        assertEquals(1, Collection.class.cast(jars.get(filter)).size());
+
+        final Field excludes = filter.getClass().getDeclaredField("excludes");
+        excludes.setAccessible(true);
+        final Collection<String> excludesValues = Collection.class.cast(excludes.get(filter));
+        assertEquals(3, excludesValues.size());
+        for ( final String exclude : Arrays.asList( "META-INF/*.SF", "META-INF/*.DSA", "META-INF/*.RSA" ) )
+        {
+            assertTrue(exclude, excludesValues.contains(exclude) );
+        }
+
+        final Field includes = filter.getClass().getDeclaredField("includes");
+        includes.setAccessible(true);
+        assertTrue(Collection.class.cast(includes.get(filter)).isEmpty());
+    }
+
     public void testShaderWithDefaultShadedPattern()
         throws Exception
     {
@@ -124,67 +170,8 @@ public class ShadeMojoTest
         createSourcesJar.setAccessible( true );
         createSourcesJar.set( mojo, Boolean.TRUE );
 
-        // configure artifactResolver (mocked) for mojo
-        ArtifactResolver mockArtifactResolver = new ArtifactResolver()
-        {
-            @Override
-            public ArtifactResult resolveArtifact( ProjectBuildingRequest req, final Artifact art )
-                throws ArtifactResolverException
-            {
-                return new ArtifactResult()
-                {
-
-                    @Override
-                    public Artifact getArtifact()
-                    {
-                        art.setResolved( true );
-                        String fileName = art.getArtifactId() + "-" + art.getVersion()
-                            + ( art.getClassifier() != null ? "-" + art.getClassifier() : "" ) + ".jar";
-                        art.setFile( new File( fileName ) );
-                        return art;
-                    }
-                };
-            }
-
-            @Override
-            public ArtifactResult resolveArtifact( ProjectBuildingRequest req, final ArtifactCoordinate coordinate )
-                throws ArtifactResolverException
-            {
-                return new ArtifactResult()
-                {
-
-                    @Override
-                    public Artifact getArtifact()
-                    {
-                        Artifact art = mock( Artifact.class );
-                        when( art.getGroupId() ).thenReturn( coordinate.getGroupId() );
-                        when( art.getArtifactId() ).thenReturn( coordinate.getArtifactId() );
-                        when( art.getType() ).thenReturn( coordinate.getExtension() );
-                        when( art.getClassifier() ).thenReturn( coordinate.getClassifier() );
-                        when( art.isResolved() ).thenReturn( true );
-                        String fileName = coordinate.getArtifactId() + "-" + coordinate.getVersion()
-                            + ( coordinate.getClassifier() != null ? "-" + coordinate.getClassifier() : "" ) + ".jar";
-                        when( art.getFile() ).thenReturn( new File( fileName ) );
-                        return art;
-                    }
-                };
-            }
-        };
-        Field artifactResolverField = ShadeMojo.class.getDeclaredField( "artifactResolver" );
-        artifactResolverField.setAccessible( true );
-        artifactResolverField.set( mojo, mockArtifactResolver );
-
-        // create and configure MavenProject
-        MavenProject project = new MavenProject();
-        ArtifactHandler artifactHandler = (ArtifactHandler) lookup( ArtifactHandler.ROLE );
-        Artifact artifact = new DefaultArtifact( "org.apache.myfaces.core", "myfaces-impl",
-                                                 VersionRange.createFromVersion( "2.0.1-SNAPSHOT" ), "compile", "jar",
-                                                 null, artifactHandler );
-        artifact = mockArtifactResolver.resolveArtifact( null, artifact ).getArtifact(); // setFile and setResolved
-        project.setArtifact( artifact );
-        Field projectField = ShadeMojo.class.getDeclaredField( "project" );
-        projectField.setAccessible( true );
-        projectField.set( mojo, project );
+        // setup a project
+        setProject(mojo);
 
         // create and configure the ArchiveFilter
         ArchiveFilter archiveFilter = new ArchiveFilter();
@@ -247,4 +234,69 @@ public class ShadeMojoTest
         s.shade( shadeRequest );
     }
 
+    private void setProject(final ShadeMojo mojo) throws Exception
+    {
+        // configure artifactResolver (mocked) for mojo
+        ArtifactResolver mockArtifactResolver = new ArtifactResolver()
+        {
+            @Override
+            public ArtifactResult resolveArtifact(ProjectBuildingRequest req, final Artifact art )
+                    throws ArtifactResolverException
+            {
+                return new ArtifactResult()
+                {
+
+                    @Override
+                    public Artifact getArtifact()
+                    {
+                        art.setResolved( true );
+                        String fileName = art.getArtifactId() + "-" + art.getVersion()
+                                + ( art.getClassifier() != null ? "-" + art.getClassifier() : "" ) + ".jar";
+                        art.setFile( new File( fileName ) );
+                        return art;
+                    }
+                };
+            }
+
+            @Override
+            public ArtifactResult resolveArtifact( ProjectBuildingRequest req, final ArtifactCoordinate coordinate )
+                    throws ArtifactResolverException
+            {
+                return new ArtifactResult()
+                {
+
+                    @Override
+                    public Artifact getArtifact()
+                    {
+                        Artifact art = mock( Artifact.class );
+                        when( art.getGroupId() ).thenReturn( coordinate.getGroupId() );
+                        when( art.getArtifactId() ).thenReturn( coordinate.getArtifactId() );
+                        when( art.getType() ).thenReturn( coordinate.getExtension() );
+                        when( art.getClassifier() ).thenReturn( coordinate.getClassifier() );
+                        when( art.isResolved() ).thenReturn( true );
+                        String fileName = coordinate.getArtifactId() + "-" + coordinate.getVersion()
+                                + ( coordinate.getClassifier() != null ? "-" + coordinate.getClassifier() : "" ) + ".jar";
+                        when( art.getFile() ).thenReturn( new File( fileName ) );
+                        return art;
+                    }
+                };
+            }
+        };
+        Field artifactResolverField = ShadeMojo.class.getDeclaredField( "artifactResolver" );
+        artifactResolverField.setAccessible( true );
+        artifactResolverField.set( mojo, mockArtifactResolver );
+
+        // create and configure MavenProject
+        MavenProject project = new MavenProject();
+        ArtifactHandler artifactHandler = (ArtifactHandler) lookup( ArtifactHandler.ROLE );
+        Artifact artifact = new DefaultArtifact( "org.apache.myfaces.core", "myfaces-impl",
+                VersionRange.createFromVersion( "2.0.1-SNAPSHOT" ), "compile", "jar",
+                null, artifactHandler );
+        artifact = mockArtifactResolver.resolveArtifact( null, artifact ).getArtifact(); // setFile and setResolved
+        project.setArtifact( artifact );
+        Field projectField = ShadeMojo.class.getDeclaredField( "project" );
+        projectField.setAccessible( true );
+        projectField.set( mojo, project );
+    }
+
 }