-
Notifications
You must be signed in to change notification settings - Fork 1k
/
JarFileUtils.java
133 lines (121 loc) · 4.52 KB
/
JarFileUtils.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package org.testng;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.Objects;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.testng.collections.Lists;
import org.testng.internal.Utils;
import org.testng.reporters.Files;
import org.testng.util.Strings;
import org.testng.xml.IPostProcessor;
import org.testng.xml.XmlSuite;
import org.testng.xml.internal.Parser;
import org.testng.xml.internal.TestNamesMatcher;
import org.testng.xml.internal.XmlSuiteUtils;
/** A Utility for extracting {@link XmlSuite} from a jar. */
class JarFileUtils {
private final IPostProcessor processor;
private final String xmlPathInJar;
private final List<String> testNames;
private final List<XmlSuite> suites = Lists.newLinkedList();
private final XmlSuite.ParallelMode mode;
JarFileUtils(IPostProcessor processor, String xmlPathInJar, List<String> testNames) {
this(processor, xmlPathInJar, testNames, XmlSuite.ParallelMode.NONE);
}
JarFileUtils(
IPostProcessor processor,
String xmlPathInJar,
List<String> testNames,
XmlSuite.ParallelMode mode) {
this.processor = processor;
this.xmlPathInJar = xmlPathInJar;
this.testNames = testNames;
this.mode = mode == null ? XmlSuite.ParallelMode.NONE : mode;
}
List<XmlSuite> extractSuitesFrom(File jarFile) {
try {
Utils.log("TestNG", 2, "Trying to open jar file:" + jarFile);
List<String> classes = Lists.newArrayList();
boolean foundTestngXml = testngXmlExistsInJar(jarFile, classes);
if (!foundTestngXml) {
Utils.log(
"TestNG",
1,
"Couldn't find the " + xmlPathInJar + " in the jar file, running all the classes");
XmlSuite suite = XmlSuiteUtils.newXmlSuiteUsing(classes);
suite.setParallel(this.mode);
suites.add(suite);
}
} catch (IOException ex) {
throw new TestNGException(ex);
}
return suites;
}
private boolean testngXmlExistsInJar(File jarFile, List<String> classes) throws IOException {
try (JarFile jf = new JarFile(jarFile)) {
Enumeration<JarEntry> entries = jf.entries();
File file = java.nio.file.Files.createTempDirectory("testngXmlPathInJar-").toFile();
String suitePath = null;
while (entries.hasMoreElements()) {
JarEntry je = entries.nextElement();
String jeName = je.getName();
if (Parser.canParse(jeName.toLowerCase())) {
InputStream inputStream = jf.getInputStream(je);
File copyFile = new File(file, jeName);
if (!copyFile.toPath().normalize().startsWith(file.toPath().normalize())) {
throw new IOException("Bad zip entry");
}
copyFile.getParentFile().mkdirs();
Files.copyFile(inputStream, copyFile);
if (matchesXmlPathInJar(je)) {
suitePath = copyFile.toString();
}
} else if (isJavaClass(je)) {
classes.add(constructClassName(je));
}
}
if (Strings.isNullOrEmpty(suitePath)) {
return false;
}
Collection<XmlSuite> parsedSuites = Parser.parse(suitePath, processor);
delete(file);
for (XmlSuite suite : parsedSuites) {
// If test names were specified, only run these test names
if (testNames != null) {
TestNamesMatcher testNamesMatcher = new TestNamesMatcher(suite, testNames);
List<String> missMatchedTestname = testNamesMatcher.getMissMatchedTestNames();
if (!missMatchedTestname.isEmpty()) {
throw new TestNGException("The test(s) <" + missMatchedTestname + "> cannot be found.");
}
suites.addAll(testNamesMatcher.getSuitesMatchingTestNames());
} else {
suites.add(suite);
}
return true;
}
}
return false;
}
private void delete(File f) throws IOException {
if (f.isDirectory()) {
for (File c : Objects.requireNonNull(f.listFiles())) delete(c);
}
if (!f.delete()) throw new FileNotFoundException("Failed to delete file: " + f);
}
private boolean matchesXmlPathInJar(JarEntry je) {
return je.getName().equals(xmlPathInJar);
}
private static boolean isJavaClass(JarEntry je) {
return je.getName().endsWith(".class");
}
private static String constructClassName(JarEntry je) {
int n = je.getName().length() - ".class".length();
return je.getName().replace("/", ".").substring(0, n);
}
}