package the.bytecode.club.bytecodeviewer.decompilers;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.DecompilerSettings;
import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
import the.bytecode.club.bytecodeviewer.decompilers.bytecode.ClassNodeDecompiler;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/***************************************************************************
* 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 <http://www.gnu.org/licenses/>. *
***************************************************************************/
/**
* Used to represent all of the decompilers/disassemblers BCV contains.
*
* @author Konloch
*
*/
public abstract class Decompiler {
private static final Map<String, Decompiler> BY_NAME = new HashMap<>();
public final static Decompiler BYTECODE = new ClassNodeDecompiler();
public final static Decompiler FERNFLOWER = new FernFlowerDecompiler();
public final static Decompiler PROCYON = new ProcyonDecompiler();
public final static Decompiler CFR = new CFRDecompiler();
public final static Decompiler KRAKATAU = new KrakatauDecompiler();
public final static Decompiler JDGUI = new JDGUIDecompiler();
public final static Decompiler KRAKATAU_DA = new KrakatauDisassembler();
public final static Decompiler SMALI = new SmaliDisassembler();
public final static Decompiler HEXCODE = new Decompiler() {
@Override
public String decompileClassNode(ClassNode cn, byte[] b) {
throw new IllegalArgumentException();
}
@Override
public void decompileToZip(String zipName) {
throw new IllegalArgumentException();
}
@Override
public String getName() {
return "Hexcode";
}
@Override
public DecompilerSettings getSettings() {
throw new IllegalArgumentException();
}
};
public Decompiler() {
BY_NAME.put(getName().toLowerCase().replace(' ', '-'), this);
}
protected DecompilerSettings settings = new DecompilerSettings(this);
public abstract String decompileClassNode(ClassNode cn, byte[] b);
public abstract void decompileToZip(String zipName);
public abstract String getName();
public DecompilerSettings getSettings() {
return settings;
}
protected String parseException(Throwable e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
e.printStackTrace();
String exception = "Bytecode Viewer Version: " + BytecodeViewer.version + BytecodeViewer.nl + BytecodeViewer.nl + sw.toString();
return getName() + " encountered a problem! Send the stacktrace to Konloch at http://the.bytecode.club or konloch@gmail.com" + BytecodeViewer.nl +
BytecodeViewer.nl +
"Suggested Fix: Click refresh class, if it fails again try another decompiler." + BytecodeViewer.nl +
BytecodeViewer.nl +
exception;
}
protected void handleException(Exception e) {
new ExceptionUI(e);
}
protected byte[] fixBytes(byte[] in) {
ClassReader reader = new ClassReader(in);
ClassNode node = new ClassNode();
reader.accept(node, ClassReader.EXPAND_FRAMES);
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
node.accept(writer);
return writer.toByteArray();
}
public static void ensureInitted() {
// Just to make sure the classes is loaded so all decompilers are loaded
}
public static Decompiler getByName(String name) {
return BY_NAME.get(name.toLowerCase().replace(' ', '-'));
}
public static Collection<Decompiler> getAllDecompilers() {
return Collections.unmodifiableCollection(BY_NAME.values());
}
}