Skip to content

Commit fa396f9

Browse files
committed
[MSHADE-366] Refactor fix by @JanMosigItemis from #83
- Simplify Jan's solution from #83 in order to use 'continue' instead of nested 'if-else'. - Factor out two helper methods from 'removeServices', because that method was way too big to still be readable. - DRY-refactor Jan's new test cases into one checking two conditions.
1 parent e608482 commit fa396f9

2 files changed

Lines changed: 78 additions & 71 deletions

File tree

src/main/java/org/apache/maven/plugins/shade/filter/MinijarFilter.java

Lines changed: 68 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@
3535
import java.io.IOException;
3636
import java.io.InputStream;
3737
import java.io.InputStreamReader;
38-
import java.nio.file.Files;
39-
import java.nio.file.Paths;
4038
import java.util.Collections;
4139
import java.util.Enumeration;
4240
import java.util.HashSet;
@@ -133,63 +131,14 @@ private void removeServices( final MavenProject project, final Clazzpath cp )
133131
{
134132
for ( final String fileName : project.getRuntimeClasspathElements() )
135133
{
136-
if ( !Files.isDirectory( Paths.get( fileName ) ) )
134+
if ( new File( fileName ).isDirectory() )
137135
{
138-
try ( final JarFile jar = new JarFile( fileName ) )
139-
{
140-
for ( final Enumeration<JarEntry> entries = jar.entries(); entries.hasMoreElements(); )
141-
{
142-
final JarEntry jarEntry = entries.nextElement();
143-
if ( jarEntry.isDirectory() || !jarEntry.getName().startsWith( "META-INF/services/" ) )
144-
{
145-
continue;
146-
}
147-
148-
final String serviceClassName =
149-
jarEntry.getName().substring( "META-INF/services/".length() );
150-
final boolean isNeededClass = neededClasses.contains( cp.getClazz( serviceClassName ) );
151-
if ( !isNeededClass )
152-
{
153-
continue;
154-
}
155-
156-
try ( final BufferedReader bufferedReader =
157-
new BufferedReader( new InputStreamReader( jar.getInputStream( jarEntry ), UTF_8 ) ) )
158-
{
159-
for ( String line = bufferedReader.readLine(); line != null;
160-
line = bufferedReader.readLine() )
161-
{
162-
final String className = line.split( "#", 2 )[0].trim();
163-
if ( className.isEmpty() )
164-
{
165-
continue;
166-
}
167-
168-
final Clazz clazz = cp.getClazz( className );
169-
if ( clazz == null || !removable.contains( clazz ) )
170-
{
171-
continue;
172-
}
173-
174-
log.debug( className + " was not removed because it is a service" );
175-
removeClass( clazz );
176-
repeatScan = true; // check whether the found classes use services in turn
177-
}
178-
}
179-
catch ( final IOException e )
180-
{
181-
log.warn( e.getMessage() );
182-
}
183-
}
184-
}
185-
catch ( final IOException e )
186-
{
187-
log.warn( e.getMessage() );
188-
}
136+
log.debug( "Not a JAR file candidate. Ignoring classpath element '" + fileName + "'." );
137+
continue;
189138
}
190-
else
139+
if ( removeServicesFromJar( cp, neededClasses, fileName ) )
191140
{
192-
log.debug( "Not a JAR file candidate. Ignoring classpath element '" + fileName + "'." );
141+
repeatScan = true;
193142
}
194143
}
195144
}
@@ -201,6 +150,69 @@ private void removeServices( final MavenProject project, final Clazzpath cp )
201150
while ( repeatScan );
202151
}
203152

153+
private boolean removeServicesFromJar( Clazzpath cp, Set<Clazz> neededClasses, String fileName )
154+
{
155+
boolean repeatScan = false;
156+
try ( final JarFile jar = new JarFile( fileName ) )
157+
{
158+
for ( final Enumeration<JarEntry> entries = jar.entries(); entries.hasMoreElements(); )
159+
{
160+
final JarEntry jarEntry = entries.nextElement();
161+
if ( jarEntry.isDirectory() || !jarEntry.getName().startsWith( "META-INF/services/" ) )
162+
{
163+
continue;
164+
}
165+
166+
final String serviceClassName = jarEntry.getName().substring( "META-INF/services/".length() );
167+
final boolean isNeededClass = neededClasses.contains( cp.getClazz( serviceClassName ) );
168+
if ( !isNeededClass )
169+
{
170+
continue;
171+
}
172+
173+
try ( final BufferedReader configFileReader = new BufferedReader(
174+
new InputStreamReader( jar.getInputStream( jarEntry ), UTF_8 ) ) )
175+
{
176+
// check whether the found classes use services in turn
177+
repeatScan = scanServiceProviderConfigFile( cp, configFileReader );
178+
}
179+
catch ( final IOException e )
180+
{
181+
log.warn( e.getMessage() );
182+
}
183+
}
184+
}
185+
catch ( final IOException e )
186+
{
187+
log.warn( e.getMessage() );
188+
}
189+
return repeatScan;
190+
}
191+
192+
private boolean scanServiceProviderConfigFile( Clazzpath cp, BufferedReader configFileReader ) throws IOException
193+
{
194+
boolean serviceClassFound = false;
195+
for ( String line = configFileReader.readLine(); line != null; line = configFileReader.readLine() )
196+
{
197+
final String className = line.split( "#", 2 )[0].trim();
198+
if ( className.isEmpty() )
199+
{
200+
continue;
201+
}
202+
203+
final Clazz clazz = cp.getClazz( className );
204+
if ( clazz == null || !removable.contains( clazz ) )
205+
{
206+
continue;
207+
}
208+
209+
log.debug( className + " was not removed because it is a service" );
210+
removeClass( clazz );
211+
serviceClassFound = true;
212+
}
213+
return serviceClassFound;
214+
}
215+
204216
private void removeClass( final Clazz clazz )
205217
{
206218
removable.remove( clazz );

src/test/java/org/apache/maven/plugins/shade/filter/MinijarFilterTest.java

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -166,27 +166,22 @@ public void finishedShouldProduceMessageForClassesTotalZero()
166166
}
167167

168168
/**
169-
* Check that the algorithm that removes services does not consider directories comming from the
170-
* classpath as jar file candidates.
171-
*
172-
* @see https://issues.apache.org/jira/browse/MSHADE-366
169+
* Verify that directories are ignored when scanning the classpath for JARs containing services,
170+
* but warnings are logged instead
171+
*
172+
* @see <a href="https://issues.apache.org/jira/browse/MSHADE-366">MSHADE-366</a>
173173
*/
174174
@Test
175-
public void remove_services_ignores_directories() throws Exception {
176-
MavenProject mockedProject = mockProject(emptyFile, tempFolder.getRoot().getAbsolutePath());
177-
178-
new MinijarFilter(mockedProject, log);
179-
180-
verify(log, never()).warn(logCaptor.capture());
181-
}
182-
183-
@Test
184-
public void remove_services_logs_ignored_items() throws Exception {
175+
public void removeServicesShouldIgnoreDirectories() throws Exception {
185176
String classPathElementToIgnore = tempFolder.getRoot().getAbsolutePath();
186177
MavenProject mockedProject = mockProject(emptyFile, classPathElementToIgnore);
187178

188179
new MinijarFilter(mockedProject, log);
189180

190-
verify(log, times(1)).debug("Not a JAR file candidate. Ignoring classpath element '" + classPathElementToIgnore + "'.");
181+
verify(log, never()).warn(logCaptor.capture());
182+
verify(log, times(1)).debug(
183+
"Not a JAR file candidate. Ignoring classpath element '" + classPathElementToIgnore + "'."
184+
);
191185
}
186+
192187
}

0 commit comments

Comments
 (0)