Skip to content

Commit df67d51

Browse files
committed
Refactor Decompiler API, fix Fernflower inner classes
Fixes #19, #18
1 parent 4c905c8 commit df67d51

File tree

8 files changed

+58
-60
lines changed

8 files changed

+58
-60
lines changed

src/main/java/the/bytecode/club/jda/JDA.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package the.bytecode.club.jda;
22

33
import org.apache.commons.io.FileUtils;
4+
import org.objectweb.asm.ClassReader;
5+
import org.objectweb.asm.ClassWriter;
46
import org.objectweb.asm.tree.ClassNode;
57
import the.bytecode.club.jda.api.ExceptionUI;
68
import the.bytecode.club.jda.gui.FileNavigationPane;
@@ -172,7 +174,7 @@ public static ClassNode getClassNode(String containerName, String name) {
172174
return null;
173175
}
174176

175-
public static byte[] getClassBytes(String containerName, String name) {
177+
public static byte[] getFileBytes(String containerName, String name) {
176178
for (FileContainer container : files) {
177179
if (container.name.equals(containerName) && container.getData().containsKey(name)) {
178180
return container.getData().get(name);
@@ -181,6 +183,30 @@ public static byte[] getClassBytes(String containerName, String name) {
181183
return null;
182184
}
183185

186+
public static byte[] getClassBytes(String containerName, ClassNode cn) {
187+
byte[] bytes = getFileBytes(containerName, getClassfileName(cn));
188+
if (cn.version < 49)
189+
bytes = fixBytes(bytes);
190+
return bytes;
191+
}
192+
193+
public static String getClassfileName(ClassNode cn) {
194+
return cn.name + ".class";
195+
}
196+
197+
public static String extractClassName(String fileName) {
198+
return fileName.substring(0, fileName.length() - 6);
199+
}
200+
201+
protected static byte[] fixBytes(byte[] in) {
202+
ClassReader reader = new ClassReader(in);
203+
ClassNode node = new ClassNode();
204+
reader.accept(node, ClassReader.EXPAND_FRAMES);
205+
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
206+
node.accept(writer);
207+
return writer.toByteArray();
208+
}
209+
184210
/**
185211
* Grabs the file contents of the loaded resources.
186212
*
@@ -329,7 +355,7 @@ public void run() {
329355
final ClassNode cn = JarUtils.getNode(bytes);
330356

331357
FileContainer container = new FileContainer(f);
332-
container.files.put(cn.name + ".class", bytes);
358+
container.files.put(getClassfileName(cn), bytes);
333359
container.add(cn);
334360
JDA.files.add(container);
335361
} else {

src/main/java/the/bytecode/club/jda/decompilers/CFRDecompiler.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,13 @@ public String getName() {
5353
}
5454

5555
@Override
56-
public String decompileClassNode(ClassNode cn, byte[] b) {
56+
public String decompileClassNode(String containerName, ClassNode cn) {
5757
try {
58+
byte[] bytes = JDA.getClassBytes(containerName, cn);
5859
Options options = new GetOptParser().parse(generateMainMethod(), OptionsImpl.getFactory());
5960
ClassFileSourceImpl classFileSource = new ClassFileSourceImpl(options);
6061
DCCommonState dcCommonState = new DCCommonState(options, classFileSource);
61-
return doClass(dcCommonState, b);
62+
return doClass(dcCommonState, bytes);
6263
} catch (Exception e) {
6364
return parseException(e);
6465
}

src/main/java/the/bytecode/club/jda/decompilers/Decompiler.java

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package the.bytecode.club.jda.decompilers;
22

3-
import org.objectweb.asm.ClassReader;
4-
import org.objectweb.asm.ClassWriter;
53
import org.objectweb.asm.tree.ClassNode;
64
import the.bytecode.club.jda.JDA;
75
import the.bytecode.club.jda.api.ExceptionUI;
@@ -23,7 +21,7 @@ public Decompiler() {
2321

2422
protected DecompilerSettings settings = new DecompilerSettings(this);
2523

26-
public abstract String decompileClassNode(ClassNode cn, byte[] b);
24+
public abstract String decompileClassNode(String containerName, ClassNode cn);
2725

2826
public abstract void decompileToZip(String zipName);
2927

@@ -49,15 +47,6 @@ protected void handleException(Exception e) {
4947
new ExceptionUI(e);
5048
}
5149

52-
protected byte[] fixBytes(byte[] in) {
53-
ClassReader reader = new ClassReader(in);
54-
ClassNode node = new ClassNode();
55-
reader.accept(node, ClassReader.EXPAND_FRAMES);
56-
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
57-
node.accept(writer);
58-
return writer.toByteArray();
59-
}
60-
6150
public static void ensureInitted() {
6251
// Just to make sure the classes is loaded so all decompilers are loaded
6352
}

src/main/java/the/bytecode/club/jda/decompilers/FernflowerDecompiler.java

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import org.jetbrains.java.decompiler.main.decompiler.PrintStreamLogger;
77
import org.jetbrains.java.decompiler.main.extern.IResultSaver;
88
import org.objectweb.asm.tree.ClassNode;
9+
import org.objectweb.asm.tree.InnerClassNode;
910
import the.bytecode.club.jda.JDA;
1011
import the.bytecode.club.jda.JarUtils;
1112
import the.bytecode.club.jda.settings.DecompilerSettings;
@@ -39,21 +40,20 @@ public String getName() {
3940
}
4041

4142
@Override
42-
public String decompileClassNode(final ClassNode cn, byte[] b) {
43+
public String decompileClassNode(String containerName, final ClassNode cn) {
4344
try {
44-
if (cn.version < 49) {
45-
b = fixBytes(b);
46-
}
47-
final byte[] bytesToUse = b;
48-
4945
Map<String, Object> options = main(generateMainMethod());
5046

5147
final AtomicReference<String> result = new AtomicReference<>();
5248
result.set(null);
5349

54-
BaseDecompiler baseDecompiler = new BaseDecompiler((s, s1) -> {
55-
byte[] clone = new byte[bytesToUse.length];
56-
System.arraycopy(bytesToUse, 0, clone, 0, bytesToUse.length);
50+
BaseDecompiler baseDecompiler = new BaseDecompiler((externalPath, internalPath) -> {
51+
System.out.println(externalPath + " " + internalPath);
52+
System.out.println(new File(externalPath).getName());
53+
ClassNode requestedCn = JDA.getClassNode(containerName, JDA.extractClassName(new File(externalPath).getName()));
54+
byte[] bytes = JDA.getClassBytes(containerName, requestedCn);
55+
byte[] clone = new byte[bytes.length];
56+
System.arraycopy(bytes, 0, clone, 0, bytes.length);
5757
return clone;
5858
}, new IResultSaver() {
5959
@Override
@@ -67,8 +67,8 @@ public void copyFile(String s, String s1, String s2) {
6767
}
6868

6969
@Override
70-
public void saveClassFile(String s, String s1, String s2, String s3, int[] ints) {
71-
result.set(s3);
70+
public void saveClassFile(String s, String s1, String s2, String decompilation, int[] ints) {
71+
result.set(decompilation);
7272
}
7373

7474
@Override
@@ -97,6 +97,8 @@ public void closeArchive(String s, String s1) {
9797
}, options, new PrintStreamLogger(System.out));
9898

9999
baseDecompiler.addSpace(new File(cn.name + ".class"), true);
100+
for (InnerClassNode innerCn : cn.innerClasses)
101+
baseDecompiler.addSpace(new File(innerCn.name + ".class"), true);
100102
baseDecompiler.decompileContext();
101103
while (true) {
102104
if (result.get() != null) {

src/main/java/the/bytecode/club/jda/decompilers/ProcyonDecompiler.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,9 @@ public DecompilerSettings getDecompilerSettings() {
7575
}
7676

7777
@Override
78-
public String decompileClassNode(final ClassNode cn, byte[] b) {
78+
public String decompileClassNode(String containerName, final ClassNode cn) {
7979
try {
80-
if (cn.version < 49) {
81-
b = fixBytes(b);
82-
}
83-
final byte[] bytesToUse = b;
80+
byte[] bytes = JDA.getClassBytes(containerName, cn);
8481
final Map<String, byte[]> loadedClasses = JDA.getLoadedBytes();
8582
DecompilerSettings settings = getDecompilerSettings();
8683
MetadataSystem metadataSystem = new MetadataSystem(new ITypeLoader() {
@@ -89,7 +86,7 @@ public String decompileClassNode(final ClassNode cn, byte[] b) {
8986
@Override
9087
public boolean tryLoadType(String s, Buffer buffer) {
9188
if (s.equals(cn.name)) {
92-
buffer.putByteArray(bytesToUse, 0, bytesToUse.length);
89+
buffer.putByteArray(bytes, 0, bytes.length);
9390
buffer.position(0);
9491
return true;
9592
} else {

src/main/java/the/bytecode/club/jda/decompilers/bytecode/ClassNodeDecompiler.java

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import org.objectweb.asm.tree.FieldNode;
66
import org.objectweb.asm.tree.InnerClassNode;
77
import org.objectweb.asm.tree.MethodNode;
8-
import the.bytecode.club.jda.FileContainer;
98
import the.bytecode.club.jda.JDA;
109
import the.bytecode.club.jda.decompilers.Decompiler;
1110
import the.bytecode.club.jda.settings.DecompilerSettings;
@@ -32,18 +31,7 @@ public String getName() {
3231
return "Bytecode";
3332
}
3433

35-
public String decompileClassNode(ClassNode cn, byte[] b) {
36-
String containerName = null;
37-
for (FileContainer container : JDA.files) {
38-
String name = cn.name + ".class";
39-
if (container.getData().containsKey(name)) {
40-
if (container.getClassNode(name) == cn)
41-
containerName = container.name;
42-
}
43-
}
44-
if (containerName == null)
45-
System.out.println("Warning: Unable to locate container for class " + cn.name + "!");
46-
34+
public String decompileClassNode(String containerName, ClassNode cn) {
4735
return decompile(new PrefixedStringBuilder(), new ArrayList<>(), containerName, cn).toString();
4836
}
4937

@@ -87,8 +75,7 @@ protected PrefixedStringBuilder decompile(PrefixedStringBuilder sb, ArrayList<St
8775
sb.append(JDA.nl);
8876
}
8977

90-
for (Object o : cn.innerClasses) {
91-
InnerClassNode innerClassNode = (InnerClassNode) o;
78+
for (InnerClassNode innerClassNode : cn.innerClasses) {
9279
String innerClassName = innerClassNode.name;
9380
if ((innerClassName != null) && !decompiledClasses.contains(innerClassName)) {
9481
decompiledClasses.add(innerClassName);

src/main/java/the/bytecode/club/jda/gui/MainViewerGUI.java

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,7 @@ private void decompileSaveOpenedClasses() {
644644

645645
Thread t = new Thread() {
646646
public void run() {
647-
final String s = workPane.getCurrentViewer().name;
647+
final String fileName = workPane.getCurrentViewer().name;
648648

649649
JFileChooser fc = new JFileChooser();
650650
fc.setFileFilter(new FileFilter() {
@@ -704,9 +704,8 @@ public String getDescription() {
704704
@Override
705705
public void run() {
706706
try {
707-
ClassNode cn1 = JDA.getClassNode(containerName, s);
708-
byte[] bytes = JDA.getClassBytes(containerName, s);
709-
String contents = Decompilers.PROCYON.decompileClassNode(cn1, bytes);
707+
ClassNode cn1 = JDA.getClassNode(containerName, fileName);
708+
String contents = Decompilers.PROCYON.decompileClassNode(containerName, cn1);
710709
FileUtils.writeStringToFile(new File(path), contents, "UTF-8");
711710
JDA.viewer.setIcon(false);
712711
} catch (Exception e) {
@@ -721,9 +720,8 @@ public void run() {
721720
@Override
722721
public void run() {
723722
try {
724-
ClassNode cn1 = JDA.getClassNode(containerName, s);
725-
byte[] bytes = JDA.getClassBytes(containerName, s);
726-
String contents = Decompilers.CFR.decompileClassNode(cn1, bytes);
723+
ClassNode cn1 = JDA.getClassNode(containerName, fileName);
724+
String contents = Decompilers.CFR.decompileClassNode(containerName, cn1);
727725
FileUtils.writeStringToFile(new File(path), contents, "UTF-8");
728726
JDA.viewer.setIcon(false);
729727
} catch (Exception e) {
@@ -738,9 +736,8 @@ public void run() {
738736
@Override
739737
public void run() {
740738
try {
741-
ClassNode cn1 = JDA.getClassNode(containerName, s);
742-
byte[] bytes = JDA.getClassBytes(containerName, s);
743-
String contents = Decompilers.FERNFLOWER.decompileClassNode(cn1, bytes);
739+
ClassNode cn1 = JDA.getClassNode(containerName, fileName);
740+
String contents = Decompilers.FERNFLOWER.decompileClassNode(containerName, cn1);
744741
FileUtils.writeStringToFile(new File(path), contents, "UTF-8");
745742
JDA.viewer.setIcon(false);
746743
} catch (Exception e) {

src/main/java/the/bytecode/club/jda/gui/PaneUpdaterThread.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,12 @@ public PaneUpdaterThread(ClassViewer viewer, Decompiler decompiler, int paneId,
3434

3535
public void run() {
3636
try {
37-
final byte[] b = JDA.getClassBytes(viewer.container, viewer.cn.name + ".class");
3837
RSyntaxTextArea panelArea = new RSyntaxTextArea();
3938
panelArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
4039
panelArea.setCodeFoldingEnabled(true);
4140
panelArea.setAntiAliasingEnabled(true);
4241
final RTextScrollPane scrollPane = new RTextScrollPane(panelArea);
43-
String decompileResult = decompiler.decompileClassNode(viewer.cn, b);
42+
String decompileResult = decompiler.decompileClassNode(viewer.container, viewer.cn);
4443
panelArea.setText(stripUndisplayableChars(decompileResult));
4544
panelArea.setCaretPosition(0);
4645
panelArea.setEditable(viewer.isPaneEditable(paneId));

0 commit comments

Comments
 (0)