Skip to content

Commit

Permalink
MSHADE-307 adding useDefaultConfiguration flag in ShadeMojo
Browse files Browse the repository at this point in the history
  • Loading branch information
rmannibucau committed Dec 15, 2018
1 parent 52eed09 commit f96c2e2
Show file tree
Hide file tree
Showing 2 changed files with 212 additions and 58 deletions.
156 changes: 127 additions & 29 deletions src/main/java/org/apache/maven/plugins/shade/mojo/ShadeMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@
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;
Expand Down Expand Up @@ -76,6 +78,7 @@
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;
Expand Down Expand Up @@ -364,6 +367,15 @@ public class ShadeMojo
@Parameter( defaultValue = "false" )
private boolean shadeTestJar;

/**
* Auto-configure the mojo to use common transformers (ServicesResourceTransformer, ManifestTransformer)
* and filters (META-INF/*.[SF,DSA,RSA]).
*
* @since 3.2.2
*/
@Parameter( defaultValue = "false" )
private boolean useDefaultConfiguration;

/**
* @since 1.6
*/
Expand Down Expand Up @@ -762,55 +774,68 @@ private List<Relocator> getRelocators()

private List<ResourceTransformer> getResourceTransformers()
{
final List<ResourceTransformer> resourceTransformers = new LinkedList<>( getDefaultResourceTransformers() );
if ( transformers == null )
{
return resourceTransformers;
}
resourceTransformers.addAll( Arrays.asList( transformers ) );
return resourceTransformers;
}

private List<ResourceTransformer> getDefaultResourceTransformers()
{
if ( !useDefaultConfiguration )
{
return Collections.emptyList();
}

return Arrays.asList( transformers );
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
{
List<Filter> filters = new ArrayList<Filter>();
List<SimpleFilter> simpleFilters = new ArrayList<SimpleFilter>();
Map<Artifact, ArtifactId> artifacts = null;

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 ) );
}
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() )
{
Expand All @@ -823,6 +848,41 @@ private List<Filter> getFilters()
}
}

if ( useDefaultConfiguration )
{
// first check for backward compatibility this is not already configured explicitly
boolean addExclusion = true;
if ( this.filters != null )
{
for ( final ArchiveFilter filter : this.filters )
{
if ( filter.getExcludes() != null
&& filter.getExcludes().contains( "META-INF/*.SF" )
&& filter.getExcludes().contains( "META-INF/*.DSA" )
&& filter.getExcludes().contains( "META-INF/*.RSA" )
&& "*:*".equals( filter.getArtifact() ) )
{
addExclusion = false;
break;
}
}
}
if ( addExclusion )
{
getLog().debug( "Adding META-INF/*.SF, META-INF/*.DSA and META-INF/*.RSA exclusion" );

if ( artifacts == null )
{
artifacts = getArtifactIds();
}
simpleFilters.add( new SimpleFilter(
getMatchingJars( artifacts , new ArtifactId( "*:*" ) ),
Collections.<String>emptySet(),
new HashSet<String>( Arrays.asList( "META-INF/*.SF", "META-INF/*.DSA", "META-INF/*.RSA" ) ) ) );
}

}

filters.addAll( simpleFilters );

if ( minimizeJar )
Expand All @@ -842,6 +902,44 @@ private List<Filter> getFilters()
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();
Expand Down
114 changes: 85 additions & 29 deletions src/test/java/org/apache/maven/plugins/shade/mojo/ShadeMojoTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
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;
Expand All @@ -41,10 +42,13 @@
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;
Expand All @@ -60,6 +64,52 @@
public class ShadeMojoTest
extends PlexusTestCase
{

public void testDefaultConfiguration() throws Exception
{
final ShadeMojo shadeMojo = new ShadeMojo();
setProject(shadeMojo);
final Field useDefaultConfiguration = ShadeMojo.class.getDeclaredField("useDefaultConfiguration");
useDefaultConfiguration.setAccessible(true);
useDefaultConfiguration.set(shadeMojo, true);

// 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
{
Expand Down Expand Up @@ -124,11 +174,45 @@ public void testShadeWithFilter()
createSourcesJar.setAccessible( true );
createSourcesJar.set( mojo, Boolean.TRUE );

// setup a project
setProject(mojo);

// create and configure the ArchiveFilter
ArchiveFilter archiveFilter = new ArchiveFilter();
Field archiveFilterArtifact = ArchiveFilter.class.getDeclaredField( "artifact" );
archiveFilterArtifact.setAccessible( true );
archiveFilterArtifact.set( archiveFilter, "org.apache.myfaces.core:myfaces-impl" );

// add ArchiveFilter to mojo
Field filtersField = ShadeMojo.class.getDeclaredField( "filters" );
filtersField.setAccessible( true );
filtersField.set( mojo, new ArchiveFilter[]{ archiveFilter } );

Field sessionField = ShadeMojo.class.getDeclaredField( "session" );
sessionField.setAccessible( true );
sessionField.set( mojo, mock( MavenSession.class ) );

// invoke getFilters()
Method getFilters = ShadeMojo.class.getDeclaredMethod( "getFilters", new Class[0] );
getFilters.setAccessible( true );
List<Filter> filters = (List<Filter>) getFilters.invoke( mojo);

// assertions - there must be one filter
assertEquals( 1, filters.size() );

// the filter must be able to filter the binary and the sources jar
Filter filter = filters.get( 0 );
assertTrue( filter.canFilter( new File( "myfaces-impl-2.0.1-SNAPSHOT.jar" ) ) ); // binary jar
assertTrue( filter.canFilter( new File( "myfaces-impl-2.0.1-SNAPSHOT-sources.jar" ) ) ); // sources jar
}

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 )
public ArtifactResult resolveArtifact(ProjectBuildingRequest req, final Artifact art )
throws ArtifactResolverException
{
return new ArtifactResult()
Expand Down Expand Up @@ -185,34 +269,6 @@ public Artifact getArtifact()
Field projectField = ShadeMojo.class.getDeclaredField( "project" );
projectField.setAccessible( true );
projectField.set( mojo, project );

// create and configure the ArchiveFilter
ArchiveFilter archiveFilter = new ArchiveFilter();
Field archiveFilterArtifact = ArchiveFilter.class.getDeclaredField( "artifact" );
archiveFilterArtifact.setAccessible( true );
archiveFilterArtifact.set( archiveFilter, "org.apache.myfaces.core:myfaces-impl" );

// add ArchiveFilter to mojo
Field filtersField = ShadeMojo.class.getDeclaredField( "filters" );
filtersField.setAccessible( true );
filtersField.set( mojo, new ArchiveFilter[]{ archiveFilter } );

Field sessionField = ShadeMojo.class.getDeclaredField( "session" );
sessionField.setAccessible( true );
sessionField.set( mojo, mock( MavenSession.class ) );

// invoke getFilters()
Method getFilters = ShadeMojo.class.getDeclaredMethod( "getFilters", new Class[0] );
getFilters.setAccessible( true );
List<Filter> filters = (List<Filter>) getFilters.invoke( mojo);

// assertions - there must be one filter
assertEquals( 1, filters.size() );

// the filter must be able to filter the binary and the sources jar
Filter filter = filters.get( 0 );
assertTrue( filter.canFilter( new File( "myfaces-impl-2.0.1-SNAPSHOT.jar" ) ) ); // binary jar
assertTrue( filter.canFilter( new File( "myfaces-impl-2.0.1-SNAPSHOT-sources.jar" ) ) ); // sources jar
}

public void shaderWithPattern( String shadedPattern, File jar )
Expand Down

0 comments on commit f96c2e2

Please sign in to comment.