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 + -
显示快捷键?