diff --git a/README.md b/README.md index b592544..c152629 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,9 @@ Java Decompiler Gui ## Languages +- [Dutch](https://github.com/sotasan/decompiler/blob/master/src/main/resources/langs/language_nl.properties) - [English](https://github.com/sotasan/decompiler/blob/master/src/main/resources/langs/language.properties) +- [French](https://github.com/sotasan/decompiler/blob/master/src/main/resources/langs/language_fr.properties) - [German](https://github.com/sotasan/decompiler/blob/master/src/main/resources/langs/language_de.properties) - [Japanese](https://github.com/sotasan/decompiler/blob/master/src/main/resources/langs/language_ja.properties) - [Russian](https://github.com/sotasan/decompiler/blob/master/src/main/resources/langs/language_ru.properties) diff --git a/build.gradle b/build.gradle index 97ed64e..4a8ad8e 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ plugins { } group = "com.sotasan" -version = "0.8.10" +version = "0.9.0" repositories { mavenCentral() diff --git a/src/main/java/com/sotasan/decompiler/controllers/TabController.java b/src/main/java/com/sotasan/decompiler/controllers/TabController.java index e609d2e..598660e 100644 --- a/src/main/java/com/sotasan/decompiler/controllers/TabController.java +++ b/src/main/java/com/sotasan/decompiler/controllers/TabController.java @@ -3,26 +3,36 @@ import com.sotasan.decompiler.models.FileModel; import com.sotasan.decompiler.views.TabView; import lombok.Getter; +import org.fife.ui.rsyntaxtextarea.SyntaxConstants; +import org.jetbrains.annotations.NotNull; @Getter public class TabController extends BaseController { private final FileModel fileModel; - public TabController(FileModel fileModel) { + public TabController(@NotNull FileModel fileModel) { super(new TabView()); this.fileModel = fileModel; + if (fileModel.isClass()) + getView().getTextArea().setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); getView().setController(this); update(); } public void update() { try { - getView().getTextArea().setText(TabsController.getINSTANCE().getTransformer().getInstance().transform(fileModel)); + getView().getTextArea().setText(getText(fileModel)); getView().getTextArea().setCaretPosition(0); } catch (Exception e) { getView().getTextArea().setText(e.getMessage()); } } + private String getText(@NotNull FileModel fileModel) throws Exception { + return fileModel.isClass() + ? TabsController.getINSTANCE().getTransformer().getInstance().transform(fileModel) + : new String(fileModel.getBytes()); + } + } \ No newline at end of file diff --git a/src/main/java/com/sotasan/decompiler/controllers/TabsController.java b/src/main/java/com/sotasan/decompiler/controllers/TabsController.java index 4de98dd..727b908 100644 --- a/src/main/java/com/sotasan/decompiler/controllers/TabsController.java +++ b/src/main/java/com/sotasan/decompiler/controllers/TabsController.java @@ -21,8 +21,11 @@ private TabsController() { @Override public void actionPerformed(ActionEvent event) { - for (int i = 0; i < getView().getTabCount(); i++) - ((TabView) getView().getComponentAt(i)).getController().update(); + for (int i = 0; i < getView().getTabCount(); i++) { + TabController controller = ((TabView) getView().getComponentAt(i)).getController(); + if (controller.getFileModel().isClass()) + controller.update(); + } } public void addTab(@NotNull FileModel fileModel) { diff --git a/src/main/java/com/sotasan/decompiler/controllers/TreeController.java b/src/main/java/com/sotasan/decompiler/controllers/TreeController.java index 5d21722..847409d 100644 --- a/src/main/java/com/sotasan/decompiler/controllers/TreeController.java +++ b/src/main/java/com/sotasan/decompiler/controllers/TreeController.java @@ -2,14 +2,14 @@ import com.sotasan.decompiler.models.ArchiveModel; import com.sotasan.decompiler.models.BaseModel; -import com.sotasan.decompiler.models.FileModel; -import com.sotasan.decompiler.models.PackageModel; import com.sotasan.decompiler.views.TreeView; import lombok.Getter; import org.jetbrains.annotations.NotNull; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; +import java.util.Collections; +import java.util.List; public class TreeController extends BaseController { @@ -29,15 +29,12 @@ public void setArchive(ArchiveModel archiveModel) { getView().getTree().expandPath(new TreePath(treeNode.getPath())); } - // TODO: Update sorting (+ Alphabetic, Inside Loader) private @NotNull DefaultMutableTreeNode createTreeNode(BaseModel baseModel) { DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode(baseModel); - for (BaseModel child : baseModel.getChildren()) - if (child instanceof PackageModel) - treeNode.add(createTreeNode(child)); - for (BaseModel child : baseModel.getChildren()) - if (child instanceof FileModel) - treeNode.add(createTreeNode(child)); + List children = baseModel.getChildren(); + Collections.sort(children); + for (BaseModel child : children) + treeNode.add(createTreeNode(child)); return treeNode; } diff --git a/src/main/java/com/sotasan/decompiler/models/BaseModel.java b/src/main/java/com/sotasan/decompiler/models/BaseModel.java index 26d8c66..90e77ad 100644 --- a/src/main/java/com/sotasan/decompiler/models/BaseModel.java +++ b/src/main/java/com/sotasan/decompiler/models/BaseModel.java @@ -2,34 +2,39 @@ import lombok.Getter; import lombok.SneakyThrows; +import org.jetbrains.annotations.NotNull; import java.awt.*; import java.util.ArrayList; import java.util.List; import java.util.Objects; -public abstract class BaseModel { +@Getter +public abstract class BaseModel implements Comparable { - @Getter private final List children = new ArrayList<>(); - @Getter private final String path; - @Getter private String name; - @Getter private Image icon; + private final List children = new ArrayList<>(); + private final String path; + private String name; + private Image icon; public BaseModel(String path, boolean directory) { this.path = path; - name = path; - - if (directory) - name = path.substring(0, path.length() - 1); + name = directory ? path.substring(0, path.length() - 1) : path; name = name.substring(name.lastIndexOf('/') + 1); } - public boolean isClass() { - return name.toLowerCase().endsWith(".class"); - } - @SneakyThrows public void setIcon(String path) { icon = Toolkit.getDefaultToolkit().createImage(Objects.requireNonNull(getClass().getClassLoader().getResourceAsStream(path)).readAllBytes()); } + @Override + public int compareTo(@NotNull BaseModel baseModel) { + Class class1 = getClass(); + Class class2 = baseModel.getClass(); + return class1.equals(class2) ? getName().compareToIgnoreCase(baseModel.getName()) + : class1.equals(FileModel.class) ? 1 + : class2.equals(FileModel.class) ? -1 + : 0; + } + } \ No newline at end of file diff --git a/src/main/java/com/sotasan/decompiler/models/FileModel.java b/src/main/java/com/sotasan/decompiler/models/FileModel.java index f76f44e..341ce44 100644 --- a/src/main/java/com/sotasan/decompiler/models/FileModel.java +++ b/src/main/java/com/sotasan/decompiler/models/FileModel.java @@ -6,10 +6,11 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; +@Getter public class FileModel extends BaseModel { - @Getter private final JarFile jarFile; - @Getter private final JarEntry jarEntry; + private final JarFile jarFile; + private final JarEntry jarEntry; public FileModel(JarFile jarFile, @NotNull JarEntry jarEntry) { super(jarEntry.getName(), false); @@ -18,6 +19,10 @@ public FileModel(JarFile jarFile, @NotNull JarEntry jarEntry) { setIcon(isClass() ? "icons/class.png" : "icons/file.png"); } + public boolean isClass() { + return getName().toLowerCase().endsWith(".class"); + } + @SneakyThrows public byte[] getBytes() { return jarFile.getInputStream(jarEntry).readAllBytes(); diff --git a/src/main/java/com/sotasan/decompiler/transformers/CFRTransformer.java b/src/main/java/com/sotasan/decompiler/transformers/CFRTransformer.java index 8877e00..37b7bc6 100644 --- a/src/main/java/com/sotasan/decompiler/transformers/CFRTransformer.java +++ b/src/main/java/com/sotasan/decompiler/transformers/CFRTransformer.java @@ -5,18 +5,25 @@ import org.benf.cfr.reader.api.ClassFileSource; import org.benf.cfr.reader.api.OutputSinkFactory; import org.benf.cfr.reader.bytecode.analysis.parse.utils.Pair; +import org.benf.cfr.reader.util.getopt.OptionsImpl; import org.jetbrains.annotations.NotNull; import java.util.*; public class CFRTransformer implements ITransformer, ClassFileSource, OutputSinkFactory, OutputSinkFactory.Sink { + private static final Map OPTIONS = Map.of( + OptionsImpl.DECOMPILE_INNER_CLASSES.getName(), String.valueOf(false), + OptionsImpl.RELINK_CONSTANT_STRINGS.getName(), String.valueOf(false), + OptionsImpl.REMOVE_INNER_CLASS_SYNTHETICS.getName(), String.valueOf(false) + ); + private FileModel fileModel; private String output; @Override public String transform(@NotNull FileModel fileModel) { this.fileModel = fileModel; - CfrDriver driver = new CfrDriver.Builder().withClassFileSource(this).withOutputSink(this).build(); + CfrDriver driver = new CfrDriver.Builder().withClassFileSource(this).withOptions(OPTIONS).withOutputSink(this).build(); driver.analyse(Collections.singletonList(fileModel.getPath())); if (output.startsWith("/")) output = output.substring(37); diff --git a/src/main/java/com/sotasan/decompiler/views/TabView.java b/src/main/java/com/sotasan/decompiler/views/TabView.java index b204dbc..4368bb9 100644 --- a/src/main/java/com/sotasan/decompiler/views/TabView.java +++ b/src/main/java/com/sotasan/decompiler/views/TabView.java @@ -5,7 +5,6 @@ import lombok.Setter; import lombok.SneakyThrows; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; -import org.fife.ui.rsyntaxtextarea.SyntaxConstants; import org.fife.ui.rsyntaxtextarea.Theme; import org.fife.ui.rtextarea.RTextScrollPane; import org.jetbrains.annotations.NotNull; @@ -35,7 +34,6 @@ public TabView() { textArea.setDropTarget(null); textArea.setEditable(false); textArea.setHighlightCurrentLine(false); - textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); scrollPane = new RTextScrollPane(textArea); theme.apply(textArea); diff --git a/src/main/java/com/sotasan/decompiler/views/TreeView.java b/src/main/java/com/sotasan/decompiler/views/TreeView.java index 1dd90e5..9416a7f 100644 --- a/src/main/java/com/sotasan/decompiler/views/TreeView.java +++ b/src/main/java/com/sotasan/decompiler/views/TreeView.java @@ -57,18 +57,20 @@ private static class TreeMouseAdapter extends MouseAdapter { @Override public void mouseClicked(@NotNull MouseEvent event) { - if (event.getClickCount() == 2) { - TreePath path = ((JTree) event.getSource()).getSelectionPath(); - if (path != null) { - DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent(); - if (node.getUserObject() != null) { - BaseModel model = (BaseModel) node.getUserObject(); - if (model instanceof FileModel && model.isClass()) { - TabsController.getINSTANCE().addTab((FileModel) model); - } - } - } - } + if (event.getClickCount() != 2) + return; + + TreePath path = ((JTree) event.getSource()).getSelectionPath(); + if (path == null) + return; + + DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent(); + if (node.getUserObject() == null) + return; + + BaseModel model = (BaseModel) node.getUserObject(); + if (model instanceof FileModel) + TabsController.getINSTANCE().addTab((FileModel) model); } } diff --git a/src/main/resources/langs/language_fr.properties b/src/main/resources/langs/language_fr.properties new file mode 100644 index 0000000..d5bff12 --- /dev/null +++ b/src/main/resources/langs/language_fr.properties @@ -0,0 +1,14 @@ +file=Fichier +file.openFile=Ouvrir un fichier +file.newInstance=Nouvelle instance +file.exit=Quitter + +help=Aide + +empty=Aucun fichier ouvert +empty.drag=Glisser-déposer pour ouvrir + +about=À propos +about.version=Version %s +about.vm=Machine Virtuelle +about.ok=OK \ No newline at end of file diff --git a/src/main/resources/langs/language_nl.properties b/src/main/resources/langs/language_nl.properties new file mode 100644 index 0000000..b4189ce --- /dev/null +++ b/src/main/resources/langs/language_nl.properties @@ -0,0 +1,14 @@ +file=Bestand +file.openFile=Bestand openen +file.newInstance=Nieuwe instantie +file.exit=Verlaten + +help=Hulp + +empty=Geen opende bestand +empty.drag=Slepen en neerzetten om te openen + +about=Over +about.version=Versie %s +about.vm=Virtuele Machine +about.ok=OK \ No newline at end of file