From b9b8d44cc15adf420beaefcc21e82191f78178de Mon Sep 17 00:00:00 2001 From: Konloch Date: Wed, 14 Jul 2021 04:33:20 -0700 Subject: [PATCH] Improved Resource Updating Still a work in progress --- .../club/bytecodeviewer/BytecodeViewer.java | 12 +- .../compilers/InternalCompiler.java | 2 +- .../compilers/impl/JavaCompiler.java | 8 +- .../compilers/impl/KrakatauAssembler.java | 6 +- .../compilers/impl/SmaliAssembler.java | 2 +- .../bytecodeviewer/gui/MainViewerGUI.java | 6 +- .../gui/components/MethodsRenderer.java | 10 +- ...eViewPanel.java => BytecodeViewPanel.java} | 25 +-- .../ResourceViewProcessing.java | 121 -------------- .../resourceviewer/viewer/ClassViewer.java | 62 +++---- ...ead.java => BytecodeViewPanelUpdater.java} | 154 +++++++++++++----- .../resources/ResourceContainer.java | 20 ++- 12 files changed, 193 insertions(+), 235 deletions(-) rename src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/{ResourceViewPanel.java => BytecodeViewPanel.java} (85%) delete mode 100644 src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/ResourceViewProcessing.java rename src/main/java/the/bytecode/club/bytecodeviewer/gui/util/{PaneUpdaterThread.java => BytecodeViewPanelUpdater.java} (70%) diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/BytecodeViewer.java b/src/main/java/the/bytecode/club/bytecodeviewer/BytecodeViewer.java index c8989c19..c389b806 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/BytecodeViewer.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/BytecodeViewer.java @@ -438,18 +438,18 @@ public class BytecodeViewer { ClassViewer cv = (ClassViewer) c; - if(noErrors && !cv.resourceViewPanel1.compile()) + if(noErrors && !cv.bytecodeViewPanel1.compile()) noErrors = false; - if(noErrors && !cv.resourceViewPanel2.compile()) + if(noErrors && !cv.bytecodeViewPanel2.compile()) noErrors = false; - if(noErrors && !cv.resourceViewPanel3.compile()) + if(noErrors && !cv.bytecodeViewPanel3.compile()) noErrors = false; - if(cv.resourceViewPanel1.textArea != null && cv.resourceViewPanel1.textArea.isEditable()) + if(cv.bytecodeViewPanel1.textArea != null && cv.bytecodeViewPanel1.textArea.isEditable()) actuallyTried = true; - if(cv.resourceViewPanel2.textArea != null && cv.resourceViewPanel2.textArea.isEditable()) + if(cv.bytecodeViewPanel2.textArea != null && cv.bytecodeViewPanel2.textArea.isEditable()) actuallyTried = true; - if(cv.resourceViewPanel3.textArea != null && cv.resourceViewPanel3.textArea.isEditable()) + if(cv.bytecodeViewPanel3.textArea != null && cv.bytecodeViewPanel3.textArea.isEditable()) actuallyTried = true; } } diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/compilers/InternalCompiler.java b/src/main/java/the/bytecode/club/bytecodeviewer/compilers/InternalCompiler.java index be5d3919..b41b1295 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/compilers/InternalCompiler.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/compilers/InternalCompiler.java @@ -26,5 +26,5 @@ package the.bytecode.club.bytecodeviewer.compilers; public abstract class InternalCompiler { - public abstract byte[] compile(String contents, String name); + public abstract byte[] compile(String contents, String fullyQualifiedName); } \ No newline at end of file diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/compilers/impl/JavaCompiler.java b/src/main/java/the/bytecode/club/bytecodeviewer/compilers/impl/JavaCompiler.java index e1babd37..7b9117c2 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/compilers/impl/JavaCompiler.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/compilers/impl/JavaCompiler.java @@ -42,14 +42,14 @@ import static the.bytecode.club.bytecodeviewer.Constants.*; public class JavaCompiler extends InternalCompiler { @Override - public byte[] compile(String contents, String name) + public byte[] compile(String contents, String fullyQualifiedName) { String fileStart = tempDirectory + fs + "temp" + MiscUtils.randomString(12) + fs; String fileStart2 = tempDirectory + fs + "temp" + MiscUtils.randomString(12) + fs; - File java = new File(fileStart + fs + name + ".java"); - File clazz = new File(fileStart2 + fs + name + ".class"); + File java = new File(fileStart + fs + fullyQualifiedName + ".java"); + File clazz = new File(fileStart2 + fs + fullyQualifiedName + ".class"); File cp = new File(tempDirectory + fs + "cpath_" + MiscUtils.randomString(12) + ".jar"); - File tempD = new File(fileStart + fs + name.substring(0, name.length() - name.split("/")[name.split("/").length - 1].length())); + File tempD = new File(fileStart + fs + fullyQualifiedName.substring(0, fullyQualifiedName.length() - fullyQualifiedName.split("/")[fullyQualifiedName.split("/").length - 1].length())); tempD.mkdirs(); new File(fileStart2).mkdirs(); diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/compilers/impl/KrakatauAssembler.java b/src/main/java/the/bytecode/club/bytecodeviewer/compilers/impl/KrakatauAssembler.java index 1ba9f36b..225d4df5 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/compilers/impl/KrakatauAssembler.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/compilers/impl/KrakatauAssembler.java @@ -44,9 +44,9 @@ import static the.bytecode.club.bytecodeviewer.Constants.*; */ public class KrakatauAssembler extends InternalCompiler { - @Override - public byte[] compile(String contents, String name) { + public byte[] compile(String contents, String fullyQualifiedName) + { if(!ExternalResources.getSingleton().hasSetPython2Command()) return null; @@ -55,7 +55,7 @@ public class KrakatauAssembler extends InternalCompiler File tempD = new File(Constants.tempDirectory + fs + MiscUtils.randomString(32) + fs); tempD.mkdir(); - File tempJ = new File(tempD.getAbsolutePath() + fs + name + ".j"); + File tempJ = new File(tempD.getAbsolutePath() + fs + fullyQualifiedName + ".j"); DiskWriter.replaceFile(tempJ.getAbsolutePath(), contents, true); final File tempDirectory = new File(Constants.tempDirectory + fs + MiscUtils.randomString(32) + fs); diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/compilers/impl/SmaliAssembler.java b/src/main/java/the/bytecode/club/bytecodeviewer/compilers/impl/SmaliAssembler.java index a9addc42..914fa915 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/compilers/impl/SmaliAssembler.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/compilers/impl/SmaliAssembler.java @@ -40,7 +40,7 @@ import static the.bytecode.club.bytecodeviewer.Constants.*; public class SmaliAssembler extends InternalCompiler { @Override - public byte[] compile(String contents, String name) + public byte[] compile(String contents, String fullyQualifiedName) { String fileStart = tempDirectory + fs + "temp"; int fileNumber = MiscUtils.getClassNumber(fileStart, ".dex"); diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/MainViewerGUI.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/MainViewerGUI.java index 573e184d..73f09f55 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/MainViewerGUI.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/MainViewerGUI.java @@ -908,9 +908,9 @@ public class MainViewerGUI extends JFrame continue; ClassViewer viewerClass = (ClassViewer) viewerResource; - Configuration.rstaTheme.apply(viewerClass.resourceViewPanel1.textArea); - Configuration.rstaTheme.apply(viewerClass.resourceViewPanel2.textArea); - Configuration.rstaTheme.apply(viewerClass.resourceViewPanel3.textArea); + Configuration.rstaTheme.apply(viewerClass.bytecodeViewPanel1.textArea); + Configuration.rstaTheme.apply(viewerClass.bytecodeViewPanel2.textArea); + Configuration.rstaTheme.apply(viewerClass.bytecodeViewPanel3.textArea); } SwingUtilities.updateComponentTreeUI(BytecodeViewer.viewer); } diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/components/MethodsRenderer.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/components/MethodsRenderer.java index bfa723c5..234d48aa 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/components/MethodsRenderer.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/components/MethodsRenderer.java @@ -1,6 +1,6 @@ package the.bytecode.club.bytecodeviewer.gui.components; -import the.bytecode.club.bytecodeviewer.gui.util.PaneUpdaterThread; +import the.bytecode.club.bytecodeviewer.gui.util.BytecodeViewPanelUpdater; import the.bytecode.club.bytecodeviewer.util.MethodParser; import javax.swing.*; @@ -31,11 +31,11 @@ import java.awt.*; */ public class MethodsRenderer extends JLabel implements ListCellRenderer { - private final PaneUpdaterThread paneUpdaterThread; + private final BytecodeViewPanelUpdater bytecodeViewPanelUpdater; - public MethodsRenderer(PaneUpdaterThread paneUpdaterThread) + public MethodsRenderer(BytecodeViewPanelUpdater bytecodeViewPanelUpdater) { - this.paneUpdaterThread = paneUpdaterThread; + this.bytecodeViewPanelUpdater = bytecodeViewPanelUpdater; setOpaque(true); } @@ -43,7 +43,7 @@ public class MethodsRenderer extends JLabel implements ListCellRenderer public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - MethodParser methods = paneUpdaterThread.viewer.methods.get(paneUpdaterThread.resourceViewPanel.decompiler.ordinal()); + MethodParser methods = bytecodeViewPanelUpdater.viewer.methods.get(bytecodeViewPanelUpdater.bytecodeViewPanel.decompiler.ordinal()); MethodParser.Method method = methods.getMethod((Integer) value); setText(method.toString()); return this; diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/ResourceViewPanel.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/BytecodeViewPanel.java similarity index 85% rename from src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/ResourceViewPanel.java rename to src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/BytecodeViewPanel.java index 96893e91..3e232522 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/ResourceViewPanel.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/BytecodeViewPanel.java @@ -6,7 +6,7 @@ import the.bytecode.club.bytecodeviewer.decompilers.Decompiler; import the.bytecode.club.bytecodeviewer.gui.components.SearchableRSyntaxTextArea; import the.bytecode.club.bytecodeviewer.gui.components.SystemConsole; import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ClassViewer; -import the.bytecode.club.bytecodeviewer.gui.util.PaneUpdaterThread; +import the.bytecode.club.bytecodeviewer.gui.util.BytecodeViewPanelUpdater; import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings; import the.bytecode.club.bytecodeviewer.util.JarUtils; @@ -34,22 +34,25 @@ import static the.bytecode.club.bytecodeviewer.Constants.nl; ***************************************************************************/ /** + * Represents a Bytecode/ClassFile View Panel + * * @author Konloch * @since 6/24/2021 */ -public class ResourceViewPanel +public class BytecodeViewPanel { public final JPanel panel = new JPanel(new BorderLayout()); public final int panelIndex; public final ClassViewer viewer; - public Decompiler decompiler = Decompiler.NONE; public SearchableRSyntaxTextArea textArea; - public PaneUpdaterThread updateThread; + public BytecodeViewPanelUpdater updateThread; + public Decompiler decompiler = Decompiler.NONE; + public Compiler compiler = Compiler.JAVA_COMPILER; - public Compiler compileMode = Compiler.JAVA_COMPILER; - - public ResourceViewPanel(int panelIndex, ClassViewer viewer) {this.panelIndex = panelIndex; + public BytecodeViewPanel(int panelIndex, ClassViewer viewer) + { + this.panelIndex = panelIndex; this.viewer = viewer; } @@ -59,14 +62,12 @@ public class ResourceViewPanel textArea = null; if(viewer.viewerClassNode == null) - { panel.add(new JLabel("ERROR: Resource Viewer Corrupt ClassNode")); - } } public void updatePane(ClassViewer cv, byte[] b, JButton button, boolean isPanelEditable) { - updateThread = new ResourceViewProcessing(this, cv, b, isPanelEditable, button); + updateThread = new BytecodeViewPanelUpdater(this, cv, b, isPanelEditable, button); } public boolean compile() @@ -83,12 +84,12 @@ public class ResourceViewPanel try { String text = textArea.getText(); - byte[] compiledClass = compileMode.getCompiler().compile(text, viewer.viewerClassNode.name); + byte[] compiledClass = compiler.getCompiler().compile(text, viewer.viewerClassNode.name); if (compiledClass != null) { ClassNode newNode = JarUtils.getNode(compiledClass); - viewer.container.updateNode(viewer.viewerClassNode, newNode); + viewer.container.updateNode(viewer.name, newNode); errConsole.finished(); return true; } diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/ResourceViewProcessing.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/ResourceViewProcessing.java deleted file mode 100644 index 0b3f1366..00000000 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/ResourceViewProcessing.java +++ /dev/null @@ -1,121 +0,0 @@ -package the.bytecode.club.bytecodeviewer.gui.resourceviewer; - -import org.objectweb.asm.ClassWriter; -import the.bytecode.club.bytecodeviewer.BytecodeViewer; -import the.bytecode.club.bytecodeviewer.decompilers.Decompiler; -import the.bytecode.club.bytecodeviewer.gui.hexviewer.JHexEditor; -import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ClassViewer; -import the.bytecode.club.bytecodeviewer.gui.util.PaneUpdaterThread; - -import javax.swing.*; -import java.awt.*; - -/*************************************************************************** - * Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite * - * Copyright (C) 2014 Kalen 'Konloch' Kinloch - http://bytecodeviewer.com * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see . * - ***************************************************************************/ - -/** - * All classfile resources get preprocessed through this class, from there the specified UI panel is used to display the data - * - * @author Konloch - * @since 6/27/2021 - */ - -public class ResourceViewProcessing extends PaneUpdaterThread -{ - private final ResourceViewPanel resourceViewPanel; - private final byte[] b; - private final JButton button; - public boolean waitingFor; - - public ResourceViewProcessing(ResourceViewPanel resourceViewPanel, ClassViewer cv, byte[] b, boolean isPanelEditable, JButton button) - { - super(cv, resourceViewPanel); - this.resourceViewPanel = resourceViewPanel; - this.b = b; - this.isPanelEditable = isPanelEditable; - this.button = button; - waitingFor = true; - } - - @Override - public void processDisplay() - { - try - { - BytecodeViewer.updateBusyStatus(true); - - if (resourceViewPanel.decompiler != Decompiler.NONE) - { - //hex viewer - if (resourceViewPanel.decompiler == Decompiler.HEXCODE_VIEWER) - { - final ClassWriter cw = new ClassWriter(0); - viewer.viewerClassNode.accept(cw); - - SwingUtilities.invokeLater(() -> - { - final JHexEditor hex = new JHexEditor(cw.toByteArray()); - hex.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int) BytecodeViewer.viewer.fontSpinner.getValue())); - - resourceViewPanel.panel.add(hex); - }); - } - else - { - final Decompiler decompiler = resourceViewPanel.decompiler; - - //perform decompiling inside of this thread - final String decompiledSource = decompiler.getDecompiler().decompileClassNode(viewer.viewerClassNode, b); - - //set the swing components on the swing thread - SwingUtilities.invokeLater(() -> - { - buildTextArea(decompiler, decompiledSource); - waitingFor = false; - }); - - //hold this thread until the swing thread has finished attaching the components - while (waitingFor) - { - try { - Thread.sleep(1); - } catch (Exception e) {} - } - } - } - } - catch (IndexOutOfBoundsException | NullPointerException e) - { - //ignore - } - catch (Exception e) - { - BytecodeViewer.handleException(e); - } - finally - { - viewer.resetDivider(); - BytecodeViewer.updateBusyStatus(false); - SwingUtilities.invokeLater(() -> - { - if (button != null) - button.setEnabled(true); - }); - } - } -} diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/viewer/ClassViewer.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/viewer/ClassViewer.java index 75ab6f8c..d1fb6eef 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/viewer/ClassViewer.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/viewer/ClassViewer.java @@ -2,7 +2,7 @@ package the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer; import the.bytecode.club.bytecodeviewer.api.ASMUtil; import the.bytecode.club.bytecodeviewer.decompilers.Decompiler; -import the.bytecode.club.bytecodeviewer.gui.resourceviewer.ResourceViewPanel; +import the.bytecode.club.bytecodeviewer.gui.resourceviewer.BytecodeViewPanel; import java.awt.BorderLayout; import java.awt.Container; @@ -59,9 +59,9 @@ public class ClassViewer extends ResourceViewer { public JSplitPane sp; public JSplitPane sp2; - public ResourceViewPanel resourceViewPanel1 = new ResourceViewPanel(0, this); - public ResourceViewPanel resourceViewPanel2 = new ResourceViewPanel(1, this); - public ResourceViewPanel resourceViewPanel3 = new ResourceViewPanel(2, this); + public BytecodeViewPanel bytecodeViewPanel1 = new BytecodeViewPanel(0, this); + public BytecodeViewPanel bytecodeViewPanel2 = new BytecodeViewPanel(1, this); + public BytecodeViewPanel bytecodeViewPanel3 = new BytecodeViewPanel(2, this); public List methods = Arrays.asList(new MethodParser(), new MethodParser(), new MethodParser()); public final String workingName; @@ -76,8 +76,8 @@ public class ClassViewer extends ResourceViewer this.setName(name); this.setLayout(new BorderLayout()); - this.sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, resourceViewPanel1.panel, resourceViewPanel2.panel); - this.sp2 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, sp, resourceViewPanel3.panel); + this.sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, bytecodeViewPanel1.panel, bytecodeViewPanel2.panel); + this.sp2 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, sp, bytecodeViewPanel3.panel); this.add(sp2, BorderLayout.CENTER); this.addComponentListener(new ComponentAdapter() { @@ -96,9 +96,9 @@ public class ClassViewer extends ResourceViewer setPanes(); refreshTitle(); - resourceViewPanel1.createPane(this); - resourceViewPanel2.createPane(this); - resourceViewPanel3.createPane(this); + bytecodeViewPanel1.createPane(this); + bytecodeViewPanel2.createPane(this); + bytecodeViewPanel3.createPane(this); byte[] classBytes = getResourceBytes(); @@ -116,9 +116,9 @@ public class ClassViewer extends ResourceViewer classBytes = ASMUtil.nodeToBytes(viewerClassNode); } - resourceViewPanel1.updatePane(this, classBytes, button, isPanel1Editable()); - resourceViewPanel2.updatePane(this, classBytes, button, isPanel2Editable()); - resourceViewPanel3.updatePane(this, classBytes, button, isPanel3Editable()); + bytecodeViewPanel1.updatePane(this, classBytes, button, isPanel1Editable()); + bytecodeViewPanel2.updatePane(this, classBytes, button, isPanel2Editable()); + bytecodeViewPanel3.updatePane(this, classBytes, button, isPanel3Editable()); Thread dumpBuild = new Thread(() -> { @@ -136,12 +136,12 @@ public class ClassViewer extends ResourceViewer BytecodeViewer.updateBusyStatus(false); - if (resourceViewPanel1.decompiler != Decompiler.NONE) - resourceViewPanel1.updateThread.startNewThread(); - if (resourceViewPanel2.decompiler != Decompiler.NONE) - resourceViewPanel2.updateThread.startNewThread(); - if (resourceViewPanel3.decompiler != Decompiler.NONE) - resourceViewPanel3.updateThread.startNewThread(); + if (bytecodeViewPanel1.decompiler != Decompiler.NONE) + bytecodeViewPanel1.updateThread.startNewThread(); + if (bytecodeViewPanel2.decompiler != Decompiler.NONE) + bytecodeViewPanel2.updateThread.startNewThread(); + if (bytecodeViewPanel3.decompiler != Decompiler.NONE) + bytecodeViewPanel3.updateThread.startNewThread(); }, "ClassViewer Temp Dump"); dumpBuild.start(); @@ -164,9 +164,9 @@ public class ClassViewer extends ResourceViewer } public void setPanes() { - resourceViewPanel1.decompiler = BytecodeViewer.viewer.viewPane1.getSelectedDecompiler(); - resourceViewPanel2.decompiler = BytecodeViewer.viewer.viewPane2.getSelectedDecompiler(); - resourceViewPanel3.decompiler = BytecodeViewer.viewer.viewPane3.getSelectedDecompiler(); + bytecodeViewPanel1.decompiler = BytecodeViewer.viewer.viewPane1.getSelectedDecompiler(); + bytecodeViewPanel2.decompiler = BytecodeViewer.viewer.viewPane2.getSelectedDecompiler(); + bytecodeViewPanel3.decompiler = BytecodeViewer.viewer.viewPane3.getSelectedDecompiler(); } public boolean isPanel1Editable() { @@ -196,13 +196,13 @@ public class ClassViewer extends ResourceViewer RSyntaxTextArea area = null; switch (paneId) { case 0: - area = classViewer.resourceViewPanel1.updateThread.updateUpdaterTextArea; + area = classViewer.bytecodeViewPanel1.updateThread.updateUpdaterTextArea; break; case 1: - area = classViewer.resourceViewPanel2.updateThread.updateUpdaterTextArea; + area = classViewer.bytecodeViewPanel2.updateThread.updateUpdaterTextArea; break; case 2: - area = classViewer.resourceViewPanel3.updateThread.updateUpdaterTextArea; + area = classViewer.bytecodeViewPanel3.updateThread.updateUpdaterTextArea; break; } @@ -270,24 +270,24 @@ public class ClassViewer extends ResourceViewer { sp.setResizeWeight(0.5); - if (resourceViewPanel2.decompiler != Decompiler.NONE && resourceViewPanel1.decompiler != Decompiler.NONE) { + if (bytecodeViewPanel2.decompiler != Decompiler.NONE && bytecodeViewPanel1.decompiler != Decompiler.NONE) { setDividerLocation(sp, 0.5); - } else if (resourceViewPanel1.decompiler != Decompiler.NONE) { + } else if (bytecodeViewPanel1.decompiler != Decompiler.NONE) { setDividerLocation(sp, 1); - } else if (resourceViewPanel2.decompiler != Decompiler.NONE) { + } else if (bytecodeViewPanel2.decompiler != Decompiler.NONE) { sp.setResizeWeight(1); setDividerLocation(sp, 0); } else { setDividerLocation(sp, 0); } - if (resourceViewPanel3.decompiler != Decompiler.NONE) { + if (bytecodeViewPanel3.decompiler != Decompiler.NONE) { sp2.setResizeWeight(0.7); setDividerLocation(sp2, 0.7); - if ((resourceViewPanel2.decompiler == Decompiler.NONE && resourceViewPanel1.decompiler != Decompiler.NONE) - || (resourceViewPanel1.decompiler == Decompiler.NONE && resourceViewPanel2.decompiler != Decompiler.NONE)) { + if ((bytecodeViewPanel2.decompiler == Decompiler.NONE && bytecodeViewPanel1.decompiler != Decompiler.NONE) + || (bytecodeViewPanel1.decompiler == Decompiler.NONE && bytecodeViewPanel2.decompiler != Decompiler.NONE)) { setDividerLocation(sp2, 0.5); - } else if (resourceViewPanel1.decompiler == Decompiler.NONE) { + } else if (bytecodeViewPanel1.decompiler == Decompiler.NONE) { setDividerLocation(sp2, 0); } } else { diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/util/PaneUpdaterThread.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/util/BytecodeViewPanelUpdater.java similarity index 70% rename from src/main/java/the/bytecode/club/bytecodeviewer/gui/util/PaneUpdaterThread.java rename to src/main/java/the/bytecode/club/bytecodeviewer/gui/util/BytecodeViewPanelUpdater.java index 1b29263f..abd0ec9b 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/util/PaneUpdaterThread.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/util/BytecodeViewPanelUpdater.java @@ -13,13 +13,15 @@ import javax.swing.event.ChangeListener; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; import org.fife.ui.rsyntaxtextarea.SyntaxConstants; import org.fife.ui.rtextarea.RTextScrollPane; +import org.objectweb.asm.ClassWriter; import the.bytecode.club.bytecodeviewer.BytecodeViewer; import the.bytecode.club.bytecodeviewer.Configuration; import the.bytecode.club.bytecodeviewer.compilers.Compiler; import the.bytecode.club.bytecodeviewer.decompilers.Decompiler; import the.bytecode.club.bytecodeviewer.gui.components.MethodsRenderer; import the.bytecode.club.bytecodeviewer.gui.components.SearchableRSyntaxTextArea; -import the.bytecode.club.bytecodeviewer.gui.resourceviewer.ResourceViewPanel; +import the.bytecode.club.bytecodeviewer.gui.hexviewer.JHexEditor; +import the.bytecode.club.bytecodeviewer.gui.resourceviewer.BytecodeViewPanel; import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ClassViewer; import the.bytecode.club.bytecodeviewer.util.MethodParser; @@ -45,29 +47,103 @@ import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.EDI ***************************************************************************/ /** - * Allows us to run a background thread + * Updates the Bytecode View Panel in a background thread * * @author Konloch * @author WaterWolf * @author DreamSworK * @since 09/26/2011 */ -public abstract class PaneUpdaterThread implements Runnable + +public class BytecodeViewPanelUpdater implements Runnable { public final ClassViewer viewer; - public final ResourceViewPanel resourceViewPanel; + public final BytecodeViewPanel bytecodeViewPanel; + private final JButton button; + private final byte[] b; + + public SearchableRSyntaxTextArea updateUpdaterTextArea; public JComboBox methodsList; public boolean isPanelEditable; + public boolean waitingFor; private Thread thread; - public PaneUpdaterThread(ClassViewer viewer, ResourceViewPanel resourceViewPanel) + public BytecodeViewPanelUpdater(BytecodeViewPanel bytecodeViewPanel, ClassViewer cv, byte[] b, boolean isPanelEditable, JButton button) { - this.viewer = viewer; - this.resourceViewPanel = resourceViewPanel; + this.viewer = cv; + this.bytecodeViewPanel = bytecodeViewPanel; + this.b = b; + this.isPanelEditable = isPanelEditable; + this.button = button; + waitingFor = true; } - public abstract void processDisplay(); + public void processDisplay() + { + try + { + BytecodeViewer.updateBusyStatus(true); + + if (bytecodeViewPanel.decompiler != Decompiler.NONE) + { + //hex viewer + if (bytecodeViewPanel.decompiler == Decompiler.HEXCODE_VIEWER) + { + final ClassWriter cw = new ClassWriter(0); + viewer.viewerClassNode.accept(cw); + + SwingUtilities.invokeLater(() -> + { + final JHexEditor hex = new JHexEditor(cw.toByteArray()); + hex.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int) BytecodeViewer.viewer.fontSpinner.getValue())); + + bytecodeViewPanel.panel.add(hex); + }); + } + else + { + final Decompiler decompiler = bytecodeViewPanel.decompiler; + + //perform decompiling inside of this thread + final String decompiledSource = decompiler.getDecompiler().decompileClassNode(viewer.viewerClassNode, b); + + //set the swing components on the swing thread + SwingUtilities.invokeLater(() -> + { + buildTextArea(decompiler, decompiledSource); + waitingFor = false; + }); + + //hold this thread until the swing thread has finished attaching the components + while (waitingFor) + { + try { + Thread.sleep(1); + } catch (Exception e) {} + } + } + } + } + catch (IndexOutOfBoundsException | NullPointerException e) + { + //ignore + } + catch (Exception e) + { + BytecodeViewer.handleException(e); + } + finally + { + viewer.resetDivider(); + BytecodeViewer.updateBusyStatus(false); + SwingUtilities.invokeLater(() -> + { + if (button != null) + button.setEnabled(true); + }); + } + } public void startNewThread() { @@ -78,7 +154,7 @@ public abstract class PaneUpdaterThread implements Runnable @Override public void run() { - if(resourceViewPanel.decompiler == Decompiler.NONE) + if(bytecodeViewPanel.decompiler == Decompiler.NONE) return; processDisplay(); @@ -89,7 +165,7 @@ public abstract class PaneUpdaterThread implements Runnable { //build an error message SwingUtilities.invokeLater(() -> - buildTextArea(resourceViewPanel.decompiler, "Critical BCV Error")); + buildTextArea(bytecodeViewPanel.decompiler, "Critical BCV Error")); return; } @@ -130,7 +206,7 @@ public abstract class PaneUpdaterThread implements Runnable @Override public void caretUpdate(CaretEvent e) { - MethodParser methods = viewer.methods.get(resourceViewPanel.panelIndex); + MethodParser methods = viewer.methods.get(bytecodeViewPanel.panelIndex); if (methods != null) { int methodLine = methods.findActiveMethod(updateUpdaterTextArea.getCaretLineNumber()); @@ -145,11 +221,11 @@ public abstract class PaneUpdaterThread implements Runnable } if (BytecodeViewer.viewer.synchronizedViewing.isSelected()) { int panes = 2; - if (viewer.resourceViewPanel3.panel != null) + if (viewer.bytecodeViewPanel3.panel != null) panes = 3; for (int i = 0; i < panes; i++) { - if (i != resourceViewPanel.panelIndex) { + if (i != bytecodeViewPanel.panelIndex) { ClassViewer.selectMethod(viewer, i, methods.getMethod(methodLine)); } } @@ -163,7 +239,7 @@ public abstract class PaneUpdaterThread implements Runnable @Override public void stateChanged(ChangeEvent e) { int panes = 2; - if (viewer.resourceViewPanel3.panel != null) + if (viewer.bytecodeViewPanel3.panel != null) panes = 3; if (BytecodeViewer.viewer.synchronizedViewing.isSelected()) { @@ -175,7 +251,7 @@ public abstract class PaneUpdaterThread implements Runnable activeViewLine; int activeLineDelta = -1; MethodParser.Method activeMethod = null; - MethodParser activeMethods = viewer.methods.get(resourceViewPanel.panelIndex); + MethodParser activeMethods = viewer.methods.get(bytecodeViewPanel.panelIndex); if (activeMethods != null) { int activeMethodLine = activeMethods.findActiveMethod(activeLine); if (activeMethodLine != -1) { @@ -185,19 +261,19 @@ public abstract class PaneUpdaterThread implements Runnable } } for (int i = 0; i < panes; i++) { - if (i != resourceViewPanel.panelIndex) { + if (i != bytecodeViewPanel.panelIndex) { int setLine = -1; RSyntaxTextArea area = null; switch (i) { case 0: - area = viewer.resourceViewPanel1.updateThread.updateUpdaterTextArea; + area = viewer.bytecodeViewPanel1.updateThread.updateUpdaterTextArea; break; case 1: - area = viewer.resourceViewPanel2.updateThread.updateUpdaterTextArea; + area = viewer.bytecodeViewPanel2.updateThread.updateUpdaterTextArea; break; case 2: - area = viewer.resourceViewPanel3.updateThread.updateUpdaterTextArea; + area = viewer.bytecodeViewPanel3.updateThread.updateUpdaterTextArea; break; } @@ -229,8 +305,8 @@ public abstract class PaneUpdaterThread implements Runnable public void synchronizePane() { - if(resourceViewPanel.decompiler == Decompiler.HEXCODE_VIEWER - || resourceViewPanel.decompiler == Decompiler.NONE) + if(bytecodeViewPanel.decompiler == Decompiler.HEXCODE_VIEWER + || bytecodeViewPanel.decompiler == Decompiler.NONE) return; SwingUtilities.invokeLater(()-> @@ -240,7 +316,7 @@ public abstract class PaneUpdaterThread implements Runnable updateUpdaterTextArea.addCaretListener(caretListener); }); - final MethodParser methods = viewer.methods.get(resourceViewPanel.panelIndex); + final MethodParser methods = viewer.methods.get(bytecodeViewPanel.panelIndex); for (int i = 0; i < updateUpdaterTextArea.getLineCount(); i++) { String lineText = updateUpdaterTextArea.getLineText(i); @@ -269,16 +345,16 @@ public abstract class PaneUpdaterThread implements Runnable int line = (int) Objects.requireNonNull(methodsList.getSelectedItem()); RSyntaxTextArea area = null; - switch (resourceViewPanel.panelIndex) + switch (bytecodeViewPanel.panelIndex) { case 0: - area = viewer.resourceViewPanel1.updateThread.updateUpdaterTextArea; + area = viewer.bytecodeViewPanel1.updateThread.updateUpdaterTextArea; break; case 1: - area = viewer.resourceViewPanel2.updateThread.updateUpdaterTextArea; + area = viewer.bytecodeViewPanel2.updateThread.updateUpdaterTextArea; break; case 2: - area = viewer.resourceViewPanel3.updateThread.updateUpdaterTextArea; + area = viewer.bytecodeViewPanel3.updateThread.updateUpdaterTextArea; break; } @@ -305,24 +381,24 @@ public abstract class PaneUpdaterThread implements Runnable updateUpdaterTextArea = new SearchableRSyntaxTextArea(); Configuration.rstaTheme.apply(updateUpdaterTextArea); - resourceViewPanel.panel.add(updateUpdaterTextArea.getScrollPane()); - resourceViewPanel.panel.add(updateUpdaterTextArea.getTitleHeader(), BorderLayout.NORTH); + bytecodeViewPanel.panel.add(updateUpdaterTextArea.getScrollPane()); + bytecodeViewPanel.panel.add(updateUpdaterTextArea.getTitleHeader(), BorderLayout.NORTH); - resourceViewPanel.textArea = updateUpdaterTextArea; - resourceViewPanel.textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); - resourceViewPanel.textArea.setCodeFoldingEnabled(true); - resourceViewPanel.textArea.setAntiAliasingEnabled(true); - resourceViewPanel.textArea.setText(decompiledSource); - resourceViewPanel.textArea.setCaretPosition(0); - resourceViewPanel.textArea.setEditable(isPanelEditable); + bytecodeViewPanel.textArea = updateUpdaterTextArea; + bytecodeViewPanel.textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); + bytecodeViewPanel.textArea.setCodeFoldingEnabled(true); + bytecodeViewPanel.textArea.setAntiAliasingEnabled(true); + bytecodeViewPanel.textArea.setText(decompiledSource); + bytecodeViewPanel.textArea.setCaretPosition(0); + bytecodeViewPanel.textArea.setEditable(isPanelEditable); if(isPanelEditable && decompiler == Decompiler.SMALI_DISASSEMBLER) - resourceViewPanel.compileMode = Compiler.SMALI_ASSEMBLER; + bytecodeViewPanel.compiler = Compiler.SMALI_ASSEMBLER; else if(isPanelEditable && decompiler == Decompiler.KRAKATAU_DISASSEMBLER) - resourceViewPanel.compileMode = Compiler.KRAKATAU_ASSEMBLER; + bytecodeViewPanel.compiler = Compiler.KRAKATAU_ASSEMBLER; String editable = isPanelEditable ? " - " + EDITABLE : ""; - resourceViewPanel.textArea.getTitleHeader().setText(decompiler.getDecompilerName() + editable); - resourceViewPanel.textArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int) BytecodeViewer.viewer.fontSpinner.getValue())); + bytecodeViewPanel.textArea.getTitleHeader().setText(decompiler.getDecompilerName() + editable); + bytecodeViewPanel.textArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int) BytecodeViewer.viewer.fontSpinner.getValue())); } } \ No newline at end of file diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/resources/ResourceContainer.java b/src/main/java/the/bytecode/club/bytecodeviewer/resources/ResourceContainer.java index bc699c1f..512772b4 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/resources/ResourceContainer.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/resources/ResourceContainer.java @@ -3,6 +3,7 @@ package the.bytecode.club.bytecodeviewer.resources; import java.io.File; import java.util.LinkedHashMap; +import org.apache.commons.compress.compressors.FileNameUtil; import org.apache.commons.io.FilenameUtils; import org.objectweb.asm.tree.ClassNode; import the.bytecode.club.bytecodeviewer.api.ASMUtil; @@ -63,6 +64,7 @@ public class ResourceContainer if(resourceClassBytes.containsKey(resourceName)) return resourceClasses.get(FilenameUtils.removeExtension(resourceName)); + //TODO check if this is even being called, it's probably not return resourceClasses.get(resourceName); } @@ -90,22 +92,22 @@ public class ResourceContainer /** * Updates the ClassNode reference on the resourceClass list and resourceClassBytes list */ - public ResourceContainer updateNode(ClassNode oldNode, ClassNode newNode) + public ResourceContainer updateNode(String resourceKey, ClassNode newNode) { + String classNodeKey = FilenameUtils.removeExtension(resourceKey); + //update all classnode references for ASM - if (resourceClasses.containsKey(oldNode.name)) + if (resourceClasses.containsKey(classNodeKey)) { - resourceClasses.remove(oldNode.name); - resourceClasses.put(newNode.name, newNode); + resourceClasses.remove(classNodeKey); + resourceClasses.put(classNodeKey, newNode); } //update the resource bytes - String oldResourceKey = oldNode.name + ".class"; - String newResourceKey = newNode.name + ".class"; - if(resourceClassBytes.containsKey(oldResourceKey)) + if(resourceClassBytes.containsKey(resourceKey)) { - resourceClassBytes.remove(oldResourceKey); - resourceClassBytes.put(newResourceKey, ASMUtil.nodeToBytes(newNode)); + resourceClassBytes.remove(resourceKey); + resourceClassBytes.put(resourceKey, ASMUtil.nodeToBytes(newNode)); } return this; }