View Javadoc
1   package org.apache.maven.plugins.shade.mojo;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import static org.mockito.Mockito.mock;
23  import static org.mockito.Mockito.when;
24  
25  import java.io.File;
26  import java.lang.reflect.Field;
27  import java.lang.reflect.Method;
28  import java.net.URL;
29  import java.net.URLClassLoader;
30  import java.util.ArrayList;
31  import java.util.Arrays;
32  import java.util.LinkedHashSet;
33  import java.util.List;
34  import java.util.Set;
35  
36  import org.apache.maven.artifact.Artifact;
37  import org.apache.maven.artifact.DefaultArtifact;
38  import org.apache.maven.artifact.handler.ArtifactHandler;
39  import org.apache.maven.artifact.versioning.VersionRange;
40  import org.apache.maven.execution.MavenSession;
41  import org.apache.maven.plugins.shade.ShadeRequest;
42  import org.apache.maven.plugins.shade.Shader;
43  import org.apache.maven.plugins.shade.filter.Filter;
44  import org.apache.maven.plugins.shade.relocation.Relocator;
45  import org.apache.maven.plugins.shade.relocation.SimpleRelocator;
46  import org.apache.maven.plugins.shade.resource.ComponentsXmlResourceTransformer;
47  import org.apache.maven.plugins.shade.resource.ResourceTransformer;
48  import org.apache.maven.project.MavenProject;
49  import org.apache.maven.project.ProjectBuildingRequest;
50  import org.apache.maven.shared.transfer.artifact.ArtifactCoordinate;
51  import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResolver;
52  import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResolverException;
53  import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResult;
54  import org.codehaus.plexus.PlexusTestCase;
55  
56  /**
57   * @author Jason van Zyl
58   * @author Mauro Talevi
59   */
60  public class ShadeMojoTest
61      extends PlexusTestCase
62  {
63      public void testShaderWithDefaultShadedPattern()
64          throws Exception
65      {
66          shaderWithPattern( null, new File( "target/foo-default.jar" ) );
67      }
68  
69      public void testShaderWithCustomShadedPattern()
70          throws Exception
71      {
72          shaderWithPattern( "org/shaded/plexus/util", new File( "target/foo-custom.jar" ) );
73      }
74  
75      public void testShaderWithExclusions()
76          throws Exception
77      {
78          File jarFile = new File( getBasedir(), "target/unit/foo-bar.jar" );
79  
80          Shader s = (Shader) lookup( Shader.ROLE, "default" );
81  
82          Set<File> set = new LinkedHashSet<>();
83          set.add( new File( getBasedir(), "src/test/jars/test-artifact-1.0-SNAPSHOT.jar" ) );
84  
85          List<Relocator> relocators = new ArrayList<>();
86          relocators.add( new SimpleRelocator( "org.codehaus.plexus.util", "hidden", null, Arrays.asList(
87                  "org.codehaus.plexus.util.xml.Xpp3Dom", "org.codehaus.plexus.util.xml.pull.*") ) );
88  
89          List<ResourceTransformer> resourceTransformers = new ArrayList<>();
90  
91          List<Filter> filters = new ArrayList<>();
92  
93          ShadeRequest shadeRequest = new ShadeRequest();
94          shadeRequest.setJars( set );
95          shadeRequest.setUberJar( jarFile );
96          shadeRequest.setFilters( filters );
97          shadeRequest.setRelocators( relocators );
98          shadeRequest.setResourceTransformers( resourceTransformers );
99  
100         s.shade( shadeRequest );
101 
102         try ( URLClassLoader cl = new URLClassLoader( new URL[]{ jarFile.toURI().toURL() } ) ) {
103             Class<?> c = cl.loadClass( "org.apache.maven.plugins.shade.Lib" );
104     
105             Field field = c.getDeclaredField( "CLASS_REALM_PACKAGE_IMPORT" );
106             assertEquals( "org.codehaus.plexus.util.xml.pull", field.get( null ) );
107     
108             Method method = c.getDeclaredMethod( "getClassRealmPackageImport" );
109             assertEquals( "org.codehaus.plexus.util.xml.pull", method.invoke( null ) );
110         }
111     }
112 
113     /**
114      * Tests if a Filter is installed correctly, also if createSourcesJar is set to true.
115      *
116      * @throws Exception
117      */
118     public void testShadeWithFilter()
119         throws Exception
120     {
121         ShadeMojo mojo = new ShadeMojo();
122 
123         // set createSourcesJar = true
124         Field createSourcesJar = ShadeMojo.class.getDeclaredField( "createSourcesJar" );
125         createSourcesJar.setAccessible( true );
126         createSourcesJar.set( mojo, Boolean.TRUE );
127 
128         // configure artifactResolver (mocked) for mojo
129         ArtifactResolver mockArtifactResolver = new ArtifactResolver()
130         {
131             @Override
132             public ArtifactResult resolveArtifact( ProjectBuildingRequest req, final Artifact art )
133                 throws ArtifactResolverException
134             {
135                 return new ArtifactResult()
136                 {
137 
138                     @Override
139                     public Artifact getArtifact()
140                     {
141                         art.setResolved( true );
142                         String fileName = art.getArtifactId() + "-" + art.getVersion()
143                             + ( art.getClassifier() != null ? "-" + art.getClassifier() : "" ) + ".jar";
144                         art.setFile( new File( fileName ) );
145                         return art;
146                     }
147                 };
148             }
149 
150             @Override
151             public ArtifactResult resolveArtifact( ProjectBuildingRequest req, final ArtifactCoordinate coordinate )
152                 throws ArtifactResolverException
153             {
154                 return new ArtifactResult()
155                 {
156 
157                     @Override
158                     public Artifact getArtifact()
159                     {
160                         Artifact art = mock( Artifact.class );
161                         when( art.getGroupId() ).thenReturn( coordinate.getGroupId() );
162                         when( art.getArtifactId() ).thenReturn( coordinate.getArtifactId() );
163                         when( art.getType() ).thenReturn( coordinate.getExtension() );
164                         when( art.getClassifier() ).thenReturn( coordinate.getClassifier() );
165                         when( art.isResolved() ).thenReturn( true );
166                         String fileName = coordinate.getArtifactId() + "-" + coordinate.getVersion()
167                             + ( coordinate.getClassifier() != null ? "-" + coordinate.getClassifier() : "" ) + ".jar";
168                         when( art.getFile() ).thenReturn( new File( fileName ) );
169                         return art;
170                     }
171                 };
172             }
173         };
174         Field artifactResolverField = ShadeMojo.class.getDeclaredField( "artifactResolver" );
175         artifactResolverField.setAccessible( true );
176         artifactResolverField.set( mojo, mockArtifactResolver );
177 
178         // create and configure MavenProject
179         MavenProject project = new MavenProject();
180         ArtifactHandler artifactHandler = (ArtifactHandler) lookup( ArtifactHandler.ROLE );
181         Artifact artifact = new DefaultArtifact( "org.apache.myfaces.core", "myfaces-impl",
182                                                  VersionRange.createFromVersion( "2.0.1-SNAPSHOT" ), "compile", "jar",
183                                                  null, artifactHandler );
184         artifact = mockArtifactResolver.resolveArtifact( null, artifact ).getArtifact(); // setFile and setResolved
185         project.setArtifact( artifact );
186         Field projectField = ShadeMojo.class.getDeclaredField( "project" );
187         projectField.setAccessible( true );
188         projectField.set( mojo, project );
189 
190         // create and configure the ArchiveFilter
191         ArchiveFilter archiveFilter = new ArchiveFilter();
192         Field archiveFilterArtifact = ArchiveFilter.class.getDeclaredField( "artifact" );
193         archiveFilterArtifact.setAccessible( true );
194         archiveFilterArtifact.set( archiveFilter, "org.apache.myfaces.core:myfaces-impl" );
195 
196         // add ArchiveFilter to mojo
197         Field filtersField = ShadeMojo.class.getDeclaredField( "filters" );
198         filtersField.setAccessible( true );
199         filtersField.set( mojo, new ArchiveFilter[]{ archiveFilter } );
200 
201         Field sessionField = ShadeMojo.class.getDeclaredField( "session" );
202         sessionField.setAccessible( true );
203         sessionField.set( mojo, mock( MavenSession.class ) );
204 
205         // invoke getFilters()
206         Method getFilters = ShadeMojo.class.getDeclaredMethod( "getFilters" );
207         getFilters.setAccessible( true );
208         List<Filter> filters = (List<Filter>) getFilters.invoke( mojo);
209 
210         // assertions - there must be one filter
211         assertEquals( 1, filters.size() );
212 
213         // the filter must be able to filter the binary and the sources jar
214         Filter filter = filters.get( 0 );
215         assertTrue( filter.canFilter( new File( "myfaces-impl-2.0.1-SNAPSHOT.jar" ) ) ); // binary jar
216         assertTrue( filter.canFilter( new File( "myfaces-impl-2.0.1-SNAPSHOT-sources.jar" ) ) ); // sources jar
217     }
218 
219     public void shaderWithPattern( String shadedPattern, File jar )
220         throws Exception
221     {
222         Shader s = (Shader) lookup( Shader.ROLE );
223 
224         Set<File> set = new LinkedHashSet<>();
225 
226         set.add( new File( getBasedir(), "src/test/jars/test-project-1.0-SNAPSHOT.jar" ) );
227 
228         set.add( new File( getBasedir(), "src/test/jars/plexus-utils-1.4.1.jar" ) );
229 
230         List<Relocator> relocators = new ArrayList<>();
231 
232         relocators.add( new SimpleRelocator( "org/codehaus/plexus/util", shadedPattern, null, Arrays.asList(
233                 "org/codehaus/plexus/util/xml/Xpp3Dom", "org/codehaus/plexus/util/xml/pull.*") ) );
234 
235         List<ResourceTransformer> resourceTransformers = new ArrayList<>();
236 
237         resourceTransformers.add( new ComponentsXmlResourceTransformer() );
238 
239         List<Filter> filters = new ArrayList<>();
240 
241         ShadeRequest shadeRequest = new ShadeRequest();
242         shadeRequest.setJars( set );
243         shadeRequest.setUberJar( jar );
244         shadeRequest.setFilters( filters );
245         shadeRequest.setRelocators( relocators );
246         shadeRequest.setResourceTransformers( resourceTransformers );
247 
248         s.shade( shadeRequest );
249     }
250 
251 }