PageRenderTime 40ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/bundles/plugins-trunk/JavaInsight/javainsight/JodeVFS.java

#
Java | 234 lines | 157 code | 41 blank | 36 comment | 29 complexity | a6c5a93bae69f00b1dbcf6ecd32cc915 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * JodeVFS.java
  3. * Copyright (c) 2001, 2002 Andre Kaplan
  4. *
  5. * jEdit edit mode settings:
  6. * :mode=java:tabSize=4:indentSize=4:noTabs=true:maxLineLen=0:
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. */
  22. package javainsight;
  23. import java.awt.Component;
  24. import java.io.*;
  25. import java.util.ArrayList;
  26. import javainsight.buildtools.ChainedIOException;
  27. import javainsight.buildtools.JavaUtils;
  28. import net.sf.jode.GlobalOptions;
  29. import net.sf.jode.bytecode.ClassInfo;
  30. import net.sf.jode.bytecode.ClassPath;
  31. import net.sf.jode.decompiler.ClassAnalyzer;
  32. import net.sf.jode.decompiler.ImportHandler;
  33. import net.sf.jode.decompiler.Options;
  34. import net.sf.jode.decompiler.TabbedPrintWriter;
  35. import org.apache.bcel.classfile.ClassParser;
  36. import org.apache.bcel.classfile.JavaClass;
  37. import org.gjt.sp.jedit.Mode;
  38. import org.gjt.sp.jedit.jEdit;
  39. import org.gjt.sp.jedit.io.VFS;
  40. import org.gjt.sp.jedit.io.VFSManager;
  41. import org.gjt.sp.util.Log;
  42. public class JodeVFS extends ByteCodeVFS
  43. {
  44. public static final String PROTOCOL = "jode";
  45. private static final Object mutex = new Object();
  46. public JodeVFS() {
  47. super(PROTOCOL);
  48. }
  49. /**
  50. * Creates an input stream. This method is called from the I/O
  51. * thread.
  52. * @param session the VFS session
  53. * @param path The path
  54. * @param ignoreErrors If true, file not found errors should be
  55. * ignored
  56. * @param comp The component that will parent error dialog boxes
  57. * @exception IOException If an I/O error occurs
  58. */
  59. @Override
  60. public InputStream _createInputStream(Object session,
  61. String path, boolean ignoreErrors, Component comp)
  62. throws IOException
  63. {
  64. String pathToClass = path;
  65. if (path.startsWith(PROTOCOL + ':')) {
  66. pathToClass = pathToClass.substring(PROTOCOL.length() + 1);
  67. }
  68. VFS vfs = VFSManager.getVFSForPath(pathToClass);
  69. if (pathToClass.endsWith(".marks")) {
  70. return null;
  71. }
  72. String className = null;
  73. try {
  74. // Get the class name from BCEL!
  75. DataInputStream in = new DataInputStream(new BufferedInputStream(
  76. vfs._createInputStream(session, pathToClass, ignoreErrors, comp)
  77. ));
  78. JavaClass java_class = new ClassParser(in, pathToClass).parse();
  79. className = java_class.getClassName();
  80. in.close();
  81. // Get the VFS path
  82. String vfsPath = vfs.getParentOfPath(pathToClass);
  83. if (vfs != VFSManager.getVFSForPath(vfsPath)) {
  84. vfsPath = null;
  85. } else {
  86. int dotIdx = className.lastIndexOf('.');
  87. while (dotIdx != -1) {
  88. vfsPath = vfs.getParentOfPath(vfsPath);
  89. if (vfs != VFSManager.getVFSForPath(vfsPath)) {
  90. vfsPath = null;
  91. break;
  92. }
  93. dotIdx = className.lastIndexOf('.', dotIdx - 1);
  94. }
  95. }
  96. ClassPath classPath = createJodeClasspath(vfsPath);
  97. Log.log(Log.DEBUG, this,
  98. "className=" + className
  99. + " vfsPath=" + vfsPath
  100. + " pathToClass=" + pathToClass
  101. + " classPath=" + classPath);
  102. in = new DataInputStream(new BufferedInputStream(
  103. vfs._createInputStream(session, pathToClass, ignoreErrors, comp)
  104. ));
  105. ClassInfo clazz = classPath.getClassInfo(className);
  106. clazz.read(in, ClassInfo.ALL);
  107. ByteArrayOutputStream baOut = new ByteArrayOutputStream();
  108. OutputStreamWriter output = new OutputStreamWriter(baOut);
  109. decompile(className, classPath, output);
  110. output.close();
  111. return new BufferedInputStream(new ByteArrayInputStream(baOut.toByteArray()));
  112. } catch (IOException ioex) {
  113. throw ioex;
  114. } catch (Throwable t) {
  115. // Jode sometimes throws java.lang.InternalError or other
  116. // messy things:
  117. throw new ChainedIOException("An error occured while decompiling " + className, t);
  118. }
  119. }
  120. private ClassPath createJodeClasspath(String vfsPath) throws SecurityException, IOException {
  121. ArrayList<ClassPath.Location> locations = new ArrayList<ClassPath.Location>();
  122. for(String cp : JavaUtils.getClasspath()) {
  123. locations.add(ClassPath.createLocation(cp));
  124. }
  125. if(vfsPath != null) {
  126. locations.add(new VFSLocation(vfsPath));
  127. }
  128. return new ClassPath(locations.toArray(new ClassPath.Location[locations.size()]));
  129. }
  130. private void decompile(String className, ClassPath classPath, Writer decompilerOutput) throws IOException {
  131. String style = jEdit.getProperty("javainsight.jode.style", "sun");
  132. boolean pretty = jEdit.getBooleanProperty("javainsight.jode.pretty", true);
  133. boolean onetime = jEdit.getBooleanProperty("javainsight.jode.onetime", false);
  134. boolean decrypt = jEdit.getBooleanProperty("javainsight.jode.decrypt", true);
  135. int importPkgLimit = 0;
  136. try {
  137. importPkgLimit = Integer.parseInt(jEdit.getProperty("javainsight.jode.pkglimit", "0"));
  138. } catch(NumberFormatException ex) {}
  139. if(importPkgLimit == 0)
  140. importPkgLimit = Integer.MAX_VALUE;
  141. int importClassLimit = 1;
  142. try {
  143. importClassLimit = Integer.parseInt(jEdit.getProperty("javainsight.jode.clslimit", "1"));
  144. } catch(NumberFormatException ex) {}
  145. if(importClassLimit == 0)
  146. importClassLimit = Integer.MAX_VALUE;
  147. Mode mode = jEdit.getMode("java");
  148. String wrapMode = mode.getProperty("wrap").toString(); // "node", "soft", "hard"
  149. int maxLineLen = (Integer) mode.getProperty("maxLineLen"); // 0 means no max. line len
  150. int tabSize = (Integer) mode.getProperty("tabSize");
  151. int indentSize = (Integer) mode.getProperty("indentSize");
  152. boolean noTabs = mode.getBooleanProperty("noTabs");
  153. if(!wrapMode.equals("hard") || maxLineLen == 0)
  154. maxLineLen = 1000;
  155. if(noTabs)
  156. tabSize = 0;
  157. int outputStyle = 0; // default for style "pascal"
  158. if(style.equals("gnu"))
  159. outputStyle = TabbedPrintWriter.GNU_SPACING | TabbedPrintWriter.INDENT_BRACES;
  160. else if(style.equals("sun"))
  161. outputStyle = TabbedPrintWriter.BRACE_AT_EOL;
  162. if(pretty)
  163. Options.options &= ~Options.OPTION_PRETTY;
  164. else
  165. Options.options |= Options.OPTION_PRETTY;
  166. if(onetime)
  167. Options.options &= ~Options.OPTION_ONETIME;
  168. else
  169. Options.options |= Options.OPTION_ONETIME;
  170. if(decrypt)
  171. Options.options &= ~Options.OPTION_DECRYPT;
  172. else
  173. Options.options |= Options.OPTION_DECRYPT;
  174. StringWriter errorOutput = new StringWriter();
  175. GlobalOptions.err = new PrintWriter(errorOutput);
  176. // JODE is not thread-safe
  177. synchronized (mutex) {
  178. ImportHandler importHandler = new ImportHandler(classPath, importPkgLimit, importClassLimit);
  179. TabbedPrintWriter tabbedPrintWriter = new TabbedPrintWriter(decompilerOutput,
  180. importHandler, true, outputStyle, indentSize, tabSize, maxLineLen);
  181. ClassInfo clazz = classPath.getClassInfo(className);
  182. ClassAnalyzer clazzAnalyzer = new ClassAnalyzer(clazz, importHandler);
  183. clazzAnalyzer.dumpJavaFile(tabbedPrintWriter);
  184. tabbedPrintWriter.close();
  185. errorOutput.close();
  186. }
  187. GlobalOptions.err = null;
  188. String errorMessages = errorOutput.toString();
  189. if(errorMessages != null && errorMessages.trim().length() > 0) {
  190. Log.log(Log.ERROR, this, "Error decompiling class " + className + ":\n" + errorMessages);
  191. }
  192. }
  193. }