-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathExecution.java
More file actions
216 lines (193 loc) · 7.99 KB
/
Execution.java
File metadata and controls
216 lines (193 loc) · 7.99 KB
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
package com.checkmarx.ast.wrapper;
import lombok.NonNull;
import org.slf4j.Logger;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.function.Function;
public final class Execution {
private Execution() {
}
private static final String OS_LINUX = "linux";
private static final String OS_WINDOWS = "windows";
private static final String OS_MAC = "mac";
private static final List<String> OS_MAC_NAMES = Arrays.asList("mac os x", "darwin", "osx");
private static final String FILE_NAME_LINUX = "cx-linux";
private static final String FILE_NAME_LINUX_ARM = "cx-linux-arm";
private static final String FILE_NAME_MAC = "cx-mac";
private static final String FILE_NAME_WINDOWS = "cx.exe";
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
private static final String TEMP_DIR = System.getProperty("java.io.tmpdir");
private static final String MD5_ALGORITHM = "MD5";
private static String executable = null;
static <T> T executeCommand(List<String> arguments,
Logger logger,
Function<String, T> lineParser)
throws IOException, InterruptedException, CxException {
Process process = buildProcess(arguments);
try (BufferedReader br = getReader(process)) {
T executionResult = null;
String line;
StringBuilder stringBuilder = new StringBuilder();
while ((line = br.readLine()) != null) {
logger.info(line);
stringBuilder.append(line).append(LINE_SEPARATOR);
T parsedLine = lineParser.apply(line);
if (parsedLine != null) {
if (areAllFieldsNotNull(parsedLine) || isAscaRequest(arguments)) {
executionResult = parsedLine;
}
}
}
process.waitFor();
if (process.exitValue() != 0) {
throw new CxException(process.exitValue(), stringBuilder.toString());
}
return executionResult;
}
}
public static boolean isAscaRequest(List<String> arguments) {
return (arguments.size() >= 3 && arguments.get(1).equals("scan") && arguments.get(2).equals("asca"));
}
private static boolean areAllFieldsNotNull(Object obj) {
for (Field field : obj.getClass().getDeclaredFields()) {
field.setAccessible(true);
try {
if (field.get(obj) == null) {
return false;
}
} catch (IllegalAccessException e) {
return false;
}
}
return true;
}
static String executeCommand(List<String> arguments,
Logger logger,
String directory,
String file)
throws IOException, InterruptedException, CxException {
Process process = buildProcess(arguments);
try (BufferedReader br = getReader(process)) {
String line;
StringBuilder stringBuilder = new StringBuilder();
while ((line = br.readLine()) != null) {
logger.info(line);
stringBuilder.append(line).append(LINE_SEPARATOR);
}
process.waitFor();
if (process.exitValue() != 0) {
throw new CxException(process.exitValue(), stringBuilder.toString());
}
}
File outputFile = new File(directory, file);
return new String(Files.readAllBytes(Paths.get(outputFile.getAbsolutePath())),
StandardCharsets.UTF_8);
}
static String getTempBinary(@NonNull Logger logger) throws IOException {
if (executable == null) {
String fileName = detectBinaryName(logger);
if (fileName == null) {
throw new IOException("Unsupported architecture");
}
URL resource = Execution.class.getClassLoader().getResource(fileName);
if (resource == null) {
throw new NoSuchFileException("Could not find CLI executable");
}
File tempExecutable = new File(TEMP_DIR, fileName);
if (!tempExecutable.exists() || !compareChecksum(resource.openStream(),
new FileInputStream(tempExecutable))) {
copyURLToFile(resource, tempExecutable);
}
if (!tempExecutable.canExecute() && !tempExecutable.setExecutable(true)) {
throw new IOException("Could not set CLI as executable");
}
executable = tempExecutable.getAbsolutePath();
}
return executable;
}
private static BufferedReader getReader(Process process) {
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
return new BufferedReader(isr);
}
private static Process buildProcess(List<String> commands) throws IOException {
ProcessBuilder lmBuilder = new ProcessBuilder(commands);
lmBuilder.redirectErrorStream(true);
return lmBuilder.start();
}
private static String detectBinaryName(@NonNull Logger logger) {
String osName = System.getProperty("os.name").toLowerCase(Locale.ENGLISH);
String osArch = System.getProperty("os.arch").toLowerCase(Locale.ENGLISH);
String fileName = null;
switch (getOperatingSystemType(osName)) {
case OS_LINUX:
fileName = osArch.contains("arm") || osArch.contains("aarch64") ? FILE_NAME_LINUX_ARM : FILE_NAME_LINUX;
break;
case OS_WINDOWS:
fileName = FILE_NAME_WINDOWS;
break;
case OS_MAC:
fileName = FILE_NAME_MAC;
break;
default:
// Handle unknown OS
logger.error("Unsupported operating system: {} Architecture: {}", osName, osArch);
break;
}
return fileName;
}
private static String getOperatingSystemType(String osName) {
if (osName.contains(OS_LINUX)) {
return OS_LINUX;
} else if (osName.contains(OS_WINDOWS)) {
return OS_WINDOWS;
} else if (OS_MAC_NAMES.stream().anyMatch(osName::contains)) {
return OS_MAC;
} else {
return "UNKNOWN"; // Handle unknown OS
}
}
private static void copyURLToFile(URL source, File destination) throws IOException {
final byte[] buf = new byte[8192];
try (InputStream reader = source.openStream();
OutputStream writer = new FileOutputStream(destination)) {
int i;
while ((i = reader.read(buf)) != -1) {
writer.write(buf, 0, i);
}
} catch (IOException e) {
throw new IOException("Could not copy CLI to the temporary directory", e);
}
}
private static boolean compareChecksum(InputStream a, InputStream b) {
String aMD5 = md5(a);
String bMD5 = md5(b);
return aMD5 != null && bMD5 != null && Objects.equals(aMD5, bMD5);
}
private static String md5(InputStream a) {
String md5 = null;
final byte[] buf = new byte[8192];
try {
MessageDigest md = MessageDigest.getInstance(MD5_ALGORITHM);
int i;
while ((i = a.read(buf)) != -1) {
md.update(buf, 0, i);
}
md5 = new String(md.digest(), StandardCharsets.UTF_8);
} catch (NoSuchAlgorithmException | IOException e) {
// ignore
}
return md5;
}
}