inputFiles) {
+ this.inputFiles = inputFiles;
+ }
+
public File getOutDir() {
return outDir;
}
@@ -41,7 +68,6 @@ public class JadxArgs implements IJadxArgs {
this.outDir = outDir;
}
- @Override
public File getOutDirSrc() {
return outDirSrc;
}
@@ -50,7 +76,6 @@ public class JadxArgs implements IJadxArgs {
this.outDirSrc = outDirSrc;
}
- @Override
public File getOutDirRes() {
return outDirRes;
}
@@ -59,7 +84,6 @@ public class JadxArgs implements IJadxArgs {
this.outDirRes = outDirRes;
}
- @Override
public int getThreadsCount() {
return threadsCount;
}
@@ -68,8 +92,7 @@ public class JadxArgs implements IJadxArgs {
this.threadsCount = threadsCount;
}
- @Override
- public boolean isCFGOutput() {
+ public boolean isCfgOutput() {
return cfgOutput;
}
@@ -77,7 +100,6 @@ public class JadxArgs implements IJadxArgs {
this.cfgOutput = cfgOutput;
}
- @Override
public boolean isRawCFGOutput() {
return rawCFGOutput;
}
@@ -86,7 +108,6 @@ public class JadxArgs implements IJadxArgs {
this.rawCFGOutput = rawCFGOutput;
}
- @Override
public boolean isFallbackMode() {
return fallbackMode;
}
@@ -95,7 +116,6 @@ public class JadxArgs implements IJadxArgs {
this.fallbackMode = fallbackMode;
}
- @Override
public boolean isShowInconsistentCode() {
return showInconsistentCode;
}
@@ -104,8 +124,7 @@ public class JadxArgs implements IJadxArgs {
this.showInconsistentCode = showInconsistentCode;
}
- @Override
- public boolean isUsingImports() {
+ public boolean isUseImports() {
return useImports;
}
@@ -113,16 +132,6 @@ public class JadxArgs implements IJadxArgs {
this.useImports = useImports;
}
- @Override
- public boolean isVerbose() {
- return isVerbose;
- }
-
- public void setVerbose(boolean verbose) {
- isVerbose = verbose;
- }
-
- @Override
public boolean isSkipResources() {
return isSkipResources;
}
@@ -131,7 +140,6 @@ public class JadxArgs implements IJadxArgs {
isSkipResources = skipResources;
}
- @Override
public boolean isSkipSources() {
return isSkipSources;
}
@@ -140,7 +148,6 @@ public class JadxArgs implements IJadxArgs {
isSkipSources = skipSources;
}
- @Override
public boolean isDeobfuscationOn() {
return isDeobfuscationOn;
}
@@ -149,7 +156,6 @@ public class JadxArgs implements IJadxArgs {
isDeobfuscationOn = deobfuscationOn;
}
- @Override
public boolean isDeobfuscationForceSave() {
return isDeobfuscationForceSave;
}
@@ -158,8 +164,7 @@ public class JadxArgs implements IJadxArgs {
isDeobfuscationForceSave = deobfuscationForceSave;
}
- @Override
- public boolean useSourceNameAsClassAlias() {
+ public boolean isUseSourceNameAsClassAlias() {
return useSourceNameAsClassAlias;
}
@@ -167,7 +172,6 @@ public class JadxArgs implements IJadxArgs {
this.useSourceNameAsClassAlias = useSourceNameAsClassAlias;
}
- @Override
public int getDeobfuscationMinLength() {
return deobfuscationMinLength;
}
@@ -176,7 +180,6 @@ public class JadxArgs implements IJadxArgs {
this.deobfuscationMinLength = deobfuscationMinLength;
}
- @Override
public int getDeobfuscationMaxLength() {
return deobfuscationMaxLength;
}
@@ -185,8 +188,7 @@ public class JadxArgs implements IJadxArgs {
this.deobfuscationMaxLength = deobfuscationMaxLength;
}
- @Override
- public boolean escapeUnicode() {
+ public boolean isEscapeUnicode() {
return escapeUnicode;
}
@@ -194,7 +196,6 @@ public class JadxArgs implements IJadxArgs {
this.escapeUnicode = escapeUnicode;
}
- @Override
public boolean isReplaceConsts() {
return replaceConsts;
}
@@ -203,7 +204,6 @@ public class JadxArgs implements IJadxArgs {
this.replaceConsts = replaceConsts;
}
- @Override
public boolean isExportAsGradleProject() {
return exportAsGradleProject;
}
diff --git a/jadx-core/src/main/java/jadx/api/JadxArgsValidator.java b/jadx-core/src/main/java/jadx/api/JadxArgsValidator.java
new file mode 100644
index 000000000..761aa09d1
--- /dev/null
+++ b/jadx-core/src/main/java/jadx/api/JadxArgsValidator.java
@@ -0,0 +1,89 @@
+package jadx.api;
+
+import java.io.File;
+
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import jadx.core.utils.exceptions.JadxRuntimeException;
+
+public class JadxArgsValidator {
+
+ private static final Logger LOG = LoggerFactory.getLogger(JadxArgsValidator.class);
+
+ public static void validate(JadxArgs args) {
+ if (args.getInputFiles().isEmpty()) {
+ throw new JadxRuntimeException("Please specify input file");
+ }
+ for (File file : args.getInputFiles()) {
+ checkFile(file);
+ }
+ validateOutDirs(args);
+ }
+
+ private static void validateOutDirs(JadxArgs args) {
+ File outDir = args.getOutDir();
+ File srcDir = args.getOutDirSrc();
+ File resDir = args.getOutDirRes();
+ if (outDir == null) {
+ if (srcDir != null) {
+ outDir = srcDir;
+ } else if (resDir != null) {
+ outDir = resDir;
+ } else {
+ outDir = makeDirFromInput(args);
+ }
+ }
+ args.setOutDir(outDir);
+ setFromOut(args);
+
+ checkDir(args.getOutDir());
+ checkDir(args.getOutDirSrc());
+ checkDir(args.getOutDirRes());
+ }
+
+ @NotNull
+ private static File makeDirFromInput(JadxArgs args) {
+ File outDir;
+ String outDirName;
+ File file = args.getInputFiles().get(0);
+ String name = file.getName();
+ int pos = name.lastIndexOf('.');
+ if (pos != -1) {
+ outDirName = name.substring(0, pos);
+ } else {
+ outDirName = name + "-" + JadxArgs.DEFAULT_OUT_DIR;
+ }
+ LOG.info("output directory: {}", outDirName);
+ outDir = new File(outDirName);
+ return outDir;
+ }
+
+ private static void setFromOut(JadxArgs args) {
+ if (args.getOutDirSrc() == null) {
+ args.setOutDirSrc(new File(args.getOutDir(), JadxArgs.DEFAULT_SRC_DIR));
+ }
+ if (args.getOutDirRes() == null) {
+ args.setOutDirRes(new File(args.getOutDir(), JadxArgs.DEFAULT_RES_DIR));
+ }
+ }
+
+ private static void checkFile(File file) {
+ if (!file.exists()) {
+ throw new JadxRuntimeException("File not found " + file.getAbsolutePath());
+ }
+ if (file.isDirectory()) {
+ throw new JadxRuntimeException("Expected file but found directory instead: " + file.getAbsolutePath());
+ }
+ }
+
+ private static void checkDir(File dir) {
+ if (dir != null && dir.exists() && !dir.isDirectory()) {
+ throw new JadxRuntimeException("Output directory exists as file " + dir);
+ }
+ }
+
+ private JadxArgsValidator() {
+ }
+}
diff --git a/jadx-core/src/main/java/jadx/api/JadxDecompiler.java b/jadx-core/src/main/java/jadx/api/JadxDecompiler.java
index 4c498956e..315a2afbd 100644
--- a/jadx-core/src/main/java/jadx/api/JadxDecompiler.java
+++ b/jadx-core/src/main/java/jadx/api/JadxDecompiler.java
@@ -1,24 +1,6 @@
package jadx.api;
-import jadx.core.Jadx;
-import jadx.core.ProcessClass;
-import jadx.core.codegen.CodeGen;
-import jadx.core.dex.attributes.AFlag;
-import jadx.core.dex.nodes.ClassNode;
-import jadx.core.dex.nodes.FieldNode;
-import jadx.core.dex.nodes.MethodNode;
-import jadx.core.dex.nodes.RootNode;
-import jadx.core.dex.visitors.IDexTreeVisitor;
-import jadx.core.dex.visitors.SaveCode;
-import jadx.core.export.ExportGradleProject;
-import jadx.core.utils.exceptions.JadxException;
-import jadx.core.utils.exceptions.JadxRuntimeException;
-import jadx.core.utils.files.InputFile;
-import jadx.core.xmlgen.BinaryXMLParser;
-import jadx.core.xmlgen.ResourcesSaver;
-
import java.io.File;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -33,16 +15,35 @@ import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import jadx.core.Jadx;
+import jadx.core.ProcessClass;
+import jadx.core.codegen.CodeGen;
+import jadx.core.dex.attributes.AFlag;
+import jadx.core.dex.nodes.ClassNode;
+import jadx.core.dex.nodes.FieldNode;
+import jadx.core.dex.nodes.MethodNode;
+import jadx.core.dex.nodes.RootNode;
+import jadx.core.dex.visitors.IDexTreeVisitor;
+import jadx.core.dex.visitors.SaveCode;
+import jadx.core.export.ExportGradleProject;
+import jadx.core.utils.exceptions.JadxRuntimeException;
+import jadx.core.utils.files.InputFile;
+import jadx.core.xmlgen.BinaryXMLParser;
+import jadx.core.xmlgen.ResourcesSaver;
+
/**
* Jadx API usage example:
*
- * JadxDecompiler jadx = new JadxDecompiler();
- * jadx.loadFile(new File("classes.dex"));
- * jadx.setOutputDir(new File("out"));
- * jadx.save();
+ * JadxArgs args = new JadxArgs();
+ * args.getInputFiles().add(new File("test.apk"));
+ * args.setOutDir(new File("jadx-test-output"));
+ *
+ * JadxDecompiler jadx = new JadxDecompiler(args);
+ * jadx.load();
+ * jadx.save();
*
*
- * Instead of 'save()' you can get list of decompiled classes:
+ * Instead of 'save()' you can iterate over decompiled classes:
*
* for(JavaClass cls : jadx.getClasses()) {
* System.out.println(cls.getCode());
@@ -52,12 +53,9 @@ import org.slf4j.LoggerFactory;
public final class JadxDecompiler {
private static final Logger LOG = LoggerFactory.getLogger(JadxDecompiler.class);
- private final IJadxArgs args;
- private final List inputFiles = new ArrayList<>();
+ private JadxArgs args;
- private File outDir;
- private File outDirRes;
- private File outDirSrc;
+ private final List inputFiles = new ArrayList<>();
private RootNode root;
private List passes;
@@ -72,54 +70,35 @@ public final class JadxDecompiler {
private Map methodsMap = new ConcurrentHashMap<>();
private Map fieldsMap = new ConcurrentHashMap<>();
- public JadxDecompiler() throws JadxException {
+ public JadxDecompiler() {
this(new JadxArgs());
}
- public JadxDecompiler(IJadxArgs jadxArgs) throws JadxException {
- this.args = jadxArgs;
- this.outDir = jadxArgs.getOutDir();
- this.outDirSrc = jadxArgs.getOutDirSrc();
- this.outDirRes = jadxArgs.getOutDirRes();
+ public JadxDecompiler(JadxArgs args) {
+ this.args = args;
+ }
+
+ public void load() {
reset();
+ JadxArgsValidator.validate(args);
init();
+ LOG.info("loading ...");
+
+ loadFiles(args.getInputFiles());
+
+ root = new RootNode(args);
+ root.load(inputFiles);
+
+ root.initClassPath();
+ root.loadResources(getResources());
+ root.initAppResClass();
+
+ initVisitors();
}
- public void setOutputDir(File outDir) throws JadxException {
- this.outDir = outDir;
- init();
- }
-
- public void setOutputDirSrc(File outDirSrc) throws JadxException {
- this.outDirSrc = outDirSrc;
- init();
- }
-
- public void setOutputDirRes(File outDirRes) throws JadxException {
- this.outDirRes = outDirRes;
- init();
- }
-
- void init() throws JadxException {
- if(outDir == null && outDirSrc == null) {
- outDirSrc = new JadxArgs().getOutDirSrc();
- }
- if(outDir == null && outDirRes == null) {
- outDirRes = new JadxArgs().getOutDirRes();
- }
- if (outDir == null) {
- outDir = new JadxArgs().getOutDir();
- }
- else {
- if(outDirSrc == null && outDirRes != null && !args.isSkipSources()) {
- throw new JadxException("--output-dir-src must be specified");
- }
- if(outDirSrc != null && outDirRes == null && !args.isSkipResources()) {
- throw new JadxException("--output-dir-res must be specified");
- }
- }
- this.passes = Jadx.getPassesList(args, outDir);
- this.codeGen = new CodeGen(args);
+ void init() {
+ this.passes = Jadx.getPassesList(args);
+ this.codeGen = new CodeGen();
}
void reset() {
@@ -135,23 +114,18 @@ public final class JadxDecompiler {
return Jadx.getVersion();
}
- public void loadFile(File file) throws JadxException {
- loadFiles(Collections.singletonList(file));
- }
-
- public void loadFiles(List files) throws JadxException {
+ private void loadFiles(List files) {
if (files.isEmpty()) {
- throw new JadxException("Empty file list");
+ throw new JadxRuntimeException("Empty file list");
}
inputFiles.clear();
for (File file : files) {
try {
InputFile.addFilesFrom(file, inputFiles, args.isSkipSources());
- } catch (IOException e) {
- throw new JadxException("Error load file: " + file, e);
+ } catch (Exception e) {
+ throw new JadxRuntimeException("Error load file: " + file, e);
}
}
- parse();
}
public void save() {
@@ -194,13 +168,13 @@ public final class JadxDecompiler {
File sourcesOutDir;
File resOutDir;
if (args.isExportAsGradleProject()) {
- ExportGradleProject export = new ExportGradleProject(root, outDir);
+ ExportGradleProject export = new ExportGradleProject(root, args.getOutDir());
export.init();
sourcesOutDir = export.getSrcOutDir();
resOutDir = export.getResOutDir();
} else {
- sourcesOutDir = outDirSrc;
- resOutDir = outDirRes;
+ sourcesOutDir = args.getOutDirSrc();
+ resOutDir = args.getOutDirRes();
}
if (saveSources) {
appendSourcesSave(executor, sourcesOutDir);
@@ -294,21 +268,6 @@ public final class JadxDecompiler {
root.getErrorsCounter().printReport();
}
- void parse() throws JadxException {
- reset();
- init();
-
- root = new RootNode(args);
- LOG.info("loading ...");
- root.load(inputFiles);
-
- root.initClassPath();
- root.loadResources(getResources());
- root.initAppResClass();
-
- initVisitors();
- }
-
private void initVisitors() {
for (IDexTreeVisitor pass : passes) {
try {
@@ -346,7 +305,7 @@ public final class JadxDecompiler {
return fieldsMap;
}
- public IJadxArgs getArgs() {
+ public JadxArgs getArgs() {
return args;
}
@@ -354,5 +313,4 @@ public final class JadxDecompiler {
public String toString() {
return "jadx decompiler " + getVersion();
}
-
}
diff --git a/jadx-core/src/main/java/jadx/core/Jadx.java b/jadx-core/src/main/java/jadx/core/Jadx.java
index aba779605..eb0ffea86 100644
--- a/jadx-core/src/main/java/jadx/core/Jadx.java
+++ b/jadx-core/src/main/java/jadx/core/Jadx.java
@@ -1,6 +1,15 @@
package jadx.core;
-import jadx.api.IJadxArgs;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.jar.Manifest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import jadx.api.JadxArgs;
import jadx.core.dex.visitors.ClassModifier;
import jadx.core.dex.visitors.CodeShrinker;
import jadx.core.dex.visitors.ConstInlineVisitor;
@@ -33,16 +42,6 @@ import jadx.core.dex.visitors.ssa.SSATransform;
import jadx.core.dex.visitors.typeinference.FinishTypeInference;
import jadx.core.dex.visitors.typeinference.TypeInference;
-import java.io.File;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.jar.Manifest;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
public class Jadx {
private static final Logger LOG = LoggerFactory.getLogger(Jadx.class);
@@ -55,7 +54,7 @@ public class Jadx {
}
}
- public static List getPassesList(IJadxArgs args, File outDir) {
+ public static List getPassesList(JadxArgs args) {
List passes = new ArrayList<>();
if (args.isFallbackMode()) {
passes.add(new FallbackModeVisitor());
@@ -71,7 +70,7 @@ public class Jadx {
passes.add(new TypeInference());
if (args.isRawCFGOutput()) {
- passes.add(DotGraphVisitor.dumpRaw(outDir));
+ passes.add(DotGraphVisitor.dumpRaw());
}
passes.add(new ConstInlineVisitor());
@@ -83,8 +82,8 @@ public class Jadx {
passes.add(new CodeShrinker());
passes.add(new ReSugarCode());
- if (args.isCFGOutput()) {
- passes.add(DotGraphVisitor.dump(outDir));
+ if (args.isCfgOutput()) {
+ passes.add(DotGraphVisitor.dump());
}
passes.add(new RegionMakerVisitor());
@@ -95,8 +94,8 @@ public class Jadx {
passes.add(new SimplifyVisitor());
passes.add(new CheckRegions());
- if (args.isCFGOutput()) {
- passes.add(DotGraphVisitor.dumpRegions(outDir));
+ if (args.isCfgOutput()) {
+ passes.add(DotGraphVisitor.dumpRegions());
}
passes.add(new MethodInlineVisitor());
diff --git a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
index 1b4a89bd6..c0a6b92e6 100644
--- a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
+++ b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
@@ -12,7 +12,7 @@ import java.util.Set;
import com.android.dx.rop.code.AccessFlags;
-import jadx.api.IJadxArgs;
+import jadx.api.JadxArgs;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.AttrNode;
@@ -48,8 +48,8 @@ public class ClassGen {
private final Set imports = new HashSet<>();
private int clsDeclLine;
- public ClassGen(ClassNode cls, IJadxArgs jadxArgs) {
- this(cls, null, jadxArgs.isUsingImports(), jadxArgs.isFallbackMode(), jadxArgs.isShowInconsistentCode());
+ public ClassGen(ClassNode cls, JadxArgs jadxArgs) {
+ this(cls, null, jadxArgs.isUseImports(), jadxArgs.isFallbackMode(), jadxArgs.isShowInconsistentCode());
}
public ClassGen(ClassNode cls, ClassGen parentClsGen) {
diff --git a/jadx-core/src/main/java/jadx/core/codegen/CodeGen.java b/jadx-core/src/main/java/jadx/core/codegen/CodeGen.java
index 90c89e1cd..8c33d8862 100644
--- a/jadx-core/src/main/java/jadx/core/codegen/CodeGen.java
+++ b/jadx-core/src/main/java/jadx/core/codegen/CodeGen.java
@@ -1,25 +1,17 @@
package jadx.core.codegen;
-import jadx.api.IJadxArgs;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.visitors.AbstractVisitor;
import jadx.core.utils.exceptions.CodegenException;
public class CodeGen extends AbstractVisitor {
- private final IJadxArgs args;
-
- public CodeGen(IJadxArgs args) {
- this.args = args;
- }
-
@Override
public boolean visit(ClassNode cls) throws CodegenException {
- ClassGen clsGen = new ClassGen(cls, args);
+ ClassGen clsGen = new ClassGen(cls, cls.root().getArgs());
CodeWriter clsCode = clsGen.makeClass();
clsCode.finish();
cls.setCode(clsCode);
return false;
}
-
}
diff --git a/jadx-core/src/main/java/jadx/core/deobf/Deobfuscator.java b/jadx-core/src/main/java/jadx/core/deobf/Deobfuscator.java
index a01f7be4f..f7764f655 100644
--- a/jadx-core/src/main/java/jadx/core/deobf/Deobfuscator.java
+++ b/jadx-core/src/main/java/jadx/core/deobf/Deobfuscator.java
@@ -1,6 +1,6 @@
package jadx.core.deobf;
-import jadx.api.IJadxArgs;
+import jadx.api.JadxArgs;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.nodes.SourceFileAttr;
import jadx.core.dex.info.ClassInfo;
@@ -34,7 +34,7 @@ public class Deobfuscator {
public static final String CLASS_NAME_SEPARATOR = ".";
public static final String INNER_CLASS_SEPARATOR = "$";
- private final IJadxArgs args;
+ private final JadxArgs args;
@NotNull
private final List dexNodes;
private final DeobfPresets deobfPresets;
@@ -58,13 +58,13 @@ public class Deobfuscator {
private int fldIndex = 0;
private int mthIndex = 0;
- public Deobfuscator(IJadxArgs args, @NotNull List dexNodes, File deobfMapFile) {
+ public Deobfuscator(JadxArgs args, @NotNull List dexNodes, File deobfMapFile) {
this.args = args;
this.dexNodes = dexNodes;
this.minLength = args.getDeobfuscationMinLength();
this.maxLength = args.getDeobfuscationMaxLength();
- this.useSourceNameAsAlias = args.useSourceNameAsClassAlias();
+ this.useSourceNameAsAlias = args.isUseSourceNameAsClassAlias();
this.deobfPresets = new DeobfPresets(this, deobfMapFile);
}
diff --git a/jadx-core/src/main/java/jadx/core/dex/info/ConstStorage.java b/jadx-core/src/main/java/jadx/core/dex/info/ConstStorage.java
index 5468be17f..7be69192f 100644
--- a/jadx-core/src/main/java/jadx/core/dex/info/ConstStorage.java
+++ b/jadx-core/src/main/java/jadx/core/dex/info/ConstStorage.java
@@ -8,7 +8,7 @@ import java.util.Set;
import org.jetbrains.annotations.Nullable;
-import jadx.api.IJadxArgs;
+import jadx.api.JadxArgs;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.instructions.args.LiteralArg;
import jadx.core.dex.instructions.args.PrimitiveType;
@@ -60,7 +60,7 @@ public class ConstStorage {
private Map resourcesNames = new HashMap<>();
- public ConstStorage(IJadxArgs args) {
+ public ConstStorage(JadxArgs args) {
this.replaceEnabled = args.isReplaceConsts();
}
diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
index d246011b3..21c18cd29 100644
--- a/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
+++ b/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
@@ -65,7 +65,7 @@ public class ClassNode extends LineAttrNode implements ILoadable, IDexNode {
// cache maps
private Map mthInfoMap = Collections.emptyMap();
- public ClassNode(DexNode dex, ClassDef cls) throws DecodeException {
+ public ClassNode(DexNode dex, ClassDef cls) {
this.dex = dex;
this.clsInfo = ClassInfo.fromDex(dex, cls.getTypeIndex());
try {
@@ -128,7 +128,7 @@ public class ClassNode extends LineAttrNode implements ILoadable, IDexNode {
buildCache();
} catch (Exception e) {
- throw new DecodeException("Error decode class: " + clsInfo, e);
+ throw new JadxRuntimeException("Error decode class: " + clsInfo, e);
}
}
diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/DexNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/DexNode.java
index b58d80281..a63434498 100644
--- a/jadx-core/src/main/java/jadx/core/dex/nodes/DexNode.java
+++ b/jadx-core/src/main/java/jadx/core/dex/nodes/DexNode.java
@@ -46,7 +46,7 @@ public class DexNode implements IDexNode {
this.dexId = dexId;
}
- public void loadClasses() throws DecodeException {
+ public void loadClasses() {
for (ClassDef cls : dexBuf.classDefs()) {
ClassNode clsNode = new ClassNode(this, cls);
classes.add(clsNode);
diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java
index 4c5ff3640..bea8bd066 100644
--- a/jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java
+++ b/jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java
@@ -1,24 +1,5 @@
package jadx.core.dex.nodes;
-import jadx.api.IJadxArgs;
-import jadx.api.ResourceFile;
-import jadx.api.ResourceType;
-import jadx.api.ResourcesLoader;
-import jadx.core.clsp.ClspGraph;
-import jadx.core.dex.info.ClassInfo;
-import jadx.core.dex.info.ConstStorage;
-import jadx.core.dex.info.InfoStorage;
-import jadx.core.utils.ErrorsCounter;
-import jadx.core.utils.StringUtils;
-import jadx.core.utils.android.AndroidResourcesUtils;
-import jadx.core.utils.exceptions.DecodeException;
-import jadx.core.utils.exceptions.JadxException;
-import jadx.core.utils.files.DexFile;
-import jadx.core.utils.files.InputFile;
-import jadx.core.xmlgen.ResContainer;
-import jadx.core.xmlgen.ResTableParser;
-import jadx.core.xmlgen.ResourceStorage;
-
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
@@ -28,11 +9,30 @@ import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import jadx.api.JadxArgs;
+import jadx.api.ResourceFile;
+import jadx.api.ResourceType;
+import jadx.api.ResourcesLoader;
+import jadx.core.clsp.ClspGraph;
+import jadx.core.dex.info.ClassInfo;
+import jadx.core.dex.info.ConstStorage;
+import jadx.core.dex.info.InfoStorage;
+import jadx.core.utils.ErrorsCounter;
+import jadx.core.utils.StringUtils;
+import jadx.core.utils.android.AndroidResourcesUtils;
+import jadx.core.utils.exceptions.JadxException;
+import jadx.core.utils.exceptions.JadxRuntimeException;
+import jadx.core.utils.files.DexFile;
+import jadx.core.utils.files.InputFile;
+import jadx.core.xmlgen.ResContainer;
+import jadx.core.xmlgen.ResTableParser;
+import jadx.core.xmlgen.ResourceStorage;
+
public class RootNode {
private static final Logger LOG = LoggerFactory.getLogger(RootNode.class);
private final ErrorsCounter errorsCounter = new ErrorsCounter();
- private final IJadxArgs args;
+ private final JadxArgs args;
private final StringUtils stringUtils;
private final ConstStorage constValues;
private final InfoStorage infoStorage = new InfoStorage();
@@ -43,13 +43,13 @@ public class RootNode {
private ClassNode appResClass;
private ClspGraph clsp;
- public RootNode(IJadxArgs args) {
+ public RootNode(JadxArgs args) {
this.args = args;
this.stringUtils = new StringUtils(args);
this.constValues = new ConstStorage(args);
}
- public void load(List inputFiles) throws DecodeException {
+ public void load(List inputFiles) {
dexNodes = new ArrayList<>();
for (InputFile input : inputFiles) {
for (DexFile dexFile : input.getDexFiles()) {
@@ -58,7 +58,7 @@ public class RootNode {
DexNode dexNode = new DexNode(this, dexFile, dexNodes.size());
dexNodes.add(dexNode);
} catch (Exception e) {
- throw new DecodeException("Error decode file: " + dexFile, e);
+ throw new JadxRuntimeException("Error decode file: " + dexFile, e);
}
}
}
@@ -103,22 +103,22 @@ public class RootNode {
appResClass = AndroidResourcesUtils.searchAppResClass(this);
}
- public void initClassPath() throws DecodeException {
+ public void initClassPath() {
try {
if (this.clsp == null) {
- ClspGraph clsp = new ClspGraph();
- clsp.load();
+ ClspGraph newClsp = new ClspGraph();
+ newClsp.load();
List classes = new ArrayList<>();
for (DexNode dexNode : dexNodes) {
classes.addAll(dexNode.getClasses());
}
- clsp.addApp(classes);
+ newClsp.addApp(classes);
- this.clsp = clsp;
+ this.clsp = newClsp;
}
- } catch (IOException e) {
- throw new DecodeException("Error loading classpath", e);
+ } catch (Exception e) {
+ throw new JadxRuntimeException("Error loading classpath", e);
}
}
@@ -188,10 +188,6 @@ public class RootNode {
return appResClass;
}
- public IJadxArgs getArgs() {
- return args;
- }
-
public StringUtils getStringUtils() {
return stringUtils;
}
@@ -204,4 +200,7 @@ public class RootNode {
return infoStorage;
}
+ public JadxArgs getArgs() {
+ return args;
+ }
}
diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java
index 54eaa4823..b78ac7c93 100644
--- a/jadx-core/src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java
+++ b/jadx-core/src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java
@@ -23,42 +23,33 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
public class DotGraphVisitor extends AbstractVisitor {
- private static final Logger LOG = LoggerFactory.getLogger(DotGraphVisitor.class);
-
private static final String NL = "\\l";
private static final boolean PRINT_DOMINATORS = false;
- private final File dir;
private final boolean useRegions;
private final boolean rawInsn;
- public static DotGraphVisitor dump(File outDir) {
- return new DotGraphVisitor(outDir, false, false);
+ public static DotGraphVisitor dump() {
+ return new DotGraphVisitor(false, false);
}
- public static DotGraphVisitor dumpRaw(File outDir) {
- return new DotGraphVisitor(outDir, false, true);
+ public static DotGraphVisitor dumpRaw() {
+ return new DotGraphVisitor(false, true);
}
- public static DotGraphVisitor dumpRegions(File outDir) {
- return new DotGraphVisitor(outDir, true, false);
+ public static DotGraphVisitor dumpRegions() {
+ return new DotGraphVisitor(true, false);
}
- public static DotGraphVisitor dumpRawRegions(File outDir) {
- return new DotGraphVisitor(outDir, true, true);
+ public static DotGraphVisitor dumpRawRegions() {
+ return new DotGraphVisitor(true, true);
}
- private DotGraphVisitor(File outDir, boolean useRegions, boolean rawInsn) {
- this.dir = outDir;
+ private DotGraphVisitor(boolean useRegions, boolean rawInsn) {
this.useRegions = useRegions;
this.rawInsn = rawInsn;
- LOG.debug("DOT {}{}graph dump dir: {}",
- useRegions ? "regions " : "", rawInsn ? "raw " : "", outDir.getAbsolutePath());
}
@Override
@@ -66,12 +57,25 @@ public class DotGraphVisitor extends AbstractVisitor {
if (mth.isNoCode()) {
return;
}
- new DumpDotGraph().process(mth);
+ File outRootDir = mth.root().getArgs().getOutDir();
+ new DumpDotGraph(outRootDir).process(mth);
+ }
+
+ public void save(File dir, MethodNode mth) {
+ if (mth.isNoCode()) {
+ return;
+ }
+ new DumpDotGraph(dir).process(mth);
}
private class DumpDotGraph {
private final CodeWriter dot = new CodeWriter();
private final CodeWriter conn = new CodeWriter();
+ private final File dir;
+
+ public DumpDotGraph(File dir) {
+ this.dir = dir;
+ }
public void process(MethodNode mth) {
dot.startLine("digraph \"CFG for");
diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/RenameVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/RenameVisitor.java
index df06281f8..3853aed7f 100644
--- a/jadx-core/src/main/java/jadx/core/dex/visitors/RenameVisitor.java
+++ b/jadx-core/src/main/java/jadx/core/dex/visitors/RenameVisitor.java
@@ -7,7 +7,7 @@ import java.util.Set;
import org.apache.commons.io.FilenameUtils;
-import jadx.api.IJadxArgs;
+import jadx.api.JadxArgs;
import jadx.core.Consts;
import jadx.core.codegen.TypeGen;
import jadx.core.deobf.Deobfuscator;
@@ -31,8 +31,6 @@ public class RenameVisitor extends AbstractVisitor {
@Override
public void init(RootNode root) {
- IJadxArgs args = root.getArgs();
-
List dexNodes = root.getDexNodes();
if (dexNodes.isEmpty()) {
return;
@@ -43,6 +41,7 @@ public class RenameVisitor extends AbstractVisitor {
String inputName = FilenameUtils.getBaseName(firstInputFileName);
File deobfMapFile = new File(inputPath, inputName + ".jobf");
+ JadxArgs args = root.getArgs();
deobfuscator = new Deobfuscator(args, dexNodes, deobfMapFile);
boolean deobfuscationOn = args.isDeobfuscationOn();
if (deobfuscationOn) {
diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/SaveCode.java b/jadx-core/src/main/java/jadx/core/dex/visitors/SaveCode.java
index 9c2a08907..abbab0d15 100644
--- a/jadx-core/src/main/java/jadx/core/dex/visitors/SaveCode.java
+++ b/jadx-core/src/main/java/jadx/core/dex/visitors/SaveCode.java
@@ -2,7 +2,7 @@ package jadx.core.dex.visitors;
import java.io.File;
-import jadx.api.IJadxArgs;
+import jadx.api.JadxArgs;
import jadx.core.codegen.CodeWriter;
import jadx.core.dex.nodes.ClassNode;
@@ -10,7 +10,7 @@ public class SaveCode {
private SaveCode() {}
- public static void save(File dir, IJadxArgs args, ClassNode cls) {
+ public static void save(File dir, JadxArgs args, ClassNode cls) {
CodeWriter clsCode = cls.getCode();
String fileName = cls.getClassInfo().getFullPath() + ".java";
if (args.isFallbackMode()) {
diff --git a/jadx-core/src/main/java/jadx/core/utils/DebugUtils.java b/jadx-core/src/main/java/jadx/core/utils/DebugUtils.java
index 4f537b004..819957053 100644
--- a/jadx-core/src/main/java/jadx/core/utils/DebugUtils.java
+++ b/jadx-core/src/main/java/jadx/core/utils/DebugUtils.java
@@ -44,9 +44,9 @@ public class DebugUtils {
public static void dump(MethodNode mth, String desc) {
File out = new File("test-graph" + desc + "-tmp");
- DotGraphVisitor.dump(out).visit(mth);
- DotGraphVisitor.dumpRaw(out).visit(mth);
- DotGraphVisitor.dumpRegions(out).visit(mth);
+ DotGraphVisitor.dump().save(out, mth);
+ DotGraphVisitor.dumpRaw().save(out, mth);
+ DotGraphVisitor.dumpRegions().save(out, mth);
}
public static void printRegionsWithBlock(MethodNode mth, BlockNode block) {
diff --git a/jadx-core/src/main/java/jadx/core/utils/StringUtils.java b/jadx-core/src/main/java/jadx/core/utils/StringUtils.java
index acdd5d0a3..186b8b23a 100644
--- a/jadx-core/src/main/java/jadx/core/utils/StringUtils.java
+++ b/jadx-core/src/main/java/jadx/core/utils/StringUtils.java
@@ -1,13 +1,13 @@
package jadx.core.utils;
-import jadx.api.IJadxArgs;
+import jadx.api.JadxArgs;
public class StringUtils {
private final boolean escapeUnicode;
- public StringUtils(IJadxArgs args) {
- this.escapeUnicode = args.escapeUnicode();
+ public StringUtils(JadxArgs args) {
+ this.escapeUnicode = args.isEscapeUnicode();
}
public String unescapeString(String str) {
diff --git a/jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java b/jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java
index 360554a3d..91633239d 100644
--- a/jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java
+++ b/jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java
@@ -214,4 +214,12 @@ public class FileUtils {
}
return IOCase.SYSTEM.isCaseSensitive();
}
+
+ public static File toFile(String path) {
+ if (path == null) {
+ return null;
+ }
+ return new File(path);
+ }
+
}
diff --git a/jadx-core/src/test/groovy/jadx/tests/TestAPI.groovy b/jadx-core/src/test/groovy/jadx/tests/TestAPI.groovy
deleted file mode 100644
index 8e4208355..000000000
--- a/jadx-core/src/test/groovy/jadx/tests/TestAPI.groovy
+++ /dev/null
@@ -1,68 +0,0 @@
-package jadx.tests
-
-import jadx.api.IJadxArgs
-import jadx.api.JadxDecompiler
-import jadx.core.utils.exceptions.JadxException
-import jadx.core.utils.exceptions.JadxRuntimeException
-import spock.lang.Specification
-
-class TestAPI extends Specification {
-
- def "no loaded files"() {
- setup:
- def d = new JadxDecompiler()
- when:
- def classes = d.getClasses()
- def packages = d.getPackages()
- then:
- notThrown(NullPointerException)
- classes?.isEmpty()
- packages?.isEmpty()
- }
-
- def "save with no loaded files"() {
- when:
- new JadxDecompiler().save()
- then:
- def e = thrown(JadxRuntimeException)
- e.message == "No loaded files"
- }
-
- def "load empty files list"() {
- when:
- new JadxDecompiler().loadFiles(Collections.emptyList())
- then:
- def e = thrown(JadxException)
- e.message == "Empty file list"
- }
-
- def "load null"() {
- when:
- new JadxDecompiler().loadFile(null)
- then:
- thrown(NullPointerException)
- }
-
- def "load missing file"() {
- when:
- new JadxDecompiler().loadFile(new File("_.dex"))
- then:
- def e = thrown(JadxException)
- e.message == "Error load file: _.dex"
- e.cause.class == IOException
- }
-
- def "pass decompiler args"() {
- setup:
- def args = Mock(IJadxArgs)
- when:
- new JadxDecompiler(args)
- then:
- noExceptionThrown()
- }
-
- def "get errors count for new decompiler"() {
- expect:
- new JadxDecompiler().getErrorsCount() == 0
- }
-}
diff --git a/jadx-core/src/test/java/jadx/api/JadxArgsValidatorOutDirsTest.java b/jadx-core/src/test/java/jadx/api/JadxArgsValidatorOutDirsTest.java
new file mode 100644
index 000000000..e03775b27
--- /dev/null
+++ b/jadx-core/src/test/java/jadx/api/JadxArgsValidatorOutDirsTest.java
@@ -0,0 +1,72 @@
+package jadx.api;
+
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import jadx.core.utils.files.FileUtils;
+
+import static jadx.core.utils.files.FileUtils.toFile;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class JadxArgsValidatorOutDirsTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(JadxArgsValidatorOutDirsTest.class);
+ public JadxArgs args;
+
+ @Test
+ public void checkAllSet() {
+ setOutDirs("r", "s", "r");
+ checkOutDirs("r", "s", "r");
+ }
+
+ @Test
+ public void checkRootOnly() {
+ setOutDirs("out", null, null);
+ checkOutDirs("out", "out/" + JadxArgs.DEFAULT_SRC_DIR, "out/" + JadxArgs.DEFAULT_RES_DIR);
+ }
+
+ @Test
+ public void checkSrcOnly() {
+ setOutDirs(null, "src", null);
+ checkOutDirs("src", "src", "src/" + JadxArgs.DEFAULT_RES_DIR);
+ }
+
+ @Test
+ public void checkResOnly() {
+ setOutDirs(null, null, "res");
+ checkOutDirs("res", "res/" + JadxArgs.DEFAULT_SRC_DIR, "res");
+ }
+
+ @Test
+ public void checkNone() {
+ setOutDirs(null, null, null);
+ String inputFileBase = args.getInputFiles().get(0).getName().replace(".apk", "");
+ checkOutDirs(inputFileBase,
+ inputFileBase + "/" + JadxArgs.DEFAULT_SRC_DIR,
+ inputFileBase + "/" + JadxArgs.DEFAULT_RES_DIR);
+ }
+
+ private void setOutDirs(String outDir, String srcDir, String resDir) {
+ args = makeArgs();
+ args.setOutDir(toFile(outDir));
+ args.setOutDirSrc(toFile(srcDir));
+ args.setOutDirRes(toFile(resDir));
+ LOG.debug("Set dirs: out={}, src={}, res={}", outDir, srcDir, resDir);
+ }
+
+ private void checkOutDirs(String outDir, String srcDir, String resDir) {
+ JadxArgsValidator.validate(args);
+ LOG.debug("Got dirs: out={}, src={}, res={}", args.getOutDir(), args.getOutDirSrc(), args.getOutDirRes());
+ assertThat(args.getOutDir(), is(toFile(outDir)));
+ assertThat(args.getOutDirSrc(), is(toFile(srcDir)));
+ assertThat(args.getOutDirRes(), is(toFile(resDir)));
+ }
+
+ private JadxArgs makeArgs() {
+ JadxArgs args = new JadxArgs();
+ args.getInputFiles().add(FileUtils.createTempFile("some.apk"));
+ return args;
+ }
+}
diff --git a/jadx-core/src/test/java/jadx/api/JadxDecompilerTest.java b/jadx-core/src/test/java/jadx/api/JadxDecompilerTest.java
new file mode 100644
index 000000000..5c3814d8d
--- /dev/null
+++ b/jadx-core/src/test/java/jadx/api/JadxDecompilerTest.java
@@ -0,0 +1,23 @@
+package jadx.api;
+
+import java.io.File;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class JadxDecompilerTest {
+
+ @Test
+ @Ignore
+ public void testExampleUsage() {
+ JadxArgs args = new JadxArgs();
+ args.getInputFiles().add(new File("test.apk"));
+ args.setOutDir(new File("jadx-test-output"));
+
+ JadxDecompiler jadx = new JadxDecompiler(args);
+ jadx.load();
+ jadx.save();
+ }
+
+ // TODO make more tests
+}
diff --git a/jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java b/jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java
index 04c5ac700..a060fc7a9 100644
--- a/jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java
+++ b/jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java
@@ -10,7 +10,6 @@ import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.jar.JarOutputStream;
@@ -29,7 +28,6 @@ import jadx.core.dex.nodes.RootNode;
import jadx.core.dex.visitors.DepthTraversal;
import jadx.core.dex.visitors.IDexTreeVisitor;
import jadx.core.utils.exceptions.CodegenException;
-import jadx.core.utils.exceptions.JadxException;
import jadx.tests.api.compiler.DynamicCompiler;
import jadx.tests.api.compiler.StaticCompiler;
import jadx.tests.api.utils.TestUtils;
@@ -65,6 +63,7 @@ public abstract class IntegrationTest extends TestUtils {
public IntegrationTest() {
args = new JadxArgs();
+ args.setOutDir(new File(outDir));
args.setShowInconsistentCode(true);
args.setThreadsCount(1);
args.setSkipResources(true);
@@ -84,9 +83,10 @@ public abstract class IntegrationTest extends TestUtils {
public ClassNode getClassNodeFromFile(File file, String clsName) {
JadxDecompiler d = null;
try {
+ args.setInputFiles(Collections.singletonList(file));
d = new JadxDecompiler(args);
- d.loadFile(file);
- } catch (JadxException e) {
+ d.load();
+ } catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
@@ -114,18 +114,18 @@ public abstract class IntegrationTest extends TestUtils {
}
private void decompile(JadxDecompiler jadx, ClassNode cls) {
- List passes = Jadx.getPassesList(jadx.getArgs(), new File(outDir));
- ProcessClass.process(cls, passes, new CodeGen(jadx.getArgs()));
+ List passes = Jadx.getPassesList(jadx.getArgs());
+ ProcessClass.process(cls, passes, new CodeGen());
}
private void decompileWithoutUnload(JadxDecompiler d, ClassNode cls) {
cls.load();
- List passes = Jadx.getPassesList(d.getArgs(), new File(outDir));
+ List passes = Jadx.getPassesList(d.getArgs());
for (IDexTreeVisitor visitor : passes) {
DepthTraversal.visit(visitor, cls);
}
try {
- new CodeGen(d.getArgs()).visit(cls);
+ new CodeGen().visit(cls);
} catch (CodegenException e) {
e.printStackTrace();
fail(e.getMessage());
diff --git a/jadx-core/src/test/java/jadx/tests/functional/JadxVisitorsOrderTest.java b/jadx-core/src/test/java/jadx/tests/functional/JadxVisitorsOrderTest.java
index 1a4774535..23d9309dc 100644
--- a/jadx-core/src/test/java/jadx/tests/functional/JadxVisitorsOrderTest.java
+++ b/jadx-core/src/test/java/jadx/tests/functional/JadxVisitorsOrderTest.java
@@ -1,6 +1,5 @@
package jadx.tests.functional;
-import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -24,7 +23,7 @@ public class JadxVisitorsOrderTest {
@Test
public void testOrder() {
- List passes = Jadx.getPassesList(new JadxArgs(), new File("out"));
+ List passes = Jadx.getPassesList(new JadxArgs());
List errors = check(passes);
for (String str : errors) {
diff --git a/jadx-gui/src/main/java/jadx/gui/JadxGUI.java b/jadx-gui/src/main/java/jadx/gui/JadxGUI.java
index 5856b924b..5ccc9c2a9 100644
--- a/jadx-gui/src/main/java/jadx/gui/JadxGUI.java
+++ b/jadx-gui/src/main/java/jadx/gui/JadxGUI.java
@@ -5,7 +5,6 @@ import javax.swing.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import jadx.core.utils.exceptions.JadxException;
import jadx.gui.settings.JadxSettings;
import jadx.gui.settings.JadxSettingsAdapter;
import jadx.gui.ui.MainWindow;
@@ -17,24 +16,17 @@ public class JadxGUI {
public static void main(String[] args) {
try {
LogCollector.register();
- final JadxSettings jadxArgs = JadxSettingsAdapter.load();
+ final JadxSettings settings = JadxSettingsAdapter.load();
// overwrite loaded settings by command line arguments
- if (!jadxArgs.processArgs(args)) {
+ if (!settings.processArgs(args)) {
return;
}
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- try {
- MainWindow window = new MainWindow(jadxArgs);
- window.open();
- }
- catch(JadxException e) {
- throw new RuntimeException(e);
- }
- }
+ SwingUtilities.invokeLater(() -> {
+ MainWindow window = new MainWindow(settings);
+ window.open();
});
- } catch (Throwable e) {
+ } catch (Exception e) {
LOG.error("Error: {}", e.getMessage(), e);
System.exit(1);
}
diff --git a/jadx-gui/src/main/java/jadx/gui/JadxWrapper.java b/jadx-gui/src/main/java/jadx/gui/JadxWrapper.java
index 406c76fe1..a17221dae 100644
--- a/jadx-gui/src/main/java/jadx/gui/JadxWrapper.java
+++ b/jadx-gui/src/main/java/jadx/gui/JadxWrapper.java
@@ -2,38 +2,38 @@ package jadx.gui;
import javax.swing.*;
import java.io.File;
+import java.util.Collections;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import jadx.api.IJadxArgs;
import jadx.api.JadxDecompiler;
import jadx.api.JavaClass;
import jadx.api.JavaPackage;
import jadx.api.ResourceFile;
-import jadx.core.utils.exceptions.DecodeException;
-import jadx.core.utils.exceptions.JadxException;
+import jadx.gui.settings.JadxSettings;
public class JadxWrapper {
private static final Logger LOG = LoggerFactory.getLogger(JadxWrapper.class);
- private final JadxDecompiler decompiler;
+ private final JadxSettings settings;
+ private JadxDecompiler decompiler;
private File openFile;
- public JadxWrapper(IJadxArgs jadxArgs) throws JadxException {
- this.decompiler = new JadxDecompiler(jadxArgs);
+ public JadxWrapper(JadxSettings settings) {
+ this.settings = settings;
}
public void openFile(File file) {
this.openFile = file;
try {
- this.decompiler.loadFile(file);
- } catch (DecodeException e) {
- LOG.error("Error decode file: {}", file, e);
- } catch (JadxException e) {
- LOG.error("Error open file: {}", file, e);
+ this.decompiler = new JadxDecompiler(settings.toJadxArgs());
+ this.decompiler.getArgs().setInputFiles(Collections.singletonList(file));
+ this.decompiler.load();
+ } catch (Exception e) {
+ LOG.error("Error load file: {}", file, e);
}
}
@@ -42,7 +42,7 @@ public class JadxWrapper {
@Override
public void run() {
try {
- decompiler.setOutputDir(dir);
+ decompiler.getArgs().setRootDir(dir);
ThreadPoolExecutor ex = (ThreadPoolExecutor) decompiler.getSaveExecutor();
ex.shutdown();
while (ex.isTerminating()) {
@@ -53,7 +53,7 @@ public class JadxWrapper {
}
progressMonitor.close();
LOG.info("done");
- } catch (InterruptedException|JadxException e) {
+ } catch (InterruptedException e) {
LOG.error("Save interrupted", e);
Thread.currentThread().interrupt();
}
diff --git a/jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java b/jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java
index e89805cb1..716d09347 100644
--- a/jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java
+++ b/jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java
@@ -11,6 +11,7 @@ import java.util.Set;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
+import jadx.api.JadxArgs;
import jadx.cli.JadxCLIArgs;
public class JadxSettings extends JadxCLIArgs {
@@ -44,7 +45,7 @@ public class JadxSettings extends JadxCLIArgs {
public void fixOnLoad() {
if (threadsCount <= 0) {
- threadsCount = DEFAULT_THREADS_COUNT;
+ threadsCount = JadxArgs.DEFAULT_THREADS_COUNT;
}
}
@@ -165,8 +166,8 @@ public class JadxSettings extends JadxCLIArgs {
this.deobfuscationForceSave = deobfuscationForceSave;
}
- public void setUseSourceNameAsClassAlias(boolean useSourceNameAsAlias) {
- this.deobfuscationUseSourceNameAsAlias = useSourceNameAsAlias;
+ public void setDeobfuscationUseSourceNameAsAlias(boolean deobfuscationUseSourceNameAsAlias) {
+ this.deobfuscationUseSourceNameAsAlias = deobfuscationUseSourceNameAsAlias;
}
public void setEscapeUnicode(boolean escapeUnicode) {
diff --git a/jadx-gui/src/main/java/jadx/gui/settings/JadxSettingsWindow.java b/jadx-gui/src/main/java/jadx/gui/settings/JadxSettingsWindow.java
index 6fb79f09c..5c28e56f2 100644
--- a/jadx-gui/src/main/java/jadx/gui/settings/JadxSettingsWindow.java
+++ b/jadx-gui/src/main/java/jadx/gui/settings/JadxSettingsWindow.java
@@ -145,10 +145,10 @@ public class JadxSettingsWindow extends JDialog {
});
JCheckBox deobfSourceAlias = new JCheckBox();
- deobfSourceAlias.setSelected(settings.useSourceNameAsClassAlias());
+ deobfSourceAlias.setSelected(settings.isDeobfuscationUseSourceNameAsAlias());
deobfSourceAlias.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
- settings.setUseSourceNameAsClassAlias(e.getStateChange() == ItemEvent.SELECTED);
+ settings.setDeobfuscationUseSourceNameAsAlias(e.getStateChange() == ItemEvent.SELECTED);
needReload();
}
});
@@ -219,6 +219,7 @@ public class JadxSettingsWindow extends JDialog {
@Override
public void stateChanged(ChangeEvent e) {
settings.setThreadsCount((Integer) threadsCount.getValue());
+ needReload();
}
});
diff --git a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
index 42cd07034..e2cec158e 100644
--- a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
+++ b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
@@ -27,12 +27,13 @@ import java.util.Arrays;
import java.util.EnumSet;
import java.util.Timer;
import java.util.TimerTask;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.ResourceFile;
-import jadx.core.utils.exceptions.JadxException;
import jadx.gui.JadxWrapper;
import jadx.gui.jobs.BackgroundWorker;
import jadx.gui.jobs.DecompileJob;
@@ -101,7 +102,7 @@ public class MainWindow extends JFrame {
private transient ProgressPanel progressPane;
private transient BackgroundWorker backgroundWorker;
- public MainWindow(JadxSettings settings) throws JadxException {
+ public MainWindow(JadxSettings settings) {
this.wrapper = new JadxWrapper(settings);
this.settings = settings;
this.cacheObject = new CacheObject();
@@ -119,10 +120,10 @@ public class MainWindow extends JFrame {
setLocationRelativeTo(null);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
- if (settings.getInput().isEmpty()) {
+ if (settings.getFiles().isEmpty()) {
openFile();
} else {
- openFile(settings.getInput().get(0));
+ openFile(new File(settings.getFiles().get(0)));
}
}
@@ -689,5 +690,4 @@ public class MainWindow extends JFrame {
public void menuCanceled(MenuEvent e) {
}
}
-
}
diff --git a/jadx-gui/src/test/java/jadx/gui/treemodel/JSourcesTest.java b/jadx-gui/src/test/java/jadx/gui/treemodel/JSourcesTest.java
index 8a248b50e..fe836984b 100644
--- a/jadx-gui/src/test/java/jadx/gui/treemodel/JSourcesTest.java
+++ b/jadx-gui/src/test/java/jadx/gui/treemodel/JSourcesTest.java
@@ -7,7 +7,7 @@ import org.junit.Before;
import org.junit.Test;
import jadx.api.Factory;
-import jadx.api.IJadxArgs;
+import jadx.api.JadxArgs;
import jadx.api.JadxDecompiler;
import jadx.api.JavaClass;
import jadx.api.JavaPackage;
@@ -30,7 +30,7 @@ public class JSourcesTest {
when(root.isFlatPackages()).thenReturn(false);
JadxWrapper wrapper = mock(JadxWrapper.class);
sources = new JSources(root, wrapper);
- decompiler = new JadxDecompiler(mock(IJadxArgs.class));
+ decompiler = new JadxDecompiler(new JadxArgs());
}
@Test