in src/main/java/com/uber/intellij/jd/Decompiler.java [47:155]
public static void main(String[] args) throws IOException {
if (args.length < 2) {
System.err.println("Should pass input jar and target directory.");
System.exit(1);
}
// Parse command-line arguments
int timeout = DEFAULT_DECOMPILER_TIMEOUT_SECONDS;
int maxFiles = DEFAULT_MAX_ALLOWED_FILES_IN_JAR;
String outputJarPath = DEFAULT_OUTPUT_FILE_NAME;
List<String> remainingArgs = new ArrayList<>();
for (String arg : args) {
if (arg.startsWith(DECOMPILER_TIMEOUT_SECONDS_KEY_PREFIX)) {
timeout =
parseIntArgument(
arg, DECOMPILER_TIMEOUT_SECONDS_KEY_PREFIX, DEFAULT_DECOMPILER_TIMEOUT_SECONDS);
} else if (arg.startsWith(MAX_ALLOWED_FILES_IN_JAR_KEY_PREFIX)) {
maxFiles =
parseIntArgument(
arg, MAX_ALLOWED_FILES_IN_JAR_KEY_PREFIX, DEFAULT_MAX_ALLOWED_FILES_IN_JAR);
} else if (arg.startsWith(DECOMPILER_OUTPUT_FILE_NAME_KEY_PREFIX)) {
outputJarPath = arg.substring(DECOMPILER_OUTPUT_FILE_NAME_KEY_PREFIX.length());
} else {
remainingArgs.add(arg);
}
}
if (outputJarPath.isEmpty() || remainingArgs.isEmpty()) {
System.err.println("Should pass input jar and output options.");
System.exit(1);
}
args = remainingArgs.toArray(new String[0]);
String jarFilePath = args[args.length - 1];
// create temp dir
Path tmpDir = Files.createTempDirectory(UUID.randomUUID().toString());
// Validate the JAR file
try {
long fileCount = countFilesInJar(jarFilePath);
if (fileCount > maxFiles) {
System.err.println(
"JAR "
+ jarFilePath
+ " contains "
+ fileCount
+ " files. More than allowed threshold of "
+ maxFiles
+ ". Creating empty JAR. Skipping decompilation.");
// create empty jars in the output location and skip decompilation
createEmptyJar(outputJarPath);
return;
}
} catch (IOException e) {
System.err.println("Error opening JAR file: " + e.getMessage());
killSignal();
}
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
// Add the temporary directory to the arguments for ConsoleDecompiler, since
// it expects the output directory as the last argument.
String[] finalArgs =
Stream.concat(Arrays.stream(args), Stream.of(tmpDir.toString())).toArray(String[]::new);
Runnable task =
() -> {
ConsoleDecompiler.main(finalArgs);
};
Runnable killSignalTask = Decompiler::killSignal;
Future<?> future = executor.submit(task);
executor.schedule(killSignalTask, timeout, TimeUnit.SECONDS);
try {
future.get(timeout, TimeUnit.SECONDS);
} catch (TimeoutException | InterruptedException | ExecutionException e) {
System.out.println("Task timed out.");
// Nuke process.
killSignal();
} finally {
executor.shutdownNow();
}
try (Stream<Path> paths = Files.walk(tmpDir)) {
Optional<Path> decompiledJar =
paths
.filter(Files::isRegularFile)
.filter(path -> path.toString().endsWith(".jar"))
.findFirst();
// If the decompiled jar is present, move it to the output path
if (decompiledJar.isPresent()) {
try {
Files.move(decompiledJar.get(), Paths.get(outputJarPath));
setCreationTimeToEpoch(outputJarPath);
} catch (IOException e) {
String message = String.format("Error moving file: %s", e.getMessage());
System.err.println(message);
throw new IOException(message, e);
}
} else {
// create empty jars in the output location in order to cache bazel action.
createEmptyJar(outputJarPath);
}
}
}