com.caucho.loader.enhancer.EnhancerFixup Maven / Gradle / Ivy
/*
* Copyright (c) 1998-2018 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.loader.enhancer;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.caucho.bytecode.Analyzer;
import com.caucho.bytecode.Attribute;
import com.caucho.bytecode.ByteCodeParser;
import com.caucho.bytecode.CodeAttribute;
import com.caucho.bytecode.CodeEnhancer;
import com.caucho.bytecode.CodeVisitor;
import com.caucho.bytecode.ConstantPool;
import com.caucho.bytecode.ConstantPoolEntry;
import com.caucho.bytecode.JClass;
import com.caucho.bytecode.JMethod;
import com.caucho.bytecode.JavaClass;
import com.caucho.bytecode.JavaClassLoader;
import com.caucho.bytecode.JavaField;
import com.caucho.bytecode.JavaMethod;
import com.caucho.bytecode.MethodRefConstant;
import com.caucho.bytecode.Utf8Constant;
import com.caucho.inject.Module;
import com.caucho.java.WorkDir;
import com.caucho.loader.DynamicClassLoader;
import com.caucho.vfs.JarPath;
import com.caucho.vfs.Path;
import com.caucho.vfs.ReadStream;
import com.caucho.vfs.Vfs;
import com.caucho.vfs.WriteStream;
/**
* Class loader which checks for changes in class files and automatically
* picks up new jars.
*
* DynamicClassLoaders can be chained creating one virtual class loader.
* From the perspective of the JDK, it's all one classloader. Internally,
* the class loader chain searches like a classpath.
*/
@Module
public class EnhancerFixup {
private static final Logger log = Logger.getLogger(EnhancerFixup.class.getName());
private static final int ACC_PUBLIC = 0x1;
private static final int ACC_PRIVATE = 0x2;
private static final int ACC_PROTECTED = 0x4;
private JavaClassLoader _jClassLoader;
private DynamicClassLoader _loader;
private Path _workPath;
private String _baseSuffix = "";
private String _extSuffix = "__ResinExt";
private ArrayList _enhancerList =
new ArrayList();
private boolean _isParentStarted;
/**
* Sets the class loader.
*/
public void setClassLoader(DynamicClassLoader loader)
{
_loader = loader;
}
/**
* Returns the parsed class loader.
*/
public void setJavaClassLoader(JavaClassLoader jClassLoader)
{
_jClassLoader = jClassLoader;
}
/**
* Returns the parsed class loader.
*/
public JavaClassLoader getJavaClassLoader()
{
return _jClassLoader;
}
/**
* Gets the work path.
*/
public Path getWorkPath()
{
if (_workPath != null)
return _workPath;
else
return WorkDir.getLocalWorkDir();
}
/**
* Sets the work path.
*/
public void setWorkPath(Path workPath)
{
_workPath = workPath;
}
/**
* Gets the work path.
*/
public final Path getPreWorkPath()
{
return getWorkPath().lookup("pre-enhance");
}
/**
* Gets the work path.
*/
public final Path getPostWorkPath()
{
return getWorkPath().lookup("post-enhance");
}
/**
* Adds a class enhancer.
*/
public void addEnhancer(ClassEnhancer enhancer)
{
_enhancerList.add(enhancer);
}
protected void fixup(String className, String extClassName)
throws Exception
{
Path prePath = getPreWorkPath();
Path postPath = getPostWorkPath();
Path source = getSource(className);
if (source == null || ! source.canRead())
return;
Path ext = prePath.lookup(extClassName.replace('.', '/') + ".class");
Path target = postPath.lookup(className.replace('.', '/') + ".class");
try {
target.getParent().mkdirs();
} catch (Exception e) {
log.log(Level.FINER, e.toString(), e);
}
if (source != null)
mergeClasses(className, target, source, ext);
else
mergeClasses(className, target, ext);
int p = className.lastIndexOf('.');
Path preTargetDir;
Path targetDir;
String classSuffix;
String prefix = "";
if (p > 0) {
prefix = className.substring(0, p).replace('.', '/');
preTargetDir = prePath.lookup(prefix);
targetDir = postPath.lookup(prefix);
classSuffix = className.substring(p + 1);
}
else {
preTargetDir = prePath;
targetDir = postPath;
classSuffix = className;
}
prefix = prefix.replace('/', '.');
if (! prefix.equals(""))
prefix = prefix + ".";
String extSuffix;
p = extClassName.lastIndexOf('.');
if (p > 0)
extSuffix = extClassName.substring(p + 1);
else
extSuffix = extClassName;
fixupPreSubClasses(preTargetDir, targetDir,
extSuffix, classSuffix);
fixupPostSubClasses(targetDir, prefix, classSuffix);
}
private void fixupPreSubClasses(Path preTargetDir, Path targetDir,
String extSuffix, String classSuffix)
throws Exception
{
String []list = preTargetDir.list();
for (int i = 0; i < list.length; i++) {
String name = list[i];
if (name.startsWith(extSuffix + '$') &&
name.endsWith(".class")) {
int p = name.indexOf('$');
String targetClass = (classSuffix + '$' +
name.substring(p + 1, name.length() - 6));
Path subTarget = targetDir.lookup(targetClass + ".class");
Path extPath = preTargetDir.lookup(name);
renameSubClass(classSuffix, subTarget, extPath);
//if (_loader != null)
// _loader.addPathClass(prefix + targetClass, subTarget);
}
else if (name.startsWith(extSuffix + '-') &&
name.endsWith(".class")) {
int p = name.indexOf('-');
String targetClass = (classSuffix + '-' +
name.substring(p + 1, name.length() - 6));
Path subTarget = targetDir.lookup(targetClass + ".class");
Path extPath = preTargetDir.lookup(name);
renameSubClass(classSuffix, subTarget, extPath);
//if (_loader != null)
// _loader.addPathClass(prefix + targetClass, subTarget);
}
}
}
private void fixupPostSubClasses(Path targetDir,
String prefix,
String classSuffix)
throws Exception
{
String []list = targetDir.list();
for (int i = 0; i < list.length; i++) {
String name = list[i];
if (! name.endsWith(".class"))
continue;
String className = name.substring(0, name.length() - ".class".length());
if (name.startsWith(classSuffix + '$')) {
if (_loader != null)
_loader.addPathClass(prefix + className, targetDir.lookup(name));
}
else if (name.startsWith(classSuffix + '-')) {
if (_loader != null)
_loader.addPathClass(prefix + className, targetDir.lookup(name));
}
else if (name.startsWith(classSuffix + '+')) {
if (_loader != null)
_loader.addPathClass(prefix + className, targetDir.lookup(name));
}
}
}
/**
* Merges the two classes.
*/
protected void renameSubClass(String className,
Path targetPath,
Path extPath)
throws Exception
{
JavaClass extClass = null;
ByteCodeParser parser = new ByteCodeParser();
parser = new ByteCodeParser();
parser.setClassLoader(new JavaClassLoader());
ReadStream is = extPath.openRead();
try {
extClass = parser.parse(is);
} finally {
if (is != null)
is.close();
}
cleanExtConstantPool(className, extClass);
WriteStream os = targetPath.openWrite();
try {
extClass.write(os);
} finally {
os.close();
}
}
/**
* Renamed the super() methods
*/
protected void renameExtSuperMethods(String className,
JavaClass baseClass,
JavaClass extClass)
throws Exception
{
ArrayList entries;
entries = extClass.getConstantPool().getEntries();
className = className.replace('.', '/');
String baseName = className + _baseSuffix;
String extName = className + "__ResinExt";
for (int i = 0; i < entries.size(); i++) {
ConstantPoolEntry entry = entries.get(i);
if (entry instanceof MethodRefConstant) {
MethodRefConstant methodRef = (MethodRefConstant) entry;
if (! methodRef.getClassName().equals(baseName))
continue;
String methodName = methodRef.getName();
String type = methodRef.getType();
if (findMethod(baseClass, methodName, type) == null)
continue;
if (findMethod(extClass, methodName, type) == null)
continue;
if (methodName.equals("")) {
methodName = "__init__super";
// methodRef.setNameAndType(methodName, type);
}
/* jpa/0h28, shouldn't automatically change this
else {
methodName = methodName + "__super";
methodRef.setNameAndType(methodName, type);
}
*/
}
}
}
/**
* Moves all methods in the base to the __super methods
*/
private void moveSuperMethods(String className,
JavaClass baseClass,
JavaClass extClass)
{
className = className.replace('.', '/');
ArrayList methods = baseClass.getMethodList();
// Move the __super methods
ArrayList extMethods = extClass.getMethodList();
for (int i = 0; i < extMethods.size(); i++) {
JavaMethod extMethod = extMethods.get(i);
fixupExtMethod(baseClass, extClass, extMethod);
String baseName = extMethod.getName();
if (baseName.endsWith("__super"))
continue;
String superName = baseName + "__super";
int j;
for (j = 0; j < methods.size(); j++) {
JavaMethod method = methods.get(j);
String type = method.getDescriptor();
if (! method.getName().equals(baseName)
|| ! method.getDescriptor().equals(extMethod.getDescriptor()))
continue;
if (baseName.equals("")) {
baseClass.getConstantPool().addUTF8("__init__super");
mergeInitMethods(baseClass, method, extClass, extMethod);
break;
}
if (baseName.equals("")) {
concatenateMethods(baseClass, method, extClass, extMethod);
break;
}
baseClass.getConstantPool().addUTF8(superName);
method.setName(superName);
baseClass.getConstantPool().addUTF8(type);
method.setDescriptor(type);
// set the super methods private
int flags = method.getAccessFlags();
flags = (flags & ~ACC_PUBLIC & ~ACC_PROTECTED) | ACC_PRIVATE;
method.setAccessFlags(flags);
break;
}
}
}
/**
* Concatenates methods
*/
private void concatenateMethods(JavaClass baseClass, JavaMethod baseMethod,
JavaClass extClass, JavaMethod extMethod)
{
extMethod = extMethod.export(extClass, baseClass);
baseMethod.concatenate(extMethod);
}
/**
* Merges the init methods
*/
private void mergeInitMethods(JavaClass baseClass, JavaMethod baseMethod,
JavaClass extClass, JavaMethod extMethod)
{
extMethod = extMethod.export(extClass, baseClass);
baseMethod.setName("__init__super");
baseClass.getMethodList().add(extMethod);
try {
InitAnalyzer initAnalyzer = new InitAnalyzer();
CodeEnhancer baseEnhancer = new CodeEnhancer(baseClass, baseMethod.getCode());
baseEnhancer.analyze(initAnalyzer);
int offset = initAnalyzer.getOffset();
byte []code = new byte[offset];
byte []oldCode = baseEnhancer.getCode();
System.arraycopy(oldCode, 0, code, 0, offset);
baseEnhancer.remove(0, offset);
baseEnhancer.update();
CodeEnhancer extEnhancer = new CodeEnhancer(baseClass, extMethod.getCode());
extEnhancer.add(0, code, 0, code.length);
ExtMethodAnalyzer extMethodAnalyzer
= new ExtMethodAnalyzer(baseClass, extMethod, offset);
extEnhancer.analyze(extMethodAnalyzer);
extEnhancer.update();
CodeAttribute baseCode = baseMethod.getCode();
CodeAttribute extCode = extMethod.getCode();
if (extCode.getMaxStack() < baseCode.getMaxStack())
extCode.setMaxStack(baseCode.getMaxStack());
// XXX: needs tests badly
extCode.removeAttribute("LocalVariableTable");
extCode.removeAttribute("LineNumberTable");
baseCode.removeAttribute("LocalVariableTable");
baseCode.removeAttribute("LineNumberTable");
/*
baseMethod.concatenate(extMethod);
*/
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Merges the init methods
*/
private void fixupExtMethod(JavaClass baseClass,
JavaClass extClass,
JavaMethod extMethod)
{
try {
if (extMethod.getName().endsWith("__super"))
return;
CodeEnhancer extEnhancer
= new CodeEnhancer(extClass, extMethod.getCode());
ExtMethodAnalyzer extMethodAnalyzer
= new ExtMethodAnalyzer(baseClass, extMethod, 0);
extEnhancer.analyze(extMethodAnalyzer);
extEnhancer.update();
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Adds the methods from the ext to the base
*/
private void addExtInterfaces(JavaClass baseClass, JavaClass extClass)
{
for (String name : extClass.getInterfaceNames()) {
baseClass.getConstantPool().addClass(name);
baseClass.addInterface(name);
}
}
/**
* Adds the methods from the ext to the base
*/
private void addExtMethods(JavaClass baseClass, JavaClass extClass)
{
ArrayList methods = baseClass.getMethodList();
ArrayList extMethods = extClass.getMethodList();
for (int i = 0; i < extMethods.size(); i++) {
JavaMethod extMethod = extMethods.get(i);
if (extMethod.getName().equals("") &&
findMethod(baseClass, "",
extMethod.getDescriptor()) != null) {
continue;
}
else if (extMethod.getName().equals(""))
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 methods = baseClass.getMethodList();
ArrayList extMethods = extClass.getMethodList();
for (int i = 0; i < extMethods.size(); i++) {
JavaMethod extMethod = extMethods.get(i);
if (extMethod.getName().equals("") &&
findMethod(baseClass, "",
extMethod.getDescriptor()) != null) {
continue;
}
else if (extMethod.getName().equals(""))
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 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 fields = baseClass.getFieldList();
ArrayList 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
// jpa/0g0s, #3574
String s = URLDecoder.decode(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(s);
}
/**
* 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 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 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 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 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("")
&& (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("")
&& (! ref.getClassName().equals(jClass.getSuperClassName())
|| ! _method.getName().equals(""))) {
return;
}
else if (! ref.getName().equals("")) {
// 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(""))
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;
}
}
}
}