Advertisement
Guest User

opal v3

a guest
Feb 21st, 2019
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 20.16 KB | None | 0 0
  1. package opalintegration;
  2.  
  3. import Compile.Compiler;
  4. import com.intellij.openapi.util.io.FileUtil;
  5. import com.intellij.openapi.vfs.LocalFileSystem;
  6. import com.intellij.openapi.vfs.VirtualFile;
  7. import com.intellij.psi.search.FilenameIndex;
  8. import com.intellij.psi.search.GlobalSearchScope;
  9. import globalData.GlobalData;
  10. import java.io.*;
  11. import java.net.JarURLConnection;
  12. import java.net.MalformedURLException;
  13. import java.net.URL;
  14. import java.nio.charset.Charset;
  15. import java.nio.file.Path;
  16. import java.nio.file.Paths;
  17. import java.util.Collection;
  18. import java.util.NoSuchElementException;
  19. import java.util.jar.JarInputStream;
  20. import java.util.regex.Matcher;
  21. import java.util.regex.Pattern;
  22.  
  23. import org.jetbrains.annotations.NotNull;
  24. import org.opalj.bi.AccessFlags;
  25. import org.opalj.br.ClassFile;
  26. import org.opalj.br.Code;
  27. import org.opalj.br.LocalVariable;
  28. import org.opalj.br.Method;
  29. import org.opalj.br.analyses.JavaProject;
  30. import org.opalj.br.analyses.Project;
  31. import org.opalj.br.instructions.Instruction;
  32. import org.opalj.collection.immutable.ConstArray;
  33. import org.opalj.collection.immutable.RefArray;
  34. import org.opalj.da.ClassFileReader;
  35. import org.opalj.tac.*;
  36. import org.opalj.value.KnownTypedValue;
  37. import scala.Function0;
  38. import scala.Function1;
  39. import scala.Some;
  40. import scala.collection.immutable.List;
  41.  
  42. public class Opal {
  43.   // uriProject wird benötigt um die OpalFrameworks mit dem Project zu verbinden.
  44.   private static Project<URL> uriProject;
  45.   // noch nicht wichtig könnted
  46.   private static JavaProject javaProject;
  47.   static Function1<Method, TACode<TACMethodParameter, DUVar<KnownTypedValue>>> methodTACodeFunction;
  48.   // INTELIJ VARS
  49.   private static com.intellij.openapi.project.Project project;
  50.   private static String classPath;
  51.  
  52.  
  53.   // =====================================================================================
  54.   // =====================================================================================
  55.   // =====================================================================================
  56.  
  57.   private static ClassFile getClassFile(VirtualFile virtualClassFile) {
  58.     String filepath = virtualClassFile.getPath();
  59.     Project<URL> uriProject = Project.apply(new File(filepath));
  60.     ConstArray<ClassFile> classFileConstArray = uriProject.allProjectClassFiles();
  61.  
  62.     if(classFileConstArray.length() > 0) {
  63.       System.out.println("Apply(0): " + classFileConstArray.apply(0));
  64.       return classFileConstArray.apply(0);
  65.     }
  66.     // else (might be) JAR
  67.     else {
  68.       System.out.println("getClassFile() JAR? : " + virtualClassFile.getName());
  69.       String jarFileRoot = getJarFileRoot(virtualClassFile);
  70.       return createClassFileFromJar(jarFileRoot);
  71.     }
  72.   }
  73.  
  74.   private static String getJarFileRoot(VirtualFile virtualClassFile) {
  75.     String jarPathWithoutClassExtension
  76.             = virtualClassFile.getParent().getPath()
  77.             + File.separator
  78.             + virtualClassFile.getNameWithoutExtension();
  79.     // this\is\the\jarPath -> this/is/the/jarPath
  80.     jarPathWithoutClassExtension = jarPathWithoutClassExtension.replaceAll("\\\\", "/");
  81.  
  82.     String jarFileRoot = jarPathWithoutClassExtension.substring(0, jarPathWithoutClassExtension.indexOf("!/"));
  83.     return jarFileRoot;
  84.   }
  85.  
  86.   // TODO: this gets called for classes we haven't clicked on as well?
  87.   private static ClassFile createClassFileFromJar(String jarFileRoot) {
  88.     Project<URL> uriProject = Project.apply(new File(jarFileRoot));
  89.  
  90.     Object classObj = Project.JavaClassFileReader(
  91.             uriProject.logContext(), uriProject.config())
  92.             .ClassFiles(new Function0<JarInputStream>() {
  93.       @Override
  94.       public JarInputStream apply() {
  95.         try {
  96.           return new JarInputStream(new FileInputStream(new File(jarFileRoot)));
  97.         } catch(IOException e) {
  98.           // ....
  99.         }
  100.  
  101.         System.out.println("ABOUT TO RETURN NULL (1)");
  102.         return null;
  103.       }
  104.     }).head()._1();
  105.  
  106.     ClassFile classFileFromJar = null;
  107.     if(classObj instanceof ClassFile) {
  108.        classFileFromJar = (ClassFile)classObj;
  109.     }
  110.  
  111.     return classFileFromJar;
  112.   }
  113.  
  114.  
  115.   /**
  116.    * create the bytecode representation (of OPAL) for a given class file
  117.    *
  118.    * @param classFile ...
  119.    * @return the bytecode representation as a String
  120.    */
  121.   private static String createBytecodeString(ClassFile classFile) {
  122.     String myString = "// ";
  123.     myString =
  124.             myString + AccessFlags.classFlagsToJava(classFile.accessFlags()) + " " + classFile.fqn();
  125.     if (classFile.superclassType().isDefined())
  126.       myString = myString + " extends " + classFile.superclassType().get().toJava();
  127.     if (classFile.interfaceTypes().length() > 0) {
  128.       myString = myString + " implements ";
  129.       for (int j = 0; j < classFile.interfaceTypes().length(); j++) {
  130.         myString = myString + classFile.interfaceTypes().apply(j).toJava() + " ";
  131.       }
  132.     }
  133.     myString =
  134.             myString
  135.                     + "\n// Source File: "
  136.                     + classFile.sourceFile()
  137.                     + " Version: "
  138.                     + classFile.jdkVersion()
  139.                     + " Size: \n";
  140.  
  141.     // TODO Constant Pool Maybe working with DA.
  142.     RefArray<Method> methods = classFile.methods();
  143.     for (int j = 0; j < methods.length(); j++) {
  144.       Method method = methods.apply(j);
  145.       if (method.body().isDefined()) {
  146.         Code body = method.body().get();
  147.         Instruction[] instructions = body.instructions();
  148.         myString =
  149.                 myString
  150.                         + method.toString()
  151.                         + "// [size :"
  152.                         + body.codeSize()
  153.                         + " bytes, max Stack: "
  154.                         + body.maxStack()
  155.                         + ", max Locals: "
  156.                         + body.maxLocals()
  157.                         + "] \n";
  158.         myString = myString + "\tPC\tLine\tInstruction\n";
  159.         for (int k = 0; k < instructions.length; k++) {
  160.           if (instructions[k] != null) {
  161.             try {
  162.               myString =
  163.                       myString
  164.                               + "\t"
  165.                               + k
  166.                               + "\t"
  167.                               + body.lineNumber(k).get().toString()
  168.                               + "\t\t"
  169.                               + instructions[k]
  170.                               + "\n";
  171.             } catch(NoSuchElementException e) {
  172.               return "Issue with Java 5? \n\n " + e.getMessage();
  173.             }
  174.  
  175.           }
  176.         }
  177.         if (body.localVariableTable().isDefined()) {
  178.           RefArray<LocalVariable> refArrayOption = body.localVariableTable().get();
  179.           myString =
  180.                   myString
  181.                           + "\n\nLocalVariableTable // [size: "
  182.                           + refArrayOption.length()
  183.                           + " item(s)]\n";
  184.           for (int k = 0; k < refArrayOption.length(); k++) {
  185.             LocalVariable localVariable = refArrayOption.apply(k);
  186.             myString =
  187.                     myString
  188.                             + "["
  189.                             + localVariable.startPC()
  190.                             + " > "
  191.                             + localVariable.length()
  192.                             + ") => "
  193.                             + localVariable.fieldType().toJava()
  194.                             + " "
  195.                             + localVariable.name()
  196.                             + "\n";
  197.           }
  198.         }
  199.         myString = myString + "\n\n\n";
  200.       }
  201.     }
  202.  
  203.     return myString;
  204.   }
  205.  
  206.  
  207.   // =====================================================================================
  208.   // =====================================================================================
  209.   // =====================================================================================
  210.  
  211.  
  212.   public static String JavaClassToTACForm(ClassFile classFile, String filepath) {
  213.     String JavaTACClassString = threeWayDisassemblerString(classFile, filepath);
  214.     return JavaTACClassString;
  215.   }
  216.  
  217.   public static String threeWayDisassemblerString(ClassFile classFile, String filepath) {
  218.     StringBuilder tacCodeString = new StringBuilder();
  219.     uriProject = Project.apply(new File(filepath));
  220.     javaProject = new JavaProject(uriProject);
  221.     methodTACodeFunction = javaProject.project().get(DefaultTACAIKey$.MODULE$);
  222.  
  223.     // iterate through the methods and generate the TAC for each
  224.     RefArray<Method> methods = classFile.methods();
  225.     for (int j = 0; j < methods.length(); j++) {
  226.       Method method = methods.apply(j);
  227.       if (method.body().isDefined()) {
  228.         System.out.println(method.toJava());
  229.         tacCodeString.append(method.toJava()).append("\n");
  230.         TACode<TACMethodParameter, DUVar<KnownTypedValue>> TacCode = methodTACodeFunction.apply(method);
  231.         tacCodeString.append(ToTxt.apply(TacCode).mkString("\n"));
  232.         tacCodeString.append("\n\n\n");
  233.       }
  234.     } // for(j)
  235.  
  236.  
  237.     System.out.println("TAC CODE TO STRING: " + tacCodeString);
  238.     return tacCodeString.toString();
  239.   }
  240.  
  241.  
  242.   // ====================================================================================
  243.   // ====================================================================================
  244.  
  245.   public static String JavaClassToHtmlForm(VirtualFile virtualClassFile) {
  246.     classPath = virtualClassFile.getPath();
  247.     String JavaHTMLClass = JavaClassToHTMLForm(classPath);
  248.     return JavaHTMLClass;
  249.   }
  250.  
  251.   public static String JavaClassToHTMLForm(String classPath) {
  252.     Path path = Paths.get(classPath);
  253.     File file = path.toFile();
  254.     // TODO scala.collection.immutable.List<Object> classFileList;
  255.     String toHtmlAsString;
  256.     try (FileInputStream fis = new FileInputStream(file);
  257.         DataInputStream dis = new DataInputStream(fis)) {
  258.       // get the class file and construct the HTML string
  259.       org.opalj.da.ClassFile cf = (org.opalj.da.ClassFile) ClassFileReader.ClassFile(dis).head();
  260.  
  261.       // ordentliches HTML Code
  262.       toHtmlAsString =
  263.           "<html>\n<head>\n<style>"
  264.               + cf.TheCSS() // cf.TheCSS()
  265.               + "</style>\n</head>\n<body>\n"
  266.               + jsOpenField()
  267.               + jsOpenMethod()
  268.               + jsScrollToField()
  269.               + jsScrollToID()
  270.               + cf.classFileToXHTML(new Some(classPath)).toString()
  271.               + "\n</body>\n</html>";
  272.  
  273.       // TODO: is this ok? (talk to M. Eichberg?)
  274.       toHtmlAsString = fixInitSymbols(toHtmlAsString);
  275.     } catch (IOException e) {
  276.       toHtmlAsString =
  277.           "<html><body><h1>Something went wrong in Opal.toHTMLForm()</h1></body></html>";
  278.     }
  279.     return toHtmlAsString;
  280.   }
  281.  
  282.   private static String fixInitSymbols(String htmlString) {
  283.     // e.g. id="&lt;clinit&gt;()V" should become id="<clinit>()V"
  284.     final String regex = "(id=\"|data-name=\")(&lt;)(\\w+)(&gt;)([^\"]*\")";
  285.     final Pattern p = Pattern.compile(regex);
  286.     final Matcher m = p.matcher(htmlString);
  287.  
  288.     StringBuffer sb = new StringBuffer();
  289.     while (m.find()) {
  290.       String replacement = m.group(1) + "<" + m.group(3) + ">" + m.group(5);
  291.       m.appendReplacement(sb, replacement);
  292.     }
  293.     m.appendTail(sb);
  294.     htmlString = sb.toString();
  295.  
  296.     return htmlString;
  297.   }
  298.  
  299.   private static String jsOpenField() {
  300.     String script =
  301.         "<script>\n"
  302.             + "function openFields() {\n"
  303.             + "   document.getElementsByClassName(\"fields\")[0].getElementsByTagName(\"details\")[0].open = true;"
  304.             + "}\n"
  305.             + "</script>\n";
  306.  
  307.     return script;
  308.   }
  309.  
  310.   private static String jsOpenMethod() {
  311.     String script =
  312.         "<script>\n"
  313.             + "function openMethods() {\n"
  314.             + "   document.getElementsByClassName(\"methods\")[0].getElementsByTagName(\"details\")[0].open = true;"
  315.             + "}\n"
  316.             + "</script>\n";
  317.  
  318.     return script;
  319.   }
  320.  
  321.   private static String jsScrollToField() {
  322.     // differentiate between light and dark IDE theme
  323.     String lightThemeHighlight = "\"#FDFF47\"";
  324.     String darkThemeHighlight = "\"#ABCDEF\"";
  325.  
  326.     //    String highlightColor = JBColor.isBright() ? lightThemeHighlight : darkThemeHighlight;
  327.     String highlightColor = lightThemeHighlight;
  328.     String originalColor = "\"#FFFFFF\""; // TODO: need one for dark theme as well
  329.  
  330.     // orig (e.g. get it from CSS)?
  331.     String script =
  332.         "<script>\n"
  333.             + "function scrollToField(dataName) {\n"
  334.             + "    var elements = document.getElementsByClassName(\"field details\");\n"
  335.             + "    for(var i=0; i < elements.length; i++) {\n"
  336.             + "       var element = elements[i];\n"
  337.             + "       if(element.getAttribute(\"data-name\") == dataName) {\n"
  338.             + "         element.scrollIntoView();\n"
  339.             + "         element.style.backgroundColor = "
  340.             + highlightColor
  341.             + ";\n"
  342.             + "         window.setTimeout(function(){\n"
  343.             + "           element.style.backgroundColor = "
  344.             + originalColor
  345.             + ";\n"
  346.             + "         }, 2000);\n"
  347.             + "         return;\n"
  348.             + "       }\n"
  349.             + "    }\n"
  350.             + "}\n"
  351.             + "</script>\n";
  352.  
  353.     return script;
  354.   }
  355.  
  356.   private static String jsScrollToID() {
  357.     // differentiate between light and dark IDE theme
  358.     String lightThemeHighlight = "\"#FDFF47\"";
  359.     String darkThemeHighlight = "\"#ABCDEF\"";
  360.  
  361.     //    String highlightColor = JBColor.isBright() ? lightThemeHighlight : darkThemeHighlight;
  362.     String highlightColor = lightThemeHighlight;
  363.     String originalColor = "\"#F7F7F7\""; // TODO: need one for dark theme as well
  364.  
  365.     // orig (e.g. get it from CSS)?
  366.     String script =
  367.         "<script>\n"
  368.             + "function scrollTo(elementId) {\n"
  369.             + "    var element = document.getElementById(elementId);\n"
  370.             + "    element.scrollIntoView(); \n"
  371.             + "    element.open  = true;\n"
  372.             + "    element.style.backgroundColor = "
  373.             + highlightColor
  374.             + ";\n"
  375.             + "    window.setTimeout(function(){\n"
  376.             + "    element.style.backgroundColor = "
  377.             + originalColor
  378.             + ";\n"
  379.             + "    }, 2000);\n"
  380.             + "}\n"
  381.             + "</script>\n";
  382.  
  383.     return script;
  384.   }
  385.  
  386.   // ====================================================================================
  387.   // ====================================================================================
  388.  
  389.   public static void setProject(com.intellij.openapi.project.Project inteliProject) {
  390.     project = inteliProject;
  391.   }
  392.  
  393.   // TODO check if date is create & up2date GOT ERROS
  394.   public static VirtualFile prepareHtml(
  395.       @NotNull com.intellij.openapi.project.Project project, @NotNull VirtualFile virtualFile) {
  396.     // All files selected in the "Project"-View
  397.     setProject(project);
  398.     Collection<VirtualFile> virtualFilesByName =
  399.         FilenameIndex.getVirtualFilesByName(
  400.             project,
  401.             virtualFile
  402.                 .getNameWithoutExtension()
  403.                 .concat(".")
  404.                 .concat(GlobalData.DISASSEMBLED_FILE_ENDING_HTML),
  405.             GlobalSearchScope.projectScope(project));
  406.     if (!Compiler.make(project) || virtualFilesByName.isEmpty()) {
  407.       // Save the decompiled code to a file
  408.       LocalFileSystem.getInstance()
  409.           .refreshAndFindFileByIoFile(
  410.               prepare(GlobalData.DISASSEMBLED_FILE_ENDING_TAC, virtualFile));
  411.       LocalFileSystem.getInstance()
  412.               .refreshAndFindFileByIoFile(
  413.                       prepare(GlobalData.DISASSEMBLED_FILE_ENDING_JBC, virtualFile));
  414.       return LocalFileSystem.getInstance()
  415.           .refreshAndFindFileByIoFile(
  416.               prepare(GlobalData.DISASSEMBLED_FILE_ENDING_HTML, virtualFile));
  417.     }
  418.     return virtualFilesByName.stream().findFirst().get();
  419.   } // prepareHtml()
  420.  
  421.   public static VirtualFile prepareTAC(
  422.       @NotNull com.intellij.openapi.project.Project project, @NotNull VirtualFile virtualFile) {
  423.     setProject(project);
  424.     Collection<VirtualFile> virtualFilesByName =
  425.         FilenameIndex.getVirtualFilesByName(
  426.             project,
  427.             virtualFile
  428.                 .getNameWithoutExtension()
  429.                 .concat(".")
  430.                 .concat(GlobalData.DISASSEMBLED_FILE_ENDING_TAC),
  431.             GlobalSearchScope.projectScope(project));
  432.     if (!Compiler.make(project) || virtualFilesByName.isEmpty()) {
  433.       LocalFileSystem.getInstance()
  434.           .refreshAndFindFileByIoFile(
  435.               prepare(GlobalData.DISASSEMBLED_FILE_ENDING_HTML, virtualFile));
  436.       LocalFileSystem.getInstance()
  437.               .refreshAndFindFileByIoFile(
  438.                       prepare(GlobalData.DISASSEMBLED_FILE_ENDING_JBC, virtualFile));
  439.       return LocalFileSystem.getInstance()
  440.           .refreshAndFindFileByIoFile(
  441.               prepare(GlobalData.DISASSEMBLED_FILE_ENDING_TAC, virtualFile));
  442.     }
  443.     return virtualFilesByName.stream().findFirst().get();
  444.   }
  445.  
  446.   // this should be called by constructor
  447.   public static VirtualFile prepareJBC(@NotNull com.intellij.openapi.project.Project project, @NotNull VirtualFile virtualFile) {
  448.     setProject(project);
  449.     Collection<VirtualFile> virtualFilesByName =
  450.             FilenameIndex.getVirtualFilesByName(
  451.                     project,
  452.                     virtualFile
  453.                             .getNameWithoutExtension()
  454.                             .concat(".")
  455.                             .concat(GlobalData.DISASSEMBLED_FILE_ENDING_JBC),
  456.                     GlobalSearchScope.projectScope(project));
  457.     if (!Compiler.make(project) || virtualFilesByName.isEmpty()) {
  458.       LocalFileSystem.getInstance()
  459.               .refreshAndFindFileByIoFile(
  460.                       prepare(GlobalData.DISASSEMBLED_FILE_ENDING_HTML, virtualFile));
  461.       LocalFileSystem.getInstance()
  462.               .refreshAndFindFileByIoFile(
  463.                       prepare(GlobalData.DISASSEMBLED_FILE_ENDING_TAC, virtualFile));
  464.       return LocalFileSystem.getInstance()
  465.               .refreshAndFindFileByIoFile(
  466.                       prepare(GlobalData.DISASSEMBLED_FILE_ENDING_JBC, virtualFile));
  467.     }
  468.  
  469.     return virtualFilesByName.stream().findFirst().get();
  470.   }
  471.  
  472.   // todo SaveFile Class erweitern?
  473.   private static File prepare(@NotNull String prepareID, VirtualFile virtualFile) {
  474.     String basePath = project.getBasePath();
  475.     classPath = virtualFile.getParent().getPath();
  476.     String absPath =
  477.         basePath
  478.             + File.separator
  479.             + GlobalData.DISASSEMBLED_FILES_DIR
  480.             + classPath.substring(basePath.length());
  481.  
  482.     String fileName = virtualFile.getNameWithoutExtension();
  483.     String representableForm = null;
  484.     ClassFile classFile;
  485.     switch (prepareID) {
  486.       case GlobalData.DISASSEMBLED_FILE_ENDING_HTML:
  487.         fileName = fileName.concat(".").concat(GlobalData.DISASSEMBLED_FILE_ENDING_HTML);
  488.         representableForm = Opal.JavaClassToHtmlForm(virtualFile);
  489.         break;
  490.       case GlobalData.DISASSEMBLED_FILE_ENDING_TAC:
  491.         fileName = fileName.concat(".").concat(GlobalData.DISASSEMBLED_FILE_ENDING_TAC);
  492.         classFile = getClassFile(virtualFile);
  493.         representableForm = Opal.JavaClassToTACForm(classFile, virtualFile.getPath());
  494.         break;
  495.       case GlobalData.DISASSEMBLED_FILE_ENDING_JBC:
  496.         fileName = fileName.concat(".").concat(GlobalData.DISASSEMBLED_FILE_ENDING_JBC);
  497.         classFile = getClassFile(virtualFile);
  498.         representableForm = Opal.createBytecodeString(classFile);
  499.         break;
  500.     }
  501.  
  502.     File disassembledFile = new File(absPath + File.separator + fileName);
  503.     writeContentToFile(disassembledFile, representableForm, false);
  504.     return disassembledFile;
  505.   }
  506.  
  507.  
  508.   /**
  509.    * an auxiliary method that writes 'content' to a 'file'
  510.    * (main purpose of this method is to encapsulate the try/catch block)
  511.    *
  512.    * @param file    file to write to
  513.    * @param content content to write into the file
  514.    */
  515.   private static void writeContentToFile(File file, String content, boolean append) {
  516.     try {
  517.       FileUtil.writeToFile(file, content, append);
  518.     } catch(IOException e) {
  519.       e.printStackTrace();
  520.     }
  521.   }
  522.  
  523. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement