diff --git a/NOTICE b/NOTICE index 97d890911..6fc624ea0 100644 --- a/NOTICE +++ b/NOTICE @@ -104,3 +104,8 @@ under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation. ******************************************************************************* + +GUI icons copied from several places: + - Eclipse Project (JDT UI) - licensed under EPL v1.0 (http://www.eclipse.org/legal/epl-v10.html) + - famfamfam silk icon set (http://www.famfamfam.com/lab/icons/silk/) - licensed under Creative Commons Attribution 2.5 License (http://creativecommons.org/licenses/by/2.5/) + diff --git a/jadx-core/src/main/java/jadx/api/Decompiler.java b/jadx-core/src/main/java/jadx/api/Decompiler.java index 986ab0f79..61fc29d1b 100644 --- a/jadx-core/src/main/java/jadx/api/Decompiler.java +++ b/jadx-core/src/main/java/jadx/api/Decompiler.java @@ -56,11 +56,7 @@ public final class Decompiler { } public void loadFile(File file) throws IOException, DecodeException { - List files = args.getInput(); - files.clear(); - files.add(file); - - loadInput(); + setInput(file); parseDex(); } @@ -119,11 +115,17 @@ public final class Decompiler { } private void loadInput() throws IOException, DecodeException { + inputFiles.clear(); for (File file : args.getInput()) { inputFiles.add(new InputFile(file)); } } + private void setInput(File file) throws IOException, DecodeException { + inputFiles.clear(); + inputFiles.add(new InputFile(file)); + } + private void parseDex() throws DecodeException { ClassInfo.clearCache(); ErrorsCounter.reset(); diff --git a/jadx-core/src/main/java/jadx/core/utils/files/InputFile.java b/jadx-core/src/main/java/jadx/core/utils/files/InputFile.java index 0f35f94d2..e46e1bcf2 100644 --- a/jadx-core/src/main/java/jadx/core/utils/files/InputFile.java +++ b/jadx-core/src/main/java/jadx/core/utils/files/InputFile.java @@ -23,6 +23,9 @@ public class InputFile { public InputFile(File file) throws IOException, DecodeException { this.file = file; + if (!file.exists()) { + throw new IOException("File not found: " + file.getAbsolutePath()); + } String fileName = file.getName(); @@ -81,5 +84,4 @@ public class InputFile { public String toString() { return file.toString(); } - } diff --git a/jadx-gui/src/main/java/jadx/gui/JadxGUI.java b/jadx-gui/src/main/java/jadx/gui/JadxGUI.java index b7c401a80..2533c6ba6 100644 --- a/jadx-gui/src/main/java/jadx/gui/JadxGUI.java +++ b/jadx-gui/src/main/java/jadx/gui/JadxGUI.java @@ -2,7 +2,8 @@ package jadx.gui; import jadx.cli.JadxArgs; -import javax.swing.*; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,7 +26,7 @@ public class JadxGUI { MainWindow mainWindow = new MainWindow(jadxArgs); mainWindow.setVisible(true); - if(!jadxArgs.getInput().isEmpty()) { + if (!jadxArgs.getInput().isEmpty()) { mainWindow.openFile(jadxArgs.getInput().get(0)); } } diff --git a/jadx-gui/src/main/java/jadx/gui/JadxWrapper.java b/jadx-gui/src/main/java/jadx/gui/JadxWrapper.java index 82af2864f..7f5f4c2b9 100644 --- a/jadx-gui/src/main/java/jadx/gui/JadxWrapper.java +++ b/jadx-gui/src/main/java/jadx/gui/JadxWrapper.java @@ -1,7 +1,7 @@ package jadx.gui; -import jadx.api.IJadxArgs; import jadx.api.Decompiler; +import jadx.api.IJadxArgs; import jadx.api.JavaClass; import jadx.api.JavaPackage; import jadx.core.utils.exceptions.DecodeException; @@ -12,12 +12,14 @@ import java.util.List; public class JadxWrapper { private final Decompiler decompiler; + private File openFile; public JadxWrapper(IJadxArgs jadxArgs) { this.decompiler = new Decompiler(jadxArgs); } public void openFile(File file) { + this.openFile = file; try { this.decompiler.loadFile(file); } catch (IOException e) { @@ -35,4 +37,7 @@ public class JadxWrapper { return decompiler.getPackages(); } + public File getOpenFile() { + return openFile; + } } diff --git a/jadx-gui/src/main/java/jadx/gui/MainWindow.java b/jadx-gui/src/main/java/jadx/gui/MainWindow.java index 61bb664e0..dd16bf19f 100644 --- a/jadx-gui/src/main/java/jadx/gui/MainWindow.java +++ b/jadx-gui/src/main/java/jadx/gui/MainWindow.java @@ -1,25 +1,35 @@ package jadx.gui; import jadx.api.JavaClass; -import jadx.api.JavaPackage; import jadx.cli.JadxArgs; -import jadx.gui.model.JClass; -import jadx.core.utils.exceptions.JadxRuntimeException; +import jadx.gui.treemodel.JClass; +import jadx.gui.treemodel.JNode; +import jadx.gui.treemodel.JRoot; -import javax.swing.*; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTree; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.filechooser.FileFilter; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.MutableTreeNode; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeSelectionModel; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.io.File; -import java.net.URL; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; import org.fife.ui.rsyntaxtextarea.SyntaxConstants; @@ -35,8 +45,8 @@ public class MainWindow extends JFrame { private final JadxWrapper wrapper; private JPanel mainPanel; - private DefaultMutableTreeNode treeRoot; private JTree tree; + private DefaultTreeModel treeModel; private RSyntaxTextArea textArea; public MainWindow(JadxArgs jadxArgs) { @@ -52,7 +62,7 @@ public class MainWindow extends JFrame { JMenu file = new JMenu("File"); file.setMnemonic(KeyEvent.VK_F); - JMenuItem exit = new JMenuItem("Exit", openIcon("application-exit")); + JMenuItem exit = new JMenuItem("Exit", Utils.openIcon("cross")); exit.setMnemonic(KeyEvent.VK_E); exit.setToolTipText("Exit application"); exit.addActionListener(new ActionListener() { @@ -61,7 +71,7 @@ public class MainWindow extends JFrame { } }); - JMenuItem open = new JMenuItem("Open", openIcon("document-open-5")); + JMenuItem open = new JMenuItem("Open", Utils.openIcon("folder")); open.setMnemonic(KeyEvent.VK_E); open.setToolTipText("Open file"); open.addActionListener(new ActionListener() { @@ -92,54 +102,49 @@ public class MainWindow extends JFrame { } private void initTree() { - treeRoot.removeAllChildren(); - for (JavaPackage pkg : wrapper.getPackages()) { - MutableTreeNode child = new DefaultMutableTreeNode(pkg); - int i = 0; - for (JavaClass javaClass : pkg.getClasses()) { - MutableTreeNode cls = new DefaultMutableTreeNode(new JClass(javaClass)); - child.insert(cls, i++); - } - treeRoot.add(child); - } + JRoot treeRoot = new JRoot(wrapper); + treeModel.setRoot(treeRoot); + treeModel.reload(); tree.expandRow(0); } - private ImageIcon openIcon(String name) { - String iconPath = "/icons-16/" + name + ".png"; - URL resource = getClass().getResource(iconPath); - if (resource == null) { - throw new JadxRuntimeException("Icon not found: " + iconPath); - } - return new ImageIcon(resource); - } - private void initUI() { mainPanel = new JPanel(new BorderLayout()); JSplitPane splitPane = new JSplitPane(); mainPanel.add(splitPane); - treeRoot = new DefaultMutableTreeNode("Please open file"); - tree = new JTree(treeRoot); + DefaultMutableTreeNode treeRoot = new DefaultMutableTreeNode("Please open file"); + treeModel = new DefaultTreeModel(treeRoot); + tree = new JTree(treeModel); // tree.setRootVisible(false); // tree.setBackground(BACKGROUND); tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); tree.addTreeSelectionListener(new TreeSelectionListener() { @Override public void valueChanged(TreeSelectionEvent e) { - Object node = tree.getLastSelectedPathComponent(); - if (node instanceof DefaultMutableTreeNode) { - Object obj = ((DefaultMutableTreeNode) node).getUserObject(); - if (obj instanceof JClass) { - JavaClass jc = ((JClass) obj).getCls(); - String code = jc.getCode(); - textArea.setText(code); - textArea.setCaretPosition(0); - } + Object obj = tree.getLastSelectedPathComponent(); + if (obj instanceof JClass) { + JavaClass jc = ((JClass) obj).getCls(); + String code = jc.getCode(); + textArea.setText(code); + textArea.setCaretPosition(0); } } }); + tree.setCellRenderer(new DefaultTreeCellRenderer() { + @Override + public Component getTreeCellRendererComponent(JTree tree, + Object value, boolean selected, boolean expanded, + boolean isLeaf, int row, boolean focused) { + Component c = super.getTreeCellRendererComponent(tree, value, selected, expanded, isLeaf, row, focused); + if (value instanceof JNode) { + setIcon(((JNode) value).getIcon()); + } + return c; + } + }); + JScrollPane treeScrollPane = new JScrollPane(tree); splitPane.setLeftComponent(treeScrollPane); diff --git a/jadx-gui/src/main/java/jadx/gui/Utils.java b/jadx-gui/src/main/java/jadx/gui/Utils.java new file mode 100644 index 000000000..f23c80101 --- /dev/null +++ b/jadx-gui/src/main/java/jadx/gui/Utils.java @@ -0,0 +1,18 @@ +package jadx.gui; + +import jadx.core.utils.exceptions.JadxRuntimeException; + +import javax.swing.ImageIcon; +import java.net.URL; + +public class Utils { + + public static ImageIcon openIcon(String name) { + String iconPath = "/icons-16/" + name + ".png"; + URL resource = Utils.class.getResource(iconPath); + if (resource == null) { + throw new JadxRuntimeException("Icon not found: " + iconPath); + } + return new ImageIcon(resource); + } +} diff --git a/jadx-gui/src/main/java/jadx/gui/model/JClass.java b/jadx-gui/src/main/java/jadx/gui/model/JClass.java deleted file mode 100644 index 39a0adf7f..000000000 --- a/jadx-gui/src/main/java/jadx/gui/model/JClass.java +++ /dev/null @@ -1,21 +0,0 @@ -package jadx.gui.model; - -import jadx.api.JavaClass; - -public class JClass { - - private final JavaClass cls; - - public JClass(JavaClass cls) { - this.cls = cls; - } - - public JavaClass getCls() { - return cls; - } - - @Override - public String toString() { - return cls.getShortName(); - } -} diff --git a/jadx-gui/src/main/java/jadx/gui/treemodel/JClass.java b/jadx-gui/src/main/java/jadx/gui/treemodel/JClass.java new file mode 100644 index 000000000..252b15b40 --- /dev/null +++ b/jadx-gui/src/main/java/jadx/gui/treemodel/JClass.java @@ -0,0 +1,30 @@ +package jadx.gui.treemodel; + +import jadx.api.JavaClass; +import jadx.gui.Utils; + +import javax.swing.Icon; +import javax.swing.tree.DefaultMutableTreeNode; + +public class JClass extends DefaultMutableTreeNode implements JNode { + + private final JavaClass cls; + + public JClass(JavaClass cls) { + this.cls = cls; + } + + public JavaClass getCls() { + return cls; + } + + @Override + public Icon getIcon() { + return Utils.openIcon("class_obj"); + } + + @Override + public String toString() { + return cls.getShortName(); + } +} diff --git a/jadx-gui/src/main/java/jadx/gui/treemodel/JNode.java b/jadx-gui/src/main/java/jadx/gui/treemodel/JNode.java new file mode 100644 index 000000000..b05409ed3 --- /dev/null +++ b/jadx-gui/src/main/java/jadx/gui/treemodel/JNode.java @@ -0,0 +1,7 @@ +package jadx.gui.treemodel; + +import javax.swing.Icon; + +public interface JNode { + Icon getIcon(); +} diff --git a/jadx-gui/src/main/java/jadx/gui/treemodel/JPackage.java b/jadx-gui/src/main/java/jadx/gui/treemodel/JPackage.java new file mode 100644 index 000000000..029c947e2 --- /dev/null +++ b/jadx-gui/src/main/java/jadx/gui/treemodel/JPackage.java @@ -0,0 +1,37 @@ +package jadx.gui.treemodel; + +import jadx.api.JavaClass; +import jadx.api.JavaPackage; +import jadx.gui.Utils; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.tree.DefaultMutableTreeNode; + +public class JPackage extends DefaultMutableTreeNode implements JNode { + private static final ImageIcon PACKAGE_ICON = Utils.openIcon("package_obj"); + + private final JavaPackage pkg; + + public JPackage(JavaPackage pkg) { + this.pkg = pkg; + + for (JavaClass javaClass : pkg.getClasses()) { + add(new JClass(javaClass)); + } + } + + public JavaPackage getPkg() { + return pkg; + } + + @Override + public Icon getIcon() { + return PACKAGE_ICON; + } + + @Override + public String toString() { + return pkg.getName(); + } +} diff --git a/jadx-gui/src/main/java/jadx/gui/treemodel/JRoot.java b/jadx-gui/src/main/java/jadx/gui/treemodel/JRoot.java new file mode 100644 index 000000000..dfc755e91 --- /dev/null +++ b/jadx-gui/src/main/java/jadx/gui/treemodel/JRoot.java @@ -0,0 +1,36 @@ +package jadx.gui.treemodel; + +import jadx.api.JavaPackage; +import jadx.gui.JadxWrapper; +import jadx.gui.Utils; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.tree.DefaultMutableTreeNode; +import java.io.File; + +public class JRoot extends DefaultMutableTreeNode implements JNode { + + private static final ImageIcon ROOT_ICON = Utils.openIcon("java_model_obj"); + + private final JadxWrapper wrapper; + + public JRoot(JadxWrapper wrapper) { + this.wrapper = wrapper; + + for (JavaPackage pkg : wrapper.getPackages()) { + add(new JPackage(pkg)); + } + } + + @Override + public Icon getIcon() { + return ROOT_ICON; + } + + @Override + public String toString() { + File file = wrapper.getOpenFile(); + return file != null ? file.getName() : "File not open"; + } +} diff --git a/jadx-gui/src/main/resources/icons-16/annotation_obj.png b/jadx-gui/src/main/resources/icons-16/annotation_obj.png new file mode 100644 index 000000000..e1b272b2e Binary files /dev/null and b/jadx-gui/src/main/resources/icons-16/annotation_obj.png differ diff --git a/jadx-gui/src/main/resources/icons-16/application-exit.png b/jadx-gui/src/main/resources/icons-16/application-exit.png deleted file mode 100644 index fc8ab3008..000000000 Binary files a/jadx-gui/src/main/resources/icons-16/application-exit.png and /dev/null differ diff --git a/jadx-gui/src/main/resources/icons-16/class_default_obj.png b/jadx-gui/src/main/resources/icons-16/class_default_obj.png new file mode 100644 index 000000000..af7e9df27 Binary files /dev/null and b/jadx-gui/src/main/resources/icons-16/class_default_obj.png differ diff --git a/jadx-gui/src/main/resources/icons-16/class_obj.png b/jadx-gui/src/main/resources/icons-16/class_obj.png new file mode 100644 index 000000000..c57c2d00f Binary files /dev/null and b/jadx-gui/src/main/resources/icons-16/class_obj.png differ diff --git a/jadx-gui/src/main/resources/icons-16/cross.png b/jadx-gui/src/main/resources/icons-16/cross.png new file mode 100644 index 000000000..1514d51a3 Binary files /dev/null and b/jadx-gui/src/main/resources/icons-16/cross.png differ diff --git a/jadx-gui/src/main/resources/icons-16/document-open-5.png b/jadx-gui/src/main/resources/icons-16/document-open-5.png deleted file mode 100644 index 727f024fd..000000000 Binary files a/jadx-gui/src/main/resources/icons-16/document-open-5.png and /dev/null differ diff --git a/jadx-gui/src/main/resources/icons-16/enum_obj.png b/jadx-gui/src/main/resources/icons-16/enum_obj.png new file mode 100644 index 000000000..5e96f5e39 Binary files /dev/null and b/jadx-gui/src/main/resources/icons-16/enum_obj.png differ diff --git a/jadx-gui/src/main/resources/icons-16/folder.png b/jadx-gui/src/main/resources/icons-16/folder.png new file mode 100644 index 000000000..784e8fa48 Binary files /dev/null and b/jadx-gui/src/main/resources/icons-16/folder.png differ diff --git a/jadx-gui/src/main/resources/icons-16/innerclass_private_obj.png b/jadx-gui/src/main/resources/icons-16/innerclass_private_obj.png new file mode 100644 index 000000000..3fbcbe916 Binary files /dev/null and b/jadx-gui/src/main/resources/icons-16/innerclass_private_obj.png differ diff --git a/jadx-gui/src/main/resources/icons-16/innerclass_protected_obj.png b/jadx-gui/src/main/resources/icons-16/innerclass_protected_obj.png new file mode 100644 index 000000000..9a668e425 Binary files /dev/null and b/jadx-gui/src/main/resources/icons-16/innerclass_protected_obj.png differ diff --git a/jadx-gui/src/main/resources/icons-16/int_obj.png b/jadx-gui/src/main/resources/icons-16/int_obj.png new file mode 100644 index 000000000..31caf5a71 Binary files /dev/null and b/jadx-gui/src/main/resources/icons-16/int_obj.png differ diff --git a/jadx-gui/src/main/resources/icons-16/java_model_obj.png b/jadx-gui/src/main/resources/icons-16/java_model_obj.png new file mode 100644 index 000000000..3918c215f Binary files /dev/null and b/jadx-gui/src/main/resources/icons-16/java_model_obj.png differ diff --git a/jadx-gui/src/main/resources/icons-16/jcu_obj.png b/jadx-gui/src/main/resources/icons-16/jcu_obj.png new file mode 100644 index 000000000..dceae7219 Binary files /dev/null and b/jadx-gui/src/main/resources/icons-16/jcu_obj.png differ diff --git a/jadx-gui/src/main/resources/icons-16/jsearch_obj.png b/jadx-gui/src/main/resources/icons-16/jsearch_obj.png new file mode 100644 index 000000000..c34b05813 Binary files /dev/null and b/jadx-gui/src/main/resources/icons-16/jsearch_obj.png differ diff --git a/jadx-gui/src/main/resources/icons-16/library_obj.png b/jadx-gui/src/main/resources/icons-16/library_obj.png new file mode 100644 index 000000000..ed1a4d626 Binary files /dev/null and b/jadx-gui/src/main/resources/icons-16/library_obj.png differ diff --git a/jadx-gui/src/main/resources/icons-16/methdef_obj.png b/jadx-gui/src/main/resources/icons-16/methdef_obj.png new file mode 100644 index 000000000..a4131b9ba Binary files /dev/null and b/jadx-gui/src/main/resources/icons-16/methdef_obj.png differ diff --git a/jadx-gui/src/main/resources/icons-16/methpri_obj.png b/jadx-gui/src/main/resources/icons-16/methpri_obj.png new file mode 100644 index 000000000..57dbb7691 Binary files /dev/null and b/jadx-gui/src/main/resources/icons-16/methpri_obj.png differ diff --git a/jadx-gui/src/main/resources/icons-16/methpro_obj.png b/jadx-gui/src/main/resources/icons-16/methpro_obj.png new file mode 100644 index 000000000..3e4c0d785 Binary files /dev/null and b/jadx-gui/src/main/resources/icons-16/methpro_obj.png differ diff --git a/jadx-gui/src/main/resources/icons-16/methpub_obj.png b/jadx-gui/src/main/resources/icons-16/methpub_obj.png new file mode 100644 index 000000000..300419528 Binary files /dev/null and b/jadx-gui/src/main/resources/icons-16/methpub_obj.png differ diff --git a/jadx-gui/src/main/resources/icons-16/package_obj.png b/jadx-gui/src/main/resources/icons-16/package_obj.png new file mode 100644 index 000000000..0afea5b86 Binary files /dev/null and b/jadx-gui/src/main/resources/icons-16/package_obj.png differ diff --git a/jadx-gui/src/main/resources/icons-16/wrench.png b/jadx-gui/src/main/resources/icons-16/wrench.png new file mode 100644 index 000000000..5c8213fef Binary files /dev/null and b/jadx-gui/src/main/resources/icons-16/wrench.png differ