Author: schor
Date: Thu Jun  9 19:15:07 2016
New Revision: 1747584

URL: http://svn.apache.org/viewvc?rev=1747584&view=rev
Log:
[UIMA-4518] fix decompiler to support passed in classpath to use while 
decompiling a byte array.

Modified:
    
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/UimaDecompiler.java

Modified: 
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/UimaDecompiler.java
URL: 
http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/UimaDecompiler.java?rev=1747584&r1=1747583&r2=1747584&view=diff
==============================================================================
--- 
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/UimaDecompiler.java
 (original)
+++ 
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/UimaDecompiler.java
 Thu Jun  9 19:15:07 2016
@@ -28,6 +28,8 @@ import java.io.OutputStreamWriter;
 import java.io.UnsupportedEncodingException;
 import java.nio.file.Path;
 import java.util.Arrays;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.apache.uima.internal.util.Misc;
 
@@ -48,6 +50,7 @@ import com.strobel.decompiler.PlainTextO
  *   Make an instance, optionally setting
  *     - class loader to use (may pass byte array instead)
  *     - directory where to write output (may output to string instead)
+ *     - class loader to use when resolving symbols during decompile
  *   
  *   call decompile
  *     - argument
@@ -78,13 +81,21 @@ public class UimaDecompiler {
     decompilerSettings.setSimplifyMemberReferences(true);
   }
 
-  private final ClassLoader classLoader;
+  private final ClassLoader classLoader; 
   
   private File outputDirectory = null;
   
   public UimaDecompiler() {
     classLoader = null;
   }
+
+  // if you want this  constructor, call the 2 arg constructor, passing null 
as the 2nd arg
+//  public UimaDecompiler(ClassLoader classLoader) {
+//    this.classLoader = classLoader; 
+//    if (classLoader != null) {
+//      setDecompilerSettingsForClassLoader();
+//    }    
+//  }
   
   public UimaDecompiler(ClassLoader classLoader, File outputDirectory) {
     this.classLoader = classLoader;
@@ -94,16 +105,33 @@ public class UimaDecompiler {
     }
   }
     
+  /**
+   * decompile className, and use the byte array passed in instead of getting 
it from the classpath
+   * @param className the dotted name of the class
+   * @param byteArray the compiled definition for this class to decompile
+   * @return the decompilation
+   */
   public ByteArrayOutputStream decompile(String className, byte[] byteArray) {
     setDecompilerSettingsForByteArray(className.replace('.', '/'), byteArray);
     return decompileCommon(className);
   }
   
+  /**
+   * decompile className, getting the compiled version from the classpath
+   * @param className the dotted name of the class
+   * @return the decompilation
+   */
   public ByteArrayOutputStream decompile(String className) {
     setDecompilerSettingsForClassLoader();
     return decompileCommon(className);
   }
   
+  /**
+   * Common part for decompiling to a ByteArrayOutputStream
+   *   the decompiler settings are set up to get the compiled form by name
+   * @param className the class to decompile
+   * @return the decompilation
+   */
   public ByteArrayOutputStream decompileCommon(String className) {
     
     ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -123,9 +151,13 @@ public class UimaDecompiler {
     return baos;
   }
   
+  /** pattern to extract name following class, interface, or enum */
+  private static final Pattern cie_name = Pattern.compile("( class | interface 
| enum )\\s*(\\w*)");
   /**
    * Decompile from the file system, maybe in a Jar.
-   * @param path the Path to the file to decompile
+   * This is a 2 pass operation, usually, to get the classname from the 
decompilation,
+   *   and then redo the decompilation with that extra bit of configuration.
+   * @param b the Path to the file to decompile
    * @return the decompiled form as a string
    */
   public String decompile(byte[] b) {
@@ -145,12 +177,11 @@ public class UimaDecompiler {
       packageName = s.substring(ip, ipe).replace('.', '/') + "/";
     }
     
-    int ic = s.indexOf(" class ");
-    if (ic >= 0) {
-      ic = ic + " class ".length();  // start of class name
-      int ice = s.indexOf(" ", ic);
-      className = s.substring(ic, ice);
-    }
+    Matcher m = cie_name.matcher(s);
+    boolean ok = m.find();
+    className = ok 
+                   ? m.group(2) 
+                   : "";    
     
     String classNameSlashes2 = packageName + className;
     
@@ -201,8 +232,8 @@ public class UimaDecompiler {
         }
       }      
     }; 
-    ITypeLoader tc = new CompositeTypeLoader(tl, new InputTypeLoader());
-    decompilerSettings.setTypeLoader(tl);
+    ITypeLoader tc = new CompositeTypeLoader(tl, getClasspathTypeLoader(), new 
InputTypeLoader());
+    decompilerSettings.setTypeLoader(tc);
   }
     
   public boolean writeIfOk(ByteArrayOutputStream baos, String className) {
@@ -218,17 +249,22 @@ public class UimaDecompiler {
   }
   
   private void setDecompilerSettingsForClassLoader() {
-    ITypeLoader tl = new ITypeLoader() {
+    decompilerSettings.setTypeLoader(getClasspathTypeLoader());
+  }
+  
+  private ITypeLoader getClasspathTypeLoader() {
+    return new ITypeLoader() {
       
       @Override
       public boolean tryLoadType(String internalName, Buffer buffer) {
         
         // read the class as a resource, and put into temporary byte array 
output stream
         // because we need to know the length
-        
+//        System.out.println("debug trying to load " + internalName);
         internalName = internalName.replace('.', '/') + ".class";
         InputStream stream = classLoader.getResourceAsStream(internalName);
         if (stream == null) {
+//          System.out.println("debug failed to load " + internalName);
           return false;
         }
         ByteArrayOutputStream baos = new ByteArrayOutputStream(1024 * 16);     
   
@@ -247,10 +283,9 @@ public class UimaDecompiler {
         b = baos.toByteArray();
         buffer.reset(length);
         System.arraycopy(b, 0, buffer.array(), 0, length);
-        
+//        System.out.println("debug OK loading " + internalName);
         return true;
       }      
     };    
-    decompilerSettings.setTypeLoader(tl);
   }
 }


Reply via email to