Skip to content

[java-source-utils] Add response file support #744

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

Expand Down Expand Up @@ -40,7 +42,8 @@
public class JavaSourceUtilsOptions implements AutoCloseable {
public static final String HELP_STRING = "[-v] [<-a|--aar> AAR]* [<-j|--jar> JAR]* [<-s|--source> DIRS]*\n" +
"\t[--bootclasspath CLASSPATH]\n" +
"\t[<-P|--output-params> OUT.params.txt] [<-D|--output-javadoc> OUT.xml] FILES";
"\t[<-P|--output-params> OUT.params.txt] [<-D|--output-javadoc> OUT.xml]\n" +
"\t[@RESPONSE-FILE]* FILES";

public static boolean verboseOutput;

Expand Down Expand Up @@ -111,14 +114,15 @@ private final TypeSolver createTypeSolver(ParserConfiguration config) throws IOE
return typeSolver;
}

public static JavaSourceUtilsOptions parse(final String[] args) throws IOException {
final JavaSourceUtilsOptions options = new JavaSourceUtilsOptions();
private final JavaSourceUtilsOptions parse(Iterator<String> args) throws IOException {
if (args == null || !args.hasNext())
return this;

for (int i = 0; i < args.length; ++i) {
final String arg = args[i];
while (args.hasNext()) {
String arg = args.next();
switch (arg) {
case "-bootclasspath": {
final String bootClassPath = getOptionValue(args, ++i, arg);
final String bootClassPath = getNextOptionValue(args, arg);
final ArrayList<File> files = new ArrayList<File>();
for (final String cp : bootClassPath.split(File.pathSeparator)) {
final File file = new File(cp);
Expand All @@ -129,46 +133,46 @@ public static JavaSourceUtilsOptions parse(final String[] args) throws IOExcepti
files.add(file);
}
for (int j = files.size(); j > 0; --j) {
options.jarFiles.add(0, files.get(j-1));
jarFiles.add(0, files.get(j-1));
}
options.haveBootClassPath = true;
haveBootClassPath = true;
break;
}
case "-a":
case "--aar": {
final File file = getOptionFile(args, ++i, arg);
final File file = getNextOptionFile(args, arg);
if (file == null) {
break;
}
options.aarFiles.add(file);
aarFiles.add(file);
break;
}
case "-j":
case "--jar": {
final File file = getOptionFile(args, ++i, arg);
final File file = getNextOptionFile(args, arg);
if (file == null) {
break;
}
options.jarFiles.add(file);
jarFiles.add(file);
break;
}
case "-s":
case "--source": {
final File dir = getOptionFile(args, ++i, arg);
final File dir = getNextOptionFile(args, arg);
if (dir == null) {
break;
}
options.sourceDirectoryFiles.add(dir);
sourceDirectoryFiles.add(dir);
break;
}
case "-D":
case "--output-javadoc": {
options.outputJavadocXml = getOptionValue(args, ++i, arg);
outputJavadocXml = getNextOptionValue(args, arg);
break;
}
case "-P":
case "--output-params": {
options.outputParamsTxt = getOptionValue(args, ++i, arg);
outputParamsTxt = getNextOptionValue(args, arg);
break;
}
case "-v": {
Expand All @@ -180,37 +184,63 @@ public static JavaSourceUtilsOptions parse(final String[] args) throws IOExcepti
return null;
}
default: {
final File file = getOptionFile(args, i, "FILES");
if (file == null)
if (arg.startsWith("@")) {
// response file?
final String responseFileName = arg.substring(1);
final File responseFile = new File(responseFileName);
if (responseFile.exists()) {
final Iterator<String> lines =
Files.readAllLines(responseFile.toPath())
.stream()
.filter(line -> line.length() > 0 && !line.startsWith("#"))
.iterator();

final JavaSourceUtilsOptions r = parse(lines);
if (r == null)
return null;
break;
}
}
final File file = new File(arg);
if (!file.exists()) {
System.err.println(App.APP_NAME + ": warning: invalid file path for option `FILES`: " + arg);
break;
}

if (file.isDirectory()) {
options.sourceDirectoryFiles.add(file);
sourceDirectoryFiles.add(file);
Files.walk(file.toPath())
.filter(f -> Files.isRegularFile(f) && f.getFileName().toString().endsWith(".java"))
.map(Path::toFile)
.forEach(f -> options.inputFiles.add(f));
.forEach(f -> inputFiles.add(f));
break;
}
if (file.getName().endsWith(".java")) {
options.inputFiles.add(file);
inputFiles.add(file);
break;
}
if (!file.getName().endsWith(".jar") && !file.getName().endsWith(".zip")) {
System.err.println(App.APP_NAME + ": warning: ignoring input file `" + file.getAbsolutePath() +"`.");
break;
}
if (options.extractedTempDir == null) {
options.extractedTempDir = Files.createTempDirectory("ji-jst").toFile();
if (extractedTempDir == null) {
extractedTempDir = Files.createTempDirectory("ji-jst").toFile();
}
File toDir = new File(options.extractedTempDir, file.getName());
options.sourceDirectoryFiles.add(toDir);
extractTo(file, toDir, options.inputFiles);
File toDir = new File(extractedTempDir, file.getName());
sourceDirectoryFiles.add(toDir);
extractTo(file, toDir, inputFiles);
break;
}
}
}
return options;
return this;
}

public static JavaSourceUtilsOptions parse(final String[] args) throws IOException {
final JavaSourceUtilsOptions options = new JavaSourceUtilsOptions();
final Iterator<String> a = Arrays.stream(args).iterator();

return options.parse(a);
}

private static void extractTo(final File zipFilePath, final File toDir, final Collection<File> inputFiles) throws IOException {
Expand All @@ -235,18 +265,18 @@ private static void extractTo(final File zipFilePath, final File toDir, final Co
}
}

static String getOptionValue(final String[] args, final int index, final String option) {
if (index >= args.length)
static String getNextOptionValue(final Iterator<String> args, final String option) {
if (!args.hasNext())
throw new IllegalArgumentException(
"Expected required value for option `" + option + "` at index " + index + ".");
return args[index];
"Expected required value for option `" + option + "`.");
return args.next();
}

static File getOptionFile(final String[] args, final int index, final String option) {
if (index >= args.length)
static File getNextOptionFile(final Iterator<String> args, final String option) {
if (!args.hasNext())
throw new IllegalArgumentException(
"Expected required value for option `" + option + "` at index " + index + ".");
final String fileName = args[index];
"Expected required value for option `" + option + "`.");
final String fileName = args.next();
final File file = new File(fileName);
if (!file.exists()) {
System.err.println(App.APP_NAME + ": warning: invalid file path for option `" + option + "`: " + fileName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@
*/
package com.microsoft.android;

import java.io.File;
import java.io.IOException;
import java.io.*;

import org.junit.Test;

import jdk.nashorn.internal.AssertsEnabled;

import static org.junit.Assert.*;

public class JavaSourceUtilsOptionsTest {
Expand All @@ -17,4 +22,52 @@ public class JavaSourceUtilsOptionsTest {
options = JavaSourceUtilsOptions.parse(new String[]{"-h"});
assertNull(options);
}

@Test public void testParse_ResponseFiles() throws IOException {
JavaSourceUtilsOptions options;

final File responseFile = File.createTempFile("jsu-test", ".java");
final String responseFilePath = responseFile.getAbsolutePath();

try (PrintWriter contents = new PrintWriter(responseFile)) {
contents.println("--help");
}

options = JavaSourceUtilsOptions.parse(new String[]{"@" + responseFilePath});
responseFile.delete();
assertNull(options);

try (PrintWriter contents = new PrintWriter(responseFile)) {
contents.println("# aar?");
contents.println("-a");
contents.println(responseFilePath);
contents.println("# jar?");
contents.println("-j");
contents.println(responseFilePath);
contents.println("# source?");
contents.println("-s");
contents.println(responseFilePath);
contents.println("-bootclasspath");
contents.println(responseFilePath + File.pathSeparator + responseFilePath);
contents.println("# params output?");
contents.println("-P");
contents.println("params.txt");
contents.println("# xml javadoc output?");
contents.println("-D");
contents.println("javadoc.xml");
contents.println("# comment; FILEs…");
contents.println(responseFilePath);
}

options = JavaSourceUtilsOptions.parse(new String[]{"@" + responseFilePath});
responseFile.delete();

assertEquals(responseFilePath, options.aarFiles.get(0).getAbsolutePath());
assertEquals(responseFilePath, options.jarFiles.get(0).getAbsolutePath());
assertEquals("params.txt", options.outputParamsTxt);
assertEquals("javadoc.xml", options.outputJavadocXml);
assertEquals(1, options.inputFiles.size());
assertEquals(responseFilePath, options.inputFiles.iterator().next().getAbsolutePath());
assertTrue(options.haveBootClassPath);
}
}