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         ClassLoader 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      * Tests if a Filter is installed correctly, also if createSourcesJar is set to true.
114      *
115      * @throws Exception
116      */
117     public void testShadeWithFilter()
118         throws Exception
119     {
120         ShadeMojo mojo = new ShadeMojo();
121 
122         // set createSourcesJar = true
123         Field createSourcesJar = ShadeMojo.class.getDeclaredField( "createSourcesJar" );
124         createSourcesJar.setAccessible( true );
125         createSourcesJar.set( mojo, Boolean.TRUE );
126 
127         // configure artifactResolver (mocked) for mojo
128         ArtifactResolver mockArtifactResolver = new ArtifactResolver()
129         {
130             @Override
131             public ArtifactResult resolveArtifact( ProjectBuildingRequest req, final Artifact art )
132                 throws ArtifactResolverException
133             {
134                 return new ArtifactResult()
135                 {
136 
137                     @Override
138                     public Artifact getArtifact()
139                     {
140                         art.setResolved( true );
141                         String fileName = art.getArtifactId() + "-" + art.getVersion()
142                             + ( art.getClassifier() != null ? "-" + art.getClassifier() : "" ) + ".jar";
143                         art.setFile( new File( fileName ) );
144                         return art;
145                     }
146                 };
147             }
148 
149             @Override
150             public ArtifactResult resolveArtifact( ProjectBuildingRequest req, final ArtifactCoordinate coordinate )
151                 throws ArtifactResolverException
152             {
153                 return new ArtifactResult()
154                 {
155 
156                     @Override
157                     public Artifact getArtifact()
158                     {
159                         Artifact art = mock( Artifact.class );
160                         when( art.getGroupId() ).thenReturn( coordinate.getGroupId() );
161                         when( art.getArtifactId() ).thenReturn( coordinate.getArtifactId() );
162                         when( art.getType() ).thenReturn( coordinate.getExtension() );
163                         when( art.getClassifier() ).thenReturn( coordinate.getClassifier() );
164                         when( art.isResolved() ).thenReturn( true );
165                         String fileName = coordinate.getArtifactId() + "-" + coordinate.getVersion()
166                             + ( coordinate.getClassifier() != null ? "-" + coordinate.getClassifier() : "" ) + ".jar";
167                         when( art.getFile() ).thenReturn( new File( fileName ) );
168                         return art;
169                     }
170                 };
171             }
172         };
173         Field artifactResolverField = ShadeMojo.class.getDeclaredField( "artifactResolver" );
174         artifactResolverField.setAccessible( true );
175         artifactResolverField.set( mojo, mockArtifactResolver );
176 
177         // create and configure MavenProject
178         MavenProject project = new MavenProject();
179         ArtifactHandler artifactHandler = (ArtifactHandler) lookup( ArtifactHandler.ROLE );
180         Artifact artifact = new DefaultArtifact( "org.apache.myfaces.core", "myfaces-impl",
181                                                  VersionRange.createFromVersion( "2.0.1-SNAPSHOT" ), "compile", "jar",
182                                                  null, artifactHandler );
183         artifact = mockArtifactResolver.resolveArtifact( null, artifact ).getArtifact(); // setFile and setResolved
184         project.setArtifact( artifact );
185         Field projectField = ShadeMojo.class.getDeclaredField( "project" );
186         projectField.setAccessible( true );
187         projectField.set( mojo, project );
188 
189         // create and configure the ArchiveFilter
190         ArchiveFilter archiveFilter = new ArchiveFilter();
191         Field archiveFilterArtifact = ArchiveFilter.class.getDeclaredField( "artifact" );
192         archiveFilterArtifact.setAccessible( true );
193         archiveFilterArtifact.set( archiveFilter, "org.apache.myfaces.core:myfaces-impl" );
194 
195         // add ArchiveFilter to mojo
196         Field filtersField = ShadeMojo.class.getDeclaredField( "filters" );
197         filtersField.setAccessible( true );
198         filtersField.set( mojo, new ArchiveFilter[]{ archiveFilter } );
199 
200         Field sessionField = ShadeMojo.class.getDeclaredField( "session" );
201         sessionField.setAccessible( true );
202         sessionField.set( mojo, mock( MavenSession.class ) );
203 
204         // invoke getFilters()
205         Method getFilters = ShadeMojo.class.getDeclaredMethod( "getFilters" );
206         getFilters.setAccessible( true );
207         List<Filter> filters = (List<Filter>) getFilters.invoke( mojo);
208 
209         // assertions - there must be one filter
210         assertEquals( 1, filters.size() );
211 
212         // the filter must be able to filter the binary and the sources jar
213         Filter filter = filters.get( 0 );
214         assertTrue( filter.canFilter( new File( "myfaces-impl-2.0.1-SNAPSHOT.jar" ) ) ); // binary jar
215         assertTrue( filter.canFilter( new File( "myfaces-impl-2.0.1-SNAPSHOT-sources.jar" ) ) ); // sources jar
216     }
217 
218     public void shaderWithPattern( String shadedPattern, File jar )
219         throws Exception
220     {
221         Shader s = (Shader) lookup( Shader.ROLE );
222 
223         Set<File> set = new LinkedHashSet<>();
224 
225         set.add( new File( getBasedir(), "src/test/jars/test-project-1.0-SNAPSHOT.jar" ) );
226 
227         set.add( new File( getBasedir(), "src/test/jars/plexus-utils-1.4.1.jar" ) );
228 
229         List<Relocator> relocators = new ArrayList<>();
230 
231         relocators.add( new SimpleRelocator( "org/codehaus/plexus/util", shadedPattern, null, Arrays.asList(
232                 "org/codehaus/plexus/util/xml/Xpp3Dom", "org/codehaus/plexus/util/xml/pull.*") ) );
233 
234         List<ResourceTransformer> resourceTransformers = new ArrayList<>();
235 
236         resourceTransformers.add( new ComponentsXmlResourceTransformer() );
237 
238         List<Filter> filters = new ArrayList<>();
239 
240         ShadeRequest shadeRequest = new ShadeRequest();
241         shadeRequest.setJars( set );
242         shadeRequest.setUberJar( jar );
243         shadeRequest.setFilters( filters );
244         shadeRequest.setRelocators( relocators );
245         shadeRequest.setResourceTransformers( resourceTransformers );
246 
247         s.shade( shadeRequest );
248     }
249 
250 }