enhancerfixup.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 1,033 行 · 第 1/2 页

JAVA
1,033
字号
      baseClass.addInterface(name);    }  }  /**   * Adds the methods from the ext to the base   */  private void addExtMethods(JavaClass baseClass, JavaClass extClass)  {    ArrayList<JavaMethod> methods = baseClass.getMethodList();    ArrayList<JavaMethod> extMethods = extClass.getMethodList();    for (int i = 0; i < extMethods.size(); i++) {      JavaMethod extMethod = extMethods.get(i);      if (extMethod.getName().equals("<clinit>") &&          findMethod(baseClass, "<clinit>",                     extMethod.getDescriptor()) != null) {        continue;      }      else if (extMethod.getName().equals("<init>"))        continue;      else if (extMethod.getName().endsWith("__super"))        continue;      log.finest("adding extension method: " + extClass.getThisClass() + ":" + extMethod.getName());      JavaMethod method = extMethod.export(extClass, baseClass);      methods.add(method);    }  }  /**   * Adds the inner classes from the ext to the base   */  private void addExtClasses(JavaClass baseClass, JavaClass extClass)  {    /*      ArrayList<JavaMethod> methods = baseClass.getMethodList();      ArrayList<JavaMethod> extMethods = extClass.getMethodList();      for (int i = 0; i < extMethods.size(); i++) {      JavaMethod extMethod = extMethods.get(i);      if (extMethod.getName().equals("<clinit>") &&      findMethod(baseClass, "<clinit>",      extMethod.getDescriptor()) != null) {      continue;      }      else if (extMethod.getName().equals("<init>"))      continue;      else if (extMethod.getName().endsWith("__super"))      continue;      log.finest("adding extension method: " + extClass.getThisClass() + ":" + extMethod.getName());      JavaMethod method = extMethod.export(extClass, baseClass);      methods.add(method);      }    */  }  /**   * Finds a matching method.   */  private static JavaMethod findMethod(JavaClass cl,				       String name,				       String descriptor)  {    ArrayList<JavaMethod> methods = cl.getMethodList();    int j;    for (j = 0; j < methods.size(); j++) {      JavaMethod method = methods.get(j);      if (method.getName().equals(name) &&          method.getDescriptor().equals(descriptor))        return method;    }    return null;  }  /**   * Adds all fields from the ext to the base   */  private void moveSuperFields(JavaClass baseClass, JavaClass extClass)  {    ArrayList<JavaField> fields = baseClass.getFieldList();    ArrayList<JavaField> extFields = extClass.getFieldList();    for (int i = 0; i < extFields.size(); i++) {    }  }  private Path getSource(String className)  {    ClassLoader loader = _loader;    if (loader == null)      loader = Thread.currentThread().getContextClassLoader();    URL url = loader.getResource(className.replace('.', '/') + ".class");    // XXX: workaround for tck    String s = url.toString();    int index = s.indexOf("jar!/");    if (index > 0) {      s = s.substring(9, index+3);      Path path = JarPath.create(Vfs.lookup(s));      path = path.lookup(className.replace('.', '/') + ".class");      return path;    }    return Vfs.lookup(url.toString());  }  /**   * Merges the two classes.   */  protected void mergeClasses(String className,                              Path targetPath,                              Path sourcePath,                              Path extPath)    throws Exception  {    JavaClass baseClass = null;    JavaClass extClass = null;    ByteCodeParser parser = new ByteCodeParser();    parser.setClassLoader(getJavaClassLoader());    ReadStream is = sourcePath.openRead();    try {      baseClass = parser.parse(is);    } finally {      if (is != null)        is.close();    }    parser = new ByteCodeParser();    parser.setClassLoader(getJavaClassLoader());    is = extPath.openRead();    try {      extClass = parser.parse(is);    } finally {      if (is != null)        is.close();    }    // jpa/0j26    // XXX: later, need to see if it's possible to keep some of this    // information for debugging    fixupLocalVariableTable(extClass);    fixupLocalVariableTable(baseClass);        // The base class will have the modified class    mergeClasses(className, baseClass, extClass);    postEnhance(baseClass);    WriteStream os = targetPath.openWrite();    try {      baseClass.write(os);    } finally {      os.close();    }  }  /**   * Merges the two classes.   */  protected void mergeClasses(String className,                              Path targetPath,                              Path extPath)    throws Exception  {    JavaClass baseClass = null;    JavaClass extClass = null;    ByteCodeParser parser = new ByteCodeParser();    parser.setClassLoader(getJavaClassLoader());    ReadStream is = extPath.openRead();    try {      extClass = parser.parse(is);    } finally {      if (is != null)        is.close();    }    cleanExtConstantPool(className, extClass);    postEnhance(baseClass);    WriteStream os = targetPath.openWrite();    try {      extClass.write(os);    } finally {      os.close();    }  }  /**   * After enhancement fixup.   */  protected void postEnhance(JavaClass baseClass)    throws Exception  {    for (int i = 0; i < _enhancerList.size(); i++) {      _enhancerList.get(i).postEnhance(baseClass);    }    fixupJdk16Methods(baseClass);  }  /**   * Merges the two classes.   */  protected void mergeClasses(String className,                              JavaClass baseClass,                              JavaClass extClass)    throws Exception  {    if (baseClass.getMajor() < extClass.getMajor()) {      baseClass.setMajor(extClass.getMajor());      baseClass.setMinor(extClass.getMinor());    }    cleanExtConstantPool(className, extClass);    renameExtSuperMethods(className, baseClass, extClass);    cleanExtConstantPool(className, baseClass);    addExtInterfaces(baseClass, extClass);    addExtFields(baseClass, extClass);    moveSuperMethods(className, baseClass, extClass);    addExtMethods(baseClass, extClass);    copyExtAnnotations(baseClass);    addExtClasses(baseClass, extClass);  }  /**   * Cleans the ext constant pool, renaming   */  protected void cleanExtConstantPool(String className, JavaClass extClass)    throws Exception  {    extClass.setThisClass(replaceString(className, extClass.getThisClass()));    extClass.setSuperClass(replaceString(className, extClass.getSuperClassName()));    ArrayList<ConstantPoolEntry> entries;    entries = extClass.getConstantPool().getEntries();    int t = className.lastIndexOf('.');    if (t > 0)      className = className.substring(t + 1);    String baseName = className + _baseSuffix;    String extName = className + "__ResinExt";    for (int i = 0; i < entries.size(); i++) {      ConstantPoolEntry entry = entries.get(i);      if (entry instanceof Utf8Constant) {        Utf8Constant utf8 = (Utf8Constant) entry;        String string = utf8.getValue();        string = replaceString(className, string);        utf8.setValue(string);      }    }    ArrayList<JavaField> fields = extClass.getFieldList();    for (int i = 0; i < fields.size(); i++) {      JavaField field = fields.get(i);      field.setName(replaceString(className, field.getName()));      field.setDescriptor(replaceString(className, field.getDescriptor()));    }    ArrayList<JavaMethod> methods = extClass.getMethodList();    for (int i = 0; i < methods.size(); i++) {      JavaMethod method = methods.get(i);      method.setName(replaceString(className, method.getName()));      method.setDescriptor(replaceString(className, method.getDescriptor()));    }  }  /**   * Adds the methods from the ext to the base   */  private void copyExtAnnotations(JavaClass baseClass)  {    for (JavaMethod method : baseClass.getMethodList()) {      if (method.getName().endsWith("__super")) {        Attribute ann = method.getAttribute("RuntimeVisibleAnnotations");        if (ann != null) {          String name = method.getName();          name = name.substring(0, name.length() - "__super".length());          JavaMethod baseMethod;          baseMethod = findMethod(baseClass, name, method.getDescriptor());          if (baseMethod != null)            baseMethod.addAttribute(ann);        }      }    }  }  /**   * Adds the methods from the ext to the base   */  private void addExtFields(JavaClass baseClass, JavaClass extClass)  {    ArrayList<JavaField> fields = baseClass.getFieldList();    for (JavaField extField : extClass.getFieldList()) {      JavaField field = extField.export(extClass, baseClass);      if (! fields.contains(field))        fields.add(field);    }  }  /**   * Remove the StackMapTable   */  private void fixupJdk16Methods(JavaClass baseClass)  {    for (JavaMethod method : baseClass.getMethodList()) {      CodeAttribute code = method.getCode();      code.removeAttribute("StackMapTable");    }  }  /**   * Remove the LocalVariableTable   */  private void fixupLocalVariableTable(JavaClass extClass)  {    for (JavaMethod method : extClass.getMethodList()) {      CodeAttribute code = method.getCode();      code.removeAttribute("LocalVariableTable");      code.removeAttribute("LocalVariableTypeTable");    }  }  private String replaceString(String className, String string)  {    string = replaceStringInt(className.replace('.', '/'), string);    string = replaceStringInt(className.replace('.', '$'), string);    string = replaceStringInt(className.replace('.', '-'), string);    return string;  }  private String replaceStringInt(String className, String string)  {    int t = className.lastIndexOf('.');    if (t > 0)      className = className.substring(t + 1);    String baseName = className + _baseSuffix;    // String extName = className + "__ResinExt";    String extName = "__ResinExt";    int p;    if (! baseName.equals(className)) {      while ((p = string.indexOf(baseName)) >= 0) {        String prefix = string.substring(0, p);        String suffix = string.substring(p + baseName.length());        string = prefix + className + suffix;      }    }    while ((p = string.indexOf(extName)) >= 0) {      String prefix = string.substring(0, p);      String suffix = string.substring(p + extName.length());      // string = prefix + className + suffix;      string = prefix + suffix;    }    return string;  }  private static class InitAnalyzer extends Analyzer {    int _offset = -1;    /**     * Returns the analyzed offset.     */    public int getOffset()    {      return _offset;    }    /**     * Analyzes the opcode.     */    public void analyze(CodeVisitor visitor)      throws Exception    {      if (_offset >= 0)        return;      switch (visitor.getOpcode()) {      case CodeVisitor.INVOKESPECIAL:        JavaClass javaClass = visitor.getJavaClass();        ConstantPool cp = javaClass.getConstantPool();        MethodRefConstant ref = cp.getMethodRef(visitor.getShortArg());        // ejb/0l00        // handler "super()" and "this()"        if (ref.getName().equals("<init>")	    && (ref.getClassName().equals(javaClass.getThisClass())		|| ref.getClassName().equals(javaClass.getSuperClassName()))) {          _offset = visitor.getOffset() + 3;        }        break;      }    }  }  //  // convert super.foo() calls to foo__super() where appropriate  //  private static class ExtMethodAnalyzer extends Analyzer {    JClass _baseClass;    JMethod _method;    int _startOffset;    boolean _isEnhanced;    ExtMethodAnalyzer(JClass baseClass, JMethod method, int length)    {      _baseClass = baseClass;      _method = method;      _startOffset = length;    }    /**     * Analyzes the opcode.     */    public void analyze(CodeVisitor visitor)      throws Exception    {      if (_isEnhanced)        return;      if (visitor.getOffset() < _startOffset)        return;      switch (visitor.getOpcode()) {      case CodeVisitor.INVOKESPECIAL:        int index = visitor.getShortArg();	JavaClass jClass = visitor.getJavaClass();        ConstantPool cp = jClass.getConstantPool();        MethodRefConstant ref;        ref = cp.getMethodRef(index);	if (ref.getName().endsWith("__super")) {	  return;	}	else if (ref.getName().equals("<init>")		 && (! ref.getClassName().equals(jClass.getSuperClassName())		     || ! _method.getName().equals("<init>"))) {	  return;	}	else if (! ref.getName().equals("<init>")) {	  // private methods are called with invokespecial, but shouldn't	  // be modified	  JMethod method = findMethod(jClass,				      ref.getName(),				      ref.getType());	  if (method != null && method.isPrivate())	    return;	}	String superName;        if (ref.getName().equals("<init>"))	  superName = "__init__super";	else	  superName = ref.getName() + "__super";        MethodRefConstant newRef;        newRef = cp.addMethodRef(ref.getClassName(),                                 superName,                                 ref.getType());        visitor.setShortArg(1, newRef.getIndex());        _isEnhanced = true;        break;      }    }  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?