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