View Javadoc
1   package org.apache.maven.plugins.shade.filter;
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.hamcrest.MatcherAssert.assertThat;
23  import static org.hamcrest.Matchers.startsWith;
24  import static org.junit.Assert.assertEquals;
25  import static org.junit.Assert.fail;
26  import static org.junit.Assume.assumeFalse;
27  import static org.mockito.Mockito.mock;
28  import static org.mockito.Mockito.times;
29  import static org.mockito.Mockito.verify;
30  import static org.mockito.Mockito.when;
31  
32  import java.io.File;
33  import java.io.FileOutputStream;
34  import java.io.IOException;
35  import java.util.ArrayList;
36  import java.util.Arrays;
37  import java.util.List;
38  import java.util.Set;
39  import java.util.TreeSet;
40  import java.util.jar.JarOutputStream;
41  
42  import org.apache.maven.artifact.Artifact;
43  import org.apache.maven.artifact.DefaultArtifact;
44  import org.apache.maven.artifact.DependencyResolutionRequiredException;
45  import org.apache.maven.model.Build;
46  import org.apache.maven.plugin.logging.Log;
47  import org.apache.maven.project.MavenProject;
48  import org.junit.Before;
49  import org.junit.Rule;
50  import org.junit.Test;
51  import org.junit.rules.TemporaryFolder;
52  import org.mockito.ArgumentCaptor;
53  
54  public class MinijarFilterTest
55  {
56  
57      @Rule
58      public TemporaryFolder tempFolder = TemporaryFolder.builder().assureDeletion().build();
59  
60      private File outputDirectory;
61      private File emptyFile;
62      private File jarFile;
63      private Log log;
64      private ArgumentCaptor<CharSequence> logCaptor;
65  
66      @Before
67      public void init()
68          throws IOException
69      {
70          this.outputDirectory = tempFolder.newFolder();
71          this.emptyFile = tempFolder.newFile();
72          this.jarFile = tempFolder.newFile();
73          new JarOutputStream( new FileOutputStream( this.jarFile ) ).close();
74          this.log = mock(Log.class);
75          logCaptor = ArgumentCaptor.forClass(CharSequence.class);
76      }
77  
78      /**
79       * This test will fail on JDK 7 because jdependency needs at least JDK 8.
80       */
81      @Test
82      public void testWithMockProject()
83          throws IOException
84      {
85          assumeFalse( "Expected to run under JDK8+", System.getProperty("java.version").startsWith("1.7") );
86  
87          MavenProject mavenProject = mockProject( outputDirectory, emptyFile );
88  
89          MinijarFilter mf = new MinijarFilter( mavenProject, log );
90  
91          mf.finished();
92  
93          verify( log, times( 1 ) ).info( logCaptor.capture() );
94  
95          assertEquals( "Minimized 0 -> 0", logCaptor.getValue() );
96  
97      }
98  
99      @Test
100     public void testWithPomProject()
101         throws IOException
102     {
103         // project with pom packaging and no artifact.
104         MavenProject mavenProject = mockProject( outputDirectory, null );
105         mavenProject.setPackaging( "pom" );
106 
107         MinijarFilter mf = new MinijarFilter( mavenProject, log );
108 
109         mf.finished();
110 
111         verify( log, times( 1 ) ).info( logCaptor.capture() );
112 
113         // verify no access to project's artifacts
114         verify( mavenProject, times( 0 ) ).getArtifacts();
115 
116         assertEquals( "Minimized 0 -> 0", logCaptor.getValue() );
117 
118     }
119 
120     private MavenProject mockProject( File outputDirectory, File file, String... classPathElements )
121     {
122         MavenProject mavenProject = mock( MavenProject.class );
123 
124         Artifact artifact = mock( Artifact.class );
125         when( artifact.getGroupId() ).thenReturn( "com" );
126         when( artifact.getArtifactId() ).thenReturn( "aid" );
127         when( artifact.getVersion() ).thenReturn( "1.9" );
128         when( artifact.getClassifier() ).thenReturn( "classifier1" );
129         when( artifact.getScope() ).thenReturn( Artifact.SCOPE_COMPILE );
130 
131         when( mavenProject.getArtifact() ).thenReturn( artifact );
132 
133         DefaultArtifact dependencyArtifact =
134             new DefaultArtifact( "dep.com", "dep.aid", "1.0", "compile", "jar", "classifier2", null );
135         dependencyArtifact.setFile( file );
136 
137         Set<Artifact> artifacts = new TreeSet<>();
138         artifacts.add( dependencyArtifact );
139 
140         when( mavenProject.getArtifacts() ).thenReturn( artifacts );
141 
142         when( mavenProject.getArtifact().getFile() ).thenReturn( file );
143 
144         Build build = new Build();
145         build.setOutputDirectory( outputDirectory.toString() );
146 
147         List<String> classpath = new ArrayList<>();
148         classpath.add( outputDirectory.toString() );
149         if ( file != null )
150         {
151             classpath.add(file.toString());
152         }
153         classpath.addAll( Arrays.asList( classPathElements ) );
154         when( mavenProject.getBuild() ).thenReturn( build );
155         try {
156             when(mavenProject.getRuntimeClasspathElements()).thenReturn(classpath);
157         } catch (DependencyResolutionRequiredException e) {
158             fail("Encountered unexpected exception: " + e.getClass().getSimpleName() + ": " + e.getMessage());
159         }
160 
161         return mavenProject;
162     }
163 
164     @Test
165     public void finsishedShouldProduceMessageForClassesTotalNonZero()
166     {
167         MinijarFilter m = new MinijarFilter( 1, 50, log );
168 
169         m.finished();
170 
171         verify( log, times( 1 ) ).info( logCaptor.capture() );
172 
173         assertEquals( "Minimized 51 -> 1 (1%)", logCaptor.getValue() );
174 
175     }
176 
177     @Test
178     public void finishedShouldProduceMessageForClassesTotalZero()
179     {
180         MinijarFilter m = new MinijarFilter( 0, 0, log );
181 
182         m.finished();
183 
184         verify( log, times( 1 ) ).info( logCaptor.capture() );
185 
186         assertEquals( "Minimized 0 -> 0", logCaptor.getValue() );
187 
188     }
189 
190     /**
191      * Verify that directories are ignored when scanning the classpath for JARs containing services,
192      * but warnings are logged instead
193      *
194      * @see <a href="https://issues.apache.org/jira/browse/MSHADE-366">MSHADE-366</a>
195      */
196     @Test
197     public void removeServicesShouldIgnoreDirectories() throws Exception {
198         String classPathElementToIgnore = tempFolder.newFolder().getAbsolutePath();
199         MavenProject mockedProject = mockProject( outputDirectory, jarFile, classPathElementToIgnore );
200 
201         new MinijarFilter(mockedProject, log);
202 
203         verify( log, times( 1 ) ).warn( logCaptor.capture() );
204 
205         assertThat( logCaptor.getValue().toString(), startsWith(
206                 "Not a JAR file candidate. Ignoring classpath element '" + classPathElementToIgnore + "' (" ) );
207     }
208 
209 }