JTree Rewrite
This is a better implementation of the managing the JTree. Instead of destroying and creating the tree each time a resource is imported. It's now preserved and the tree nodes are managed by the resource container
This commit is contained in:
parent
130eddc7cc
commit
995158a8d2
23 changed files with 167 additions and 147 deletions
|
@ -67,6 +67,7 @@ import static the.bytecode.club.bytecodeviewer.util.MiscUtils.guessLanguage;
|
||||||
* http://the.bytecode.club
|
* http://the.bytecode.club
|
||||||
*
|
*
|
||||||
* TODO BUGS:
|
* TODO BUGS:
|
||||||
|
* + Switching from Dark to System theme crashes
|
||||||
* + View>Visual Settings>Show Class Methods
|
* + View>Visual Settings>Show Class Methods
|
||||||
* + Spam-clicking the refresh button will cause the swing thread to deadlock (Quickly opening resources used to also do this)
|
* + Spam-clicking the refresh button will cause the swing thread to deadlock (Quickly opening resources used to also do this)
|
||||||
* This is caused by the ctrlMouseWheelZoom code, a temporary patch is just removing it worst case
|
* This is caused by the ctrlMouseWheelZoom code, a temporary patch is just removing it worst case
|
||||||
|
@ -80,7 +81,7 @@ import static the.bytecode.club.bytecodeviewer.util.MiscUtils.guessLanguage;
|
||||||
* + Anything using blindlySearchForClassNode() should instead search through the resource container search function
|
* + Anything using blindlySearchForClassNode() should instead search through the resource container search function
|
||||||
*
|
*
|
||||||
* TODO IN-PROGRESS:
|
* TODO IN-PROGRESS:
|
||||||
* + Resource Exporter/Save/Decompile As Zip needs to be rewrittern
|
* + Resource Exporter/Save/Decompile As Zip needs to be rewritten
|
||||||
* + Finish dragging code
|
* + Finish dragging code
|
||||||
* + Finish right-click tab menu detection
|
* + Finish right-click tab menu detection
|
||||||
* + Fix hook inject for EZ-Injection
|
* + Fix hook inject for EZ-Injection
|
||||||
|
@ -274,6 +275,22 @@ public class BytecodeViewer
|
||||||
openFiles(new File[]{new File(s)}, true);
|
openFiles(new File[]{new File(s)}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a resource container to BCVs resource container list
|
||||||
|
*/
|
||||||
|
public static void addResourceContainer(ResourceContainer container)
|
||||||
|
{
|
||||||
|
resourceContainers.add(container);
|
||||||
|
SwingUtilities.invokeLater(()->
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
viewer.resourcePane.addResourceContainer(container);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if there is at least one file resource loaded
|
* Returns true if there is at least one file resource loaded
|
||||||
*/
|
*/
|
||||||
|
@ -571,6 +588,20 @@ public class BytecodeViewer
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if there are no loaded resource classes
|
||||||
|
*/
|
||||||
|
public static boolean promptIfNoLoadedResources()
|
||||||
|
{
|
||||||
|
if (BytecodeViewer.resourceContainers.isEmpty())
|
||||||
|
{
|
||||||
|
BytecodeViewer.showMessage("First open a resource such as class, jar, zip or apk file.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle the exception by creating a new window for bug reporting
|
* Handle the exception by creating a new window for bug reporting
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -78,7 +78,7 @@ public class GlobalHotKeys
|
||||||
{
|
{
|
||||||
Configuration.lastHotKeyExecuted = System.currentTimeMillis();
|
Configuration.lastHotKeyExecuted = System.currentTimeMillis();
|
||||||
|
|
||||||
if (BytecodeViewer.promptIfNoLoadedClasses())
|
if (BytecodeViewer.promptIfNoLoadedResources())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Thread resourceExport = new Thread(() ->
|
Thread resourceExport = new Thread(() ->
|
||||||
|
|
|
@ -222,7 +222,7 @@ public class SettingsSerializer
|
||||||
//line 129 is used normal loading
|
//line 129 is used normal loading
|
||||||
Configuration.language = Language.valueOf(asString(130));
|
Configuration.language = Language.valueOf(asString(130));
|
||||||
}
|
}
|
||||||
catch (ArrayIndexOutOfBoundsException e)
|
catch (IndexOutOfBoundsException e)
|
||||||
{
|
{
|
||||||
//ignore because errors are expected, first start up and outdated settings.
|
//ignore because errors are expected, first start up and outdated settings.
|
||||||
}
|
}
|
||||||
|
@ -389,7 +389,7 @@ public class SettingsSerializer
|
||||||
Configuration.python2Extra = asString(135);
|
Configuration.python2Extra = asString(135);
|
||||||
Configuration.python3Extra = asString(136);
|
Configuration.python3Extra = asString(136);
|
||||||
}
|
}
|
||||||
catch (ArrayIndexOutOfBoundsException e)
|
catch (IndexOutOfBoundsException e)
|
||||||
{
|
{
|
||||||
//ignore because errors are expected, first start up and outdated settings.
|
//ignore because errors are expected, first start up and outdated settings.
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,7 +123,7 @@ public class ExceptionUI extends JFrame
|
||||||
*/
|
*/
|
||||||
public static String buildErrorLogHeader(String author)
|
public static String buildErrorLogHeader(String author)
|
||||||
{
|
{
|
||||||
String fatJar = FAT_JAR ? " [FatJar] " : "";
|
String fatJar = FAT_JAR ? " [FatJar]" : "";
|
||||||
|
|
||||||
return "Please send this error log to " + author +
|
return "Please send this error log to " + author +
|
||||||
"\nIf you hold appropriate legal rights to the relevant class/jar/apk file please include that as well." +
|
"\nIf you hold appropriate legal rights to the relevant class/jar/apk file please include that as well." +
|
||||||
|
|
|
@ -44,7 +44,7 @@ public abstract class Plugin extends Thread
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (BytecodeViewer.promptIfNoLoadedClasses())
|
if (BytecodeViewer.promptIfNoLoadedResources())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
executeContainer();
|
executeContainer();
|
||||||
|
|
|
@ -153,7 +153,10 @@ public class KrakatauDecompiler extends InternalDecompiler
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String decompileClassNode(ClassNode cn, byte[] b) {
|
public String decompileClassNode(ClassNode cn, byte[] b)
|
||||||
|
{
|
||||||
|
//TODO look into transforming through krakatau as a zip rather than direct classfile
|
||||||
|
|
||||||
if(!ExternalResources.getSingleton().hasSetPython2Command())
|
if(!ExternalResources.getSingleton().hasSetPython2Command())
|
||||||
return "You need to set your Python 2.7 (or PyPy 2.7 for speed) executable path!";
|
return "You need to set your Python 2.7 (or PyPy 2.7 for speed) executable path!";
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,8 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File
|
||||||
|
|
||||||
public final KeyAdapter search = new SearchKeyAdapter(this);
|
public final KeyAdapter search = new SearchKeyAdapter(this);
|
||||||
|
|
||||||
private void showPopMenu(ResourceTree tree, TreePath selPath, int x, int y) {
|
private void showPopMenu(ResourceTree tree, TreePath selPath, int x, int y)
|
||||||
|
{
|
||||||
if (selPath == null)
|
if (selPath == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -87,16 +88,20 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File
|
||||||
|
|
||||||
rightClickMenu.add(new ResourceListRightClickRemove(this, x, y, tree));
|
rightClickMenu.add(new ResourceListRightClickRemove(this, x, y, tree));
|
||||||
|
|
||||||
rightClickMenu.add(new AbstractAction("Expand", IconResources.CollapsedIcon.createCollapsedIcon()) {
|
rightClickMenu.add(new AbstractAction("Expand", IconResources.CollapsedIcon.createCollapsedIcon())
|
||||||
|
{
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e)
|
||||||
|
{
|
||||||
TreePath selPath = ResourceListPane.this.tree.getPathForLocation(x, y);
|
TreePath selPath = ResourceListPane.this.tree.getPathForLocation(x, y);
|
||||||
expandAll(tree, Objects.requireNonNull(selPath), true);
|
expandAll(tree, Objects.requireNonNull(selPath), true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
rightClickMenu.add(new AbstractAction("Collapse", IconResources.ExpandedIcon.createExpandedIcon()) {
|
rightClickMenu.add(new AbstractAction("Collapse", IconResources.ExpandedIcon.createExpandedIcon())
|
||||||
|
{
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e)
|
||||||
|
{
|
||||||
TreePath selPath = ResourceListPane.this.tree.getPathForLocation(x, y);
|
TreePath selPath = ResourceListPane.this.tree.getPathForLocation(x, y);
|
||||||
expandAll(tree, Objects.requireNonNull(selPath), false);
|
expandAll(tree, Objects.requireNonNull(selPath), false);
|
||||||
}
|
}
|
||||||
|
@ -152,108 +157,109 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File
|
||||||
BytecodeViewer.openFiles(files, true);
|
BytecodeViewer.openFiles(files, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateTree()
|
public void addResourceContainer(ResourceContainer container)
|
||||||
{
|
{
|
||||||
try
|
ResourceTreeNode root = container.treeNode = new ResourceTreeNode(container.name);
|
||||||
{
|
|
||||||
//TODO refresh while preserving the opened files from before the refresh
|
|
||||||
treeRoot.removeAllChildren();
|
|
||||||
for (ResourceContainer container : BytecodeViewer.resourceContainers)
|
|
||||||
{
|
|
||||||
ResourceTreeNode root = new ResourceTreeNode(container.name);
|
|
||||||
treeRoot.add(root);
|
|
||||||
|
|
||||||
ResourceListIconRenderer renderer = new ResourceListIconRenderer();
|
treeRoot.add(root);
|
||||||
tree.setCellRenderer(renderer);
|
tree.setCellRenderer(new ResourceListIconRenderer());
|
||||||
|
|
||||||
if (!container.resourceClasses.isEmpty())
|
buildTree(container, root);
|
||||||
{
|
|
||||||
for (String name : container.resourceClasses.keySet())
|
|
||||||
{
|
|
||||||
final String[] spl = name.split("/");
|
|
||||||
if (spl.length < 2)
|
|
||||||
{
|
|
||||||
root.add(new ResourceTreeNode(name + ".class"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ResourceTreeNode parent = root;
|
|
||||||
for (int i1 = 0; i1 < spl.length; i1++)
|
|
||||||
{
|
|
||||||
String s = spl[i1];
|
|
||||||
|
|
||||||
if (i1 == spl.length - 1)
|
treeRoot.sort();
|
||||||
s += ".class";
|
|
||||||
|
|
||||||
ResourceTreeNode child = null;
|
tree.expandPath(new TreePath(tree.getModel().getRoot()));
|
||||||
for (int i = 0; i < parent.getChildCount(); i++)
|
tree.updateUI();
|
||||||
{
|
|
||||||
if (((ResourceTreeNode) parent.getChildAt(i)).getUserObject().equals(s))
|
|
||||||
{
|
|
||||||
child = (ResourceTreeNode) parent.getChildAt(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (child == null)
|
|
||||||
{
|
|
||||||
child = new ResourceTreeNode(s);
|
|
||||||
parent.add(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
parent = child;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!container.resourceFiles.isEmpty())
|
|
||||||
{
|
|
||||||
for (final Entry<String, byte[]> entry : container.resourceFiles.entrySet())
|
|
||||||
{
|
|
||||||
String name = entry.getKey();
|
|
||||||
final String[] spl = name.split("/");
|
|
||||||
if (spl.length < 2)
|
|
||||||
{
|
|
||||||
root.add(new ResourceTreeNode(name));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ResourceTreeNode parent = root;
|
|
||||||
for (final String s : spl)
|
|
||||||
{
|
|
||||||
ResourceTreeNode child = null;
|
|
||||||
for (int i = 0; i < parent.getChildCount(); i++)
|
|
||||||
{
|
|
||||||
if (((ResourceTreeNode) parent.getChildAt(i)).getUserObject().equals(s))
|
|
||||||
{
|
|
||||||
child = (ResourceTreeNode) parent.getChildAt(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (child == null)
|
|
||||||
{
|
|
||||||
child = new ResourceTreeNode(s);
|
|
||||||
parent.add(child);
|
|
||||||
}
|
|
||||||
parent = child;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
treeRoot.sort();
|
|
||||||
tree.expandPath(new TreePath(tree.getModel().getRoot()));
|
|
||||||
tree.updateUI();
|
|
||||||
} catch (java.util.ConcurrentModificationException e) {
|
|
||||||
//ignore, the last file will reset everything
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO add a setting for this
|
//TODO add a setting for this
|
||||||
// expandAll(tree, true);
|
// expandAll(tree, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeResource(ResourceContainer container)
|
||||||
|
{
|
||||||
|
container.treeNode.removeFromParent();
|
||||||
|
tree.updateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildTree(ResourceContainer container, ResourceTreeNode root)
|
||||||
|
{
|
||||||
|
if (!container.resourceClasses.isEmpty())
|
||||||
|
{
|
||||||
|
for (String name : container.resourceClasses.keySet())
|
||||||
|
{
|
||||||
|
final String[] spl = name.split("/");
|
||||||
|
if (spl.length < 2)
|
||||||
|
{
|
||||||
|
root.add(new ResourceTreeNode(name + ".class"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ResourceTreeNode parent = root;
|
||||||
|
for (int i1 = 0; i1 < spl.length; i1++)
|
||||||
|
{
|
||||||
|
String s = spl[i1];
|
||||||
|
|
||||||
|
if (i1 == spl.length - 1)
|
||||||
|
s += ".class";
|
||||||
|
|
||||||
|
ResourceTreeNode child = null;
|
||||||
|
for (int i = 0; i < parent.getChildCount(); i++)
|
||||||
|
{
|
||||||
|
if (((ResourceTreeNode) parent.getChildAt(i)).getUserObject().equals(s))
|
||||||
|
{
|
||||||
|
child = (ResourceTreeNode) parent.getChildAt(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child == null)
|
||||||
|
{
|
||||||
|
child = new ResourceTreeNode(s);
|
||||||
|
parent.add(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
parent = child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!container.resourceFiles.isEmpty())
|
||||||
|
{
|
||||||
|
for (final Entry<String, byte[]> entry : container.resourceFiles.entrySet())
|
||||||
|
{
|
||||||
|
String name = entry.getKey();
|
||||||
|
final String[] spl = name.split("/");
|
||||||
|
if (spl.length < 2)
|
||||||
|
{
|
||||||
|
root.add(new ResourceTreeNode(name));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ResourceTreeNode parent = root;
|
||||||
|
for (final String s : spl)
|
||||||
|
{
|
||||||
|
ResourceTreeNode child = null;
|
||||||
|
for (int i = 0; i < parent.getChildCount(); i++)
|
||||||
|
{
|
||||||
|
if (((ResourceTreeNode) parent.getChildAt(i)).getUserObject().equals(s))
|
||||||
|
{
|
||||||
|
child = (ResourceTreeNode) parent.getChildAt(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (child == null)
|
||||||
|
{
|
||||||
|
child = new ResourceTreeNode(s);
|
||||||
|
parent.add(child);
|
||||||
|
}
|
||||||
|
parent = child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
private void expandAll(final JTree tree, final TreePath parent,
|
private void expandAll(final JTree tree, final TreePath parent,
|
||||||
final boolean expand) {
|
final boolean expand) {
|
||||||
|
@ -339,14 +345,6 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
imp.getImporter().open(tempFile);
|
imp.getImporter().open(tempFile);
|
||||||
SwingUtilities.invokeLater(()->
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
updateTree();
|
|
||||||
}
|
|
||||||
catch (NullPointerException ignored) { }
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -48,12 +48,12 @@ public class ResourceListRightClickRemove extends AbstractAction
|
||||||
{
|
{
|
||||||
if (resourceContainer.name.equals(selectNode.toString()))
|
if (resourceContainer.name.equals(selectNode.toString()))
|
||||||
{
|
{
|
||||||
|
resourceListPane.removeResource(resourceContainer);
|
||||||
resourceListPane.removeFile(resourceContainer);
|
resourceListPane.removeFile(resourceContainer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resourceListPane.updateTree();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,18 +45,12 @@ public class CodeSequenceDiagram extends Plugin
|
||||||
{
|
{
|
||||||
public static void open()
|
public static void open()
|
||||||
{
|
{
|
||||||
if (BytecodeViewer.promptIfNoLoadedClasses())
|
|
||||||
return;
|
|
||||||
|
|
||||||
PluginManager.runPlugin(new CodeSequenceDiagram());
|
PluginManager.runPlugin(new CodeSequenceDiagram());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(ArrayList<ClassNode> classNodeList)
|
public void execute(ArrayList<ClassNode> classNodeList)
|
||||||
{
|
{
|
||||||
if (BytecodeViewer.promptIfNoLoadedClasses())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!BytecodeViewer.isActiveResourceClass())
|
if (!BytecodeViewer.isActiveResourceClass())
|
||||||
{
|
{
|
||||||
BytecodeViewer.showMessage("First open a class file.");
|
BytecodeViewer.showMessage("First open a class file.");
|
||||||
|
|
|
@ -7,6 +7,7 @@ import org.apache.commons.compress.compressors.FileNameUtil;
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import the.bytecode.club.bytecodeviewer.api.ASMUtil;
|
import the.bytecode.club.bytecodeviewer.api.ASMUtil;
|
||||||
|
import the.bytecode.club.bytecodeviewer.gui.resourcelist.ResourceTreeNode;
|
||||||
import the.bytecode.club.bytecodeviewer.util.LazyNameUtil;
|
import the.bytecode.club.bytecodeviewer.util.LazyNameUtil;
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
@ -38,7 +39,8 @@ public class ResourceContainer
|
||||||
{
|
{
|
||||||
public File file;
|
public File file;
|
||||||
public String name;
|
public String name;
|
||||||
public File APKToolContents = null;
|
public File APKToolContents;
|
||||||
|
public ResourceTreeNode treeNode;
|
||||||
|
|
||||||
public LinkedHashMap<String, byte[]> resourceFiles = new LinkedHashMap<>();
|
public LinkedHashMap<String, byte[]> resourceFiles = new LinkedHashMap<>();
|
||||||
public LinkedHashMap<String, byte[]> resourceClassBytes = new LinkedHashMap<>();
|
public LinkedHashMap<String, byte[]> resourceClassBytes = new LinkedHashMap<>();
|
||||||
|
|
|
@ -25,7 +25,7 @@ public class APKExport implements Exporter
|
||||||
@Override
|
@Override
|
||||||
public void promptForExport()
|
public void promptForExport()
|
||||||
{
|
{
|
||||||
if (BytecodeViewer.promptIfNoLoadedClasses())
|
if (BytecodeViewer.promptIfNoLoadedResources())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
List<ResourceContainer> containers = BytecodeViewer.getResourceContainers();
|
List<ResourceContainer> containers = BytecodeViewer.getResourceContainers();
|
||||||
|
|
|
@ -25,7 +25,7 @@ public class DexExport implements Exporter
|
||||||
@Override
|
@Override
|
||||||
public void promptForExport()
|
public void promptForExport()
|
||||||
{
|
{
|
||||||
if (BytecodeViewer.promptIfNoLoadedClasses())
|
if (BytecodeViewer.promptIfNoLoadedResources())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Thread exportThread = new Thread(() ->
|
Thread exportThread = new Thread(() ->
|
||||||
|
|
|
@ -19,7 +19,7 @@ public class RunnableJarExporter implements Exporter
|
||||||
@Override
|
@Override
|
||||||
public void promptForExport()
|
public void promptForExport()
|
||||||
{
|
{
|
||||||
if (BytecodeViewer.promptIfNoLoadedClasses())
|
if (BytecodeViewer.promptIfNoLoadedResources())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Thread exportThread = new Thread(() ->
|
Thread exportThread = new Thread(() ->
|
||||||
|
|
|
@ -19,7 +19,7 @@ public class ZipExport implements Exporter
|
||||||
@Override
|
@Override
|
||||||
public void promptForExport()
|
public void promptForExport()
|
||||||
{
|
{
|
||||||
if (BytecodeViewer.promptIfNoLoadedClasses())
|
if (BytecodeViewer.promptIfNoLoadedResources())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Thread exportThread = new Thread(() ->
|
Thread exportThread = new Thread(() ->
|
||||||
|
|
|
@ -70,14 +70,6 @@ public class ImportResource implements Runnable
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
BytecodeViewer.updateBusyStatus(false);
|
BytecodeViewer.updateBusyStatus(false);
|
||||||
SwingUtilities.invokeLater(()->
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
BytecodeViewer.viewer.resourcePane.updateTree();
|
|
||||||
}
|
|
||||||
catch (NullPointerException ignored) { }
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,6 @@ public class APKResourceImporter implements Importer
|
||||||
container.copy(new ResourceContainerImporter(
|
container.copy(new ResourceContainerImporter(
|
||||||
new ResourceContainer(output)).importAsZip().getContainer());
|
new ResourceContainer(output)).importAsZip().getContainer());
|
||||||
|
|
||||||
BytecodeViewer.resourceContainers.add(container);
|
BytecodeViewer.addResourceContainer(container);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,6 @@ public class ClassResourceImporter implements Importer
|
||||||
//TODO double check this
|
//TODO double check this
|
||||||
container.resourceFiles.put(name, bytes);
|
container.resourceFiles.put(name, bytes);
|
||||||
}
|
}
|
||||||
BytecodeViewer.resourceContainers.add(container);
|
BytecodeViewer.addResourceContainer(container);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,6 @@ public class DEXResourceImporter implements Importer
|
||||||
container.copy(new ResourceContainerImporter(
|
container.copy(new ResourceContainerImporter(
|
||||||
new ResourceContainer(output)).importAsZip().getContainer());
|
new ResourceContainer(output)).importAsZip().getContainer());
|
||||||
|
|
||||||
BytecodeViewer.resourceContainers.add(container);
|
BytecodeViewer.addResourceContainer(container);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,6 @@ public class DirectoryResourceImporter implements Importer
|
||||||
|
|
||||||
container.resourceClasses.putAll(allDirectoryClasses);
|
container.resourceClasses.putAll(allDirectoryClasses);
|
||||||
container.resourceFiles = allDirectoryFiles;
|
container.resourceFiles = allDirectoryFiles;
|
||||||
BytecodeViewer.resourceContainers.add(container);
|
BytecodeViewer.addResourceContainer(container);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,6 @@ public class FileResourceImporter implements Importer
|
||||||
//import the file into the resource container
|
//import the file into the resource container
|
||||||
importer.importAsFile();
|
importer.importAsFile();
|
||||||
//add the resource container to BCV's total loaded files
|
//add the resource container to BCV's total loaded files
|
||||||
BytecodeViewer.resourceContainers.add(container);
|
BytecodeViewer.addResourceContainer(container);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ public class XAPKResourceImporter implements Importer
|
||||||
Configuration.silenceExceptionGUI--; //turn exceptions back on
|
Configuration.silenceExceptionGUI--; //turn exceptions back on
|
||||||
BytecodeViewer.viewer.clearBusyStatus(); //clear errant busy signals from failed APK imports
|
BytecodeViewer.viewer.clearBusyStatus(); //clear errant busy signals from failed APK imports
|
||||||
container.resourceFiles = allDirectoryFiles; //store the file resource
|
container.resourceFiles = allDirectoryFiles; //store the file resource
|
||||||
BytecodeViewer.resourceContainers.add(container); //add the resource container to BCV's total loaded files
|
BytecodeViewer.addResourceContainer(container); //add the resource container to BCV's total loaded files
|
||||||
}
|
}
|
||||||
|
|
||||||
public File exportTo(File original, String extension, byte[] bytes)
|
public File exportTo(File original, String extension, byte[] bytes)
|
||||||
|
|
|
@ -23,6 +23,6 @@ public class ZipResourceImporter implements Importer
|
||||||
//import the file as zip into the resource container
|
//import the file as zip into the resource container
|
||||||
importer.importAsZip();
|
importer.importAsZip();
|
||||||
//add the resource container to BCV's total loaded files
|
//add the resource container to BCV's total loaded files
|
||||||
BytecodeViewer.resourceContainers.add(container);
|
BytecodeViewer.addResourceContainer(container);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ public class JarUtils
|
||||||
}
|
}
|
||||||
jis.close();
|
jis.close();
|
||||||
container.resourceFiles = files;
|
container.resourceFiles = files;
|
||||||
BytecodeViewer.resourceContainers.add(container);
|
BytecodeViewer.addResourceContainer(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ public class JarUtils
|
||||||
}
|
}
|
||||||
|
|
||||||
container.resourceFiles = files;
|
container.resourceFiles = files;
|
||||||
BytecodeViewer.resourceContainers.add(container);
|
BytecodeViewer.addResourceContainer(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ArrayList<ClassNode> loadClasses(final File jarFile) throws IOException
|
public static ArrayList<ClassNode> loadClasses(final File jarFile) throws IOException
|
||||||
|
|
Loading…
Reference in a new issue