Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 3 additions & 9 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@

<groupId>com.checkmarx.ast</groupId>
<artifactId>ast-cli-java-wrapper</artifactId>
<version>1.0.15</version>
<version>1.0.17</version>
<packaging>jar</packaging>

<name>Checkmarx AST Client</name>
<description>Checkmarx AST ClI SDK</description>
<url>https://www.checkmarx.com</url>

<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>

<dependencies>
Expand Down Expand Up @@ -66,12 +66,6 @@
<version>5.7.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
15 changes: 6 additions & 9 deletions src/main/java/com/checkmarx/ast/wrapper/CxWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -32,21 +29,21 @@ public class CxWrapper {
@NonNull
private final Logger logger;
@NonNull
private final URI executable;
private final String executable;

public CxWrapper(@NonNull CxConfig cxConfig)
throws CxConfig.InvalidCLIConfigException, URISyntaxException, IOException {
throws CxConfig.InvalidCLIConfigException, IOException {
this(cxConfig, LoggerFactory.getLogger(CxWrapper.class));
}

public CxWrapper(@NonNull CxConfig cxConfig, @NonNull Logger logger) throws CxConfig.InvalidCLIConfigException,
URISyntaxException, IOException {
IOException {
cxConfig.validate();
this.cxConfig = cxConfig;
this.logger = logger;
this.executable = StringUtils.isBlank(this.cxConfig.getPathToExecutable())
? Execution.detectBinary()
: new File(this.cxConfig.getPathToExecutable()).toURI();
? Execution.getTempBinary()
: this.cxConfig.getPathToExecutable();
this.logger.info("using executable: " + executable);
}

Expand Down Expand Up @@ -189,7 +186,7 @@ public String results(@NonNull UUID scanId, ReportFormat reportFormat)
private List<String> withConfigArguments(List<String> commands) {
List<String> arguments = new ArrayList<>();

arguments.add(this.executable.getPath());
arguments.add(this.executable);
arguments.addAll(commands);
arguments.addAll(this.cxConfig.toArguments());

Expand Down
105 changes: 74 additions & 31 deletions src/main/java/com/checkmarx/ast/wrapper/Execution.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
import org.slf4j.Logger;

import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
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 {
Expand All @@ -29,8 +30,9 @@ private Execution() {
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 URL executable = null;
private static String executable = null;

static <T> T executeCommand(List<String> arguments,
Logger logger,
Expand Down Expand Up @@ -83,6 +85,29 @@ static String executeCommand(List<String> arguments,
StandardCharsets.UTF_8);
}

static String getTempBinary() throws IOException {
if (executable == null) {
String fileName = detectBinaryName();
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);
Expand All @@ -95,38 +120,56 @@ private static Process buildProcess(List<String> commands) throws IOException {
return lmBuilder.start();
}

/**
* Detect binary name by the current architecture.
*
* @return binary name
* @throws IOException when architecture is unsupported
* @throws URISyntaxException when the file has an invalid URI
*/
public static URI detectBinary() throws IOException, URISyntaxException {
if (executable == null) {
final String arch = OS_NAME;
String fileName = null;
if (arch.contains(OS_LINUX)) {
fileName = FILE_NAME_LINUX;
} else if (arch.contains(OS_WINDOWS)) {
fileName = FILE_NAME_WINDOWS;
} else {
for (String macStr : OS_MAC) {
if (arch.contains(macStr)) {
fileName = FILE_NAME_MAC;
break;
}
private static String detectBinaryName() {
String arch = OS_NAME;
String fileName = null;
if (arch.contains(OS_LINUX)) {
fileName = FILE_NAME_LINUX;
} else if (arch.contains(OS_WINDOWS)) {
fileName = FILE_NAME_WINDOWS;
} else {
for (String macStr : OS_MAC) {
if (arch.contains(macStr)) {
fileName = FILE_NAME_MAC;
break;
}
}
if (fileName == null) {
throw new IOException("Unsupported architecture");
}
return fileName;
}

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);
}
executable = Execution.class.getClassLoader().getResource(fileName);
} catch (IOException e) {
throw new IOException("Could not copy CLI to the temporary directory", e);
}
URL resource = executable;
if (resource == null) {
throw new NoSuchFileException("Could not find CLI executable");
}

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");
int i;
while ((i = a.read(buf)) != -1) {
md.update(buf, 0, i);
}
md5 = new String(md.digest());
} catch (NoSuchAlgorithmException | IOException e) {
// ignore
}
return resource.toURI();
return md5;
}
}