Package de.loskutov.bco.editors

Source Code of de.loskutov.bco.editors.BytecodeSourceMapper

package de.loskutov.bco.editors;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.BitSet;
import java.util.WeakHashMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.internal.ui.contexts.DebugContextManager;
import org.eclipse.debug.ui.contexts.DebugContextEvent;
import org.eclipse.debug.ui.contexts.IDebugContextListener;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.debug.core.IJavaReferenceType;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.internal.core.BinaryType;
import org.eclipse.jdt.internal.debug.core.model.JDIStackFrame;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;

import de.loskutov.bco.BytecodeOutlinePlugin;
import de.loskutov.bco.asm.DecompiledClass;
import de.loskutov.bco.asm.DecompilerClassVisitor;
import de.loskutov.bco.ui.JdtUtils;

/**
* @author Jochen Klein
* @author Andrei
*/
public class BytecodeSourceMapper implements IDebugContextListener {

    /** key is IClassFile, value is DecompiledClass */
    private WeakHashMap classToDecompiled;
    private IJavaReferenceType lastTypeInDebugger;
    private String lastMethodInDebugger;

    public BytecodeSourceMapper() {
        super();
        classToDecompiled = new WeakHashMap();
        DebugContextManager.getDefault().addDebugContextListener(this);
    }

    public char[] getSource(IClassFile classFile, BitSet decompilerFlags) {
        IType type;
        type = classFile.getType();
        if (type == null || !type.isBinary()) {
            return null;
        }
        IBinaryType info = null;
        try {
            info = (IBinaryType) ((BinaryType) type).getElementInfo();
        } catch (JavaModelException e) {
            BytecodeOutlinePlugin.log(e, IStatus.ERROR);
            return null;
        }
        if (info == null) {
            return null;
        }
        return findSource(type, info, classFile, decompilerFlags);
    }

    public char[] getSource(IFile file, IClassFile cf, BitSet decompilerFlags) {
        StringBuffer source = new StringBuffer();

        DecompiledClass decompiledClass = decompile(source, file.getLocation()
            .toOSString(), decompilerFlags);

        classToDecompiled.put(cf, decompiledClass);

        return source.toString().toCharArray();
    }

    /**
     *
     */
    protected char[] findSource(IType type, IBinaryType info, IClassFile cf,
        BitSet decompilerFlags) {

        IPackageFragment pkgFrag = type.getPackageFragment();
        IPackageFragmentRoot root = (IPackageFragmentRoot) pkgFrag.getParent();
        String pkg = type.getPackageFragment().getElementName().replace(
            '.', '/');

        String classFile = new String(info.getFileName());
        int p = classFile.lastIndexOf('/');
        classFile = classFile.substring(p + 1);

        StringBuffer source = new StringBuffer();
        String location = null;
        String className = pkg + "/" + classFile;
        if (root.isArchive()) {
            location = getArchivePath(root);
            DecompiledClass decompiledClass = decompileFromArchive(
                source, location, className, decompilerFlags);
            classToDecompiled.put(cf, decompiledClass);
        } else {
            try {
                location = root.getUnderlyingResource().getLocation()
                    .toOSString()
                    + "/" + className;
                DecompiledClass decompiledClass = decompile(
                    source, location, decompilerFlags);
                classToDecompiled.put(cf, decompiledClass);
            } catch (JavaModelException e) {
                BytecodeOutlinePlugin.log(e, IStatus.ERROR);
            }
        }

        source.append("\n\n// DECOMPILED FROM: ");
        source.append(location).append("\n");
        return source.toString().toCharArray();
    }

    public int getDecompiledLine(IMember elt, IClassFile cf) {
        DecompiledClass dc = (DecompiledClass) classToDecompiled.get(cf);
        if (dc != null) {
            String signature = JdtUtils.getMethodSignature(elt);
            if (signature != null) {
                return dc.getDecompiledLine(signature);
            }
        }
        return 0;
    }

    protected DecompiledClass decompile(StringBuffer source, String filePath,
        BitSet decompilerFlags) {
        FileInputStream inputStream = null;
        DecompiledClass dc = null;
        try {
            inputStream = new FileInputStream(filePath);
            dc = decompile(source, inputStream, decompilerFlags);
        } catch (IOException e) {
            source.append(e.toString());
            BytecodeOutlinePlugin.log(e, IStatus.ERROR);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    BytecodeOutlinePlugin.log(e, IStatus.ERROR);
                }
            }
        }
        return dc;
    }

    protected DecompiledClass decompileFromArchive(StringBuffer source,
        String archivePath, String className, BitSet decompilerFlags) {
        if(archivePath == null){
            return null;
        }
        InputStream inputStream = null;
        DecompiledClass decompiledClass = null;
        try {
            ZipFile zf = new ZipFile(archivePath);
            ZipEntry ze = zf.getEntry(className);
            inputStream = zf.getInputStream(ze);
            decompiledClass = decompile(source, inputStream, decompilerFlags);
        } catch (IOException e) {
            source.append(e.toString());
            BytecodeOutlinePlugin.log(e, IStatus.ERROR);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    BytecodeOutlinePlugin.log(e, IStatus.ERROR);
                }
            }
        }
        return decompiledClass;
    }

    private DecompiledClass decompile(StringBuffer source, InputStream is,
        BitSet decompilerFlags) throws IOException {
        DecompiledClass decompiledClass = DecompilerClassVisitor
            .getDecompiledClass(is, null, null, decompilerFlags, null);
        source.append(decompiledClass.getText());
        return decompiledClass;
    }

    private String getArchivePath(IPackageFragmentRoot root) {
        String archivePath = null;
        IResource resource;

        try {
            if ((resource = root.getUnderlyingResource()) != null) {
                // jar in workspace
                archivePath = resource.getLocation().toOSString();
            } else {
                // external jar
                archivePath = root.getPath().toOSString();
            }
        } catch (JavaModelException e) {
            BytecodeOutlinePlugin.log(e, IStatus.ERROR);
        }
        return archivePath;
    }

    protected IJavaElement findElement(IClassFile cf, int decompiledLine) {
        DecompiledClass dc = (DecompiledClass) classToDecompiled.get(cf);
        if (dc != null) {
            return dc.getJavaElement(decompiledLine, cf);
        }
        return cf;
    }

    public int mapToSource(int decompiledLine, IClassFile cf) {
        if (cf == null) {
            return 0;
        }
        DecompiledClass dc = (DecompiledClass) classToDecompiled.get(cf);
        if (dc != null) {
            return dc.getSourceLine(decompiledLine);
        }
        return 0;
    }

    /**
     *
     * @param cf
     * @return mapped class or null
     */
    public DecompiledClass getDecompiledClass(IClassFile cf){
        if(cf == null){
            return null;
        }
        return (DecompiledClass) classToDecompiled.get(cf);
    }

    public int mapToDecompiled(int sourceLine, IClassFile cf) {
        if (cf == null) {
            return 0;
        }
        DecompiledClass dc = (DecompiledClass) classToDecompiled.get(cf);
        if (dc != null) {
            return dc.getDecompiledLine(sourceLine);
        }
        return 0;
    }

    public IJavaReferenceType getLastTypeInDebugger() {
        return lastTypeInDebugger;
    }

    public int mapDebuggerToDecompiled(IClassFile cf) {
        if(cf == null || lastMethodInDebugger == null){
            return -1;
        }
        DecompiledClass dc = (DecompiledClass) classToDecompiled.get(cf);
        if (dc != null) {
            return dc.getDecompiledLine(lastMethodInDebugger);
        }
        return -1;
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.contexts.IDebugContextListener#debugContextChanged(org.eclipse.debug.ui.contexts.DebugContextEvent)
     */
    public void debugContextChanged(DebugContextEvent event) {
        ISelection selection = event.getContext();
        if(selection instanceof IStructuredSelection){
            IStructuredSelection sSelection = (IStructuredSelection) selection;
            if(sSelection.isEmpty()){
                return;
            }
            Object element = sSelection.getFirstElement();
            if(element instanceof JDIStackFrame){
                JDIStackFrame frame = (JDIStackFrame) element;
                try {
                    lastTypeInDebugger = frame.getReferenceType();
                    lastMethodInDebugger = frame.getMethodName() + frame.getSignature();
                } catch (DebugException e) {
                    BytecodeOutlinePlugin.log(e, IStatus.ERROR);
                }
            }
        }
    }

}
TOP

Related Classes of de.loskutov.bco.editors.BytecodeSourceMapper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.