1 package de.loskutov.bco.editors; 2 3 import java.io.FileInputStream ; 4 import java.io.IOException ; 5 import java.io.InputStream ; 6 import java.util.BitSet ; 7 import java.util.WeakHashMap ; 8 import java.util.zip.ZipEntry ; 9 import java.util.zip.ZipFile ; 10 11 import org.eclipse.core.resources.IFile; 12 import org.eclipse.core.resources.IResource; 13 import org.eclipse.core.runtime.IStatus; 14 import org.eclipse.debug.core.DebugException; 15 import org.eclipse.debug.internal.ui.contexts.DebugContextManager; 16 import org.eclipse.debug.internal.ui.contexts.provisional.IDebugContextListener; 17 import org.eclipse.jdt.core.IClassFile; 18 import org.eclipse.jdt.core.IJavaElement; 19 import org.eclipse.jdt.core.IMember; 20 import org.eclipse.jdt.core.IPackageFragment; 21 import org.eclipse.jdt.core.IPackageFragmentRoot; 22 import org.eclipse.jdt.core.IType; 23 import org.eclipse.jdt.core.JavaModelException; 24 import org.eclipse.jdt.debug.core.IJavaReferenceType; 25 import org.eclipse.jdt.internal.compiler.env.IBinaryType; 26 import org.eclipse.jdt.internal.core.BinaryType; 27 import org.eclipse.jdt.internal.debug.core.model.JDIStackFrame; 28 import org.eclipse.jface.viewers.ISelection; 29 import org.eclipse.jface.viewers.IStructuredSelection; 30 import org.eclipse.ui.IWorkbenchPart; 31 32 import de.loskutov.bco.BytecodeOutlinePlugin; 33 import de.loskutov.bco.asm.DecompiledClass; 34 import de.loskutov.bco.asm.DecompilerClassVisitor; 35 import de.loskutov.bco.ui.JdtUtils; 36 37 41 public class BytecodeSourceMapper implements IDebugContextListener { 42 43 44 private WeakHashMap classToDecompiled; 45 private IJavaReferenceType lastTypeInDebugger; 46 private String lastMethodInDebugger; 47 48 public BytecodeSourceMapper() { 49 super(); 50 classToDecompiled = new WeakHashMap (); 51 DebugContextManager.getDefault().addDebugContextListener(this); 52 } 53 54 public char[] getSource(IClassFile classFile, BitSet decompilerFlags) { 55 IType type; 56 try { 57 type = classFile.getType(); 58 } catch (JavaModelException e) { 59 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 60 return null; 61 } 62 if (!type.isBinary()) { 63 return null; 64 } 65 IBinaryType info = null; 66 try { 67 info = (IBinaryType) ((BinaryType) type).getElementInfo(); 68 } catch (JavaModelException e) { 69 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 70 return null; 71 } 72 if (info == null) { 73 return null; 74 } 75 return findSource(type, info, classFile, decompilerFlags); 76 } 77 78 public char[] getSource(IFile file, IClassFile cf, BitSet decompilerFlags) { 79 StringBuffer source = new StringBuffer (); 80 81 DecompiledClass decompiledClass = decompile(source, file.getLocation() 82 .toOSString(), decompilerFlags); 83 84 classToDecompiled.put(cf, decompiledClass); 85 86 return source.toString().toCharArray(); 87 } 88 89 92 protected char[] findSource(IType type, IBinaryType info, IClassFile cf, 93 BitSet decompilerFlags) { 94 95 IPackageFragment pkgFrag = type.getPackageFragment(); 96 IPackageFragmentRoot root = (IPackageFragmentRoot) pkgFrag.getParent(); 97 String pkg = type.getPackageFragment().getElementName().replace( 98 '.', '/'); 99 100 String classFile = new String (info.getFileName()); 101 int p = classFile.lastIndexOf('/'); 102 classFile = classFile.substring(p + 1); 103 104 StringBuffer source = new StringBuffer (); 105 String location = null; 106 String className = pkg + "/" + classFile; 107 if (root.isArchive()) { 108 location = getArchivePath(root); 109 DecompiledClass decompiledClass = decompileFromArchive( 110 source, location, className, decompilerFlags); 111 classToDecompiled.put(cf, decompiledClass); 112 } else { 113 try { 114 location = root.getUnderlyingResource().getLocation() 115 .toOSString() 116 + "/" + className; 117 DecompiledClass decompiledClass = decompile( 118 source, location, decompilerFlags); 119 classToDecompiled.put(cf, decompiledClass); 120 } catch (JavaModelException e) { 121 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 122 } 123 } 124 125 source.append("\n\n// DECOMPILED FROM: "); 126 source.append(location).append("\n"); 127 return source.toString().toCharArray(); 128 } 129 130 public int getDecompiledLine(IMember elt, IClassFile cf) { 131 DecompiledClass dc = (DecompiledClass) classToDecompiled.get(cf); 132 if (dc != null) { 133 String signature = JdtUtils.getMethodSignature(elt); 134 if (signature != null) { 135 return dc.getDecompiledLine(signature); 136 } 137 } 138 return 0; 139 } 140 141 protected DecompiledClass decompile(StringBuffer source, String filePath, 142 BitSet decompilerFlags) { 143 FileInputStream inputStream = null; 144 DecompiledClass dc = null; 145 try { 146 inputStream = new FileInputStream (filePath); 147 dc = decompile(source, inputStream, decompilerFlags); 148 } catch (IOException e) { 149 source.append(e.toString()); 150 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 151 } finally { 152 if (inputStream != null) { 153 try { 154 inputStream.close(); 155 } catch (IOException e) { 156 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 157 } 158 } 159 } 160 return dc; 161 } 162 163 protected DecompiledClass decompileFromArchive(StringBuffer source, 164 String archivePath, String className, BitSet decompilerFlags) { 165 if(archivePath == null){ 166 return null; 167 } 168 InputStream inputStream = null; 169 DecompiledClass decompiledClass = null; 170 try { 171 ZipFile zf = new ZipFile (archivePath); 172 ZipEntry ze = zf.getEntry(className); 173 inputStream = zf.getInputStream(ze); 174 decompiledClass = decompile(source, inputStream, decompilerFlags); 175 } catch (IOException e) { 176 source.append(e.toString()); 177 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 178 } finally { 179 if (inputStream != null) { 180 try { 181 inputStream.close(); 182 } catch (IOException e) { 183 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 184 } 185 } 186 } 187 return decompiledClass; 188 } 189 190 private DecompiledClass decompile(StringBuffer source, InputStream is, 191 BitSet decompilerFlags) throws IOException { 192 DecompiledClass decompiledClass = DecompilerClassVisitor 193 .getDecompiledClass(is, null, null, decompilerFlags, null); 194 source.append(decompiledClass.getText()); 195 return decompiledClass; 196 } 197 198 private String getArchivePath(IPackageFragmentRoot root) { 199 String archivePath = null; 200 IResource resource; 201 202 try { 203 if ((resource = root.getUnderlyingResource()) != null) { 204 archivePath = resource.getLocation().toOSString(); 206 } else { 207 archivePath = root.getPath().toOSString(); 209 } 210 } catch (JavaModelException e) { 211 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 212 } 213 return archivePath; 214 } 215 216 protected IJavaElement findElement(IClassFile cf, int decompiledLine) { 217 DecompiledClass dc = (DecompiledClass) classToDecompiled.get(cf); 218 if (dc != null) { 219 return dc.getJavaElement(decompiledLine, cf); 220 } 221 return cf; 222 } 223 224 public int mapToSource(int decompiledLine, IClassFile cf) { 225 if (cf == null) { 226 return 0; 227 } 228 DecompiledClass dc = (DecompiledClass) classToDecompiled.get(cf); 229 if (dc != null) { 230 return dc.getSourceLine(decompiledLine); 231 } 232 return 0; 233 } 234 235 240 public DecompiledClass getDecompiledClass(IClassFile cf){ 241 if(cf == null){ 242 return null; 243 } 244 return (DecompiledClass) classToDecompiled.get(cf); 245 } 246 247 public int mapToDecompiled(int sourceLine, IClassFile cf) { 248 if (cf == null) { 249 return 0; 250 } 251 DecompiledClass dc = (DecompiledClass) classToDecompiled.get(cf); 252 if (dc != null) { 253 return dc.getDecompiledLine(sourceLine); 254 } 255 return 0; 256 } 257 258 public void contextActivated(ISelection selection, IWorkbenchPart part) { 259 if(selection instanceof IStructuredSelection){ 260 IStructuredSelection sSelection = (IStructuredSelection) selection; 261 if(sSelection.isEmpty()){ 262 return; 263 } 264 Object element = sSelection.getFirstElement(); 265 if(element instanceof JDIStackFrame){ 266 JDIStackFrame frame = (JDIStackFrame) element; 267 try { 268 lastTypeInDebugger = frame.getReferenceType(); 269 lastMethodInDebugger = frame.getMethodName() + frame.getSignature(); 270 } catch (DebugException e) { 271 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 272 } 273 } 274 } 275 } 276 277 public void contextChanged(ISelection selection, IWorkbenchPart part) { 278 contextActivated(selection, part); 279 } 280 281 public IJavaReferenceType getLastTypeInDebugger() { 282 return lastTypeInDebugger; 283 } 284 285 public int mapDebuggerToDecompiled(IClassFile cf) { 286 if(cf == null || lastMethodInDebugger == null){ 287 return -1; 288 } 289 DecompiledClass dc = (DecompiledClass) classToDecompiled.get(cf); 290 if (dc != null) { 291 return dc.getDecompiledLine(lastMethodInDebugger); 292 } 293 return -1; 294 } 295 296 } 297 | Popular Tags |