From 6b3e8f083c06aef2f8eabe5cfe507db8cf29aab8 Mon Sep 17 00:00:00 2001 From: Skylot Date: Mon, 29 Oct 2018 18:11:47 +0300 Subject: [PATCH] fix(gui): override settings by cmd options --- .../main/java/jadx/cli/JCommanderWrapper.java | 105 ++++++++++++++++++ .../src/main/java/jadx/cli/JadxCLIArgs.java | 93 +++------------- .../test/java/jadx/cli/JadxCLIArgsTest.java | 26 ++++- jadx-gui/src/main/java/jadx/gui/JadxGUI.java | 2 +- 4 files changed, 145 insertions(+), 81 deletions(-) create mode 100644 jadx-cli/src/main/java/jadx/cli/JCommanderWrapper.java diff --git a/jadx-cli/src/main/java/jadx/cli/JCommanderWrapper.java b/jadx-cli/src/main/java/jadx/cli/JCommanderWrapper.java new file mode 100644 index 000000000..b4ca72798 --- /dev/null +++ b/jadx-cli/src/main/java/jadx/cli/JCommanderWrapper.java @@ -0,0 +1,105 @@ +package jadx.cli; + +import java.io.PrintStream; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import com.beust.jcommander.JCommander; +import com.beust.jcommander.ParameterDescription; +import com.beust.jcommander.ParameterException; +import com.beust.jcommander.Parameterized; + +import jadx.api.JadxDecompiler; + +public class JCommanderWrapper { + private final JCommander jc; + + public JCommanderWrapper(T obj) { + this.jc = JCommander.newBuilder().addObject(obj).build(); + } + + public boolean parse(String[] args) { + try { + jc.parse(args); + return true; + } catch (ParameterException e) { + System.err.println("Arguments parse error: " + e.getMessage()); + printUsage(); + return false; + } + } + + public void overrideProvided(T obj) { + List fieldsParams = jc.getParameters(); + List parameters = new ArrayList<>(1 + fieldsParams.size()); + parameters.add(jc.getMainParameterValue()); + parameters.addAll(fieldsParams); + for (ParameterDescription parameter : parameters) { + if (parameter.isAssigned()) { + // copy assigned field value to obj + Parameterized parameterized = parameter.getParameterized(); + Object val = parameterized.get(parameter.getObject()); + parameterized.set(obj, val); + } + } + } + + public void printUsage() { + // print usage in not sorted fields order (by default its sorted by description) + PrintStream out = System.out; + out.println(); + out.println("jadx - dex to java decompiler, version: " + JadxDecompiler.getVersion()); + out.println(); + out.println("usage: jadx [options] " + jc.getMainParameterDescription()); + out.println("options:"); + + List params = jc.getParameters(); + Map paramsMap = new LinkedHashMap<>(params.size()); + int maxNamesLen = 0; + for (ParameterDescription p : params) { + paramsMap.put(p.getParameterized().getName(), p); + int len = p.getNames().length(); + if (len > maxNamesLen) { + maxNamesLen = len; + } + } + JadxCLIArgs args = new JadxCLIArgs(); + Field[] fields = args.getClass().getDeclaredFields(); + for (Field f : fields) { + String name = f.getName(); + ParameterDescription p = paramsMap.get(name); + if (p == null) { + continue; + } + StringBuilder opt = new StringBuilder(); + opt.append(" ").append(p.getNames()); + addSpaces(opt, maxNamesLen - opt.length() + 3); + opt.append("- ").append(p.getDescription()); + addDefaultValue(args, f, opt); + out.println(opt); + } + out.println("Example:"); + out.println(" jadx -d out classes.dex"); + } + + private void addDefaultValue(JadxCLIArgs args, Field f, StringBuilder opt) { + Class fieldType = f.getType(); + if (fieldType == int.class) { + try { + int val = f.getInt(args); + opt.append(" (default: ").append(val).append(")"); + } catch (Exception e) { + // ignore + } + } + } + + private static void addSpaces(StringBuilder str, int count) { + for (int i = 0; i < count; i++) { + str.append(' '); + } + } +} diff --git a/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java b/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java index 4fb90ba91..708582a29 100644 --- a/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java +++ b/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java @@ -1,19 +1,12 @@ package jadx.cli; -import java.io.PrintStream; -import java.lang.reflect.Field; import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.Appender; -import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; -import com.beust.jcommander.ParameterDescription; -import com.beust.jcommander.ParameterException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -94,27 +87,26 @@ public class JadxCLIArgs { protected boolean printHelp = false; public boolean processArgs(String[] args) { - return parse(args) && process(); + JCommanderWrapper jcw = new JCommanderWrapper<>(this); + return jcw.parse(args) && process(jcw); } - private boolean parse(String[] args) { - try { - makeJCommander().parse(args); - return true; - } catch (ParameterException e) { - System.err.println("Arguments parse error: " + e.getMessage()); - printUsage(); + /** + * Set values only for options provided in cmd. + * Used to merge saved options and options passed in command line. + */ + public boolean overrideProvided(String[] args) { + JCommanderWrapper jcw = new JCommanderWrapper<>(new JadxCLIArgs()); + if (!jcw.parse(args)) { return false; } + jcw.overrideProvided(this); + return process(jcw); } - private JCommander makeJCommander() { - return JCommander.newBuilder().addObject(this).build(); - } - - private boolean process() { + private boolean process(JCommanderWrapper jcw) { if (printHelp) { - printUsage(); + jcw.printUsage(); return false; } if (printVersion) { @@ -136,69 +128,12 @@ public class JadxCLIArgs { } } catch (JadxException e) { System.err.println("ERROR: " + e.getMessage()); - printUsage(); + jcw.printUsage(); return false; } return true; } - public void printUsage() { - JCommander jc = makeJCommander(); - // print usage in not sorted fields order (by default its sorted by description) - PrintStream out = System.out; - out.println(); - out.println("jadx - dex to java decompiler, version: " + JadxDecompiler.getVersion()); - out.println(); - out.println("usage: jadx [options] " + jc.getMainParameterDescription()); - out.println("options:"); - - List params = jc.getParameters(); - Map paramsMap = new LinkedHashMap<>(params.size()); - int maxNamesLen = 0; - for (ParameterDescription p : params) { - paramsMap.put(p.getParameterized().getName(), p); - int len = p.getNames().length(); - if (len > maxNamesLen) { - maxNamesLen = len; - } - } - JadxCLIArgs args = new JadxCLIArgs(); - Field[] fields = args.getClass().getDeclaredFields(); - for (Field f : fields) { - String name = f.getName(); - ParameterDescription p = paramsMap.get(name); - if (p == null) { - continue; - } - StringBuilder opt = new StringBuilder(); - opt.append(" ").append(p.getNames()); - addSpaces(opt, maxNamesLen - opt.length() + 3); - opt.append("- ").append(p.getDescription()); - addDefaultValue(args, f, opt); - out.println(opt); - } - out.println("Example:"); - out.println(" jadx -d out classes.dex"); - } - - private void addDefaultValue(JadxCLIArgs args, Field f, StringBuilder opt) { - Class fieldType = f.getType(); - if (fieldType == int.class) { - try { - int val = f.getInt(args); - opt.append(" (default: ").append(val).append(")"); - } catch (Exception e) { - // ignore - } - } - } - - private static void addSpaces(StringBuilder str, int count) { - for (int i = 0; i < count; i++) { - str.append(' '); - } - } - public JadxArgs toJadxArgs() { JadxArgs args = new JadxArgs(); args.setInputFiles(files.stream().map(FileUtils::toFile).collect(Collectors.toList())); diff --git a/jadx-cli/src/test/java/jadx/cli/JadxCLIArgsTest.java b/jadx-cli/src/test/java/jadx/cli/JadxCLIArgsTest.java index 5afff66e4..7f8658fb4 100644 --- a/jadx-cli/src/test/java/jadx/cli/JadxCLIArgsTest.java +++ b/jadx-cli/src/test/java/jadx/cli/JadxCLIArgsTest.java @@ -30,11 +30,35 @@ public class JadxCLIArgsTest { assertThat(parse("").isSkipSources(), is(false)); } + @Test + public void testOptionsOverride() { + assertThat(override(new JadxCLIArgs(), "--no-imports").isUseImports(), is(false)); + assertThat(override(new JadxCLIArgs(), "").isUseImports(), is(true)); + + JadxCLIArgs args = new JadxCLIArgs(); + args.useImports = false; + assertThat(override(args, "--no-imports").isUseImports(), is(false)); + + args = new JadxCLIArgs(); + args.useImports = false; + assertThat(override(args, "").isUseImports(), is(false)); + } + private JadxCLIArgs parse(String... args) { - JadxCLIArgs jadxArgs = new JadxCLIArgs(); + return parse(new JadxCLIArgs(), args); + } + + private JadxCLIArgs parse(JadxCLIArgs jadxArgs, String... args) { boolean res = jadxArgs.processArgs(args); assertThat(res, is(true)); LOG.info("Jadx args: {}", jadxArgs.toJadxArgs()); return jadxArgs; } + + private JadxCLIArgs override(JadxCLIArgs jadxArgs, String... args) { + boolean res = jadxArgs.overrideProvided(args); + assertThat(res, is(true)); + LOG.info("Jadx args: {}", jadxArgs.toJadxArgs()); + return jadxArgs; + } } diff --git a/jadx-gui/src/main/java/jadx/gui/JadxGUI.java b/jadx-gui/src/main/java/jadx/gui/JadxGUI.java index f3710d910..7f73bb7ac 100644 --- a/jadx-gui/src/main/java/jadx/gui/JadxGUI.java +++ b/jadx-gui/src/main/java/jadx/gui/JadxGUI.java @@ -19,7 +19,7 @@ public class JadxGUI { LogCollector.register(); final JadxSettings settings = JadxSettingsAdapter.load(); // overwrite loaded settings by command line arguments - if (!settings.processArgs(args)) { + if (!settings.overrideProvided(args)) { return; } if (!tryDefaultLookAndFeel()) {