1 package org.apache.maven.plugin.surefire.util;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 import static org.apache.maven.plugin.surefire.util.ScannerUtil.convertJarFileResourceToJavaClassName;
22 import static org.apache.maven.plugin.surefire.util.ScannerUtil.convertSlashToSystemFileSeparator;
23 import static org.apache.maven.plugin.surefire.util.ScannerUtil.processIncludesExcludes;
24
25 import java.io.File;
26 import java.io.IOException;
27 import java.util.ArrayList;
28 import java.util.Enumeration;
29 import java.util.List;
30 import java.util.jar.JarEntry;
31 import java.util.jar.JarFile;
32
33 import org.apache.maven.artifact.Artifact;
34 import org.apache.maven.plugin.MojoExecutionException;
35 import org.apache.maven.shared.utils.io.MatchPatterns;
36 import org.apache.maven.surefire.util.DefaultScanResult;
37
38 import javax.annotation.Nonnull;
39 import javax.annotation.Nullable;
40
41
42
43
44
45
46 public class DependencyScanner
47 {
48
49 private final List<File> dependenciesToScan;
50
51 protected final List<String> includes;
52
53 protected final @Nonnull List<String> excludes;
54
55 protected final List<String> specificTests;
56
57 public DependencyScanner( List<File> dependenciesToScan, List<String> includes, @Nonnull List<String> excludes, List<String> specificTests )
58 {
59 this.dependenciesToScan = dependenciesToScan;
60 this.includes = includes;
61 this.excludes = excludes;
62 this.specificTests = specificTests;
63 }
64
65 public DefaultScanResult scan()
66 throws MojoExecutionException
67 {
68 Matcher matcher = new Matcher( includes, excludes, specificTests );
69 List<String> found = new ArrayList<String>();
70 for ( File artifact : dependenciesToScan )
71 {
72 try
73 {
74 found.addAll( scanArtifact( artifact, matcher ) );
75 }
76 catch ( IOException e )
77 {
78 throw new MojoExecutionException( "Could not scan dependency " + artifact.toString(), e );
79 }
80 }
81 return new DefaultScanResult( found );
82 }
83
84 private List<String> scanArtifact( File artifact, Matcher matcher )
85 throws IOException
86 {
87 List<String> found = new ArrayList<String>();
88
89 if ( artifact != null )
90 {
91 if ( artifact.isFile() )
92 {
93 JarFile jar = null;
94 try
95 {
96 jar = new JarFile( artifact );
97 Enumeration<JarEntry> entries = jar.entries();
98 while ( entries.hasMoreElements() )
99 {
100 JarEntry entry = entries.nextElement();
101 if ( matcher.shouldInclude( entry.getName() ) )
102 {
103 found.add( convertJarFileResourceToJavaClassName( entry.getName() ) );
104 }
105 }
106 }
107 finally
108 {
109 if ( jar != null )
110 {
111 jar.close();
112 }
113 }
114 }
115 }
116 return found;
117 }
118
119 public static List<File> filter( List<Artifact> artifacts, List<String> groupArtifactIds )
120 {
121 List<File> matches = new ArrayList<File>();
122 if ( groupArtifactIds == null || artifacts == null )
123 {
124 return matches;
125 }
126 for ( Artifact artifact : artifacts )
127 {
128 for ( String groups : groupArtifactIds )
129 {
130 String[] groupArtifact = groups.split( ":" );
131 if ( groupArtifact.length != 2 )
132 {
133 throw new IllegalArgumentException(
134 "dependencyToScan argument should be in format 'groupid:artifactid': "
135 + groups );
136 }
137 if ( artifact.getGroupId().matches( groupArtifact[0] )
138 && artifact.getArtifactId().matches( groupArtifact[1] ) )
139 {
140 matches.add( artifact.getFile() );
141 }
142 }
143 }
144 return matches;
145 }
146
147 private class Matcher
148 {
149
150 private MatchPatterns includes;
151
152 private MatchPatterns excludes;
153
154 private SpecificFileFilter specificTestFilter;
155
156 public Matcher( @Nullable List<String> includes, @Nonnull List<String> excludes, @Nullable List<String> specificTests )
157 {
158 String[] specific = specificTests == null ? new String[0] : processIncludesExcludes( specificTests );
159 specificTestFilter = new SpecificFileFilter( specific );
160
161 if ( includes != null && includes.size() > 0 )
162 {
163 this.includes = MatchPatterns.from( processIncludesExcludes( includes ) );
164 }
165 else
166 {
167 this.includes = MatchPatterns.from( "**" );
168 }
169 this.excludes = MatchPatterns.from( processIncludesExcludes( excludes ) );
170 }
171
172 public boolean shouldInclude( String name )
173 {
174 if ( !name.endsWith( ".class" ) )
175 {
176 return false;
177 }
178 name = convertSlashToSystemFileSeparator( name );
179 boolean isIncluded = includes.matches( name, false );
180 boolean isExcluded = excludes.matches( name, false );
181
182 return isIncluded && !isExcluded && specificTestFilter.accept( name );
183 }
184 }
185 }