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