The following were applied during multiple itterations through the source. * Parameterize raw types. * Mark unused members. * Annotate override and deprecated methods. * Convert loops to enhance for loop. * Remove redundant else statements. * Widening collection type references. * Optimize code for improved readability. * Squash compiler warnings. * Identify smells.tags/rel_3_23_0_ga
@@ -16,9 +16,10 @@ | |||
package javassist; | |||
import java.io.*; | |||
import java.net.URL; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.InputStream; | |||
import java.net.MalformedURLException; | |||
import java.net.URL; | |||
/** | |||
* A <code>ByteArrayClassPath</code> contains bytes that is served as | |||
@@ -37,7 +38,7 @@ import java.net.MalformedURLException; | |||
* | |||
* <p>The <code>ClassPool</code> object <code>cp</code> uses the created | |||
* <code>ByteArrayClassPath</code> object as the source of the class file. | |||
* | |||
* | |||
* <p>A <code>ByteArrayClassPath</code> must be instantiated for every | |||
* class. It contains only a single class file. | |||
* | |||
@@ -65,8 +66,10 @@ public class ByteArrayClassPath implements ClassPath { | |||
/** | |||
* Closes this class path. | |||
*/ | |||
@Override | |||
public void close() {} | |||
@Override | |||
public String toString() { | |||
return "byte[]:" + classname; | |||
} | |||
@@ -74,16 +77,17 @@ public class ByteArrayClassPath implements ClassPath { | |||
/** | |||
* Opens the class file. | |||
*/ | |||
@Override | |||
public InputStream openClassfile(String classname) { | |||
if(this.classname.equals(classname)) | |||
return new ByteArrayInputStream(classfile); | |||
else | |||
return null; | |||
return null; | |||
} | |||
/** | |||
* Obtains the URL. | |||
*/ | |||
@Override | |||
public URL find(String classname) { | |||
if(this.classname.equals(classname)) { | |||
String cname = classname.replace('.', '/') + ".class"; |
@@ -30,7 +30,8 @@ public class CannotCompileException extends Exception { | |||
* Gets the cause of this throwable. | |||
* It is for JDK 1.3 compatibility. | |||
*/ | |||
public Throwable getCause() { | |||
@Override | |||
public synchronized Throwable getCause() { | |||
return (myCause == this ? null : myCause); | |||
} | |||
@@ -38,6 +39,7 @@ public class CannotCompileException extends Exception { | |||
* Initializes the cause of this throwable. | |||
* It is for JDK 1.3 compatibility. | |||
*/ | |||
@Override | |||
public synchronized Throwable initCause(Throwable cause) { | |||
myCause = cause; | |||
return this; | |||
@@ -51,8 +53,7 @@ public class CannotCompileException extends Exception { | |||
public String getReason() { | |||
if (message != null) | |||
return message; | |||
else | |||
return this.toString(); | |||
return this.toString(); | |||
} | |||
/** |
@@ -19,8 +19,6 @@ package javassist; | |||
import java.io.InputStream; | |||
import java.net.URL; | |||
import javassist.bytecode.ClassFile; | |||
/** | |||
* A search-path for obtaining a class file | |||
* by <code>getResourceAsStream()</code> in <code>java.lang.Class</code>. | |||
@@ -43,13 +41,13 @@ import javassist.bytecode.ClassFile; | |||
* <p>Class files in a named module are private to that module. | |||
* This method cannot obtain class files in named modules. | |||
* </p> | |||
* | |||
* | |||
* @see ClassPool#insertClassPath(ClassPath) | |||
* @see ClassPool#appendClassPath(ClassPath) | |||
* @see LoaderClassPath | |||
*/ | |||
public class ClassClassPath implements ClassPath { | |||
private Class thisClass; | |||
private Class<?> thisClass; | |||
/** Creates a search path. | |||
* | |||
@@ -57,7 +55,7 @@ public class ClassClassPath implements ClassPath { | |||
* file. <code>getResourceAsStream()</code> is called on | |||
* this object. | |||
*/ | |||
public ClassClassPath(Class c) { | |||
public ClassClassPath(Class<?> c) { | |||
thisClass = c; | |||
} | |||
@@ -76,6 +74,7 @@ public class ClassClassPath implements ClassPath { | |||
/** | |||
* Obtains a class file by <code>getResourceAsStream()</code>. | |||
*/ | |||
@Override | |||
public InputStream openClassfile(String classname) throws NotFoundException { | |||
String filename = '/' + classname.replace('.', '/') + ".class"; | |||
return thisClass.getResourceAsStream(filename); | |||
@@ -84,8 +83,9 @@ public class ClassClassPath implements ClassPath { | |||
/** | |||
* Obtains the URL of the specified class file. | |||
* | |||
* @return null if the class file could not be found. | |||
* @return null if the class file could not be found. | |||
*/ | |||
@Override | |||
public URL find(String classname) { | |||
String filename = '/' + classname.replace('.', '/') + ".class"; | |||
return thisClass.getResource(filename); | |||
@@ -94,9 +94,11 @@ public class ClassClassPath implements ClassPath { | |||
/** | |||
* Does nothing. | |||
*/ | |||
@Override | |||
public void close() { | |||
} | |||
@Override | |||
public String toString() { | |||
return thisClass.getName() + ".class"; | |||
} |
@@ -16,6 +16,8 @@ | |||
package javassist; | |||
import java.util.HashMap; | |||
import javassist.bytecode.Descriptor; | |||
/** | |||
@@ -47,7 +49,7 @@ import javassist.bytecode.Descriptor; | |||
* @see CtClass#replaceClassName(ClassMap) | |||
* @see CtNewMethod#copy(CtMethod,String,CtClass,ClassMap) | |||
*/ | |||
public class ClassMap extends java.util.HashMap { | |||
public class ClassMap extends HashMap<String,String> { | |||
/** default serialVersionUID */ | |||
private static final long serialVersionUID = 1L; | |||
private ClassMap parent; | |||
@@ -76,7 +78,7 @@ public class ClassMap extends java.util.HashMap { | |||
/** | |||
* Maps a class name to another name in this hashtable. | |||
* If the hashtable contains another mapping from the same | |||
* class name, the old mapping is replaced. | |||
* class name, the old mapping is replaced. | |||
* This method translates the given class names into the | |||
* internal form used in the JVM before putting it in | |||
* the hashtable. | |||
@@ -91,21 +93,23 @@ public class ClassMap extends java.util.HashMap { | |||
* @param newname the substituted class name. | |||
* @see #fix(String) | |||
*/ | |||
public void put(String oldname, String newname) { | |||
@Override | |||
public String put(String oldname, String newname) { | |||
if (oldname == newname) | |||
return; | |||
return oldname; | |||
String oldname2 = toJvmName(oldname); | |||
String s = (String)get(oldname2); | |||
String s = get(oldname2); | |||
if (s == null || !s.equals(oldname2)) | |||
super.put(oldname2, toJvmName(newname)); | |||
return super.put(oldname2, toJvmName(newname)); | |||
return s; | |||
} | |||
/** | |||
* Is equivalent to <code>put()</code> except that | |||
* the given mapping is not recorded into the hashtable | |||
* if another mapping from <code>oldname</code> is | |||
* already included. | |||
* already included. | |||
* | |||
* @param oldname the original class name. | |||
* @param newname the substituted class name. | |||
@@ -115,13 +119,13 @@ public class ClassMap extends java.util.HashMap { | |||
return; | |||
String oldname2 = toJvmName(oldname); | |||
String s = (String)get(oldname2); | |||
String s = get(oldname2); | |||
if (s == null) | |||
super.put(oldname2, toJvmName(newname)); | |||
} | |||
protected final void put0(Object oldname, Object newname) { | |||
super.put(oldname, newname); | |||
protected final String put0(String oldname, String newname) { | |||
return super.put(oldname, newname); | |||
} | |||
/** | |||
@@ -134,14 +138,13 @@ public class ClassMap extends java.util.HashMap { | |||
* @see #toJvmName(String) | |||
* @see #toJavaName(String) | |||
*/ | |||
public Object get(Object jvmClassName) { | |||
Object found = super.get(jvmClassName); | |||
@Override | |||
public String get(Object jvmClassName) { | |||
String found = super.get(jvmClassName); | |||
if (found == null && parent != null) | |||
return parent.get(jvmClassName); | |||
else | |||
return found; | |||
return found; | |||
} | |||
/** | |||
* Prevents a mapping from the specified class name to another name. | |||
*/ |
@@ -39,7 +39,7 @@ public interface ClassPath { | |||
* | |||
* <p>This method can return null if the specified class file is not | |||
* found. If null is returned, the next search path is examined. | |||
* However, if an error happens, this method must throw an exception | |||
* However, if an error happens, this method must throw an exception | |||
* so that the search will be terminated. | |||
* | |||
* <p>This method should not modify the contents of the class file. |
@@ -45,6 +45,7 @@ final class DirClassPath implements ClassPath { | |||
directory = dirName; | |||
} | |||
@Override | |||
public InputStream openClassfile(String classname) { | |||
try { | |||
char sep = File.separatorChar; | |||
@@ -57,6 +58,7 @@ final class DirClassPath implements ClassPath { | |||
return null; | |||
} | |||
@Override | |||
public URL find(String classname) { | |||
char sep = File.separatorChar; | |||
String filename = directory + sep | |||
@@ -72,8 +74,10 @@ final class DirClassPath implements ClassPath { | |||
return null; | |||
} | |||
@Override | |||
public void close() {} | |||
@Override | |||
public String toString() { | |||
return directory; | |||
} | |||
@@ -84,6 +88,7 @@ final class JarDirClassPath implements ClassPath { | |||
JarDirClassPath(String dirName) throws NotFoundException { | |||
File[] files = new File(dirName).listFiles(new FilenameFilter() { | |||
@Override | |||
public boolean accept(File dir, String name) { | |||
name = name.toLowerCase(); | |||
return name.endsWith(".jar") || name.endsWith(".zip"); | |||
@@ -97,6 +102,7 @@ final class JarDirClassPath implements ClassPath { | |||
} | |||
} | |||
@Override | |||
public InputStream openClassfile(String classname) throws NotFoundException { | |||
if (jars != null) | |||
for (int i = 0; i < jars.length; i++) { | |||
@@ -108,6 +114,7 @@ final class JarDirClassPath implements ClassPath { | |||
return null; // not found | |||
} | |||
@Override | |||
public URL find(String classname) { | |||
if (jars != null) | |||
for (int i = 0; i < jars.length; i++) { | |||
@@ -119,6 +126,7 @@ final class JarDirClassPath implements ClassPath { | |||
return null; // not found | |||
} | |||
@Override | |||
public void close() { | |||
if (jars != null) | |||
for (int i = 0; i < jars.length; i++) | |||
@@ -141,6 +149,7 @@ final class JarClassPath implements ClassPath { | |||
throw new NotFoundException(pathname); | |||
} | |||
@Override | |||
public InputStream openClassfile(String classname) | |||
throws NotFoundException | |||
{ | |||
@@ -149,14 +158,14 @@ final class JarClassPath implements ClassPath { | |||
JarEntry je = jarfile.getJarEntry(jarname); | |||
if (je != null) | |||
return jarfile.getInputStream(je); | |||
else | |||
return null; // not found | |||
return null; // not found | |||
} | |||
catch (IOException e) {} | |||
throw new NotFoundException("broken jar file?: " | |||
+ jarfile.getName()); | |||
} | |||
@Override | |||
public URL find(String classname) { | |||
String jarname = classname.replace('.', '/') + ".class"; | |||
JarEntry je = jarfile.getJarEntry(jarname); | |||
@@ -169,6 +178,7 @@ final class JarClassPath implements ClassPath { | |||
return null; // not found | |||
} | |||
@Override | |||
public void close() { | |||
try { | |||
jarfile.close(); | |||
@@ -177,6 +187,7 @@ final class JarClassPath implements ClassPath { | |||
catch (IOException e) {} | |||
} | |||
@Override | |||
public String toString() { | |||
return jarfile == null ? "<null>" : jarfile.toString(); | |||
} | |||
@@ -189,6 +200,7 @@ final class ClassPoolTail { | |||
pathList = null; | |||
} | |||
@Override | |||
public String toString() { | |||
StringBuffer buf = new StringBuffer(); | |||
buf.append("[class path: "); | |||
@@ -242,10 +254,8 @@ final class ClassPoolTail { | |||
public ClassPath appendSystemPath() { | |||
if (javassist.bytecode.ClassFile.MAJOR_VERSION < javassist.bytecode.ClassFile.JAVA_9) | |||
return appendClassPath(new ClassClassPath()); | |||
else { | |||
ClassLoader cl = Thread.currentThread().getContextClassLoader(); | |||
return appendClassPath(new LoaderClassPath(cl)); | |||
} | |||
ClassLoader cl = Thread.currentThread().getContextClassLoader(); | |||
return appendClassPath(new LoaderClassPath(cl)); | |||
} | |||
public ClassPath insertClassPath(String pathname) | |||
@@ -346,8 +356,7 @@ final class ClassPoolTail { | |||
if (error != null) | |||
throw error; | |||
else | |||
return null; // not found | |||
return null; // not found | |||
} | |||
/** |
@@ -666,6 +666,7 @@ public class CodeConverter { | |||
* Returns "arrayReadByteOrBoolean" as the name of the static method with the signature | |||
* (Ljava/lang/Object;I)B to replace reading from a byte[]. | |||
*/ | |||
@Override | |||
public String byteOrBooleanRead() | |||
{ | |||
return "arrayReadByteOrBoolean"; | |||
@@ -675,6 +676,7 @@ public class CodeConverter { | |||
* Returns "arrayWriteByteOrBoolean" as the name of the static method with the signature | |||
* (Ljava/lang/Object;IB)V to replace writing to a byte[]. | |||
*/ | |||
@Override | |||
public String byteOrBooleanWrite() | |||
{ | |||
return "arrayWriteByteOrBoolean"; | |||
@@ -684,6 +686,7 @@ public class CodeConverter { | |||
* Returns "arrayReadChar" as the name of the static method with the signature | |||
* (Ljava/lang/Object;I)C to replace reading from a char[]. | |||
*/ | |||
@Override | |||
public String charRead() | |||
{ | |||
return "arrayReadChar"; | |||
@@ -693,6 +696,7 @@ public class CodeConverter { | |||
* Returns "arrayWriteChar" as the name of the static method with the signature | |||
* (Ljava/lang/Object;IC)V to replace writing to a byte[]. | |||
*/ | |||
@Override | |||
public String charWrite() | |||
{ | |||
return "arrayWriteChar"; | |||
@@ -702,6 +706,7 @@ public class CodeConverter { | |||
* Returns "arrayReadDouble" as the name of the static method with the signature | |||
* (Ljava/lang/Object;I)D to replace reading from a double[]. | |||
*/ | |||
@Override | |||
public String doubleRead() | |||
{ | |||
return "arrayReadDouble"; | |||
@@ -711,6 +716,7 @@ public class CodeConverter { | |||
* Returns "arrayWriteDouble" as the name of the static method with the signature | |||
* (Ljava/lang/Object;ID)V to replace writing to a double[]. | |||
*/ | |||
@Override | |||
public String doubleWrite() | |||
{ | |||
return "arrayWriteDouble"; | |||
@@ -720,6 +726,7 @@ public class CodeConverter { | |||
* Returns "arrayReadFloat" as the name of the static method with the signature | |||
* (Ljava/lang/Object;I)F to replace reading from a float[]. | |||
*/ | |||
@Override | |||
public String floatRead() | |||
{ | |||
return "arrayReadFloat"; | |||
@@ -729,6 +736,7 @@ public class CodeConverter { | |||
* Returns "arrayWriteFloat" as the name of the static method with the signature | |||
* (Ljava/lang/Object;IF)V to replace writing to a float[]. | |||
*/ | |||
@Override | |||
public String floatWrite() | |||
{ | |||
return "arrayWriteFloat"; | |||
@@ -738,6 +746,7 @@ public class CodeConverter { | |||
* Returns "arrayReadInt" as the name of the static method with the signature | |||
* (Ljava/lang/Object;I)I to replace reading from a int[]. | |||
*/ | |||
@Override | |||
public String intRead() | |||
{ | |||
return "arrayReadInt"; | |||
@@ -747,6 +756,7 @@ public class CodeConverter { | |||
* Returns "arrayWriteInt" as the name of the static method with the signature | |||
* (Ljava/lang/Object;II)V to replace writing to a int[]. | |||
*/ | |||
@Override | |||
public String intWrite() | |||
{ | |||
return "arrayWriteInt"; | |||
@@ -756,6 +766,7 @@ public class CodeConverter { | |||
* Returns "arrayReadLong" as the name of the static method with the signature | |||
* (Ljava/lang/Object;I)J to replace reading from a long[]. | |||
*/ | |||
@Override | |||
public String longRead() | |||
{ | |||
return "arrayReadLong"; | |||
@@ -765,6 +776,7 @@ public class CodeConverter { | |||
* Returns "arrayWriteLong" as the name of the static method with the signature | |||
* (Ljava/lang/Object;IJ)V to replace writing to a long[]. | |||
*/ | |||
@Override | |||
public String longWrite() | |||
{ | |||
return "arrayWriteLong"; | |||
@@ -774,6 +786,7 @@ public class CodeConverter { | |||
* Returns "arrayReadObject" as the name of the static method with the signature | |||
* (Ljava/lang/Object;I)Ljava/lang/Object; to replace reading from a Object[] (or any subclass of object). | |||
*/ | |||
@Override | |||
public String objectRead() | |||
{ | |||
return "arrayReadObject"; | |||
@@ -783,6 +796,7 @@ public class CodeConverter { | |||
* Returns "arrayWriteObject" as the name of the static method with the signature | |||
* (Ljava/lang/Object;ILjava/lang/Object;)V to replace writing to a Object[] (or any subclass of object). | |||
*/ | |||
@Override | |||
public String objectWrite() | |||
{ | |||
return "arrayWriteObject"; | |||
@@ -792,6 +806,7 @@ public class CodeConverter { | |||
* Returns "arrayReadShort" as the name of the static method with the signature | |||
* (Ljava/lang/Object;I)S to replace reading from a short[]. | |||
*/ | |||
@Override | |||
public String shortRead() | |||
{ | |||
return "arrayReadShort"; | |||
@@ -801,6 +816,7 @@ public class CodeConverter { | |||
* Returns "arrayWriteShort" as the name of the static method with the signature | |||
* (Ljava/lang/Object;IS)V to replace writing to a short[]. | |||
*/ | |||
@Override | |||
public String shortWrite() | |||
{ | |||
return "arrayWriteShort"; |
@@ -19,26 +19,34 @@ package javassist; | |||
/** | |||
* Array types. | |||
*/ | |||
final class CtArray extends CtClass { | |||
final class CtArray extends CtClass | |||
{ | |||
protected ClassPool pool; | |||
// the name of array type ends with "[]". | |||
CtArray(String name, ClassPool cp) { | |||
CtArray(String name, ClassPool cp) | |||
{ | |||
super(name); | |||
pool = cp; | |||
} | |||
public ClassPool getClassPool() { | |||
@Override | |||
public ClassPool getClassPool() | |||
{ | |||
return pool; | |||
} | |||
public boolean isArray() { | |||
@Override | |||
public boolean isArray() | |||
{ | |||
return true; | |||
} | |||
private CtClass[] interfaces = null; | |||
public int getModifiers() { | |||
@Override | |||
public int getModifiers() | |||
{ | |||
int mod = Modifier.FINAL; | |||
try { | |||
mod |= getComponentType().getModifiers() | |||
@@ -48,9 +56,11 @@ final class CtArray extends CtClass { | |||
return mod; | |||
} | |||
public CtClass[] getInterfaces() throws NotFoundException { | |||
@Override | |||
public CtClass[] getInterfaces() throws NotFoundException | |||
{ | |||
if (interfaces == null) { | |||
Class[] intfs = Object[].class.getInterfaces(); | |||
Class<?>[] intfs = Object[].class.getInterfaces(); | |||
// java.lang.Cloneable and java.io.Serializable. | |||
// If the JVM is CLDC, intfs is empty. | |||
interfaces = new CtClass[intfs.length]; | |||
@@ -61,7 +71,9 @@ final class CtArray extends CtClass { | |||
return interfaces; | |||
} | |||
public boolean subtypeOf(CtClass clazz) throws NotFoundException { | |||
@Override | |||
public boolean subtypeOf(CtClass clazz) throws NotFoundException | |||
{ | |||
if (super.subtypeOf(clazz)) | |||
return true; | |||
@@ -78,16 +90,22 @@ final class CtArray extends CtClass { | |||
&& getComponentType().subtypeOf(clazz.getComponentType()); | |||
} | |||
public CtClass getComponentType() throws NotFoundException { | |||
@Override | |||
public CtClass getComponentType() throws NotFoundException | |||
{ | |||
String name = getName(); | |||
return pool.get(name.substring(0, name.length() - 2)); | |||
} | |||
public CtClass getSuperclass() throws NotFoundException { | |||
@Override | |||
public CtClass getSuperclass() throws NotFoundException | |||
{ | |||
return pool.get(javaLangObject); | |||
} | |||
public CtMethod[] getMethods() { | |||
@Override | |||
public CtMethod[] getMethods() | |||
{ | |||
try { | |||
return getSuperclass().getMethods(); | |||
} | |||
@@ -96,13 +114,16 @@ final class CtArray extends CtClass { | |||
} | |||
} | |||
@Override | |||
public CtMethod getMethod(String name, String desc) | |||
throws NotFoundException | |||
{ | |||
return getSuperclass().getMethod(name, desc); | |||
} | |||
public CtConstructor[] getConstructors() { | |||
@Override | |||
public CtConstructor[] getConstructors() | |||
{ | |||
try { | |||
return getSuperclass().getConstructors(); | |||
} |
@@ -81,6 +81,7 @@ public abstract class CtBehavior extends CtMember { | |||
} | |||
} | |||
@Override | |||
protected void extendToString(StringBuffer buffer) { | |||
buffer.append(' '); | |||
buffer.append(getName()); | |||
@@ -140,6 +141,7 @@ public abstract class CtBehavior extends CtMember { | |||
* <code>javassist.Modifier</code>. | |||
* @see Modifier | |||
*/ | |||
@Override | |||
public int getModifiers() { | |||
return AccessFlag.toModifier(methodInfo.getAccessFlags()); | |||
} | |||
@@ -153,6 +155,7 @@ public abstract class CtBehavior extends CtMember { | |||
* | |||
* @see Modifier | |||
*/ | |||
@Override | |||
public void setModifiers(int mod) { | |||
declaringClass.checkModify(); | |||
methodInfo.setAccessFlags(AccessFlag.of(mod)); | |||
@@ -166,6 +169,7 @@ public abstract class CtBehavior extends CtMember { | |||
* otherwise <code>false</code>. | |||
* @since 3.21 | |||
*/ | |||
@Override | |||
public boolean hasAnnotation(String typeName) { | |||
MethodInfo mi = getMethodInfo2(); | |||
AnnotationsAttribute ainfo = (AnnotationsAttribute) | |||
@@ -188,7 +192,8 @@ public abstract class CtBehavior extends CtMember { | |||
* @return the annotation if found, otherwise <code>null</code>. | |||
* @since 3.11 | |||
*/ | |||
public Object getAnnotation(Class clz) throws ClassNotFoundException { | |||
@Override | |||
public Object getAnnotation(Class<?> clz) throws ClassNotFoundException { | |||
MethodInfo mi = getMethodInfo2(); | |||
AnnotationsAttribute ainfo = (AnnotationsAttribute) | |||
mi.getAttribute(AnnotationsAttribute.invisibleTag); | |||
@@ -206,6 +211,7 @@ public abstract class CtBehavior extends CtMember { | |||
* @see #getAvailableAnnotations() | |||
* @since 3.1 | |||
*/ | |||
@Override | |||
public Object[] getAnnotations() throws ClassNotFoundException { | |||
return getAnnotations(false); | |||
} | |||
@@ -219,6 +225,7 @@ public abstract class CtBehavior extends CtMember { | |||
* @see #getAnnotations() | |||
* @since 3.3 | |||
*/ | |||
@Override | |||
public Object[] getAvailableAnnotations(){ | |||
try{ | |||
return getAnnotations(true); | |||
@@ -324,6 +331,7 @@ public abstract class CtBehavior extends CtMember { | |||
* @see javassist.bytecode.Descriptor | |||
* @see #getGenericSignature() | |||
*/ | |||
@Override | |||
public String getSignature() { | |||
return methodInfo.getDescriptor(); | |||
} | |||
@@ -335,6 +343,7 @@ public abstract class CtBehavior extends CtMember { | |||
* @see SignatureAttribute#toMethodSignature(String) | |||
* @since 3.17 | |||
*/ | |||
@Override | |||
public String getGenericSignature() { | |||
SignatureAttribute sa | |||
= (SignatureAttribute)methodInfo.getAttribute(SignatureAttribute.tag); | |||
@@ -351,6 +360,7 @@ public abstract class CtBehavior extends CtMember { | |||
* @see javassist.bytecode.SignatureAttribute.MethodSignature#encode() | |||
* @since 3.17 | |||
*/ | |||
@Override | |||
public void setGenericSignature(String sig) { | |||
declaringClass.checkModify(); | |||
methodInfo.addAttribute(new SignatureAttribute(methodInfo.getConstPool(), sig)); | |||
@@ -489,12 +499,13 @@ public abstract class CtBehavior extends CtMember { | |||
* | |||
* @param name attribute name | |||
*/ | |||
public byte[] getAttribute(String name) { | |||
@Override | |||
public byte[] getAttribute(String name) | |||
{ | |||
AttributeInfo ai = methodInfo.getAttribute(name); | |||
if (ai == null) | |||
return null; | |||
else | |||
return ai.get(); | |||
return ai.get(); | |||
} | |||
/** | |||
@@ -507,7 +518,9 @@ public abstract class CtBehavior extends CtMember { | |||
* @param name attribute name | |||
* @param data attribute value | |||
*/ | |||
public void setAttribute(String name, byte[] data) { | |||
@Override | |||
public void setAttribute(String name, byte[] data) | |||
{ | |||
declaringClass.checkModify(); | |||
methodInfo.addAttribute(new AttributeInfo(methodInfo.getConstPool(), | |||
name, data)); | |||
@@ -530,7 +543,8 @@ public abstract class CtBehavior extends CtMember { | |||
* | |||
* @see javassist.runtime.Cflow | |||
*/ | |||
public void useCflow(String name) throws CannotCompileException { | |||
public void useCflow(String name) throws CannotCompileException | |||
{ | |||
CtClass cc = declaringClass; | |||
cc.checkModify(); | |||
ClassPool pool = cc.getClassPool(); |
@@ -198,6 +198,7 @@ public abstract class CtClass { | |||
/** | |||
* Converts the object to a string. | |||
*/ | |||
@Override | |||
public String toString() { | |||
StringBuffer buf = new StringBuffer(getClass().getName()); | |||
buf.append("@"); | |||
@@ -361,8 +362,7 @@ public abstract class CtClass { | |||
int index = qname.lastIndexOf('.'); | |||
if (index < 0) | |||
return qname; | |||
else | |||
return qname.substring(index + 1); | |||
return qname.substring(index + 1); | |||
} | |||
/** | |||
@@ -373,8 +373,7 @@ public abstract class CtClass { | |||
int index = qname.lastIndexOf('.'); | |||
if (index < 0) | |||
return null; | |||
else | |||
return qname.substring(0, index); | |||
return qname.substring(0, index); | |||
} | |||
/** | |||
@@ -517,30 +516,30 @@ public abstract class CtClass { | |||
* | |||
* @return a <code>Collection<String></code> object. | |||
*/ | |||
public synchronized Collection getRefClasses() { | |||
public synchronized Collection<String> getRefClasses() { | |||
ClassFile cf = getClassFile2(); | |||
if (cf != null) { | |||
ClassMap cm = new ClassMap() { | |||
/** default serialVersionUID */ | |||
private static final long serialVersionUID = 1L; | |||
public void put(String oldname, String newname) { | |||
put0(oldname, newname); | |||
@Override | |||
public String put(String oldname, String newname) { | |||
return put0(oldname, newname); | |||
} | |||
public Object get(Object jvmClassName) { | |||
@Override | |||
public String get(Object jvmClassName) { | |||
String n = toJavaName((String)jvmClassName); | |||
put0(n, n); | |||
return null; | |||
} | |||
@Override | |||
public void fix(String name) {} | |||
}; | |||
cf.getRefClasses(cm); | |||
return cm.values(); | |||
} | |||
else | |||
return null; | |||
return null; | |||
} | |||
/** | |||
@@ -591,7 +590,7 @@ public abstract class CtClass { | |||
* @return <code>true</code> if the annotation is found, otherwise <code>false</code>. | |||
* @since 3.11 | |||
*/ | |||
public boolean hasAnnotation(Class annotationType) { | |||
public boolean hasAnnotation(Class<?> annotationType) { | |||
return hasAnnotation(annotationType.getName()); | |||
} | |||
@@ -617,7 +616,7 @@ public abstract class CtClass { | |||
* @return the annotation if found, otherwise <code>null</code>. | |||
* @since 3.11 | |||
*/ | |||
public Object getAnnotation(Class clz) throws ClassNotFoundException { | |||
public Object getAnnotation(Class<?> clz) throws ClassNotFoundException { | |||
return null; | |||
} | |||
@@ -785,6 +784,7 @@ public abstract class CtClass { | |||
* Use {@link #getEnclosingBehavior()}. | |||
* @see #getEnclosingBehavior() | |||
*/ | |||
@Deprecated | |||
public final CtMethod getEnclosingMethod() throws NotFoundException { | |||
CtBehavior b = getEnclosingBehavior(); | |||
if (b == null) | |||
@@ -1274,7 +1274,7 @@ public abstract class CtClass { | |||
* @see #toClass(java.lang.ClassLoader,ProtectionDomain) | |||
* @see ClassPool#toClass(CtClass) | |||
*/ | |||
public Class toClass() throws CannotCompileException { | |||
public Class<?> toClass() throws CannotCompileException { | |||
return getClassPool().toClass(this); | |||
} | |||
@@ -1309,7 +1309,7 @@ public abstract class CtClass { | |||
* @see ClassPool#toClass(CtClass,java.lang.ClassLoader) | |||
* @since 3.3 | |||
*/ | |||
public Class toClass(ClassLoader loader, ProtectionDomain domain) | |||
public Class<?> toClass(ClassLoader loader, ProtectionDomain domain) | |||
throws CannotCompileException | |||
{ | |||
ClassPool cp = getClassPool(); | |||
@@ -1328,7 +1328,8 @@ public abstract class CtClass { | |||
* | |||
* @deprecated Replaced by {@link #toClass(ClassLoader,ProtectionDomain)} | |||
*/ | |||
public final Class toClass(ClassLoader loader) | |||
@Deprecated | |||
public final Class<?> toClass(ClassLoader loader) | |||
throws CannotCompileException | |||
{ | |||
return getClassPool().toClass(this, loader); | |||
@@ -1547,27 +1548,32 @@ public abstract class CtClass { | |||
file = new FileOutputStream(filename); | |||
} | |||
@Override | |||
public void write(int b) throws IOException { | |||
init(); | |||
file.write(b); | |||
} | |||
@Override | |||
public void write(byte[] b) throws IOException { | |||
init(); | |||
file.write(b); | |||
} | |||
@Override | |||
public void write(byte[] b, int off, int len) throws IOException { | |||
init(); | |||
file.write(b, off, len); | |||
} | |||
@Override | |||
public void flush() throws IOException { | |||
init(); | |||
file.flush(); | |||
} | |||
@Override | |||
public void close() throws IOException { | |||
init(); | |||
file.close(); |
@@ -16,6 +16,7 @@ | |||
package javassist; | |||
import java.lang.ref.Reference; | |||
import java.lang.ref.WeakReference; | |||
import java.io.BufferedInputStream; | |||
import java.io.ByteArrayOutputStream; | |||
@@ -29,6 +30,7 @@ import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import java.util.Hashtable; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Set; | |||
import javassist.bytecode.AccessFlag; | |||
@@ -55,7 +57,7 @@ import javassist.compiler.Javac; | |||
import javassist.expr.ExprEditor; | |||
/** | |||
* Class types. | |||
* Class<?> types. | |||
*/ | |||
class CtClassType extends CtClass { | |||
ClassPool classPool; | |||
@@ -66,11 +68,11 @@ class CtClassType extends CtClass { | |||
ClassFile classfile; | |||
byte[] rawClassfile; // backup storage | |||
private WeakReference memberCache; | |||
private Reference<CtMember.Cache> memberCache; | |||
private AccessorMaker accessors; | |||
private FieldInitLink fieldInitializers; | |||
private Hashtable hiddenMethods; // must be synchronous | |||
private Map<CtMethod,String> hiddenMethods; // must be synchronous | |||
private int uniqueNumberSeed; | |||
private boolean doPruning = ClassPool.doPruning; | |||
@@ -103,6 +105,7 @@ class CtClassType extends CtClass { | |||
qualifiedName = classfile.getName(); | |||
} | |||
@Override | |||
protected void extendToString(StringBuffer buffer) { | |||
if (wasChanged) | |||
buffer.append("changed "); | |||
@@ -162,6 +165,7 @@ class CtClassType extends CtClass { | |||
} | |||
} | |||
@Override | |||
public AccessorMaker getAccessorMaker() { | |||
if (accessors == null) | |||
accessors = new AccessorMaker(this); | |||
@@ -169,6 +173,7 @@ class CtClassType extends CtClass { | |||
return accessors; | |||
} | |||
@Override | |||
public ClassFile getClassFile2() { | |||
return getClassFile3(true); | |||
} | |||
@@ -229,6 +234,7 @@ class CtClassType extends CtClass { | |||
* @see javassist.CtClass#incGetCounter() | |||
* @see #toBytecode(DataOutputStream) | |||
*/ | |||
@Override | |||
final void incGetCounter() { ++getCount; } | |||
/** | |||
@@ -236,6 +242,7 @@ class CtClassType extends CtClass { | |||
* It releases the class files that have not been recently used | |||
* if they are unmodified. | |||
*/ | |||
@Override | |||
void compress() { | |||
if (getCount < GET_THRESHOLD) | |||
if (!isModified() && ClassPool.releaseUnmodifiedClassFile) | |||
@@ -282,24 +289,29 @@ class CtClassType extends CtClass { | |||
return classfile; | |||
} | |||
@Override | |||
public ClassPool getClassPool() { return classPool; } | |||
void setClassPool(ClassPool cp) { classPool = cp; } | |||
@Override | |||
public URL getURL() throws NotFoundException { | |||
URL url = classPool.find(getName()); | |||
if (url == null) | |||
throw new NotFoundException(getName()); | |||
else | |||
return url; | |||
return url; | |||
} | |||
@Override | |||
public boolean isModified() { return wasChanged; } | |||
@Override | |||
public boolean isFrozen() { return wasFrozen; } | |||
@Override | |||
public void freeze() { wasFrozen = true; } | |||
@Override | |||
void checkModify() throws RuntimeException { | |||
if (isFrozen()) { | |||
String msg = getName() + " class is frozen"; | |||
@@ -312,11 +324,13 @@ class CtClassType extends CtClass { | |||
wasChanged = true; | |||
} | |||
@Override | |||
public void defrost() { | |||
checkPruned("defrost"); | |||
wasFrozen = false; | |||
} | |||
@Override | |||
public boolean subtypeOf(CtClass clazz) throws NotFoundException { | |||
int i; | |||
String cname = clazz.getName(); | |||
@@ -344,6 +358,7 @@ class CtClassType extends CtClass { | |||
return false; | |||
} | |||
@Override | |||
public void setName(String name) throws RuntimeException { | |||
String oldname = getName(); | |||
if (name.equals(oldname)) | |||
@@ -358,24 +373,27 @@ class CtClassType extends CtClass { | |||
classPool.classNameChanged(oldname, this); | |||
} | |||
@Override | |||
public String getGenericSignature() { | |||
SignatureAttribute sa | |||
= (SignatureAttribute)getClassFile2().getAttribute(SignatureAttribute.tag); | |||
return sa == null ? null : sa.getSignature(); | |||
} | |||
@Override | |||
public void setGenericSignature(String sig) { | |||
ClassFile cf = getClassFile(); | |||
SignatureAttribute sa = new SignatureAttribute(cf.getConstPool(), sig); | |||
cf.addAttribute(sa); | |||
} | |||
@Override | |||
public void replaceClassName(ClassMap classnames) | |||
throws RuntimeException | |||
{ | |||
String oldClassName = getName(); | |||
String newClassName | |||
= (String)classnames.get(Descriptor.toJvmName(oldClassName)); | |||
= classnames.get(Descriptor.toJvmName(oldClassName)); | |||
if (newClassName != null) { | |||
newClassName = Descriptor.toJavaName(newClassName); | |||
// check this in advance although classNameChanged() below does. | |||
@@ -393,6 +411,7 @@ class CtClassType extends CtClass { | |||
} | |||
} | |||
@Override | |||
public void replaceClassName(String oldname, String newname) | |||
throws RuntimeException | |||
{ | |||
@@ -406,18 +425,22 @@ class CtClassType extends CtClass { | |||
} | |||
} | |||
@Override | |||
public boolean isInterface() { | |||
return Modifier.isInterface(getModifiers()); | |||
} | |||
@Override | |||
public boolean isAnnotation() { | |||
return Modifier.isAnnotation(getModifiers()); | |||
} | |||
@Override | |||
public boolean isEnum() { | |||
return Modifier.isEnum(getModifiers()); | |||
} | |||
@Override | |||
public int getModifiers() { | |||
ClassFile cf = getClassFile2(); | |||
int acc = cf.getAccessFlags(); | |||
@@ -429,6 +452,7 @@ class CtClassType extends CtClass { | |||
return AccessFlag.toModifier(acc); | |||
} | |||
@Override | |||
public CtClass[] getNestedClasses() throws NotFoundException { | |||
ClassFile cf = getClassFile2(); | |||
InnerClassesAttribute ica | |||
@@ -438,7 +462,7 @@ class CtClassType extends CtClass { | |||
String thisName = cf.getName() + "$"; | |||
int n = ica.tableLength(); | |||
ArrayList list = new ArrayList(n); | |||
List<CtClass> list = new ArrayList<CtClass>(n); | |||
for (int i = 0; i < n; i++) { | |||
String name = ica.innerClass(i); | |||
if (name != null) | |||
@@ -449,9 +473,10 @@ class CtClassType extends CtClass { | |||
} | |||
} | |||
return (CtClass[])list.toArray(new CtClass[list.size()]); | |||
return list.toArray(new CtClass[list.size()]); | |||
} | |||
@Override | |||
public void setModifiers(int mod) { | |||
checkModify(); | |||
updateInnerEntry(mod, getName(), this, true); | |||
@@ -495,7 +520,7 @@ class CtClassType extends CtClass { | |||
+ " into a static class"); | |||
} | |||
//@Override | |||
@Override | |||
public boolean hasAnnotation(String annotationName) { | |||
ClassFile cf = getClassFile2(); | |||
AnnotationsAttribute ainfo = (AnnotationsAttribute) | |||
@@ -508,7 +533,8 @@ class CtClassType extends CtClass { | |||
/** | |||
* @deprecated | |||
*/ | |||
static boolean hasAnnotationType(Class clz, ClassPool cp, | |||
@Deprecated | |||
static boolean hasAnnotationType(Class<?> clz, ClassPool cp, | |||
AnnotationsAttribute a1, | |||
AnnotationsAttribute a2) | |||
{ | |||
@@ -544,7 +570,8 @@ class CtClassType extends CtClass { | |||
return false; | |||
} | |||
public Object getAnnotation(Class clz) throws ClassNotFoundException { | |||
@Override | |||
public Object getAnnotation(Class<?> clz) throws ClassNotFoundException { | |||
ClassFile cf = getClassFile2(); | |||
AnnotationsAttribute ainfo = (AnnotationsAttribute) | |||
cf.getAttribute(AnnotationsAttribute.invisibleTag); | |||
@@ -553,7 +580,7 @@ class CtClassType extends CtClass { | |||
return getAnnotationType(clz, getClassPool(), ainfo, ainfo2); | |||
} | |||
static Object getAnnotationType(Class clz, ClassPool cp, | |||
static Object getAnnotationType(Class<?> clz, ClassPool cp, | |||
AnnotationsAttribute a1, AnnotationsAttribute a2) | |||
throws ClassNotFoundException | |||
{ | |||
@@ -583,10 +610,12 @@ class CtClassType extends CtClass { | |||
return null; | |||
} | |||
@Override | |||
public Object[] getAnnotations() throws ClassNotFoundException { | |||
return getAnnotations(false); | |||
} | |||
@Override | |||
public Object[] getAvailableAnnotations(){ | |||
try { | |||
return getAnnotations(true); | |||
@@ -642,23 +671,19 @@ class CtClassType extends CtClass { | |||
return result; | |||
} | |||
else{ | |||
ArrayList annotations = new ArrayList(); | |||
for (int i = 0 ; i < size1 ; i++){ | |||
try{ | |||
annotations.add(toAnnoType(anno1[i], cp)); | |||
} | |||
catch(ClassNotFoundException e){} | |||
} | |||
for (int j = 0; j < size2; j++) { | |||
try{ | |||
annotations.add(toAnnoType(anno2[j], cp)); | |||
} | |||
catch(ClassNotFoundException e){} | |||
} | |||
List<Object> annotations = new ArrayList<Object>(); | |||
for (int i = 0 ; i < size1 ; i++) | |||
try{ | |||
annotations.add(toAnnoType(anno1[i], cp)); | |||
} | |||
catch(ClassNotFoundException e){} | |||
for (int j = 0; j < size2; j++) | |||
try{ | |||
annotations.add(toAnnoType(anno2[j], cp)); | |||
} | |||
catch(ClassNotFoundException e){} | |||
return annotations.toArray(); | |||
} | |||
return annotations.toArray(); | |||
} | |||
static Object[][] toAnnotationType(boolean ignoreNotFound, ClassPool cp, | |||
@@ -707,7 +732,7 @@ class CtClassType extends CtClass { | |||
result[i][j + size1] = toAnnoType(anno2[j], cp); | |||
} | |||
else{ | |||
ArrayList annotations = new ArrayList(); | |||
List<Object> annotations = new ArrayList<Object>(); | |||
for (int j = 0 ; j < size1 ; j++){ | |||
try{ | |||
annotations.add(toAnnoType(anno1[j], cp)); | |||
@@ -742,7 +767,7 @@ class CtClassType extends CtClass { | |||
} | |||
catch (ClassNotFoundException e2){ | |||
try { | |||
Class clazz = cp.get(anno.getTypeName()).toClass(); | |||
Class<?> clazz = cp.get(anno.getTypeName()).toClass(); | |||
return javassist.bytecode.annotation.AnnotationImpl.make( | |||
clazz.getClassLoader(), | |||
clazz, cp, anno); | |||
@@ -754,6 +779,7 @@ class CtClassType extends CtClass { | |||
} | |||
} | |||
@Override | |||
public boolean subclassOf(CtClass superclass) { | |||
if (superclass == null) | |||
return false; | |||
@@ -772,14 +798,15 @@ class CtClassType extends CtClass { | |||
return false; | |||
} | |||
@Override | |||
public CtClass getSuperclass() throws NotFoundException { | |||
String supername = getClassFile2().getSuperclass(); | |||
if (supername == null) | |||
return null; | |||
else | |||
return classPool.get(supername); | |||
return classPool.get(supername); | |||
} | |||
@Override | |||
public void setSuperclass(CtClass clazz) throws CannotCompileException { | |||
checkModify(); | |||
if (isInterface()) | |||
@@ -788,6 +815,7 @@ class CtClassType extends CtClass { | |||
getClassFile2().setSuperclass(clazz.getName()); | |||
} | |||
@Override | |||
public CtClass[] getInterfaces() throws NotFoundException { | |||
String[] ifs = getClassFile2().getInterfaces(); | |||
int num = ifs.length; | |||
@@ -798,6 +826,7 @@ class CtClassType extends CtClass { | |||
return ifc; | |||
} | |||
@Override | |||
public void setInterfaces(CtClass[] list) { | |||
checkModify(); | |||
String[] ifs; | |||
@@ -813,12 +842,14 @@ class CtClassType extends CtClass { | |||
getClassFile2().setInterfaces(ifs); | |||
} | |||
@Override | |||
public void addInterface(CtClass anInterface) { | |||
checkModify(); | |||
if (anInterface != null) | |||
getClassFile2().addInterface(anInterface.getName()); | |||
} | |||
@Override | |||
public CtClass getDeclaringClass() throws NotFoundException { | |||
ClassFile cf = getClassFile2(); | |||
InnerClassesAttribute ica = (InnerClassesAttribute)cf.getAttribute( | |||
@@ -833,39 +864,41 @@ class CtClassType extends CtClass { | |||
String outName = ica.outerClass(i); | |||
if (outName != null) | |||
return classPool.get(outName); | |||
else { | |||
// maybe anonymous or local class. | |||
EnclosingMethodAttribute ema | |||
= (EnclosingMethodAttribute)cf.getAttribute( | |||
EnclosingMethodAttribute.tag); | |||
if (ema != null) | |||
return classPool.get(ema.className()); | |||
} | |||
// maybe anonymous or local class. | |||
EnclosingMethodAttribute ema | |||
= (EnclosingMethodAttribute)cf.getAttribute( | |||
EnclosingMethodAttribute.tag); | |||
if (ema != null) | |||
return classPool.get(ema.className()); | |||
} | |||
return null; | |||
} | |||
public CtBehavior getEnclosingBehavior() throws NotFoundException { | |||
@Override | |||
public CtBehavior getEnclosingBehavior() throws NotFoundException | |||
{ | |||
ClassFile cf = getClassFile2(); | |||
EnclosingMethodAttribute ema | |||
= (EnclosingMethodAttribute)cf.getAttribute( | |||
EnclosingMethodAttribute.tag); | |||
if (ema == null) | |||
return null; | |||
else { | |||
CtClass enc = classPool.get(ema.className()); | |||
String name = ema.methodName(); | |||
if (MethodInfo.nameInit.equals(name)) | |||
return enc.getConstructor(ema.methodDescriptor()); | |||
else if(MethodInfo.nameClinit.equals(name)) | |||
return enc.getClassInitializer(); | |||
else | |||
return enc.getMethod(name, ema.methodDescriptor()); | |||
} | |||
CtClass enc = classPool.get(ema.className()); | |||
String name = ema.methodName(); | |||
if (MethodInfo.nameInit.equals(name)) | |||
return enc.getConstructor(ema.methodDescriptor()); | |||
else if(MethodInfo.nameClinit.equals(name)) | |||
return enc.getClassInitializer(); | |||
else | |||
return enc.getMethod(name, ema.methodDescriptor()); | |||
} | |||
public CtClass makeNestedClass(String name, boolean isStatic) { | |||
@Override | |||
public CtClass makeNestedClass(String name, boolean isStatic) | |||
{ | |||
if (!isStatic) | |||
throw new RuntimeException( | |||
"sorry, only nested static class is supported"); | |||
@@ -905,60 +938,47 @@ class CtClassType extends CtClass { | |||
* Returns null if members are not cached. | |||
*/ | |||
protected CtMember.Cache hasMemberCache() { | |||
WeakReference cache = memberCache; | |||
if (cache != null) | |||
return (CtMember.Cache)cache.get(); | |||
else | |||
return null; | |||
if (memberCache != null) | |||
return memberCache.get(); | |||
return null; | |||
} | |||
protected synchronized CtMember.Cache getMembers() { | |||
CtMember.Cache cache = null; | |||
if (memberCache == null | |||
|| (cache = (CtMember.Cache)memberCache.get()) == null) { | |||
|| (cache = memberCache.get()) == null) { | |||
cache = new CtMember.Cache(this); | |||
makeFieldCache(cache); | |||
makeBehaviorCache(cache); | |||
memberCache = new WeakReference(cache); | |||
memberCache = new WeakReference<CtMember.Cache>(cache); | |||
} | |||
return cache; | |||
} | |||
private void makeFieldCache(CtMember.Cache cache) { | |||
List list = getClassFile3(false).getFields(); | |||
int n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
FieldInfo finfo = (FieldInfo)list.get(i); | |||
CtField newField = new CtField(finfo, this); | |||
cache.addField(newField); | |||
} | |||
List<FieldInfo> fields = getClassFile3(false).getFields(); | |||
for (FieldInfo finfo:fields) | |||
cache.addField(new CtField(finfo, this)); | |||
} | |||
private void makeBehaviorCache(CtMember.Cache cache) { | |||
List list = getClassFile3(false).getMethods(); | |||
int n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
MethodInfo minfo = (MethodInfo)list.get(i); | |||
if (minfo.isMethod()) { | |||
CtMethod newMethod = new CtMethod(minfo, this); | |||
cache.addMethod(newMethod); | |||
} | |||
else { | |||
CtConstructor newCons = new CtConstructor(minfo, this); | |||
cache.addConstructor(newCons); | |||
} | |||
} | |||
List<MethodInfo> methods = getClassFile3(false).getMethods(); | |||
for (MethodInfo minfo:methods) | |||
if (minfo.isMethod()) | |||
cache.addMethod(new CtMethod(minfo, this)); | |||
else | |||
cache.addConstructor(new CtConstructor(minfo, this)); | |||
} | |||
@Override | |||
public CtField[] getFields() { | |||
ArrayList alist = new ArrayList(); | |||
List<CtMember> alist = new ArrayList<CtMember>(); | |||
getFields(alist, this); | |||
return (CtField[])alist.toArray(new CtField[alist.size()]); | |||
return alist.toArray(new CtField[alist.size()]); | |||
} | |||
private static void getFields(ArrayList alist, CtClass cc) { | |||
int i, num; | |||
private static void getFields(List<CtMember> alist, CtClass cc) { | |||
if (cc == null) | |||
return; | |||
@@ -969,9 +989,8 @@ class CtClassType extends CtClass { | |||
try { | |||
CtClass[] ifs = cc.getInterfaces(); | |||
num = ifs.length; | |||
for (i = 0; i < num; ++i) | |||
getFields(alist, ifs[i]); | |||
for (CtClass ctc : ifs) | |||
getFields(alist, ctc); | |||
} | |||
catch (NotFoundException e) {} | |||
@@ -985,6 +1004,7 @@ class CtClassType extends CtClass { | |||
} | |||
} | |||
@Override | |||
public CtField getField(String name, String desc) throws NotFoundException { | |||
CtField f = getField2(name, desc); | |||
return checkGetField(f, name, desc); | |||
@@ -1000,10 +1020,10 @@ class CtClassType extends CtClass { | |||
throw new NotFoundException(msg + " in " + getName()); | |||
} | |||
else | |||
return f; | |||
return f; | |||
} | |||
@Override | |||
CtField getField2(String name, String desc) { | |||
CtField df = getDeclaredField2(name, desc); | |||
if (df != null) | |||
@@ -1011,9 +1031,8 @@ class CtClassType extends CtClass { | |||
try { | |||
CtClass[] ifs = getInterfaces(); | |||
int num = ifs.length; | |||
for (int i = 0; i < num; ++i) { | |||
CtField f = ifs[i].getField2(name, desc); | |||
for (CtClass ctc : ifs) { | |||
CtField f = ctc.getField2(name, desc); | |||
if (f != null) | |||
return f; | |||
} | |||
@@ -1026,6 +1045,7 @@ class CtClassType extends CtClass { | |||
return null; | |||
} | |||
@Override | |||
public CtField[] getDeclaredFields() { | |||
CtMember.Cache memCache = getMembers(); | |||
CtMember field = memCache.fieldHead(); | |||
@@ -1041,10 +1061,12 @@ class CtClassType extends CtClass { | |||
return cfs; | |||
} | |||
@Override | |||
public CtField getDeclaredField(String name) throws NotFoundException { | |||
return getDeclaredField(name, null); | |||
} | |||
@Override | |||
public CtField getDeclaredField(String name, String desc) throws NotFoundException { | |||
CtField f = getDeclaredField2(name, desc); | |||
return checkGetField(f, name, desc); | |||
@@ -1064,6 +1086,7 @@ class CtClassType extends CtClass { | |||
return null; | |||
} | |||
@Override | |||
public CtBehavior[] getDeclaredBehaviors() { | |||
CtMember.Cache memCache = getMembers(); | |||
CtMember cons = memCache.consHead(); | |||
@@ -1088,6 +1111,7 @@ class CtClassType extends CtClass { | |||
return cb; | |||
} | |||
@Override | |||
public CtConstructor[] getConstructors() { | |||
CtMember.Cache memCache = getMembers(); | |||
CtMember cons = memCache.consHead(); | |||
@@ -1119,6 +1143,7 @@ class CtClassType extends CtClass { | |||
&& cons.isConstructor(); | |||
} | |||
@Override | |||
public CtConstructor getConstructor(String desc) | |||
throws NotFoundException | |||
{ | |||
@@ -1137,6 +1162,7 @@ class CtClassType extends CtClass { | |||
return super.getConstructor(desc); | |||
} | |||
@Override | |||
public CtConstructor[] getDeclaredConstructors() { | |||
CtMember.Cache memCache = getMembers(); | |||
CtMember cons = memCache.consHead(); | |||
@@ -1164,6 +1190,7 @@ class CtClassType extends CtClass { | |||
return result; | |||
} | |||
@Override | |||
public CtConstructor getClassInitializer() { | |||
CtMember.Cache memCache = getMembers(); | |||
CtMember cons = memCache.consHead(); | |||
@@ -1179,18 +1206,18 @@ class CtClassType extends CtClass { | |||
return null; | |||
} | |||
@Override | |||
public CtMethod[] getMethods() { | |||
HashMap h = new HashMap(); | |||
Map<String,CtMember> h = new HashMap<String,CtMember>(); | |||
getMethods0(h, this); | |||
return (CtMethod[])h.values().toArray(new CtMethod[h.size()]); | |||
return h.values().toArray(new CtMethod[h.size()]); | |||
} | |||
private static void getMethods0(HashMap h, CtClass cc) { | |||
private static void getMethods0(Map<String,CtMember> h, CtClass cc) { | |||
try { | |||
CtClass[] ifs = cc.getInterfaces(); | |||
int size = ifs.length; | |||
for (int i = 0; i < size; ++i) | |||
getMethods0(h, ifs[i]); | |||
for (CtClass ctc : ifs) | |||
getMethods0(h, ctc); | |||
} | |||
catch (NotFoundException e) {} | |||
@@ -1214,15 +1241,15 @@ class CtClassType extends CtClass { | |||
} | |||
} | |||
@Override | |||
public CtMethod getMethod(String name, String desc) | |||
throws NotFoundException | |||
{ | |||
CtMethod m = getMethod0(this, name, desc); | |||
if (m != null) | |||
return m; | |||
else | |||
throw new NotFoundException(name + "(..) is not found in " | |||
+ getName()); | |||
throw new NotFoundException(name + "(..) is not found in " | |||
+ getName()); | |||
} | |||
private static CtMethod getMethod0(CtClass cc, | |||
@@ -1252,9 +1279,8 @@ class CtClassType extends CtClass { | |||
try { | |||
CtClass[] ifs = cc.getInterfaces(); | |||
int size = ifs.length; | |||
for (int i = 0; i < size; ++i) { | |||
CtMethod m = getMethod0(ifs[i], name, desc); | |||
for (CtClass ctc : ifs) { | |||
CtMethod m = getMethod0(ctc, name, desc); | |||
if (m != null) | |||
return m; | |||
} | |||
@@ -1263,35 +1289,36 @@ class CtClassType extends CtClass { | |||
return null; | |||
} | |||
@Override | |||
public CtMethod[] getDeclaredMethods() { | |||
CtMember.Cache memCache = getMembers(); | |||
CtMember mth = memCache.methodHead(); | |||
CtMember mthTail = memCache.lastMethod(); | |||
int num = CtMember.Cache.count(mth, mthTail); | |||
CtMethod[] cms = new CtMethod[num]; | |||
int i = 0; | |||
List<CtMember> methods = new ArrayList<CtMember>(); | |||
while (mth != mthTail) { | |||
mth = mth.next(); | |||
cms[i++] = (CtMethod)mth; | |||
methods.add(mth); | |||
} | |||
return cms; | |||
return methods.toArray(new CtMethod[methods.size()]); | |||
} | |||
@Override | |||
public CtMethod[] getDeclaredMethods(String name) throws NotFoundException { | |||
CtMember.Cache memCache = getMembers(); | |||
CtMember mth = memCache.methodHead(); | |||
CtMember mthTail = memCache.lastMethod(); | |||
ArrayList methods = new ArrayList(); | |||
List<CtMember> methods = new ArrayList<CtMember>(); | |||
while (mth != mthTail) { | |||
mth = mth.next(); | |||
if (mth.getName().equals(name)) | |||
methods.add((CtMethod)mth); | |||
methods.add(mth); | |||
} | |||
return (CtMethod[]) methods.toArray(new CtMethod[methods.size()]); | |||
return methods.toArray(new CtMethod[methods.size()]); | |||
} | |||
@Override | |||
public CtMethod getDeclaredMethod(String name) throws NotFoundException { | |||
CtMember.Cache memCache = getMembers(); | |||
CtMember mth = memCache.methodHead(); | |||
@@ -1306,6 +1333,7 @@ class CtClassType extends CtClass { | |||
+ getName()); | |||
} | |||
@Override | |||
public CtMethod getDeclaredMethod(String name, CtClass[] params) | |||
throws NotFoundException | |||
{ | |||
@@ -1325,12 +1353,14 @@ class CtClassType extends CtClass { | |||
+ getName()); | |||
} | |||
@Override | |||
public void addField(CtField f, String init) | |||
throws CannotCompileException | |||
{ | |||
addField(f, CtField.Initializer.byExpr(init)); | |||
} | |||
@Override | |||
public void addField(CtField f, CtField.Initializer init) | |||
throws CannotCompileException | |||
{ | |||
@@ -1373,6 +1403,7 @@ class CtClassType extends CtClass { | |||
} | |||
} | |||
@Override | |||
public void removeField(CtField f) throws NotFoundException { | |||
checkModify(); | |||
FieldInfo fi = f.getFieldInfo2(); | |||
@@ -1385,6 +1416,7 @@ class CtClassType extends CtClass { | |||
throw new NotFoundException(f.toString()); | |||
} | |||
@Override | |||
public CtConstructor makeClassInitializer() | |||
throws CannotCompileException | |||
{ | |||
@@ -1399,6 +1431,7 @@ class CtClassType extends CtClass { | |||
return getClassInitializer(); | |||
} | |||
@Override | |||
public void addConstructor(CtConstructor c) | |||
throws CannotCompileException | |||
{ | |||
@@ -1410,6 +1443,7 @@ class CtClassType extends CtClass { | |||
getClassFile2().addMethod(c.getMethodInfo2()); | |||
} | |||
@Override | |||
public void removeConstructor(CtConstructor m) throws NotFoundException { | |||
checkModify(); | |||
MethodInfo mi = m.getMethodInfo2(); | |||
@@ -1422,6 +1456,7 @@ class CtClassType extends CtClass { | |||
throw new NotFoundException(m.toString()); | |||
} | |||
@Override | |||
public void addMethod(CtMethod m) throws CannotCompileException { | |||
checkModify(); | |||
if (m.getDeclaringClass() != this) | |||
@@ -1442,7 +1477,9 @@ class CtClassType extends CtClass { | |||
setModifiers(getModifiers() | Modifier.ABSTRACT); | |||
} | |||
public void removeMethod(CtMethod m) throws NotFoundException { | |||
@Override | |||
public void removeMethod(CtMethod m) throws NotFoundException | |||
{ | |||
checkModify(); | |||
MethodInfo mi = m.getMethodInfo2(); | |||
ClassFile cf = getClassFile2(); | |||
@@ -1454,52 +1491,53 @@ class CtClassType extends CtClass { | |||
throw new NotFoundException(m.toString()); | |||
} | |||
public byte[] getAttribute(String name) { | |||
@Override | |||
public byte[] getAttribute(String name) | |||
{ | |||
AttributeInfo ai = getClassFile2().getAttribute(name); | |||
if (ai == null) | |||
return null; | |||
else | |||
return ai.get(); | |||
return ai.get(); | |||
} | |||
public void setAttribute(String name, byte[] data) { | |||
@Override | |||
public void setAttribute(String name, byte[] data) | |||
{ | |||
checkModify(); | |||
ClassFile cf = getClassFile2(); | |||
cf.addAttribute(new AttributeInfo(cf.getConstPool(), name, data)); | |||
} | |||
@Override | |||
public void instrument(CodeConverter converter) | |||
throws CannotCompileException | |||
{ | |||
checkModify(); | |||
ClassFile cf = getClassFile2(); | |||
ConstPool cp = cf.getConstPool(); | |||
List list = cf.getMethods(); | |||
int n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
MethodInfo minfo = (MethodInfo)list.get(i); | |||
List<MethodInfo> methods = cf.getMethods(); | |||
for (MethodInfo minfo:methods) | |||
converter.doit(this, minfo, cp); | |||
} | |||
} | |||
@Override | |||
public void instrument(ExprEditor editor) | |||
throws CannotCompileException | |||
{ | |||
checkModify(); | |||
ClassFile cf = getClassFile2(); | |||
List list = cf.getMethods(); | |||
int n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
MethodInfo minfo = (MethodInfo)list.get(i); | |||
List<MethodInfo> methods = cf.getMethods(); | |||
for (MethodInfo minfo:methods) | |||
editor.doit(this, minfo); | |||
} | |||
} | |||
/** | |||
* @see javassist.CtClass#prune() | |||
* @see javassist.CtClass#stopPruning(boolean) | |||
*/ | |||
public void prune() { | |||
@Override | |||
public void prune() | |||
{ | |||
if (wasPruned) | |||
return; | |||
@@ -1507,8 +1545,10 @@ class CtClassType extends CtClass { | |||
getClassFile2().prune(); | |||
} | |||
@Override | |||
public void rebuildClassFile() { gcConstPool = true; } | |||
@Override | |||
public void toBytecode(DataOutputStream out) | |||
throws CannotCompileException, IOException | |||
{ | |||
@@ -1552,7 +1592,8 @@ class CtClassType extends CtClass { | |||
} | |||
} | |||
private void dumpClassFile(ClassFile cf) throws IOException { | |||
private void dumpClassFile(ClassFile cf) throws IOException | |||
{ | |||
DataOutputStream dump = makeFileOutput(debugDump); | |||
try { | |||
cf.write(dump); | |||
@@ -1564,13 +1605,16 @@ class CtClassType extends CtClass { | |||
/* See also checkModified() | |||
*/ | |||
private void checkPruned(String method) { | |||
private void checkPruned(String method) | |||
{ | |||
if (wasPruned) | |||
throw new RuntimeException(method + "(): " + getName() | |||
+ " was pruned."); | |||
} | |||
public boolean stopPruning(boolean stop) { | |||
@Override | |||
public boolean stopPruning(boolean stop) | |||
{ | |||
boolean prev = !doPruning; | |||
doPruning = !stop; | |||
return prev; | |||
@@ -1655,10 +1699,8 @@ class CtClassType extends CtClass { | |||
return; | |||
ConstPool cp = cf.getConstPool(); | |||
List list = cf.getMethods(); | |||
int n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
MethodInfo minfo = (MethodInfo)list.get(i); | |||
List<MethodInfo> methods = cf.getMethods(); | |||
for (MethodInfo minfo:methods) { | |||
if (minfo.isConstructor()) { | |||
CodeAttribute codeAttr = minfo.getCodeAttribute(); | |||
if (codeAttr != null) | |||
@@ -1729,19 +1771,20 @@ class CtClassType extends CtClass { | |||
// Methods used by CtNewWrappedMethod | |||
Hashtable getHiddenMethods() { | |||
Map<CtMethod,String> getHiddenMethods() { | |||
if (hiddenMethods == null) | |||
hiddenMethods = new Hashtable(); | |||
hiddenMethods = new Hashtable<CtMethod,String>(); | |||
return hiddenMethods; | |||
} | |||
int getUniqueNumber() { return uniqueNumberSeed++; } | |||
@Override | |||
public String makeUniqueName(String prefix) { | |||
HashMap table = new HashMap(); | |||
Map<Object,CtClassType> table = new HashMap<Object,CtClassType>(); | |||
makeMemberList(table); | |||
Set keys = table.keySet(); | |||
Set<Object> keys = table.keySet(); | |||
String[] methods = new String[keys.size()]; | |||
keys.toArray(methods); | |||
@@ -1768,17 +1811,14 @@ class CtClassType extends CtClass { | |||
return true; | |||
} | |||
private void makeMemberList(HashMap table) { | |||
private void makeMemberList(Map<Object,CtClassType> table) { | |||
int mod = getModifiers(); | |||
if (Modifier.isAbstract(mod) || Modifier.isInterface(mod)) | |||
try { | |||
CtClass[] ifs = getInterfaces(); | |||
int size = ifs.length; | |||
for (int i = 0; i < size; i++) { | |||
CtClass ic =ifs[i]; | |||
for (CtClass ic : ifs) | |||
if (ic != null && ic instanceof CtClassType) | |||
((CtClassType)ic).makeMemberList(table); | |||
} | |||
} | |||
catch (NotFoundException e) {} | |||
@@ -1789,19 +1829,13 @@ class CtClassType extends CtClass { | |||
} | |||
catch (NotFoundException e) {} | |||
List list = getClassFile2().getMethods(); | |||
int n = list.size(); | |||
for (int i = 0; i < n; i++) { | |||
MethodInfo minfo = (MethodInfo)list.get(i); | |||
List<MethodInfo> methods = getClassFile2().getMethods(); | |||
for (MethodInfo minfo:methods) | |||
table.put(minfo.getName(), this); | |||
} | |||
list = getClassFile2().getFields(); | |||
n = list.size(); | |||
for (int i = 0; i < n; i++) { | |||
FieldInfo finfo = (FieldInfo)list.get(i); | |||
List<FieldInfo> fields = getClassFile2().getFields(); | |||
for (FieldInfo finfo:fields) | |||
table.put(finfo.getName(), this); | |||
} | |||
} | |||
} | |||
@@ -122,6 +122,7 @@ public final class CtConstructor extends CtBehavior { | |||
* | |||
* @since 3.5 | |||
*/ | |||
@Override | |||
public String getLongName() { | |||
return getDeclaringClass().getName() | |||
+ (isConstructor() ? Descriptor.toString(getSignature()) | |||
@@ -134,11 +135,11 @@ public final class CtConstructor extends CtBehavior { | |||
* constructor. If this object represents a class initializer, | |||
* then this method returns <code>"<clinit>"</code>. | |||
*/ | |||
@Override | |||
public String getName() { | |||
if (methodInfo.isStaticInitializer()) | |||
return MethodInfo.nameClinit; | |||
else | |||
return declaringClass.getSimpleName(); | |||
return declaringClass.getSimpleName(); | |||
} | |||
/** | |||
@@ -148,6 +149,7 @@ public final class CtConstructor extends CtBehavior { | |||
* calling <code>super()</code> (the no-argument constructor of | |||
* the super class). | |||
*/ | |||
@Override | |||
public boolean isEmpty() { | |||
CodeAttribute ca = getMethodInfo2().getCodeAttribute(); | |||
if (ca == null) | |||
@@ -207,6 +209,7 @@ public final class CtConstructor extends CtBehavior { | |||
* constructor body does nothing except calling | |||
* <code>super()</code>. | |||
*/ | |||
@Override | |||
public void setBody(String src) throws CannotCompileException { | |||
if (src == null) | |||
if (isClassInitializer()) | |||
@@ -280,6 +283,7 @@ public final class CtConstructor extends CtBehavior { | |||
/* This method is called by addCatch() in CtBehavior. | |||
* super() and this() must not be in a try statement. | |||
*/ | |||
@Override | |||
int getStartPosOfBody(CodeAttribute ca) throws CannotCompileException { | |||
CodeIterator ci = ca.iterator(); | |||
try { |
@@ -16,6 +16,8 @@ | |||
package javassist; | |||
import java.util.List; | |||
import javassist.bytecode.*; | |||
import javassist.compiler.Javac; | |||
import javassist.compiler.SymbolTable; | |||
@@ -83,15 +85,12 @@ public class CtField extends CtMember { | |||
{ | |||
this(src.fieldInfo.getDescriptor(), src.fieldInfo.getName(), | |||
declaring); | |||
java.util.ListIterator iterator | |||
= src.fieldInfo.getAttributes().listIterator(); | |||
FieldInfo fi = fieldInfo; | |||
fi.setAccessFlags(src.fieldInfo.getAccessFlags()); | |||
ConstPool cp = fi.getConstPool(); | |||
while (iterator.hasNext()) { | |||
AttributeInfo ainfo = (AttributeInfo)iterator.next(); | |||
List<AttributeInfo> attributes = src.fieldInfo.getAttributes(); | |||
for (AttributeInfo ainfo : attributes) | |||
fi.addAttribute(ainfo.copy(cp, null)); | |||
} | |||
} | |||
private CtField(String typeDesc, String name, CtClass clazz) | |||
@@ -114,11 +113,13 @@ public class CtField extends CtMember { | |||
/** | |||
* Returns a String representation of the object. | |||
*/ | |||
@Override | |||
public String toString() { | |||
return getDeclaringClass().getName() + "." + getName() | |||
+ ":" + fieldInfo.getDescriptor(); | |||
} | |||
@Override | |||
protected void extendToString(StringBuffer buffer) { | |||
buffer.append(' '); | |||
buffer.append(getName()); | |||
@@ -126,18 +127,15 @@ public class CtField extends CtMember { | |||
buffer.append(fieldInfo.getDescriptor()); | |||
} | |||
/* Javac.CtFieldWithInit overrides. | |||
*/ | |||
/* Javac.CtFieldWithInit overrides. */ | |||
protected ASTree getInitAST() { return null; } | |||
/* Called by CtClassType.addField(). | |||
*/ | |||
/* Called by CtClassType.addField(). */ | |||
Initializer getInit() { | |||
ASTree tree = getInitAST(); | |||
if (tree == null) | |||
return null; | |||
else | |||
return Initializer.byExpr(tree); | |||
return Initializer.byExpr(tree); | |||
} | |||
/** | |||
@@ -202,6 +200,7 @@ public class CtField extends CtMember { | |||
/** | |||
* Returns the class declaring the field. | |||
*/ | |||
@Override | |||
public CtClass getDeclaringClass() { | |||
// this is redundant but for javadoc. | |||
return super.getDeclaringClass(); | |||
@@ -210,6 +209,7 @@ public class CtField extends CtMember { | |||
/** | |||
* Returns the name of the field. | |||
*/ | |||
@Override | |||
public String getName() { | |||
return fieldInfo.getName(); | |||
} | |||
@@ -227,6 +227,7 @@ public class CtField extends CtMember { | |||
* | |||
* @see Modifier | |||
*/ | |||
@Override | |||
public int getModifiers() { | |||
return AccessFlag.toModifier(fieldInfo.getAccessFlags()); | |||
} | |||
@@ -236,6 +237,7 @@ public class CtField extends CtMember { | |||
* | |||
* @see Modifier | |||
*/ | |||
@Override | |||
public void setModifiers(int mod) { | |||
declaringClass.checkModify(); | |||
fieldInfo.setAccessFlags(AccessFlag.of(mod)); | |||
@@ -248,6 +250,7 @@ public class CtField extends CtMember { | |||
* @return <code>true</code> if the annotation is found, otherwise <code>false</code>. | |||
* @since 3.21 | |||
*/ | |||
@Override | |||
public boolean hasAnnotation(String typeName) { | |||
FieldInfo fi = getFieldInfo2(); | |||
AnnotationsAttribute ainfo = (AnnotationsAttribute) | |||
@@ -269,7 +272,8 @@ public class CtField extends CtMember { | |||
* @return the annotation if found, otherwise <code>null</code>. | |||
* @since 3.11 | |||
*/ | |||
public Object getAnnotation(Class clz) throws ClassNotFoundException { | |||
@Override | |||
public Object getAnnotation(Class<?> clz) throws ClassNotFoundException { | |||
FieldInfo fi = getFieldInfo2(); | |||
AnnotationsAttribute ainfo = (AnnotationsAttribute) | |||
fi.getAttribute(AnnotationsAttribute.invisibleTag); | |||
@@ -286,6 +290,7 @@ public class CtField extends CtMember { | |||
* @see #getAvailableAnnotations() | |||
* @since 3.1 | |||
*/ | |||
@Override | |||
public Object[] getAnnotations() throws ClassNotFoundException { | |||
return getAnnotations(false); | |||
} | |||
@@ -299,6 +304,7 @@ public class CtField extends CtMember { | |||
* @see #getAnnotations() | |||
* @since 3.3 | |||
*/ | |||
@Override | |||
public Object[] getAvailableAnnotations(){ | |||
try { | |||
return getAnnotations(true); | |||
@@ -332,6 +338,7 @@ public class CtField extends CtMember { | |||
* @see javassist.bytecode.Descriptor | |||
* @see #getGenericSignature() | |||
*/ | |||
@Override | |||
public String getSignature() { | |||
return fieldInfo.getDescriptor(); | |||
} | |||
@@ -343,6 +350,7 @@ public class CtField extends CtMember { | |||
* @see SignatureAttribute#toFieldSignature(String) | |||
* @since 3.17 | |||
*/ | |||
@Override | |||
public String getGenericSignature() { | |||
SignatureAttribute sa | |||
= (SignatureAttribute)fieldInfo.getAttribute(SignatureAttribute.tag); | |||
@@ -359,6 +367,7 @@ public class CtField extends CtMember { | |||
* @see javassist.bytecode.SignatureAttribute.ObjectType#encode() | |||
* @since 3.17 | |||
*/ | |||
@Override | |||
public void setGenericSignature(String sig) { | |||
declaringClass.checkModify(); | |||
fieldInfo.addAttribute(new SignatureAttribute(fieldInfo.getConstPool(), sig)); | |||
@@ -426,8 +435,7 @@ public class CtField extends CtMember { | |||
// "Z" means boolean type. | |||
if ("Z".equals(fieldInfo.getDescriptor())) | |||
return Boolean.valueOf(value != 0); | |||
else | |||
return Integer.valueOf(value); | |||
return Integer.valueOf(value); | |||
case ConstPool.CONST_String : | |||
return cp.getStringInfo(index); | |||
default : | |||
@@ -447,12 +455,12 @@ public class CtField extends CtMember { | |||
* | |||
* @param name attribute name | |||
*/ | |||
@Override | |||
public byte[] getAttribute(String name) { | |||
AttributeInfo ai = fieldInfo.getAttribute(name); | |||
if (ai == null) | |||
return null; | |||
else | |||
return ai.get(); | |||
return ai.get(); | |||
} | |||
/** | |||
@@ -465,6 +473,7 @@ public class CtField extends CtMember { | |||
* @param name attribute name | |||
* @param data attribute value | |||
*/ | |||
@Override | |||
public void setAttribute(String name, byte[] data) { | |||
declaringClass.checkModify(); | |||
fieldInfo.addAttribute(new AttributeInfo(fieldInfo.getConstPool(), | |||
@@ -854,6 +863,7 @@ public class CtField extends CtMember { | |||
static abstract class CodeInitializer0 extends Initializer { | |||
abstract void compileExpr(Javac drv) throws CompileError; | |||
@Override | |||
int compile(CtClass type, String name, Bytecode code, | |||
CtClass[] parameters, Javac drv) | |||
throws CannotCompileException | |||
@@ -869,6 +879,7 @@ public class CtField extends CtMember { | |||
} | |||
} | |||
@Override | |||
int compileIfStatic(CtClass type, String name, Bytecode code, | |||
Javac drv) throws CannotCompileException | |||
{ | |||
@@ -887,9 +898,9 @@ public class CtField extends CtMember { | |||
if (tree instanceof IntConst) { | |||
long value = ((IntConst)tree).get(); | |||
if (type == CtClass.doubleType) | |||
return cp.addDoubleInfo((double)value); | |||
return cp.addDoubleInfo(value); | |||
else if (type == CtClass.floatType) | |||
return cp.addFloatInfo((float)value); | |||
return cp.addFloatInfo(value); | |||
else if (type == CtClass.longType) | |||
return cp.addLongInfo(value); | |||
else if (type != CtClass.voidType) | |||
@@ -916,10 +927,12 @@ public class CtField extends CtMember { | |||
CodeInitializer(String expr) { expression = expr; } | |||
@Override | |||
void compileExpr(Javac drv) throws CompileError { | |||
drv.compileExpr(expression); | |||
} | |||
@Override | |||
int getConstantValue(ConstPool cp, CtClass type) { | |||
try { | |||
ASTree t = Javac.parseExpr(expression, new SymbolTable()); | |||
@@ -936,10 +949,12 @@ public class CtField extends CtMember { | |||
PtreeInitializer(ASTree expr) { expression = expr; } | |||
@Override | |||
void compileExpr(Javac drv) throws CompileError { | |||
drv.compileExpr(expression); | |||
} | |||
@Override | |||
int getConstantValue(ConstPool cp, CtClass type) { | |||
return getConstantValue2(cp, type, expression); | |||
} | |||
@@ -954,6 +969,7 @@ public class CtField extends CtMember { | |||
ParamInitializer() {} | |||
@Override | |||
int compile(CtClass type, String name, Bytecode code, | |||
CtClass[] parameters, Javac drv) | |||
throws CannotCompileException | |||
@@ -965,8 +981,7 @@ public class CtField extends CtMember { | |||
code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); | |||
return s; // stack size | |||
} | |||
else | |||
return 0; // do not initialize | |||
return 0; // do not initialize | |||
} | |||
/** | |||
@@ -998,6 +1013,7 @@ public class CtField extends CtMember { | |||
return k; | |||
} | |||
@Override | |||
int compileIfStatic(CtClass type, String name, Bytecode code, | |||
Javac drv) throws CannotCompileException | |||
{ | |||
@@ -1019,6 +1035,7 @@ public class CtField extends CtMember { | |||
* Produces codes in which a new object is created and assigned to | |||
* the field as the initial value. | |||
*/ | |||
@Override | |||
int compile(CtClass type, String name, Bytecode code, | |||
CtClass[] parameters, Javac drv) | |||
throws CannotCompileException | |||
@@ -1053,16 +1070,17 @@ public class CtField extends CtMember { | |||
return "(Ljava/lang/Object;[Ljava/lang/Object;)V"; | |||
else | |||
return "(Ljava/lang/Object;)V"; | |||
else | |||
if (withConstructorParams) | |||
return desc3; | |||
else | |||
return "(Ljava/lang/Object;[Ljava/lang/String;)V"; | |||
if (withConstructorParams) | |||
return desc3; | |||
return "(Ljava/lang/Object;[Ljava/lang/String;)V"; | |||
} | |||
/** | |||
* Produces codes for a static field. | |||
*/ | |||
@Override | |||
int compileIfStatic(CtClass type, String name, Bytecode code, | |||
Javac drv) throws CannotCompileException | |||
{ | |||
@@ -1115,6 +1133,7 @@ public class CtField extends CtMember { | |||
* Produces codes in which a new object is created and assigned to | |||
* the field as the initial value. | |||
*/ | |||
@Override | |||
int compile(CtClass type, String name, Bytecode code, | |||
CtClass[] parameters, Javac drv) | |||
throws CannotCompileException | |||
@@ -1149,16 +1168,17 @@ public class CtField extends CtMember { | |||
return "(Ljava/lang/Object;[Ljava/lang/Object;)"; | |||
else | |||
return "(Ljava/lang/Object;)"; | |||
else | |||
if (withConstructorParams) | |||
return desc3; | |||
else | |||
return "(Ljava/lang/Object;[Ljava/lang/String;)"; | |||
if (withConstructorParams) | |||
return desc3; | |||
return "(Ljava/lang/Object;[Ljava/lang/String;)"; | |||
} | |||
/** | |||
* Produces codes for a static field. | |||
*/ | |||
@Override | |||
int compileIfStatic(CtClass type, String name, Bytecode code, | |||
Javac drv) throws CannotCompileException | |||
{ | |||
@@ -1184,12 +1204,14 @@ public class CtField extends CtMember { | |||
IntInitializer(int v) { value = v; } | |||
@Override | |||
void check(String desc) throws CannotCompileException { | |||
char c = desc.charAt(0); | |||
if (c != 'I' && c != 'S' && c != 'B' && c != 'C' && c != 'Z') | |||
throw new CannotCompileException("type mismatch"); | |||
} | |||
@Override | |||
int compile(CtClass type, String name, Bytecode code, | |||
CtClass[] parameters, Javac drv) | |||
throws CannotCompileException | |||
@@ -1200,6 +1222,7 @@ public class CtField extends CtMember { | |||
return 2; // stack size | |||
} | |||
@Override | |||
int compileIfStatic(CtClass type, String name, Bytecode code, | |||
Javac drv) throws CannotCompileException | |||
{ | |||
@@ -1208,6 +1231,7 @@ public class CtField extends CtMember { | |||
return 1; // stack size | |||
} | |||
@Override | |||
int getConstantValue(ConstPool cp, CtClass type) { | |||
return cp.addIntegerInfo(value); | |||
} | |||
@@ -1218,11 +1242,13 @@ public class CtField extends CtMember { | |||
LongInitializer(long v) { value = v; } | |||
@Override | |||
void check(String desc) throws CannotCompileException { | |||
if (!desc.equals("J")) | |||
throw new CannotCompileException("type mismatch"); | |||
} | |||
@Override | |||
int compile(CtClass type, String name, Bytecode code, | |||
CtClass[] parameters, Javac drv) | |||
throws CannotCompileException | |||
@@ -1233,6 +1259,7 @@ public class CtField extends CtMember { | |||
return 3; // stack size | |||
} | |||
@Override | |||
int compileIfStatic(CtClass type, String name, Bytecode code, | |||
Javac drv) throws CannotCompileException | |||
{ | |||
@@ -1241,11 +1268,11 @@ public class CtField extends CtMember { | |||
return 2; // stack size | |||
} | |||
@Override | |||
int getConstantValue(ConstPool cp, CtClass type) { | |||
if (type == CtClass.longType) | |||
return cp.addLongInfo(value); | |||
else | |||
return 0; | |||
return 0; | |||
} | |||
} | |||
@@ -1254,11 +1281,13 @@ public class CtField extends CtMember { | |||
FloatInitializer(float v) { value = v; } | |||
@Override | |||
void check(String desc) throws CannotCompileException { | |||
if (!desc.equals("F")) | |||
throw new CannotCompileException("type mismatch"); | |||
} | |||
@Override | |||
int compile(CtClass type, String name, Bytecode code, | |||
CtClass[] parameters, Javac drv) | |||
throws CannotCompileException | |||
@@ -1269,6 +1298,7 @@ public class CtField extends CtMember { | |||
return 3; // stack size | |||
} | |||
@Override | |||
int compileIfStatic(CtClass type, String name, Bytecode code, | |||
Javac drv) throws CannotCompileException | |||
{ | |||
@@ -1277,11 +1307,11 @@ public class CtField extends CtMember { | |||
return 2; // stack size | |||
} | |||
@Override | |||
int getConstantValue(ConstPool cp, CtClass type) { | |||
if (type == CtClass.floatType) | |||
return cp.addFloatInfo(value); | |||
else | |||
return 0; | |||
return 0; | |||
} | |||
} | |||
@@ -1290,11 +1320,13 @@ public class CtField extends CtMember { | |||
DoubleInitializer(double v) { value = v; } | |||
@Override | |||
void check(String desc) throws CannotCompileException { | |||
if (!desc.equals("D")) | |||
throw new CannotCompileException("type mismatch"); | |||
} | |||
@Override | |||
int compile(CtClass type, String name, Bytecode code, | |||
CtClass[] parameters, Javac drv) | |||
throws CannotCompileException | |||
@@ -1305,6 +1337,7 @@ public class CtField extends CtMember { | |||
return 3; // stack size | |||
} | |||
@Override | |||
int compileIfStatic(CtClass type, String name, Bytecode code, | |||
Javac drv) throws CannotCompileException | |||
{ | |||
@@ -1313,11 +1346,11 @@ public class CtField extends CtMember { | |||
return 2; // stack size | |||
} | |||
@Override | |||
int getConstantValue(ConstPool cp, CtClass type) { | |||
if (type == CtClass.doubleType) | |||
return cp.addDoubleInfo(value); | |||
else | |||
return 0; | |||
return 0; | |||
} | |||
} | |||
@@ -1326,6 +1359,7 @@ public class CtField extends CtMember { | |||
StringInitializer(String v) { value = v; } | |||
@Override | |||
int compile(CtClass type, String name, Bytecode code, | |||
CtClass[] parameters, Javac drv) | |||
throws CannotCompileException | |||
@@ -1336,6 +1370,7 @@ public class CtField extends CtMember { | |||
return 2; // stack size | |||
} | |||
@Override | |||
int compileIfStatic(CtClass type, String name, Bytecode code, | |||
Javac drv) throws CannotCompileException | |||
{ | |||
@@ -1344,11 +1379,11 @@ public class CtField extends CtMember { | |||
return 1; // stack size | |||
} | |||
@Override | |||
int getConstantValue(ConstPool cp, CtClass type) { | |||
if (type.getName().equals(javaLangString)) | |||
return cp.addStringInfo(value); | |||
else | |||
return 0; | |||
return 0; | |||
} | |||
} | |||
@@ -1366,6 +1401,7 @@ public class CtField extends CtMember { | |||
code.addAnewarray(type, size); | |||
} | |||
@Override | |||
int compile(CtClass type, String name, Bytecode code, | |||
CtClass[] parameters, Javac drv) | |||
throws CannotCompileException | |||
@@ -1376,6 +1412,7 @@ public class CtField extends CtMember { | |||
return 2; // stack size | |||
} | |||
@Override | |||
int compileIfStatic(CtClass type, String name, Bytecode code, | |||
Javac drv) throws CannotCompileException | |||
{ | |||
@@ -1391,11 +1428,13 @@ public class CtField extends CtMember { | |||
MultiArrayInitializer(CtClass t, int[] d) { type = t; dim = d; } | |||
@Override | |||
void check(String desc) throws CannotCompileException { | |||
if (desc.charAt(0) != '[') | |||
throw new CannotCompileException("type mismatch"); | |||
} | |||
@Override | |||
int compile(CtClass type, String name, Bytecode code, | |||
CtClass[] parameters, Javac drv) | |||
throws CannotCompileException | |||
@@ -1406,6 +1445,7 @@ public class CtField extends CtMember { | |||
return s + 1; // stack size | |||
} | |||
@Override | |||
int compileIfStatic(CtClass type, String name, Bytecode code, | |||
Javac drv) throws CannotCompileException | |||
{ |
@@ -29,20 +29,33 @@ public abstract class CtMember { | |||
* at the same time. | |||
*/ | |||
static class Cache extends CtMember { | |||
@Override | |||
protected void extendToString(StringBuffer buffer) {} | |||
@Override | |||
public boolean hasAnnotation(String clz) { return false; } | |||
public Object getAnnotation(Class clz) | |||
@Override | |||
public Object getAnnotation(Class<?> clz) | |||
throws ClassNotFoundException { return null; } | |||
@Override | |||
public Object[] getAnnotations() | |||
throws ClassNotFoundException { return null; } | |||
@Override | |||
public byte[] getAttribute(String name) { return null; } | |||
@Override | |||
public Object[] getAvailableAnnotations() { return null; } | |||
@Override | |||
public int getModifiers() { return 0; } | |||
@Override | |||
public String getName() { return null; } | |||
@Override | |||
public String getSignature() { return null; } | |||
@Override | |||
public void setAttribute(String name, byte[] data) {} | |||
@Override | |||
public void setModifiers(int mod) {} | |||
@Override | |||
public String getGenericSignature() { return null; } | |||
@Override | |||
public void setGenericSignature(String sig) {} | |||
private CtMember methodTail; | |||
@@ -120,8 +133,7 @@ public abstract class CtMember { | |||
break; | |||
} | |||
else | |||
m = m.next; | |||
m = m.next; | |||
} | |||
} | |||
} | |||
@@ -141,6 +153,7 @@ public abstract class CtMember { | |||
*/ | |||
void nameReplaced() {} | |||
@Override | |||
public String toString() { | |||
StringBuffer buffer = new StringBuffer(getClass().getName()); | |||
buffer.append("@"); | |||
@@ -214,7 +227,7 @@ public abstract class CtMember { | |||
* @return <code>true</code> if the annotation is found, otherwise <code>false</code>. | |||
* @since 3.11 | |||
*/ | |||
public boolean hasAnnotation(Class clz) { | |||
public boolean hasAnnotation(Class<?> clz) { | |||
return hasAnnotation(clz.getName()); | |||
} | |||
@@ -238,7 +251,7 @@ public abstract class CtMember { | |||
* @return the annotation if found, otherwise <code>null</code>. | |||
* @since 3.11 | |||
*/ | |||
public abstract Object getAnnotation(Class annotationType) throws ClassNotFoundException; | |||
public abstract Object getAnnotation(Class<?> annotationType) throws ClassNotFoundException; | |||
/** | |||
* Returns the annotations associated with this member. |
@@ -155,6 +155,7 @@ public final class CtMethod extends CtBehavior { | |||
* If two methods have the same name and signature, then | |||
* the hash codes for the two methods are equal. | |||
*/ | |||
@Override | |||
public int hashCode() { | |||
return getStringRep().hashCode(); | |||
} | |||
@@ -163,6 +164,7 @@ public final class CtMethod extends CtBehavior { | |||
* This method is invoked when setName() or replaceClassName() | |||
* in CtClass is called. | |||
*/ | |||
@Override | |||
void nameReplaced() { | |||
cachedStringRep = null; | |||
} | |||
@@ -181,6 +183,7 @@ public final class CtMethod extends CtBehavior { | |||
* Indicates whether <code>obj</code> has the same name and the | |||
* same signature as this method. | |||
*/ | |||
@Override | |||
public boolean equals(Object obj) { | |||
return obj != null && obj instanceof CtMethod | |||
&& ((CtMethod)obj).getStringRep().equals(getStringRep()); | |||
@@ -192,6 +195,7 @@ public final class CtMethod extends CtBehavior { | |||
* | |||
* @since 3.5 | |||
*/ | |||
@Override | |||
public String getLongName() { | |||
return getDeclaringClass().getName() + "." | |||
+ getName() + Descriptor.toString(getSignature()); | |||
@@ -200,6 +204,7 @@ public final class CtMethod extends CtBehavior { | |||
/** | |||
* Obtains the name of this method. | |||
*/ | |||
@Override | |||
public String getName() { | |||
return methodInfo.getName(); | |||
} | |||
@@ -223,6 +228,7 @@ public final class CtMethod extends CtBehavior { | |||
* Returns true if the method body is empty, that is, <code>{}</code>. | |||
* It also returns true if the method is an abstract method. | |||
*/ | |||
@Override | |||
public boolean isEmpty() { | |||
CodeAttribute ca = getMethodInfo2().getCodeAttribute(); | |||
if (ca == null) // abstract or native | |||
@@ -380,15 +386,18 @@ public final class CtMethod extends CtBehavior { | |||
param = i; | |||
} | |||
@Override | |||
int compile(Bytecode code) throws CannotCompileException { | |||
code.addIconst(param); | |||
return 1; | |||
} | |||
@Override | |||
String descriptor() { | |||
return "([Ljava/lang/Object;I)Ljava/lang/Object;"; | |||
} | |||
@Override | |||
String constDescriptor() { | |||
return "([Ljava/lang/Object;I)V"; | |||
} | |||
@@ -401,15 +410,18 @@ public final class CtMethod extends CtBehavior { | |||
param = l; | |||
} | |||
@Override | |||
int compile(Bytecode code) throws CannotCompileException { | |||
code.addLconst(param); | |||
return 2; | |||
} | |||
@Override | |||
String descriptor() { | |||
return "([Ljava/lang/Object;J)Ljava/lang/Object;"; | |||
} | |||
@Override | |||
String constDescriptor() { | |||
return "([Ljava/lang/Object;J)V"; | |||
} | |||
@@ -422,15 +434,18 @@ public final class CtMethod extends CtBehavior { | |||
param = s; | |||
} | |||
@Override | |||
int compile(Bytecode code) throws CannotCompileException { | |||
code.addLdc(param); | |||
return 1; | |||
} | |||
@Override | |||
String descriptor() { | |||
return "([Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;"; | |||
} | |||
@Override | |||
String constDescriptor() { | |||
return "([Ljava/lang/Object;Ljava/lang/String;)V"; | |||
} |
@@ -43,6 +43,7 @@ class CtNewClass extends CtClassType { | |||
hasConstructor = isInterface; | |||
} | |||
@Override | |||
protected void extendToString(StringBuffer buffer) { | |||
if (hasConstructor) | |||
buffer.append("hasConstructor "); | |||
@@ -50,6 +51,7 @@ class CtNewClass extends CtClassType { | |||
super.extendToString(buffer); | |||
} | |||
@Override | |||
public void addConstructor(CtConstructor c) | |||
throws CannotCompileException | |||
{ | |||
@@ -57,6 +59,7 @@ class CtNewClass extends CtClassType { | |||
super.addConstructor(c); | |||
} | |||
@Override | |||
public void toBytecode(DataOutputStream out) | |||
throws CannotCompileException, IOException | |||
{ | |||
@@ -117,8 +120,7 @@ class CtNewClass extends CtClassType { | |||
String pname2 = superclazz.getPackageName(); | |||
if (pname == null) | |||
return pname2 == null; | |||
else | |||
return pname.equals(pname2); | |||
return pname.equals(pname2); | |||
} | |||
return true; |
@@ -18,7 +18,8 @@ package javassist; | |||
import javassist.bytecode.*; | |||
import javassist.compiler.JvstCodeGen; | |||
import java.util.Hashtable; | |||
import java.util.Map; | |||
import javassist.CtMethod.ConstParameter; | |||
class CtNewWrappedMethod { | |||
@@ -139,8 +140,8 @@ class CtNewWrappedMethod { | |||
CtMethod src) | |||
throws BadBytecode, CannotCompileException | |||
{ | |||
Hashtable bodies = clazz.getHiddenMethods(); | |||
String bodyname = (String)bodies.get(src); | |||
Map<CtMethod,String> bodies = clazz.getHiddenMethods(); | |||
String bodyname = bodies.get(src); | |||
if (bodyname == null) { | |||
do { | |||
bodyname = addedWrappedMethod + clazz.getUniqueNumber(); |
@@ -47,6 +47,7 @@ public final class CtPrimitiveType extends CtClass { | |||
* Java type: boolean, byte, char, short, int, long, float, double, | |||
* or void. | |||
*/ | |||
@Override | |||
public boolean isPrimitive() { return true; } | |||
/** | |||
@@ -55,6 +56,7 @@ public final class CtPrimitiveType extends CtClass { | |||
* | |||
* @see Modifier | |||
*/ | |||
@Override | |||
public int getModifiers() { | |||
return Modifier.PUBLIC | Modifier.FINAL; | |||
} |
@@ -17,6 +17,8 @@ | |||
package javassist; | |||
import java.io.*; | |||
import java.lang.reflect.InvocationTargetException; | |||
import java.util.Arrays; | |||
import java.util.Hashtable; | |||
import java.util.Vector; | |||
import java.security.ProtectionDomain; | |||
@@ -134,8 +136,8 @@ import java.security.ProtectionDomain; | |||
* @see javassist.Translator | |||
*/ | |||
public class Loader extends ClassLoader { | |||
private Hashtable notDefinedHere; // must be atomic. | |||
private Vector notDefinedPackages; // must be atomic. | |||
private Hashtable<String,ClassLoader> notDefinedHere; // must be atomic. | |||
private Vector<String> notDefinedPackages; // must be atomic. | |||
private ClassPool source; | |||
private Translator translator; | |||
private ProtectionDomain domain; | |||
@@ -182,8 +184,8 @@ public class Loader extends ClassLoader { | |||
} | |||
private void init(ClassPool cp) { | |||
notDefinedHere = new Hashtable(); | |||
notDefinedPackages = new Vector(); | |||
notDefinedHere = new Hashtable<String,ClassLoader>(); | |||
notDefinedPackages = new Vector<String>(); | |||
source = cp; | |||
translator = null; | |||
domain = null; | |||
@@ -266,14 +268,8 @@ public class Loader extends ClassLoader { | |||
* to the target {@code main()}. | |||
*/ | |||
public void run(String[] args) throws Throwable { | |||
int n = args.length - 1; | |||
if (n >= 0) { | |||
String[] args2 = new String[n]; | |||
for (int i = 0; i < n; ++i) | |||
args2[i] = args[i + 1]; | |||
run(args[0], args2); | |||
} | |||
if (args.length >= 1) | |||
run(args[0], Arrays.copyOfRange(args, 1, args.length)); | |||
} | |||
/** | |||
@@ -283,13 +279,13 @@ public class Loader extends ClassLoader { | |||
* @param args parameters passed to <code>main()</code>. | |||
*/ | |||
public void run(String classname, String[] args) throws Throwable { | |||
Class c = loadClass(classname); | |||
Class<?> c = loadClass(classname); | |||
try { | |||
c.getDeclaredMethod("main", new Class[] { String[].class }).invoke( | |||
c.getDeclaredMethod("main", new Class<?>[] { String[].class }).invoke( | |||
null, | |||
new Object[] { args }); | |||
} | |||
catch (java.lang.reflect.InvocationTargetException e) { | |||
catch (InvocationTargetException e) { | |||
throw e.getTargetException(); | |||
} | |||
} | |||
@@ -297,11 +293,12 @@ public class Loader extends ClassLoader { | |||
/** | |||
* Requests the class loader to load a class. | |||
*/ | |||
protected Class loadClass(String name, boolean resolve) | |||
@Override | |||
protected Class<?> loadClass(String name, boolean resolve) | |||
throws ClassFormatError, ClassNotFoundException { | |||
name = name.intern(); | |||
synchronized (name) { | |||
Class c = findLoadedClass(name); | |||
Class<?> c = findLoadedClass(name); | |||
if (c == null) | |||
c = loadClassByDelegation(name); | |||
@@ -330,7 +327,8 @@ public class Loader extends ClassLoader { | |||
* @throws ClassNotFoundException if an exception is thrown while | |||
* obtaining a class file. | |||
*/ | |||
protected Class findClass(String name) throws ClassNotFoundException { | |||
@Override | |||
protected Class<?> findClass(String name) throws ClassNotFoundException { | |||
byte[] classfile; | |||
try { | |||
if (source != null) { | |||
@@ -375,11 +373,10 @@ public class Loader extends ClassLoader { | |||
if (domain == null) | |||
return defineClass(name, classfile, 0, classfile.length); | |||
else | |||
return defineClass(name, classfile, 0, classfile.length, domain); | |||
return defineClass(name, classfile, 0, classfile.length, domain); | |||
} | |||
protected Class loadClassByDelegation(String name) | |||
protected Class<?> loadClassByDelegation(String name) | |||
throws ClassNotFoundException | |||
{ | |||
/* The swing components must be loaded by a system | |||
@@ -392,7 +389,7 @@ public class Loader extends ClassLoader { | |||
* by this class loader. | |||
*/ | |||
Class c = null; | |||
Class<?> c = null; | |||
if (doDelegation) | |||
if (name.startsWith("java.") | |||
|| name.startsWith("javax.") | |||
@@ -407,24 +404,22 @@ public class Loader extends ClassLoader { | |||
} | |||
private boolean notDelegated(String name) { | |||
if (notDefinedHere.get(name) != null) | |||
if (notDefinedHere.containsKey(name)) | |||
return true; | |||
int n = notDefinedPackages.size(); | |||
for (int i = 0; i < n; ++i) | |||
if (name.startsWith((String)notDefinedPackages.elementAt(i))) | |||
for (String pack : notDefinedPackages) | |||
if (name.startsWith(pack)) | |||
return true; | |||
return false; | |||
} | |||
protected Class delegateToParent(String classname) | |||
protected Class<?> delegateToParent(String classname) | |||
throws ClassNotFoundException | |||
{ | |||
ClassLoader cl = getParent(); | |||
if (cl != null) | |||
return cl.loadClass(classname); | |||
else | |||
return findSystemClass(classname); | |||
return findSystemClass(classname); | |||
} | |||
} |
@@ -18,6 +18,7 @@ package javassist; | |||
import java.io.InputStream; | |||
import java.net.URL; | |||
import java.lang.ref.Reference; | |||
import java.lang.ref.WeakReference; | |||
/** | |||
@@ -44,21 +45,18 @@ import java.lang.ref.WeakReference; | |||
* @see ClassClassPath | |||
*/ | |||
public class LoaderClassPath implements ClassPath { | |||
private WeakReference clref; | |||
private Reference<ClassLoader> clref; | |||
/** | |||
* Creates a search path representing a class loader. | |||
*/ | |||
public LoaderClassPath(ClassLoader cl) { | |||
clref = new WeakReference(cl); | |||
clref = new WeakReference<ClassLoader>(cl); | |||
} | |||
@Override | |||
public String toString() { | |||
Object cl = null; | |||
if (clref != null) | |||
cl = clref.get(); | |||
return cl == null ? "<null>" : cl.toString(); | |||
return clref.get() == null ? "<null>" : clref.get().toString(); | |||
} | |||
/** | |||
@@ -66,15 +64,14 @@ public class LoaderClassPath implements ClassPath { | |||
* This method calls <code>getResourceAsStream(String)</code> | |||
* on the class loader. | |||
*/ | |||
@Override | |||
public InputStream openClassfile(String classname) throws NotFoundException { | |||
String cname = classname.replace('.', '/') + ".class"; | |||
ClassLoader cl = (ClassLoader)clref.get(); | |||
ClassLoader cl = clref.get(); | |||
if (cl == null) | |||
return null; // not found | |||
else { | |||
InputStream is = cl.getResourceAsStream(cname); | |||
return is; | |||
} | |||
InputStream is = cl.getResourceAsStream(cname); | |||
return is; | |||
} | |||
/** | |||
@@ -84,20 +81,20 @@ public class LoaderClassPath implements ClassPath { | |||
* | |||
* @return null if the class file could not be found. | |||
*/ | |||
@Override | |||
public URL find(String classname) { | |||
String cname = classname.replace('.', '/') + ".class"; | |||
ClassLoader cl = (ClassLoader)clref.get(); | |||
ClassLoader cl = clref.get(); | |||
if (cl == null) | |||
return null; // not found | |||
else { | |||
URL url = cl.getResource(cname); | |||
return url; | |||
} | |||
URL url = cl.getResource(cname); | |||
return url; | |||
} | |||
/** | |||
* Closes this class path. | |||
*/ | |||
@Override | |||
public void close() { | |||
clref = null; | |||
} |
@@ -108,16 +108,15 @@ public class SerialVersionUID { | |||
// fields. | |||
CtField[] fields = clazz.getDeclaredFields(); | |||
Arrays.sort(fields, new Comparator() { | |||
public int compare(Object o1, Object o2) { | |||
CtField field1 = (CtField)o1; | |||
CtField field2 = (CtField)o2; | |||
Arrays.sort(fields, new Comparator<CtField>() { | |||
@Override | |||
public int compare(CtField field1, CtField field2) { | |||
return field1.getName().compareTo(field2.getName()); | |||
} | |||
}); | |||
for (int i = 0; i < fields.length; i++) { | |||
CtField field = (CtField) fields[i]; | |||
CtField field = fields[i]; | |||
int mods = field.getModifiers(); | |||
if (((mods & Modifier.PRIVATE) == 0) || | |||
((mods & (Modifier.STATIC | Modifier.TRANSIENT)) == 0)) { | |||
@@ -136,10 +135,9 @@ public class SerialVersionUID { | |||
// constructors. | |||
CtConstructor[] constructors = clazz.getDeclaredConstructors(); | |||
Arrays.sort(constructors, new Comparator() { | |||
public int compare(Object o1, Object o2) { | |||
CtConstructor c1 = (CtConstructor)o1; | |||
CtConstructor c2 = (CtConstructor)o2; | |||
Arrays.sort(constructors, new Comparator<CtConstructor>() { | |||
@Override | |||
public int compare(CtConstructor c1, CtConstructor c2) { | |||
return c1.getMethodInfo2().getDescriptor().compareTo( | |||
c2.getMethodInfo2().getDescriptor()); | |||
} | |||
@@ -157,10 +155,9 @@ public class SerialVersionUID { | |||
} | |||
// methods. | |||
Arrays.sort(methods, new Comparator() { | |||
public int compare(Object o1, Object o2) { | |||
CtMethod m1 = (CtMethod)o1; | |||
CtMethod m2 = (CtMethod)o2; | |||
Arrays.sort(methods, new Comparator<CtMethod>() { | |||
@Override | |||
public int compare(CtMethod m1, CtMethod m2) { | |||
int value = m1.getName().compareTo(m2.getName()); | |||
if (value == 0) | |||
value = m1.getMethodInfo2().getDescriptor() |
@@ -65,6 +65,7 @@ public class URLClassPath implements ClassPath { | |||
this.packageName = packageName; | |||
} | |||
@Override | |||
public String toString() { | |||
return hostname + ":" + port + directory; | |||
} | |||
@@ -74,6 +75,7 @@ public class URLClassPath implements ClassPath { | |||
* | |||
* @return null if the class file could not be found. | |||
*/ | |||
@Override | |||
public InputStream openClassfile(String classname) { | |||
try { | |||
URLConnection con = openClassfile0(classname); | |||
@@ -90,8 +92,7 @@ public class URLClassPath implements ClassPath { | |||
= directory + classname.replace('.', '/') + ".class"; | |||
return fetchClass0(hostname, port, jarname); | |||
} | |||
else | |||
return null; // not found | |||
return null; // not found | |||
} | |||
/** | |||
@@ -99,6 +100,7 @@ public class URLClassPath implements ClassPath { | |||
* | |||
* @return null if the class file could not be obtained. | |||
*/ | |||
@Override | |||
public URL find(String classname) { | |||
try { | |||
URLConnection con = openClassfile0(classname); | |||
@@ -115,6 +117,7 @@ public class URLClassPath implements ClassPath { | |||
/** | |||
* Closes this class path. | |||
*/ | |||
@Override | |||
public void close() {} | |||
/** |
@@ -104,7 +104,8 @@ public class AnnotationDefaultAttribute extends AttributeInfo { | |||
/** | |||
* Copies this attribute and returns a new copy. | |||
*/ | |||
public AttributeInfo copy(ConstPool newCp, Map classnames) { | |||
@Override | |||
public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) { | |||
AnnotationsAttribute.Copier copier | |||
= new AnnotationsAttribute.Copier(info, constPool, newCp, classnames); | |||
try { | |||
@@ -154,6 +155,7 @@ public class AnnotationDefaultAttribute extends AttributeInfo { | |||
/** | |||
* Returns a string representation of this object. | |||
*/ | |||
@Override | |||
public String toString() { | |||
return getDefaultValue().toString(); | |||
} |
@@ -160,7 +160,8 @@ public class AnnotationsAttribute extends AttributeInfo { | |||
/** | |||
* Copies this attribute and returns a new copy. | |||
*/ | |||
public AttributeInfo copy(ConstPool newCp, Map classnames) { | |||
@Override | |||
public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) { | |||
Copier copier = new Copier(info, constPool, newCp, classnames); | |||
try { | |||
copier.annotationArray(); | |||
@@ -297,13 +298,15 @@ public class AnnotationsAttribute extends AttributeInfo { | |||
* @param oldname a JVM class name. | |||
* @param newname a JVM class name. | |||
*/ | |||
@Override | |||
void renameClass(String oldname, String newname) { | |||
HashMap map = new HashMap(); | |||
Map<String,String> map = new HashMap<String,String>(); | |||
map.put(oldname, newname); | |||
renameClass(map); | |||
} | |||
void renameClass(Map classnames) { | |||
@Override | |||
void renameClass(Map<String,String> classnames) { | |||
Renamer renamer = new Renamer(info, getConstPool(), classnames); | |||
try { | |||
renamer.annotationArray(); | |||
@@ -312,11 +315,13 @@ public class AnnotationsAttribute extends AttributeInfo { | |||
} | |||
} | |||
void getRefClasses(Map classnames) { renameClass(classnames); } | |||
@Override | |||
void getRefClasses(Map<String,String> classnames) { renameClass(classnames); } | |||
/** | |||
* Returns a string representation of this object. | |||
*/ | |||
@Override | |||
public String toString() { | |||
Annotation[] a = getAnnotations(); | |||
StringBuilder sbuf = new StringBuilder(); | |||
@@ -458,7 +463,7 @@ public class AnnotationsAttribute extends AttributeInfo { | |||
static class Renamer extends Walker { | |||
ConstPool cpool; | |||
Map classnames; | |||
Map<String,String> classnames; | |||
/** | |||
* Constructs a renamer. It renames some class names | |||
@@ -469,17 +474,19 @@ public class AnnotationsAttribute extends AttributeInfo { | |||
* @param map pairs of replaced and substituted class names. | |||
* It can be null. | |||
*/ | |||
Renamer(byte[] info, ConstPool cp, Map map) { | |||
Renamer(byte[] info, ConstPool cp, Map<String,String> map) { | |||
super(info); | |||
cpool = cp; | |||
classnames = map; | |||
} | |||
@Override | |||
int annotation(int pos, int type, int numPairs) throws Exception { | |||
renameType(pos - 4, type); | |||
return super.annotation(pos, type, numPairs); | |||
} | |||
@Override | |||
void enumMemberValue(int pos, int typeNameIndex, int constNameIndex) | |||
throws Exception | |||
{ | |||
@@ -487,6 +494,7 @@ public class AnnotationsAttribute extends AttributeInfo { | |||
super.enumMemberValue(pos, typeNameIndex, constNameIndex); | |||
} | |||
@Override | |||
void classMemberValue(int pos, int index) throws Exception { | |||
renameType(pos + 1, index); | |||
super.classMemberValue(pos, index); | |||
@@ -506,7 +514,7 @@ public class AnnotationsAttribute extends AttributeInfo { | |||
ByteArrayOutputStream output; | |||
AnnotationsWriter writer; | |||
ConstPool srcPool, destPool; | |||
Map classnames; | |||
Map<String,String> classnames; | |||
/** | |||
* Constructs a copier. This copier renames some class names | |||
@@ -519,11 +527,11 @@ public class AnnotationsAttribute extends AttributeInfo { | |||
* @param map pairs of replaced and substituted class names. | |||
* It can be null. | |||
*/ | |||
Copier(byte[] info, ConstPool src, ConstPool dest, Map map) { | |||
Copier(byte[] info, ConstPool src, ConstPool dest, Map<String,String> map) { | |||
this(info, src, dest, map, true); | |||
} | |||
Copier(byte[] info, ConstPool src, ConstPool dest, Map map, boolean makeWriter) { | |||
Copier(byte[] info, ConstPool src, ConstPool dest, Map<String,String> map, boolean makeWriter) { | |||
super(info); | |||
output = new ByteArrayOutputStream(); | |||
if (makeWriter) | |||
@@ -539,31 +547,37 @@ public class AnnotationsAttribute extends AttributeInfo { | |||
return output.toByteArray(); | |||
} | |||
@Override | |||
void parameters(int numParam, int pos) throws Exception { | |||
writer.numParameters(numParam); | |||
super.parameters(numParam, pos); | |||
} | |||
@Override | |||
int annotationArray(int pos, int num) throws Exception { | |||
writer.numAnnotations(num); | |||
return super.annotationArray(pos, num); | |||
} | |||
@Override | |||
int annotation(int pos, int type, int numPairs) throws Exception { | |||
writer.annotation(copyType(type), numPairs); | |||
return super.annotation(pos, type, numPairs); | |||
} | |||
@Override | |||
int memberValuePair(int pos, int nameIndex) throws Exception { | |||
writer.memberValuePair(copy(nameIndex)); | |||
return super.memberValuePair(pos, nameIndex); | |||
} | |||
@Override | |||
void constValueMember(int tag, int index) throws Exception { | |||
writer.constValueIndex(tag, copy(index)); | |||
super.constValueMember(tag, index); | |||
} | |||
@Override | |||
void enumMemberValue(int pos, int typeNameIndex, int constNameIndex) | |||
throws Exception | |||
{ | |||
@@ -571,16 +585,19 @@ public class AnnotationsAttribute extends AttributeInfo { | |||
super.enumMemberValue(pos, typeNameIndex, constNameIndex); | |||
} | |||
@Override | |||
void classMemberValue(int pos, int index) throws Exception { | |||
writer.classInfoIndex(copyType(index)); | |||
super.classMemberValue(pos, index); | |||
} | |||
@Override | |||
int annotationMemberValue(int pos) throws Exception { | |||
writer.annotationValue(); | |||
return super.annotationMemberValue(pos); | |||
} | |||
@Override | |||
int arrayMemberValue(int pos, int num) throws Exception { | |||
writer.arrayValue(num); | |||
return super.arrayMemberValue(pos, num); | |||
@@ -650,6 +667,7 @@ public class AnnotationsAttribute extends AttributeInfo { | |||
return currentMember; | |||
} | |||
@Override | |||
void parameters(int numParam, int pos) throws Exception { | |||
Annotation[][] params = new Annotation[numParam][]; | |||
for (int i = 0; i < numParam; ++i) { | |||
@@ -660,6 +678,7 @@ public class AnnotationsAttribute extends AttributeInfo { | |||
allParams = params; | |||
} | |||
@Override | |||
int annotationArray(int pos, int num) throws Exception { | |||
Annotation[] array = new Annotation[num]; | |||
for (int i = 0; i < num; ++i) { | |||
@@ -671,17 +690,20 @@ public class AnnotationsAttribute extends AttributeInfo { | |||
return pos; | |||
} | |||
@Override | |||
int annotation(int pos, int type, int numPairs) throws Exception { | |||
currentAnno = new Annotation(type, pool); | |||
return super.annotation(pos, type, numPairs); | |||
} | |||
@Override | |||
int memberValuePair(int pos, int nameIndex) throws Exception { | |||
pos = super.memberValuePair(pos, nameIndex); | |||
currentAnno.addMemberValue(nameIndex, currentMember); | |||
return pos; | |||
} | |||
@Override | |||
void constValueMember(int tag, int index) throws Exception { | |||
MemberValue m; | |||
ConstPool cp = pool; | |||
@@ -721,6 +743,7 @@ public class AnnotationsAttribute extends AttributeInfo { | |||
super.constValueMember(tag, index); | |||
} | |||
@Override | |||
void enumMemberValue(int pos, int typeNameIndex, int constNameIndex) | |||
throws Exception | |||
{ | |||
@@ -729,11 +752,13 @@ public class AnnotationsAttribute extends AttributeInfo { | |||
super.enumMemberValue(pos, typeNameIndex, constNameIndex); | |||
} | |||
@Override | |||
void classMemberValue(int pos, int index) throws Exception { | |||
currentMember = new ClassMemberValue(index, pool); | |||
super.classMemberValue(pos, index); | |||
} | |||
@Override | |||
int annotationMemberValue(int pos) throws Exception { | |||
Annotation anno = currentAnno; | |||
pos = super.annotationMemberValue(pos); | |||
@@ -742,6 +767,7 @@ public class AnnotationsAttribute extends AttributeInfo { | |||
return pos; | |||
} | |||
@Override | |||
int arrayMemberValue(int pos, int num) throws Exception { | |||
ArrayMemberValue amv = new ArrayMemberValue(pool); | |||
MemberValue[] elements = new MemberValue[num]; |
@@ -19,11 +19,12 @@ package javassist.bytecode; | |||
import java.io.DataInputStream; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
import java.util.Map; | |||
import java.util.ArrayList; | |||
import java.util.ListIterator; | |||
import java.util.List; | |||
import java.util.Arrays; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.ListIterator; | |||
import java.util.Map; | |||
// Note: if you define a new subclass of AttributeInfo, then | |||
// update AttributeInfo.read(), .copy(), and (maybe) write(). | |||
@@ -79,65 +80,58 @@ public class AttributeInfo { | |||
int name = in.readUnsignedShort(); | |||
String nameStr = cp.getUtf8Info(name); | |||
char first = nameStr.charAt(0); | |||
if (first < 'M') { | |||
if (first < 'E') { | |||
if (nameStr.equals(AnnotationDefaultAttribute.tag)) | |||
return new AnnotationDefaultAttribute(cp, name, in); | |||
else if (nameStr.equals(BootstrapMethodsAttribute.tag)) | |||
return new BootstrapMethodsAttribute(cp, name, in); | |||
else if (nameStr.equals(CodeAttribute.tag)) | |||
return new CodeAttribute(cp, name, in); | |||
else if (nameStr.equals(ConstantAttribute.tag)) | |||
return new ConstantAttribute(cp, name, in); | |||
else if (nameStr.equals(DeprecatedAttribute.tag)) | |||
return new DeprecatedAttribute(cp, name, in); | |||
} | |||
else { | |||
if (nameStr.equals(EnclosingMethodAttribute.tag)) | |||
return new EnclosingMethodAttribute(cp, name, in); | |||
else if (nameStr.equals(ExceptionsAttribute.tag)) | |||
return new ExceptionsAttribute(cp, name, in); | |||
else if (nameStr.equals(InnerClassesAttribute.tag)) | |||
return new InnerClassesAttribute(cp, name, in); | |||
else if (nameStr.equals(LineNumberAttribute.tag)) | |||
return new LineNumberAttribute(cp, name, in); | |||
else if (nameStr.equals(LocalVariableAttribute.tag)) | |||
return new LocalVariableAttribute(cp, name, in); | |||
else if (nameStr.equals(LocalVariableTypeAttribute.tag)) | |||
return new LocalVariableTypeAttribute(cp, name, in); | |||
} | |||
} | |||
else { | |||
if (first < 'S') { | |||
/* Note that the names of Annotations attributes begin with 'R'. | |||
*/ | |||
if (nameStr.equals(MethodParametersAttribute.tag)) | |||
return new MethodParametersAttribute(cp, name, in); | |||
else if (nameStr.equals(AnnotationsAttribute.visibleTag) | |||
|| nameStr.equals(AnnotationsAttribute.invisibleTag)) { | |||
// RuntimeVisibleAnnotations or RuntimeInvisibleAnnotations | |||
return new AnnotationsAttribute(cp, name, in); | |||
} | |||
else if (nameStr.equals(ParameterAnnotationsAttribute.visibleTag) | |||
|| nameStr.equals(ParameterAnnotationsAttribute.invisibleTag)) | |||
return new ParameterAnnotationsAttribute(cp, name, in); | |||
else if (nameStr.equals(TypeAnnotationsAttribute.visibleTag) | |||
|| nameStr.equals(TypeAnnotationsAttribute.invisibleTag)) | |||
return new TypeAnnotationsAttribute(cp, name, in); | |||
} | |||
else { | |||
if (nameStr.equals(SignatureAttribute.tag)) | |||
return new SignatureAttribute(cp, name, in); | |||
else if (nameStr.equals(SourceFileAttribute.tag)) | |||
return new SourceFileAttribute(cp, name, in); | |||
else if (nameStr.equals(SyntheticAttribute.tag)) | |||
return new SyntheticAttribute(cp, name, in); | |||
else if (nameStr.equals(StackMap.tag)) | |||
return new StackMap(cp, name, in); | |||
else if (nameStr.equals(StackMapTable.tag)) | |||
return new StackMapTable(cp, name, in); | |||
} | |||
} | |||
if (first < 'E') | |||
if (nameStr.equals(AnnotationDefaultAttribute.tag)) | |||
return new AnnotationDefaultAttribute(cp, name, in); | |||
else if (nameStr.equals(BootstrapMethodsAttribute.tag)) | |||
return new BootstrapMethodsAttribute(cp, name, in); | |||
else if (nameStr.equals(CodeAttribute.tag)) | |||
return new CodeAttribute(cp, name, in); | |||
else if (nameStr.equals(ConstantAttribute.tag)) | |||
return new ConstantAttribute(cp, name, in); | |||
else if (nameStr.equals(DeprecatedAttribute.tag)) | |||
return new DeprecatedAttribute(cp, name, in); | |||
if (first < 'M') | |||
if (nameStr.equals(EnclosingMethodAttribute.tag)) | |||
return new EnclosingMethodAttribute(cp, name, in); | |||
else if (nameStr.equals(ExceptionsAttribute.tag)) | |||
return new ExceptionsAttribute(cp, name, in); | |||
else if (nameStr.equals(InnerClassesAttribute.tag)) | |||
return new InnerClassesAttribute(cp, name, in); | |||
else if (nameStr.equals(LineNumberAttribute.tag)) | |||
return new LineNumberAttribute(cp, name, in); | |||
else if (nameStr.equals(LocalVariableAttribute.tag)) | |||
return new LocalVariableAttribute(cp, name, in); | |||
else if (nameStr.equals(LocalVariableTypeAttribute.tag)) | |||
return new LocalVariableTypeAttribute(cp, name, in); | |||
if (first < 'S') | |||
/* Note that the names of Annotations attributes begin with 'R'. */ | |||
if (nameStr.equals(MethodParametersAttribute.tag)) | |||
return new MethodParametersAttribute(cp, name, in); | |||
else if (nameStr.equals(AnnotationsAttribute.visibleTag) | |||
|| nameStr.equals(AnnotationsAttribute.invisibleTag)) | |||
// RuntimeVisibleAnnotations or RuntimeInvisibleAnnotations | |||
return new AnnotationsAttribute(cp, name, in); | |||
else if (nameStr.equals(ParameterAnnotationsAttribute.visibleTag) | |||
|| nameStr.equals(ParameterAnnotationsAttribute.invisibleTag)) | |||
return new ParameterAnnotationsAttribute(cp, name, in); | |||
else if (nameStr.equals(TypeAnnotationsAttribute.visibleTag) | |||
|| nameStr.equals(TypeAnnotationsAttribute.invisibleTag)) | |||
return new TypeAnnotationsAttribute(cp, name, in); | |||
if (first >= 'S') | |||
if (nameStr.equals(SignatureAttribute.tag)) | |||
return new SignatureAttribute(cp, name, in); | |||
else if (nameStr.equals(SourceFileAttribute.tag)) | |||
return new SourceFileAttribute(cp, name, in); | |||
else if (nameStr.equals(SyntheticAttribute.tag)) | |||
return new SyntheticAttribute(cp, name, in); | |||
else if (nameStr.equals(StackMap.tag)) | |||
return new StackMap(cp, name, in); | |||
else if (nameStr.equals(StackMapTable.tag)) | |||
return new StackMapTable(cp, name, in); | |||
return new AttributeInfo(cp, name, in); | |||
} | |||
@@ -189,88 +183,68 @@ public class AttributeInfo { | |||
* @param classnames pairs of replaced and substituted | |||
* class names. | |||
*/ | |||
public AttributeInfo copy(ConstPool newCp, Map classnames) { | |||
int s = info.length; | |||
byte[] srcInfo = info; | |||
byte[] newInfo = new byte[s]; | |||
for (int i = 0; i < s; ++i) | |||
newInfo[i] = srcInfo[i]; | |||
return new AttributeInfo(newCp, getName(), newInfo); | |||
public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) | |||
{ | |||
return new AttributeInfo(newCp, getName(), Arrays.copyOf(info, info.length)); | |||
} | |||
void write(DataOutputStream out) throws IOException { | |||
void write(DataOutputStream out) throws IOException | |||
{ | |||
out.writeShort(name); | |||
out.writeInt(info.length); | |||
if (info.length > 0) | |||
out.write(info); | |||
} | |||
static int getLength(ArrayList list) { | |||
static int getLength(List<AttributeInfo> attributes) { | |||
int size = 0; | |||
int n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
AttributeInfo attr = (AttributeInfo)list.get(i); | |||
for (AttributeInfo attr:attributes) | |||
size += attr.length(); | |||
} | |||
return size; | |||
} | |||
static AttributeInfo lookup(ArrayList list, String name) { | |||
if (list == null) | |||
static AttributeInfo lookup(List<AttributeInfo> attributes, String name) { | |||
if (attributes == null) | |||
return null; | |||
ListIterator iterator = list.listIterator(); | |||
while (iterator.hasNext()) { | |||
AttributeInfo ai = (AttributeInfo)iterator.next(); | |||
for (AttributeInfo ai:attributes) | |||
if (ai.getName().equals(name)) | |||
return ai; | |||
} | |||
return null; // no such attribute | |||
} | |||
static synchronized AttributeInfo remove(ArrayList list, String name) { | |||
if (list == null) | |||
static synchronized AttributeInfo remove(List<AttributeInfo> attributes, String name) { | |||
if (attributes == null) | |||
return null; | |||
AttributeInfo removed = null; | |||
ListIterator iterator = list.listIterator(); | |||
while (iterator.hasNext()) { | |||
AttributeInfo ai = (AttributeInfo)iterator.next(); | |||
if (ai.getName().equals(name)) { | |||
iterator.remove(); | |||
removed = ai; | |||
} | |||
} | |||
return removed; | |||
for (AttributeInfo ai:attributes) | |||
if (ai.getName().equals(name)) | |||
if (attributes.remove(ai)) | |||
return ai; | |||
return null; | |||
} | |||
static void writeAll(ArrayList list, DataOutputStream out) | |||
static void writeAll(List<AttributeInfo> attributes, DataOutputStream out) | |||
throws IOException | |||
{ | |||
if (list == null) | |||
if (attributes == null) | |||
return; | |||
int n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
AttributeInfo attr = (AttributeInfo)list.get(i); | |||
for (AttributeInfo attr:attributes) | |||
attr.write(out); | |||
} | |||
} | |||
static ArrayList copyAll(ArrayList list, ConstPool cp) { | |||
if (list == null) | |||
static List<AttributeInfo> copyAll(List<AttributeInfo> attributes, ConstPool cp) { | |||
if (attributes == null) | |||
return null; | |||
ArrayList newList = new ArrayList(); | |||
int n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
AttributeInfo attr = (AttributeInfo)list.get(i); | |||
List<AttributeInfo> newList = new ArrayList<AttributeInfo>(); | |||
for (AttributeInfo attr:attributes) | |||
newList.add(attr.copy(cp, null)); | |||
} | |||
return newList; | |||
} | |||
@@ -282,31 +256,31 @@ public class AttributeInfo { | |||
* override these methods. | |||
*/ | |||
void renameClass(String oldname, String newname) {} | |||
void renameClass(Map classnames) {} | |||
void renameClass(Map<String,String> classnames) {} | |||
static void renameClass(List<AttributeInfo> attributes, String oldname, String newname) { | |||
if (attributes == null) | |||
return; | |||
static void renameClass(List attributes, String oldname, String newname) { | |||
Iterator iterator = attributes.iterator(); | |||
while (iterator.hasNext()) { | |||
AttributeInfo ai = (AttributeInfo)iterator.next(); | |||
for (AttributeInfo ai:attributes) | |||
ai.renameClass(oldname, newname); | |||
} | |||
} | |||
static void renameClass(List attributes, Map classnames) { | |||
Iterator iterator = attributes.iterator(); | |||
while (iterator.hasNext()) { | |||
AttributeInfo ai = (AttributeInfo)iterator.next(); | |||
static void renameClass(List<AttributeInfo> attributes, Map<String,String> classnames) { | |||
if (attributes == null) | |||
return; | |||
for (AttributeInfo ai:attributes) | |||
ai.renameClass(classnames); | |||
} | |||
} | |||
void getRefClasses(Map classnames) {} | |||
void getRefClasses(Map<String,String> classnames) {} | |||
static void getRefClasses(List<AttributeInfo> attributes, Map<String,String> classnames) { | |||
if (attributes == null) | |||
return; | |||
static void getRefClasses(List attributes, Map classnames) { | |||
Iterator iterator = attributes.iterator(); | |||
while (iterator.hasNext()) { | |||
AttributeInfo ai = (AttributeInfo)iterator.next(); | |||
for (AttributeInfo ai:attributes) | |||
ai.getRefClasses(classnames); | |||
} | |||
} | |||
} |
@@ -108,7 +108,8 @@ public class BootstrapMethodsAttribute extends AttributeInfo { | |||
* @param classnames pairs of replaced and substituted | |||
* class names. | |||
*/ | |||
public AttributeInfo copy(ConstPool newCp, Map classnames) { | |||
@Override | |||
public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) { | |||
BootstrapMethod[] methods = getMethods(); | |||
ConstPool thisCp = getConstPool(); | |||
for (int i = 0; i < methods.length; i++) { |
@@ -38,16 +38,19 @@ final class ByteStream extends OutputStream { | |||
count += len; | |||
} | |||
@Override | |||
public void write(byte[] data) { | |||
write(data, 0, data.length); | |||
} | |||
@Override | |||
public void write(byte[] data, int off, int len) { | |||
enlarge(len); | |||
System.arraycopy(data, off, buf, count, len); | |||
count += len; | |||
} | |||
@Override | |||
public void write(int b) { | |||
enlarge(1); | |||
int oldCount = count; |
@@ -28,6 +28,7 @@ class ByteVector implements Cloneable { | |||
size = 0; | |||
} | |||
@Override | |||
public Object clone() throws CloneNotSupportedException { | |||
ByteVector bv = (ByteVector)super.clone(); | |||
bv.buffer = (byte[])buffer.clone(); | |||
@@ -164,6 +165,7 @@ public class Bytecode extends ByteVector implements Cloneable, Opcode { | |||
* The constant pool object is shared between this object | |||
* and the cloned object. | |||
*/ | |||
@Override | |||
public Object clone() { | |||
try { | |||
Bytecode bc = (Bytecode)super.clone(); | |||
@@ -325,6 +327,7 @@ public class Bytecode extends ByteVector implements Cloneable, Opcode { | |||
* | |||
* @throws ArrayIndexOutOfBoundsException if offset is invalid. | |||
*/ | |||
@Override | |||
public int read(int offset) { | |||
return super.read(offset); | |||
} | |||
@@ -355,6 +358,7 @@ public class Bytecode extends ByteVector implements Cloneable, Opcode { | |||
* | |||
* @throws ArrayIndexOutOfBoundsException if offset is invalid. | |||
*/ | |||
@Override | |||
public void write(int offset, int value) { | |||
super.write(offset, value); | |||
} | |||
@@ -380,6 +384,7 @@ public class Bytecode extends ByteVector implements Cloneable, Opcode { | |||
/** | |||
* Appends an 8bit value to the end of the bytecode sequence. | |||
*/ | |||
@Override | |||
public void add(int code) { | |||
super.add(code); | |||
} | |||
@@ -396,6 +401,7 @@ public class Bytecode extends ByteVector implements Cloneable, Opcode { | |||
* | |||
* @param length the gap length in byte. | |||
*/ | |||
@Override | |||
public void addGap(int length) { | |||
super.addGap(length); | |||
} |
@@ -62,9 +62,9 @@ public final class ClassFile { | |||
int accessFlags; | |||
int superClass; | |||
int[] interfaces; | |||
ArrayList fields; | |||
ArrayList methods; | |||
ArrayList attributes; | |||
List<FieldInfo> fields; | |||
List<MethodInfo> methods; | |||
List<AttributeInfo> attributes; | |||
String thisclassname; // not JVM-internal name | |||
String[] cachedInterfaces; | |||
String cachedSuperclass; | |||
@@ -186,11 +186,11 @@ public final class ClassFile { | |||
initSuperclass(superclass); | |||
interfaces = null; | |||
fields = new ArrayList(); | |||
methods = new ArrayList(); | |||
fields = new ArrayList<FieldInfo>(); | |||
methods = new ArrayList<MethodInfo>(); | |||
thisclassname = classname; | |||
attributes = new ArrayList(); | |||
attributes = new ArrayList<AttributeInfo>(); | |||
attributes.add(new SourceFileAttribute(constPool, | |||
getSourcefileName(thisclassname))); | |||
} | |||
@@ -207,11 +207,7 @@ public final class ClassFile { | |||
} | |||
private static String getSourcefileName(String qname) { | |||
int index = qname.lastIndexOf('.'); | |||
if (index >= 0) | |||
qname = qname.substring(index + 1); | |||
return qname + ".java"; | |||
return qname.replaceAll("^.*\\.","") + ".java"; | |||
} | |||
/** | |||
@@ -221,19 +217,11 @@ public final class ClassFile { | |||
*/ | |||
public void compact() { | |||
ConstPool cp = compact0(); | |||
ArrayList list = methods; | |||
int n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
MethodInfo minfo = (MethodInfo)list.get(i); | |||
for (MethodInfo minfo:methods) | |||
minfo.compact(cp); | |||
} | |||
list = fields; | |||
n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
FieldInfo finfo = (FieldInfo)list.get(i); | |||
for (FieldInfo finfo:fields) | |||
finfo.compact(cp); | |||
} | |||
attributes = AttributeInfo.copyAll(attributes, cp); | |||
constPool = cp; | |||
@@ -246,12 +234,10 @@ public final class ClassFile { | |||
if (sc != null) | |||
superClass = cp.addClassInfo(getSuperclass()); | |||
if (interfaces != null) { | |||
int n = interfaces.length; | |||
for (int i = 0; i < n; ++i) | |||
if (interfaces != null) | |||
for (int i = 0; i < interfaces.length; ++i) | |||
interfaces[i] | |||
= cp.addClassInfo(constPool.getClassInfo(interfaces[i])); | |||
} | |||
return cp; | |||
} | |||
@@ -264,7 +250,7 @@ public final class ClassFile { | |||
*/ | |||
public void prune() { | |||
ConstPool cp = compact0(); | |||
ArrayList newAttributes = new ArrayList(); | |||
List<AttributeInfo> newAttributes = new ArrayList<AttributeInfo>(); | |||
AttributeInfo invisibleAnnotations | |||
= getAttribute(AnnotationsAttribute.invisibleTag); | |||
if (invisibleAnnotations != null) { | |||
@@ -279,26 +265,18 @@ public final class ClassFile { | |||
newAttributes.add(visibleAnnotations); | |||
} | |||
AttributeInfo signature | |||
AttributeInfo signature | |||
= getAttribute(SignatureAttribute.tag); | |||
if (signature != null) { | |||
signature = signature.copy(cp, null); | |||
newAttributes.add(signature); | |||
} | |||
ArrayList list = methods; | |||
int n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
MethodInfo minfo = (MethodInfo)list.get(i); | |||
for (MethodInfo minfo:methods) | |||
minfo.prune(cp); | |||
} | |||
list = fields; | |||
n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
FieldInfo finfo = (FieldInfo)list.get(i); | |||
for (FieldInfo finfo:fields) | |||
finfo.prune(cp); | |||
} | |||
attributes = newAttributes; | |||
constPool = cp; | |||
@@ -423,12 +401,8 @@ public final class ClassFile { | |||
try { | |||
this.superClass = constPool.addClassInfo(superclass); | |||
ArrayList list = methods; | |||
int n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
MethodInfo minfo = (MethodInfo)list.get(i); | |||
for (MethodInfo minfo:methods) | |||
minfo.setSuperclass(superclass); | |||
} | |||
} | |||
catch (BadBytecode e) { | |||
throw new CannotCompileException(e); | |||
@@ -451,9 +425,6 @@ public final class ClassFile { | |||
* the substituted class name | |||
*/ | |||
public final void renameClass(String oldname, String newname) { | |||
ArrayList list; | |||
int n; | |||
if (oldname.equals(newname)) | |||
return; | |||
@@ -465,19 +436,13 @@ public final class ClassFile { | |||
constPool.renameClass(oldname, newname); | |||
AttributeInfo.renameClass(attributes, oldname, newname); | |||
list = methods; | |||
n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
MethodInfo minfo = (MethodInfo)list.get(i); | |||
for (MethodInfo minfo :methods) { | |||
String desc = minfo.getDescriptor(); | |||
minfo.setDescriptor(Descriptor.rename(desc, oldname, newname)); | |||
AttributeInfo.renameClass(minfo.getAttributes(), oldname, newname); | |||
} | |||
list = fields; | |||
n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
FieldInfo finfo = (FieldInfo)list.get(i); | |||
for (FieldInfo finfo:fields) { | |||
String desc = finfo.getDescriptor(); | |||
finfo.setDescriptor(Descriptor.rename(desc, oldname, newname)); | |||
AttributeInfo.renameClass(finfo.getAttributes(), oldname, newname); | |||
@@ -493,8 +458,8 @@ public final class ClassFile { | |||
* representation like <code>java/lang/Object</code>. | |||
* @see #renameClass(String,String) | |||
*/ | |||
public final void renameClass(Map classnames) { | |||
String jvmNewThisName = (String)classnames.get(Descriptor | |||
public final void renameClass(Map<String,String> classnames) { | |||
String jvmNewThisName = classnames.get(Descriptor | |||
.toJvmName(thisclassname)); | |||
if (jvmNewThisName != null) | |||
thisclassname = Descriptor.toJavaName(jvmNewThisName); | |||
@@ -502,19 +467,13 @@ public final class ClassFile { | |||
constPool.renameClass(classnames); | |||
AttributeInfo.renameClass(attributes, classnames); | |||
ArrayList list = methods; | |||
int n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
MethodInfo minfo = (MethodInfo)list.get(i); | |||
for (MethodInfo minfo:methods) { | |||
String desc = minfo.getDescriptor(); | |||
minfo.setDescriptor(Descriptor.rename(desc, classnames)); | |||
AttributeInfo.renameClass(minfo.getAttributes(), classnames); | |||
} | |||
list = fields; | |||
n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
FieldInfo finfo = (FieldInfo)list.get(i); | |||
for (FieldInfo finfo:fields) { | |||
String desc = finfo.getDescriptor(); | |||
finfo.setDescriptor(Descriptor.rename(desc, classnames)); | |||
AttributeInfo.renameClass(finfo.getAttributes(), classnames); | |||
@@ -525,23 +484,17 @@ public final class ClassFile { | |||
* Internal-use only. | |||
* <code>CtClass.getRefClasses()</code> calls this method. | |||
*/ | |||
public final void getRefClasses(Map classnames) { | |||
public final void getRefClasses(Map<String,String> classnames) { | |||
constPool.renameClass(classnames); | |||
AttributeInfo.getRefClasses(attributes, classnames); | |||
ArrayList list = methods; | |||
int n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
MethodInfo minfo = (MethodInfo)list.get(i); | |||
for (MethodInfo minfo:methods) { | |||
String desc = minfo.getDescriptor(); | |||
Descriptor.rename(desc, classnames); | |||
AttributeInfo.getRefClasses(minfo.getAttributes(), classnames); | |||
} | |||
list = fields; | |||
n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
FieldInfo finfo = (FieldInfo)list.get(i); | |||
for (FieldInfo finfo:fields) { | |||
String desc = finfo.getDescriptor(); | |||
Descriptor.rename(desc, classnames); | |||
AttributeInfo.getRefClasses(finfo.getAttributes(), classnames); | |||
@@ -560,9 +513,8 @@ public final class ClassFile { | |||
if (interfaces == null) | |||
rtn = new String[0]; | |||
else { | |||
int n = interfaces.length; | |||
String[] list = new String[n]; | |||
for (int i = 0; i < n; ++i) | |||
String[] list = new String[interfaces.length]; | |||
for (int i = 0; i < interfaces.length; ++i) | |||
list[i] = constPool.getClassInfo(interfaces[i]); | |||
rtn = list; | |||
@@ -581,9 +533,8 @@ public final class ClassFile { | |||
public void setInterfaces(String[] nameList) { | |||
cachedInterfaces = null; | |||
if (nameList != null) { | |||
int n = nameList.length; | |||
interfaces = new int[n]; | |||
for (int i = 0; i < n; ++i) | |||
interfaces = new int[nameList.length]; | |||
for (int i = 0; i < nameList.length; ++i) | |||
interfaces[i] = constPool.addClassInfo(nameList[i]); | |||
} | |||
} | |||
@@ -613,7 +564,7 @@ public final class ClassFile { | |||
* @return a list of <code>FieldInfo</code>. | |||
* @see FieldInfo | |||
*/ | |||
public List getFields() { | |||
public List<FieldInfo> getFields() { | |||
return fields; | |||
} | |||
@@ -641,12 +592,9 @@ public final class ClassFile { | |||
private void testExistingField(String name, String descriptor) | |||
throws DuplicateMemberException { | |||
ListIterator it = fields.listIterator(0); | |||
while (it.hasNext()) { | |||
FieldInfo minfo = (FieldInfo)it.next(); | |||
for (FieldInfo minfo:fields) | |||
if (minfo.getName().equals(name)) | |||
throw new DuplicateMemberException("duplicate field: " + name); | |||
} | |||
} | |||
/** | |||
@@ -655,7 +603,7 @@ public final class ClassFile { | |||
* @return a list of <code>MethodInfo</code>. | |||
* @see MethodInfo | |||
*/ | |||
public List getMethods() { | |||
public List<MethodInfo> getMethods() { | |||
return methods; | |||
} | |||
@@ -666,14 +614,9 @@ public final class ClassFile { | |||
* @return null if no such method is found. | |||
*/ | |||
public MethodInfo getMethod(String name) { | |||
ArrayList list = methods; | |||
int n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
MethodInfo minfo = (MethodInfo)list.get(i); | |||
for (MethodInfo minfo:methods) | |||
if (minfo.getName().equals(name)) | |||
return minfo; | |||
} | |||
return null; | |||
} | |||
@@ -714,16 +657,16 @@ public final class ClassFile { | |||
{ | |||
String name = newMinfo.getName(); | |||
String descriptor = newMinfo.getDescriptor(); | |||
ListIterator it = methods.listIterator(0); | |||
ListIterator<MethodInfo> it = methods.listIterator(0); | |||
while (it.hasNext()) | |||
if (isDuplicated(newMinfo, name, descriptor, (MethodInfo)it.next(), it)) | |||
if (isDuplicated(newMinfo, name, descriptor, it.next(), it)) | |||
throw new DuplicateMemberException("duplicate method: " + name | |||
+ " in " + this.getName()); | |||
} | |||
private static boolean isDuplicated(MethodInfo newMethod, String newName, | |||
String newDesc, MethodInfo minfo, | |||
ListIterator it) | |||
ListIterator<MethodInfo> it) | |||
{ | |||
if (!minfo.getName().equals(newName)) | |||
return false; | |||
@@ -735,14 +678,11 @@ public final class ClassFile { | |||
if (desc.equals(newDesc)) { | |||
if (notBridgeMethod(minfo)) | |||
return true; | |||
else { | |||
// if the bridge method with the same signature | |||
// already exists, replace it. | |||
it.remove(); | |||
return false; | |||
} | |||
it.remove(); | |||
return false; | |||
} | |||
else | |||
return false; | |||
// return notBridgeMethod(minfo) && notBridgeMethod(newMethod); | |||
} | |||
@@ -763,7 +703,7 @@ public final class ClassFile { | |||
* @return a list of <code>AttributeInfo</code> objects. | |||
* @see AttributeInfo | |||
*/ | |||
public List getAttributes() { | |||
public List<AttributeInfo> getAttributes() { | |||
return attributes; | |||
} | |||
@@ -776,19 +716,14 @@ public final class ClassFile { | |||
* {@link AnnotationsAttribute#visibleTag} or | |||
* {@link AnnotationsAttribute#invisibleTag}. | |||
* </p> | |||
* | |||
* | |||
* @param name attribute name | |||
* @see #getAttributes() | |||
*/ | |||
public AttributeInfo getAttribute(String name) { | |||
ArrayList list = attributes; | |||
int n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
AttributeInfo ai = (AttributeInfo)list.get(i); | |||
for (AttributeInfo ai:attributes) | |||
if (ai.getName().equals(name)) | |||
return ai; | |||
} | |||
return null; | |||
} | |||
@@ -824,8 +759,7 @@ public final class ClassFile { | |||
= (SourceFileAttribute)getAttribute(SourceFileAttribute.tag); | |||
if (sf == null) | |||
return null; | |||
else | |||
return sf.getFileName(); | |||
return sf.getFileName(); | |||
} | |||
private void read(DataInputStream in) throws IOException { | |||
@@ -852,16 +786,16 @@ public final class ClassFile { | |||
ConstPool cp = constPool; | |||
n = in.readUnsignedShort(); | |||
fields = new ArrayList(); | |||
fields = new ArrayList<FieldInfo>(); | |||
for (i = 0; i < n; ++i) | |||
addField2(new FieldInfo(cp, in)); | |||
n = in.readUnsignedShort(); | |||
methods = new ArrayList(); | |||
methods = new ArrayList<MethodInfo>(); | |||
for (i = 0; i < n; ++i) | |||
addMethod2(new MethodInfo(cp, in)); | |||
attributes = new ArrayList(); | |||
attributes = new ArrayList<AttributeInfo>(); | |||
n = in.readUnsignedShort(); | |||
for (i = 0; i < n; ++i) | |||
addAttribute(AttributeInfo.read(cp, in)); | |||
@@ -892,21 +826,16 @@ public final class ClassFile { | |||
for (i = 0; i < n; ++i) | |||
out.writeShort(interfaces[i]); | |||
ArrayList list = fields; | |||
n = list.size(); | |||
n = fields.size(); | |||
out.writeShort(n); | |||
for (i = 0; i < n; ++i) { | |||
FieldInfo finfo = (FieldInfo)list.get(i); | |||
FieldInfo finfo = fields.get(i); | |||
finfo.write(out); | |||
} | |||
list = methods; | |||
n = list.size(); | |||
out.writeShort(n); | |||
for (i = 0; i < n; ++i) { | |||
MethodInfo minfo = (MethodInfo)list.get(i); | |||
out.writeShort(methods.size()); | |||
for (MethodInfo minfo:methods) | |||
minfo.write(out); | |||
} | |||
out.writeShort(attributes.size()); | |||
AttributeInfo.writeAll(attributes, out); |
@@ -37,9 +37,6 @@ public class ClassFilePrinter { | |||
* Prints the contents of a class file. | |||
*/ | |||
public static void print(ClassFile cf, PrintWriter out) { | |||
List list; | |||
int n; | |||
/* 0x0020 (SYNCHRONIZED) means ACC_SUPER if the modifiers | |||
* are of a class. | |||
*/ | |||
@@ -62,10 +59,8 @@ public class ClassFilePrinter { | |||
} | |||
out.println(); | |||
list = cf.getFields(); | |||
n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
FieldInfo finfo = (FieldInfo)list.get(i); | |||
List<FieldInfo> fields = cf.getFields(); | |||
for (FieldInfo finfo:fields) { | |||
int acc = finfo.getAccessFlags(); | |||
out.println(Modifier.toString(AccessFlag.toModifier(acc)) | |||
+ " " + finfo.getName() + "\t" | |||
@@ -74,10 +69,8 @@ public class ClassFilePrinter { | |||
} | |||
out.println(); | |||
list = cf.getMethods(); | |||
n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
MethodInfo minfo = (MethodInfo)list.get(i); | |||
List<MethodInfo> methods = cf.getMethods(); | |||
for (MethodInfo minfo:methods) { | |||
int acc = minfo.getAccessFlags(); | |||
out.println(Modifier.toString(AccessFlag.toModifier(acc)) | |||
+ " " + minfo.getName() + "\t" | |||
@@ -90,13 +83,11 @@ public class ClassFilePrinter { | |||
printAttributes(cf.getAttributes(), out, 'c'); | |||
} | |||
static void printAttributes(List list, PrintWriter out, char kind) { | |||
static void printAttributes(List<AttributeInfo> list, PrintWriter out, char kind) { | |||
if (list == null) | |||
return; | |||
int n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
AttributeInfo ai = (AttributeInfo)list.get(i); | |||
for (AttributeInfo ai:list) { | |||
if (ai instanceof CodeAttribute) { | |||
CodeAttribute ca = (CodeAttribute)ai; | |||
out.println("attribute: " + ai.getName() + ": " |
@@ -19,9 +19,8 @@ package javassist.bytecode; | |||
import java.io.DataInputStream; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
import java.util.List; | |||
import java.util.ArrayList; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Map; | |||
/** | |||
@@ -45,7 +44,7 @@ public class CodeAttribute extends AttributeInfo implements Opcode { | |||
private int maxStack; | |||
private int maxLocals; | |||
private ExceptionTable exceptions; | |||
private ArrayList attributes; | |||
private List<AttributeInfo> attributes; | |||
/** | |||
* Constructs a <code>Code_attribute</code>. | |||
@@ -64,7 +63,7 @@ public class CodeAttribute extends AttributeInfo implements Opcode { | |||
maxLocals = locals; | |||
info = code; | |||
exceptions = etable; | |||
attributes = new ArrayList(); | |||
attributes = new ArrayList<AttributeInfo>(); | |||
} | |||
/** | |||
@@ -76,7 +75,7 @@ public class CodeAttribute extends AttributeInfo implements Opcode { | |||
* @param classnames pairs of replaced and substituted | |||
* class names. | |||
*/ | |||
private CodeAttribute(ConstPool cp, CodeAttribute src, Map classnames) | |||
private CodeAttribute(ConstPool cp, CodeAttribute src, Map<String,String> classnames) | |||
throws BadBytecode | |||
{ | |||
super(cp, tag); | |||
@@ -84,11 +83,11 @@ public class CodeAttribute extends AttributeInfo implements Opcode { | |||
maxStack = src.getMaxStack(); | |||
maxLocals = src.getMaxLocals(); | |||
exceptions = src.getExceptionTable().copy(cp, classnames); | |||
attributes = new ArrayList(); | |||
List src_attr = src.getAttributes(); | |||
attributes = new ArrayList<AttributeInfo>(); | |||
List<AttributeInfo> src_attr = src.getAttributes(); | |||
int num = src_attr.size(); | |||
for (int i = 0; i < num; ++i) { | |||
AttributeInfo ai = (AttributeInfo)src_attr.get(i); | |||
AttributeInfo ai = src_attr.get(i); | |||
attributes.add(ai.copy(cp, classnames)); | |||
} | |||
@@ -99,6 +98,7 @@ public class CodeAttribute extends AttributeInfo implements Opcode { | |||
throws IOException | |||
{ | |||
super(cp, name_id, (byte[])null); | |||
@SuppressWarnings("unused") | |||
int attr_len = in.readInt(); | |||
maxStack = in.readUnsignedShort(); | |||
@@ -110,7 +110,7 @@ public class CodeAttribute extends AttributeInfo implements Opcode { | |||
exceptions = new ExceptionTable(cp, in); | |||
attributes = new ArrayList(); | |||
attributes = new ArrayList<AttributeInfo>(); | |||
int num = in.readUnsignedShort(); | |||
for (int i = 0; i < num; ++i) | |||
attributes.add(AttributeInfo.read(cp, in)); | |||
@@ -130,7 +130,8 @@ public class CodeAttribute extends AttributeInfo implements Opcode { | |||
* | |||
* @return <code>CodeAttribute</code> object. | |||
*/ | |||
public AttributeInfo copy(ConstPool newCp, Map classnames) | |||
@Override | |||
public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) | |||
throws RuntimeCopyException | |||
{ | |||
try { | |||
@@ -162,11 +163,13 @@ public class CodeAttribute extends AttributeInfo implements Opcode { | |||
* structure. | |||
* The returned value is <code>attribute_length + 6</code>. | |||
*/ | |||
@Override | |||
public int length() { | |||
return 18 + info.length + exceptions.size() * 8 | |||
+ AttributeInfo.getLength(attributes); | |||
} | |||
@Override | |||
void write(DataOutputStream out) throws IOException { | |||
out.writeShort(name); // attribute_name_index | |||
out.writeInt(length() - 6); // attribute_length | |||
@@ -184,7 +187,8 @@ public class CodeAttribute extends AttributeInfo implements Opcode { | |||
* | |||
* @throws java.lang.UnsupportedOperationException always thrown. | |||
*/ | |||
public byte[] get() { | |||
@Override | |||
public byte[] get() { | |||
throw new UnsupportedOperationException("CodeAttribute.get()"); | |||
} | |||
@@ -193,19 +197,23 @@ public class CodeAttribute extends AttributeInfo implements Opcode { | |||
* | |||
* @throws java.lang.UnsupportedOperationException always thrown. | |||
*/ | |||
@Override | |||
public void set(byte[] newinfo) { | |||
throw new UnsupportedOperationException("CodeAttribute.set()"); | |||
} | |||
@Override | |||
void renameClass(String oldname, String newname) { | |||
AttributeInfo.renameClass(attributes, oldname, newname); | |||
} | |||
void renameClass(Map classnames) { | |||
@Override | |||
void renameClass(Map<String,String> classnames) { | |||
AttributeInfo.renameClass(attributes, classnames); | |||
} | |||
void getRefClasses(Map classnames) { | |||
@Override | |||
void getRefClasses(Map<String,String> classnames) { | |||
AttributeInfo.getRefClasses(attributes, classnames); | |||
} | |||
@@ -297,7 +305,7 @@ public class CodeAttribute extends AttributeInfo implements Opcode { | |||
* | |||
* @see AttributeInfo | |||
*/ | |||
public List getAttributes() { return attributes; } | |||
public List<AttributeInfo> getAttributes() { return attributes; } | |||
/** | |||
* Returns the attribute with the specified name. | |||
@@ -342,7 +350,7 @@ public class CodeAttribute extends AttributeInfo implements Opcode { | |||
/** | |||
* Copies code. | |||
*/ | |||
private byte[] copyCode(ConstPool destCp, Map classnames, | |||
private byte[] copyCode(ConstPool destCp, Map<String,String> classnames, | |||
ExceptionTable etable, CodeAttribute destCa) | |||
throws BadBytecode | |||
{ | |||
@@ -356,7 +364,7 @@ public class CodeAttribute extends AttributeInfo implements Opcode { | |||
private static LdcEntry copyCode(byte[] code, int beginPos, int endPos, | |||
ConstPool srcCp, byte[] newcode, | |||
ConstPool destCp, Map classnameMap) | |||
ConstPool destCp, Map<String,String> classnameMap) | |||
throws BadBytecode | |||
{ | |||
int i2, index; | |||
@@ -428,7 +436,7 @@ public class CodeAttribute extends AttributeInfo implements Opcode { | |||
private static void copyConstPoolInfo(int i, byte[] code, ConstPool srcCp, | |||
byte[] newcode, ConstPool destCp, | |||
Map classnameMap) { | |||
Map<String,String> classnameMap) { | |||
int index = ((code[i] & 0xff) << 8) | (code[i + 1] & 0xff); | |||
index = srcCp.copy(index, destCp, classnameMap); | |||
newcode[i] = (byte)(index >> 8); |
@@ -17,6 +17,7 @@ | |||
package javassist.bytecode; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
/** | |||
* An iterator for editing a code attribute. | |||
@@ -305,8 +306,8 @@ public class CodeIterator implements Opcode { | |||
String cname = cp.getMethodrefClassName(mref); | |||
if (cname.equals(thisClassName) == (skipThis > 0)) | |||
return index; | |||
else | |||
break; | |||
break; | |||
} | |||
} | |||
} | |||
@@ -772,19 +773,15 @@ public class CodeIterator implements Opcode { | |||
return index + 6; | |||
else | |||
return index + 4; // WIDE ... | |||
else { | |||
int index2 = (index & ~3) + 8; | |||
if (opcode == LOOKUPSWITCH) { | |||
int npairs = ByteArray.read32bit(code, index2); | |||
return index2 + npairs * 8 + 4; | |||
} | |||
else if (opcode == TABLESWITCH) { | |||
int low = ByteArray.read32bit(code, index2); | |||
int high = ByteArray.read32bit(code, index2 + 4); | |||
return index2 + (high - low + 1) * 4 + 8; | |||
} | |||
// else | |||
// throw new BadBytecode(opcode); | |||
int index2 = (index & ~3) + 8; | |||
if (opcode == LOOKUPSWITCH) { | |||
int npairs = ByteArray.read32bit(code, index2); | |||
return index2 + npairs * 8 + 4; | |||
} | |||
else if (opcode == TABLESWITCH) { | |||
int low = ByteArray.read32bit(code, index2); | |||
int high = ByteArray.read32bit(code, index2 + 4); | |||
return index2 + (high - low + 1) * 4 + 8; | |||
} | |||
} | |||
catch (IndexOutOfBoundsException e) { | |||
@@ -1078,7 +1075,7 @@ public class CodeIterator implements Opcode { | |||
throws BadBytecode | |||
{ | |||
Pointers pointers = new Pointers(0, 0, 0, etable, ca); | |||
ArrayList jumps = makeJumpList(code, code.length, pointers); | |||
List<Branch> jumps = makeJumpList(code, code.length, pointers); | |||
while (ldcs != null) { | |||
addLdcW(ldcs, jumps); | |||
ldcs = ldcs.next; | |||
@@ -1088,12 +1085,12 @@ public class CodeIterator implements Opcode { | |||
return r; | |||
} | |||
private static void addLdcW(CodeAttribute.LdcEntry ldcs, ArrayList jumps) { | |||
private static void addLdcW(CodeAttribute.LdcEntry ldcs, List<Branch> jumps) { | |||
int where = ldcs.where; | |||
LdcW ldcw = new LdcW(where, ldcs.index); | |||
int s = jumps.size(); | |||
for (int i = 0; i < s; i++) | |||
if (where < ((Branch)jumps.get(i)).orgPos) { | |||
if (where < jumps.get(i).orgPos) { | |||
jumps.add(i, ldcw); | |||
return; | |||
} | |||
@@ -1122,7 +1119,7 @@ public class CodeIterator implements Opcode { | |||
return code; | |||
Pointers pointers = new Pointers(currentPos, mark, where, etable, ca); | |||
ArrayList jumps = makeJumpList(code, code.length, pointers); | |||
List<Branch> jumps = makeJumpList(code, code.length, pointers); | |||
byte[] r = insertGap2w(code, where, gapLength, exclusive, jumps, pointers); | |||
currentPos = pointers.cursor; | |||
mark = pointers.mark; | |||
@@ -1139,42 +1136,39 @@ public class CodeIterator implements Opcode { | |||
} | |||
private static byte[] insertGap2w(byte[] code, int where, int gapLength, | |||
boolean exclusive, ArrayList jumps, Pointers ptrs) | |||
boolean exclusive, List<Branch> jumps, Pointers ptrs) | |||
throws BadBytecode | |||
{ | |||
int n = jumps.size(); | |||
if (gapLength > 0) { | |||
ptrs.shiftPc(where, gapLength, exclusive); | |||
for (int i = 0; i < n; i++) | |||
((Branch)jumps.get(i)).shift(where, gapLength, exclusive); | |||
for (Branch b:jumps) | |||
b.shift(where, gapLength, exclusive); | |||
} | |||
boolean unstable = true; | |||
do { | |||
while (unstable) { | |||
unstable = false; | |||
for (int i = 0; i < n; i++) { | |||
Branch b = (Branch)jumps.get(i); | |||
for (Branch b:jumps) { | |||
if (b.expanded()) { | |||
unstable = true; | |||
int p = b.pos; | |||
int delta = b.deltaSize(); | |||
ptrs.shiftPc(p, delta, false); | |||
for (int j = 0; j < n; j++) | |||
((Branch)jumps.get(j)).shift(p, delta, false); | |||
for (Branch bb:jumps) | |||
bb.shift(p, delta, false); | |||
} | |||
} | |||
} | |||
for (int i = 0; i < n; i++) { | |||
Branch b = (Branch)jumps.get(i); | |||
for (Branch b:jumps) { | |||
int diff = b.gapChanged(); | |||
if (diff > 0) { | |||
unstable = true; | |||
int p = b.pos; | |||
ptrs.shiftPc(p, diff, false); | |||
for (int j = 0; j < n; j++) | |||
((Branch)jumps.get(j)).shift(p, diff, false); | |||
for (Branch bb:jumps) | |||
bb.shift(p, diff, false); | |||
} | |||
} | |||
} while (unstable); | |||
@@ -1182,10 +1176,10 @@ public class CodeIterator implements Opcode { | |||
return makeExapndedCode(code, jumps, where, gapLength); | |||
} | |||
private static ArrayList makeJumpList(byte[] code, int endPos, Pointers ptrs) | |||
private static List<Branch> makeJumpList(byte[] code, int endPos, Pointers ptrs) | |||
throws BadBytecode | |||
{ | |||
ArrayList jumps = new ArrayList(); | |||
List<Branch> jumps = new ArrayList<Branch>(); | |||
int nextPos; | |||
for (int i = 0; i < endPos; i = nextPos) { | |||
nextPos = nextOpcode(code, i); | |||
@@ -1243,16 +1237,14 @@ public class CodeIterator implements Opcode { | |||
return jumps; | |||
} | |||
private static byte[] makeExapndedCode(byte[] code, ArrayList jumps, | |||
private static byte[] makeExapndedCode(byte[] code, List<Branch> jumps, | |||
int where, int gapLength) | |||
throws BadBytecode | |||
{ | |||
int n = jumps.size(); | |||
int size = code.length + gapLength; | |||
for (int i = 0; i < n; i++) { | |||
Branch b = (Branch)jumps.get(i); | |||
for (Branch b:jumps) | |||
size += b.deltaSize(); | |||
} | |||
byte[] newcode = new byte[size]; | |||
int src = 0, dest = 0, bindex = 0; | |||
@@ -1260,12 +1252,12 @@ public class CodeIterator implements Opcode { | |||
Branch b; | |||
int bpos; | |||
if (0 < n) { | |||
b = (Branch)jumps.get(0); | |||
b = jumps.get(0); | |||
bpos = b.orgPos; | |||
} | |||
else { | |||
b = null; | |||
bpos = len; // src will be never equal to bpos | |||
bpos = len; // src will be never equal to bpos | |||
} | |||
while (src < len) { | |||
@@ -1282,7 +1274,7 @@ public class CodeIterator implements Opcode { | |||
src += s; | |||
dest += s + b.deltaSize(); | |||
if (++bindex < n) { | |||
b = (Branch)jumps.get(bindex); | |||
b = jumps.get(bindex); | |||
bpos = b.orgPos; | |||
} | |||
else { | |||
@@ -1344,17 +1336,19 @@ public class CodeIterator implements Opcode { | |||
state = true; | |||
} | |||
@Override | |||
boolean expanded() { | |||
if (state) { | |||
state = false; | |||
return true; | |||
} | |||
else | |||
return false; | |||
return false; | |||
} | |||
@Override | |||
int deltaSize() { return 1; } | |||
@Override | |||
int write(int srcPos, byte[] code, int destPos, byte[] newcode) { | |||
newcode[destPos] = LDC_W; | |||
ByteArray.write16bit(index, newcode, destPos + 1); | |||
@@ -1375,6 +1369,7 @@ public class CodeIterator implements Opcode { | |||
state = BIT16; | |||
} | |||
@Override | |||
void shift(int where, int gapLength, boolean exclusive) { | |||
offset = shiftOffset(pos, offset, where, gapLength, exclusive); | |||
super.shift(where, gapLength, exclusive); | |||
@@ -1383,18 +1378,20 @@ public class CodeIterator implements Opcode { | |||
state = EXPAND; | |||
} | |||
@Override | |||
boolean expanded() { | |||
if (state == EXPAND) { | |||
state = BIT32; | |||
return true; | |||
} | |||
else | |||
return false; | |||
return false; | |||
} | |||
@Override | |||
abstract int deltaSize(); | |||
abstract void write32(int src, byte[] code, int dest, byte[] newcode); | |||
@Override | |||
int write(int src, byte[] code, int dest, byte[] newcode) { | |||
if (state == BIT32) | |||
write32(src, code, dest, newcode); | |||
@@ -1413,10 +1410,12 @@ public class CodeIterator implements Opcode { | |||
super(p, off); | |||
} | |||
@Override | |||
int deltaSize() { | |||
return state == BIT32 ? 2 : 0; | |||
} | |||
@Override | |||
void write32(int src, byte[] code, int dest, byte[] newcode) { | |||
newcode[dest] = (byte)(((code[src] & 0xff) == GOTO) ? GOTO_W : JSR_W); | |||
ByteArray.write32bit(offset, newcode, dest + 1); | |||
@@ -1429,10 +1428,12 @@ public class CodeIterator implements Opcode { | |||
super(p, off); | |||
} | |||
@Override | |||
int deltaSize() { | |||
return state == BIT32 ? 5 : 0; | |||
} | |||
@Override | |||
void write32(int src, byte[] code, int dest, byte[] newcode) { | |||
newcode[dest] = (byte)opcode(code[src] & 0xff); | |||
newcode[dest + 1] = 0; | |||
@@ -1446,12 +1447,9 @@ public class CodeIterator implements Opcode { | |||
return IFNONNULL; | |||
else if (op == IFNONNULL) | |||
return IFNULL; | |||
else { | |||
if (((op - IFEQ) & 1) == 0) | |||
return op + 1; | |||
else | |||
return op - 1; | |||
} | |||
if (((op - IFEQ) & 1) == 0) | |||
return op + 1; | |||
return op - 1; | |||
} | |||
} | |||
@@ -1463,11 +1461,13 @@ public class CodeIterator implements Opcode { | |||
offset = off; | |||
} | |||
@Override | |||
void shift(int where, int gapLength, boolean exclusive) { | |||
offset = shiftOffset(pos, offset, where, gapLength, exclusive); | |||
super.shift(where, gapLength, exclusive); | |||
} | |||
@Override | |||
int write(int src, byte[] code, int dest, byte[] newcode) { | |||
newcode[dest] = code[src]; | |||
ByteArray.write32bit(offset, newcode, dest + 1); | |||
@@ -1488,6 +1488,7 @@ public class CodeIterator implements Opcode { | |||
this.pointers = ptrs; | |||
} | |||
@Override | |||
void shift(int where, int gapLength, boolean exclusive) { | |||
int p = pos; | |||
defaultByte = shiftOffset(p, defaultByte, where, gapLength, exclusive); | |||
@@ -1498,6 +1499,7 @@ public class CodeIterator implements Opcode { | |||
super.shift(where, gapLength, exclusive); | |||
} | |||
@Override | |||
int gapChanged() { | |||
int newGap = 3 - (pos & 3); | |||
if (newGap > gap) { | |||
@@ -1509,10 +1511,12 @@ public class CodeIterator implements Opcode { | |||
return 0; | |||
} | |||
@Override | |||
int deltaSize() { | |||
return gap - (3 - (orgPos & 3)); | |||
} | |||
@Override | |||
int write(int src, byte[] code, int dest, byte[] newcode) throws BadBytecode { | |||
int padding = 3 - (pos & 3); | |||
int nops = gap - padding; | |||
@@ -1565,6 +1569,7 @@ public class CodeIterator implements Opcode { | |||
this.high = high; | |||
} | |||
@Override | |||
int write2(int dest, byte[] newcode) { | |||
ByteArray.write32bit(low, newcode, dest); | |||
ByteArray.write32bit(high, newcode, dest + 4); | |||
@@ -1578,6 +1583,7 @@ public class CodeIterator implements Opcode { | |||
return 8 + 4 * n; | |||
} | |||
@Override | |||
int tableSize() { return 8 + 4 * offsets.length; } | |||
} | |||
@@ -1589,6 +1595,7 @@ public class CodeIterator implements Opcode { | |||
this.matches = matches; | |||
} | |||
@Override | |||
int write2(int dest, byte[] newcode) { | |||
int n = matches.length; | |||
ByteArray.write32bit(n, newcode, dest); | |||
@@ -1602,6 +1609,7 @@ public class CodeIterator implements Opcode { | |||
return 4 + 8 * n; | |||
} | |||
@Override | |||
int tableSize() { return 4 + 8 * matches.length; } | |||
} | |||
} |
@@ -65,7 +65,8 @@ public class ConstantAttribute extends AttributeInfo { | |||
* @param classnames pairs of replaced and substituted | |||
* class names. | |||
*/ | |||
public AttributeInfo copy(ConstPool newCp, Map classnames) { | |||
@Override | |||
public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) { | |||
int index = getConstPool().copy(getConstantValue(), newCp, | |||
classnames); | |||
return new ConstantAttribute(newCp, index); |
@@ -50,7 +50,8 @@ public class DeprecatedAttribute extends AttributeInfo { | |||
* @param newCp the constant pool table used by the new copy. | |||
* @param classnames should be null. | |||
*/ | |||
public AttributeInfo copy(ConstPool newCp, Map classnames) { | |||
@Override | |||
public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) { | |||
return new DeprecatedAttribute(newCp); | |||
} | |||
} |
@@ -59,8 +59,7 @@ public class Descriptor { | |||
public static String toJvmName(CtClass clazz) { | |||
if (clazz.isArray()) | |||
return of(clazz); | |||
else | |||
return toJvmName(clazz.getName()); | |||
return toJvmName(clazz.getName()); | |||
} | |||
/** | |||
@@ -109,14 +108,12 @@ public class Descriptor { | |||
if (arrayDim == 0) | |||
return name; | |||
else { | |||
StringBuffer sbuf = new StringBuffer(name); | |||
do { | |||
sbuf.append("[]"); | |||
} while (--arrayDim > 0); | |||
StringBuffer sbuf = new StringBuffer(name); | |||
do { | |||
sbuf.append("[]"); | |||
} while (--arrayDim > 0); | |||
return sbuf.toString(); | |||
} | |||
return sbuf.toString(); | |||
} | |||
/** | |||
@@ -183,13 +180,11 @@ public class Descriptor { | |||
if (head == 0) | |||
return desc; | |||
else { | |||
int len = desc.length(); | |||
if (head < len) | |||
newdesc.append(desc.substring(head, len)); | |||
int len = desc.length(); | |||
if (head < len) | |||
newdesc.append(desc.substring(head, len)); | |||
return newdesc.toString(); | |||
} | |||
return newdesc.toString(); | |||
} | |||
/** | |||
@@ -200,7 +195,7 @@ public class Descriptor { | |||
* JVM class names. | |||
* @see Descriptor#toJvmName(String) | |||
*/ | |||
public static String rename(String desc, Map map) { | |||
public static String rename(String desc, Map<String,String> map) { | |||
if (map == null) | |||
return desc; | |||
@@ -218,7 +213,7 @@ public class Descriptor { | |||
i = k + 1; | |||
String name = desc.substring(j + 1, k); | |||
String name2 = (String)map.get(name); | |||
String name2 = map.get(name); | |||
if (name2 != null) { | |||
newdesc.append(desc.substring(head, j)); | |||
newdesc.append('L'); | |||
@@ -230,13 +225,11 @@ public class Descriptor { | |||
if (head == 0) | |||
return desc; | |||
else { | |||
int len = desc.length(); | |||
if (head < len) | |||
newdesc.append(desc.substring(head, len)); | |||
int len = desc.length(); | |||
if (head < len) | |||
newdesc.append(desc.substring(head, len)); | |||
return newdesc.toString(); | |||
} | |||
return newdesc.toString(); | |||
} | |||
/** | |||
@@ -329,15 +322,13 @@ public class Descriptor { | |||
int i = desc.indexOf(')'); | |||
if (i < 0) | |||
return desc; | |||
else { | |||
StringBuffer newdesc = new StringBuffer(); | |||
newdesc.append(desc.substring(0, i)); | |||
newdesc.append('L'); | |||
newdesc.append(classname.replace('.', '/')); | |||
newdesc.append(';'); | |||
newdesc.append(desc.substring(i)); | |||
return newdesc.toString(); | |||
} | |||
StringBuffer newdesc = new StringBuffer(); | |||
newdesc.append(desc.substring(0, i)); | |||
newdesc.append('L'); | |||
newdesc.append(classname.replace('.', '/')); | |||
newdesc.append(';'); | |||
newdesc.append(desc.substring(i)); | |||
return newdesc.toString(); | |||
} | |||
/** | |||
@@ -353,9 +344,8 @@ public class Descriptor { | |||
public static String insertParameter(String classname, String desc) { | |||
if (desc.charAt(0) != '(') | |||
return desc; | |||
else | |||
return "(L" + classname.replace('.', '/') + ';' | |||
+ desc.substring(1); | |||
return "(L" + classname.replace('.', '/') + ';' | |||
+ desc.substring(1); | |||
} | |||
/** | |||
@@ -370,13 +360,11 @@ public class Descriptor { | |||
int i = descriptor.indexOf(')'); | |||
if (i < 0) | |||
return descriptor; | |||
else { | |||
StringBuffer newdesc = new StringBuffer(); | |||
newdesc.append(descriptor.substring(0, i)); | |||
toDescriptor(newdesc, type); | |||
newdesc.append(descriptor.substring(i)); | |||
return newdesc.toString(); | |||
} | |||
StringBuffer newdesc = new StringBuffer(); | |||
newdesc.append(descriptor.substring(0, i)); | |||
toDescriptor(newdesc, type); | |||
newdesc.append(descriptor.substring(i)); | |||
return newdesc.toString(); | |||
} | |||
/** | |||
@@ -391,8 +379,7 @@ public class Descriptor { | |||
String descriptor) { | |||
if (descriptor.charAt(0) != '(') | |||
return descriptor; | |||
else | |||
return "(" + of(type) + descriptor.substring(1); | |||
return "(" + of(type) + descriptor.substring(1); | |||
} | |||
/** | |||
@@ -407,14 +394,12 @@ public class Descriptor { | |||
int i = desc.indexOf(')'); | |||
if (i < 0) | |||
return desc; | |||
else { | |||
StringBuffer newdesc = new StringBuffer(); | |||
newdesc.append(desc.substring(0, i + 1)); | |||
newdesc.append('L'); | |||
newdesc.append(classname.replace('.', '/')); | |||
newdesc.append(';'); | |||
return newdesc.toString(); | |||
} | |||
StringBuffer newdesc = new StringBuffer(); | |||
newdesc.append(desc.substring(0, i + 1)); | |||
newdesc.append('L'); | |||
newdesc.append(classname.replace('.', '/')); | |||
newdesc.append(';'); | |||
return newdesc.toString(); | |||
} | |||
/** | |||
@@ -430,16 +415,14 @@ public class Descriptor { | |||
{ | |||
if (desc.charAt(0) != '(') | |||
return null; | |||
else { | |||
int num = numOfParameters(desc); | |||
CtClass[] args = new CtClass[num]; | |||
int n = 0; | |||
int i = 1; | |||
do { | |||
i = toCtClass(cp, desc, i, args, n++); | |||
} while (i > 0); | |||
return args; | |||
} | |||
int num = numOfParameters(desc); | |||
CtClass[] args = new CtClass[num]; | |||
int n = 0; | |||
int i = 1; | |||
do { | |||
i = toCtClass(cp, desc, i, args, n++); | |||
} while (i > 0); | |||
return args; | |||
} | |||
/** | |||
@@ -484,11 +467,9 @@ public class Descriptor { | |||
int i = desc.indexOf(')'); | |||
if (i < 0) | |||
return null; | |||
else { | |||
CtClass[] type = new CtClass[1]; | |||
toCtClass(cp, desc, i + 1, type, 0); | |||
return type[0]; | |||
} | |||
CtClass[] type = new CtClass[1]; | |||
toCtClass(cp, desc, i + 1, type, 0); | |||
return type[0]; | |||
} | |||
/** | |||
@@ -542,11 +523,9 @@ public class Descriptor { | |||
int res = toCtClass(cp, desc, 0, clazz, 0); | |||
if (res >= 0) | |||
return clazz[0]; | |||
else { | |||
// maybe, you forgot to surround the class name with | |||
// L and ;. It violates the protocol, but I'm tolerant... | |||
return cp.get(desc.replace('/', '.')); | |||
} | |||
// maybe, you forgot to surround the class name with | |||
// L and ;. It violates the protocol, but I'm tolerant... | |||
return cp.get(desc.replace('/', '.')); | |||
} | |||
private static int toCtClass(ClassPool cp, String desc, int i, | |||
@@ -577,8 +556,7 @@ public class Descriptor { | |||
args[n] = type; | |||
return i2; // neither an array type or a class type | |||
} | |||
else | |||
name = type.getName(); | |||
name = type.getName(); | |||
} | |||
if (arrayDim > 0) { |
@@ -108,10 +108,8 @@ public class EnclosingMethodAttribute extends AttributeInfo { | |||
int mi = methodIndex(); | |||
if (mi == 0) | |||
return MethodInfo.nameClinit; | |||
else { | |||
int ni = cp.getNameAndTypeName(mi); | |||
return cp.getUtf8Info(ni); | |||
} | |||
int ni = cp.getNameAndTypeName(mi); | |||
return cp.getUtf8Info(ni); | |||
} | |||
/** | |||
@@ -132,11 +130,11 @@ public class EnclosingMethodAttribute extends AttributeInfo { | |||
* @param classnames pairs of replaced and substituted | |||
* class names. | |||
*/ | |||
public AttributeInfo copy(ConstPool newCp, Map classnames) { | |||
if (methodIndex() == 0) | |||
@Override | |||
public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) { | |||
if (methodIndex() == 0) | |||
return new EnclosingMethodAttribute(newCp, className()); | |||
else | |||
return new EnclosingMethodAttribute(newCp, className(), | |||
methodName(), methodDescriptor()); | |||
return new EnclosingMethodAttribute(newCp, className(), | |||
methodName(), methodDescriptor()); | |||
} | |||
} |
@@ -20,6 +20,7 @@ import java.io.DataInputStream; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import java.util.Map; | |||
class ExceptionTableEntry { | |||
@@ -41,7 +42,7 @@ class ExceptionTableEntry { | |||
*/ | |||
public class ExceptionTable implements Cloneable { | |||
private ConstPool constPool; | |||
private ArrayList entries; | |||
private List<ExceptionTableEntry> entries; | |||
/** | |||
* Constructs an <code>exception_table[]</code>. | |||
@@ -50,13 +51,13 @@ public class ExceptionTable implements Cloneable { | |||
*/ | |||
public ExceptionTable(ConstPool cp) { | |||
constPool = cp; | |||
entries = new ArrayList(); | |||
entries = new ArrayList<ExceptionTableEntry>(); | |||
} | |||
ExceptionTable(ConstPool cp, DataInputStream in) throws IOException { | |||
constPool = cp; | |||
int length = in.readUnsignedShort(); | |||
ArrayList list = new ArrayList(length); | |||
List<ExceptionTableEntry> list = new ArrayList<ExceptionTableEntry>(length); | |||
for (int i = 0; i < length; ++i) { | |||
int start = in.readUnsignedShort(); | |||
int end = in.readUnsignedShort(); | |||
@@ -73,9 +74,10 @@ public class ExceptionTable implements Cloneable { | |||
* The constant pool object is shared between this object | |||
* and the cloned object. | |||
*/ | |||
@Override | |||
public Object clone() throws CloneNotSupportedException { | |||
ExceptionTable r = (ExceptionTable)super.clone(); | |||
r.entries = new ArrayList(entries); | |||
r.entries = new ArrayList<ExceptionTableEntry>(entries); | |||
return r; | |||
} | |||
@@ -93,8 +95,7 @@ public class ExceptionTable implements Cloneable { | |||
* @param nth the <i>n</i>-th (>= 0). | |||
*/ | |||
public int startPc(int nth) { | |||
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth); | |||
return e.startPc; | |||
return entries.get(nth).startPc; | |||
} | |||
/** | |||
@@ -104,8 +105,7 @@ public class ExceptionTable implements Cloneable { | |||
* @param value new value. | |||
*/ | |||
public void setStartPc(int nth, int value) { | |||
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth); | |||
e.startPc = value; | |||
entries.get(nth).startPc = value; | |||
} | |||
/** | |||
@@ -114,8 +114,7 @@ public class ExceptionTable implements Cloneable { | |||
* @param nth the <i>n</i>-th (>= 0). | |||
*/ | |||
public int endPc(int nth) { | |||
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth); | |||
return e.endPc; | |||
return entries.get(nth).endPc; | |||
} | |||
/** | |||
@@ -125,8 +124,7 @@ public class ExceptionTable implements Cloneable { | |||
* @param value new value. | |||
*/ | |||
public void setEndPc(int nth, int value) { | |||
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth); | |||
e.endPc = value; | |||
entries.get(nth).endPc = value; | |||
} | |||
/** | |||
@@ -135,8 +133,7 @@ public class ExceptionTable implements Cloneable { | |||
* @param nth the <i>n</i>-th (>= 0). | |||
*/ | |||
public int handlerPc(int nth) { | |||
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth); | |||
return e.handlerPc; | |||
return entries.get(nth).handlerPc; | |||
} | |||
/** | |||
@@ -146,8 +143,7 @@ public class ExceptionTable implements Cloneable { | |||
* @param value new value. | |||
*/ | |||
public void setHandlerPc(int nth, int value) { | |||
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth); | |||
e.handlerPc = value; | |||
entries.get(nth).handlerPc = value; | |||
} | |||
/** | |||
@@ -158,8 +154,7 @@ public class ExceptionTable implements Cloneable { | |||
* or zero if this exception handler is for all exceptions. | |||
*/ | |||
public int catchType(int nth) { | |||
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth); | |||
return e.catchType; | |||
return entries.get(nth).catchType; | |||
} | |||
/** | |||
@@ -169,8 +164,7 @@ public class ExceptionTable implements Cloneable { | |||
* @param value new value. | |||
*/ | |||
public void setCatchType(int nth, int value) { | |||
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth); | |||
e.catchType = value; | |||
entries.get(nth).catchType = value; | |||
} | |||
/** | |||
@@ -183,8 +177,7 @@ public class ExceptionTable implements Cloneable { | |||
public void add(int index, ExceptionTable table, int offset) { | |||
int len = table.size(); | |||
while (--len >= 0) { | |||
ExceptionTableEntry e | |||
= (ExceptionTableEntry)table.entries.get(len); | |||
ExceptionTableEntry e = table.entries.get(len); | |||
add(index, e.startPc + offset, e.endPc + offset, | |||
e.handlerPc + offset, e.catchType); | |||
} | |||
@@ -236,12 +229,10 @@ public class ExceptionTable implements Cloneable { | |||
* @param classnames pairs of replaced and substituted | |||
* class names. | |||
*/ | |||
public ExceptionTable copy(ConstPool newCp, Map classnames) { | |||
public ExceptionTable copy(ConstPool newCp, Map<String,String> classnames) { | |||
ExceptionTable et = new ExceptionTable(newCp); | |||
ConstPool srcCp = constPool; | |||
int len = size(); | |||
for (int i = 0; i < len; ++i) { | |||
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(i); | |||
for (ExceptionTableEntry e:entries) { | |||
int type = srcCp.copy(e.catchType, newCp, classnames); | |||
et.add(e.startPc, e.endPc, e.handlerPc, type); | |||
} | |||
@@ -250,9 +241,7 @@ public class ExceptionTable implements Cloneable { | |||
} | |||
void shiftPc(int where, int gapLength, boolean exclusive) { | |||
int len = size(); | |||
for (int i = 0; i < len; ++i) { | |||
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(i); | |||
for (ExceptionTableEntry e:entries) { | |||
e.startPc = shiftPc(e.startPc, where, gapLength, exclusive); | |||
e.endPc = shiftPc(e.endPc, where, gapLength, exclusive); | |||
e.handlerPc = shiftPc(e.handlerPc, where, gapLength, exclusive); | |||
@@ -268,10 +257,8 @@ public class ExceptionTable implements Cloneable { | |||
} | |||
void write(DataOutputStream out) throws IOException { | |||
int len = size(); | |||
out.writeShort(len); // exception_table_length | |||
for (int i = 0; i < len; ++i) { | |||
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(i); | |||
out.writeShort(size()); // exception_table_length | |||
for (ExceptionTableEntry e:entries) { | |||
out.writeShort(e.startPc); | |||
out.writeShort(e.endPc); | |||
out.writeShort(e.handlerPc); |
@@ -42,7 +42,7 @@ public class ExceptionsAttribute extends AttributeInfo { | |||
* @param src source attribute. | |||
*/ | |||
private ExceptionsAttribute(ConstPool cp, ExceptionsAttribute src, | |||
Map classnames) { | |||
Map<String,String> classnames) { | |||
super(cp, tag); | |||
copyFrom(src, classnames); | |||
} | |||
@@ -67,7 +67,8 @@ public class ExceptionsAttribute extends AttributeInfo { | |||
* @param classnames pairs of replaced and substituted | |||
* class names. It can be <code>null</code>. | |||
*/ | |||
public AttributeInfo copy(ConstPool newCp, Map classnames) { | |||
@Override | |||
public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) { | |||
return new ExceptionsAttribute(newCp, this, classnames); | |||
} | |||
@@ -79,7 +80,7 @@ public class ExceptionsAttribute extends AttributeInfo { | |||
* @param classnames pairs of replaced and substituted | |||
* class names. | |||
*/ | |||
private void copyFrom(ExceptionsAttribute srcAttr, Map classnames) { | |||
private void copyFrom(ExceptionsAttribute srcAttr, Map<String,String> classnames) { | |||
ConstPool srcCp = srcAttr.constPool; | |||
ConstPool destCp = this.constPool; | |||
byte[] src = srcAttr.info; |
@@ -43,7 +43,7 @@ public final class FieldInfo { | |||
String cachedName; | |||
String cachedType; | |||
int descriptor; | |||
ArrayList attribute; // may be null. | |||
List<AttributeInfo> attribute; // may be null. | |||
private FieldInfo(ConstPool cp) { | |||
constPool = cp; | |||
@@ -75,6 +75,7 @@ public final class FieldInfo { | |||
/** | |||
* Returns a string representation of the object. | |||
*/ | |||
@Override | |||
public String toString() { | |||
return getName() + " " + getDescriptor(); | |||
} | |||
@@ -95,7 +96,7 @@ public final class FieldInfo { | |||
} | |||
void prune(ConstPool cp) { | |||
ArrayList newAttributes = new ArrayList(); | |||
List<AttributeInfo> newAttributes = new ArrayList<AttributeInfo>(); | |||
AttributeInfo invisibleAnnotations | |||
= getAttribute(AnnotationsAttribute.invisibleTag); | |||
if (invisibleAnnotations != null) { | |||
@@ -110,13 +111,13 @@ public final class FieldInfo { | |||
newAttributes.add(visibleAnnotations); | |||
} | |||
AttributeInfo signature | |||
AttributeInfo signature | |||
= getAttribute(SignatureAttribute.tag); | |||
if (signature != null) { | |||
signature = signature.copy(cp, null); | |||
newAttributes.add(signature); | |||
} | |||
int index = getConstantValue(); | |||
if (index != 0) { | |||
index = constPool.copy(index, cp, null); | |||
@@ -206,8 +207,7 @@ public final class FieldInfo { | |||
= (ConstantAttribute)getAttribute(ConstantAttribute.tag); | |||
if (attr == null) | |||
return 0; | |||
else | |||
return attr.getConstantValue(); | |||
return attr.getConstantValue(); | |||
} | |||
/** | |||
@@ -220,9 +220,9 @@ public final class FieldInfo { | |||
* @return a list of <code>AttributeInfo</code> objects. | |||
* @see AttributeInfo | |||
*/ | |||
public List getAttributes() { | |||
public List<AttributeInfo> getAttributes() { | |||
if (attribute == null) | |||
attribute = new ArrayList(); | |||
attribute = new ArrayList<AttributeInfo>(); | |||
return attribute; | |||
} | |||
@@ -262,7 +262,7 @@ public final class FieldInfo { | |||
*/ | |||
public void addAttribute(AttributeInfo info) { | |||
if (attribute == null) | |||
attribute = new ArrayList(); | |||
attribute = new ArrayList<AttributeInfo>(); | |||
AttributeInfo.remove(attribute, info.getName()); | |||
attribute.add(info); | |||
@@ -273,7 +273,7 @@ public final class FieldInfo { | |||
name = in.readUnsignedShort(); | |||
descriptor = in.readUnsignedShort(); | |||
int n = in.readUnsignedShort(); | |||
attribute = new ArrayList(); | |||
attribute = new ArrayList<AttributeInfo>(); | |||
for (int i = 0; i < n; ++i) | |||
attribute.add(AttributeInfo.read(constPool, in)); | |||
} |
@@ -73,8 +73,7 @@ public class InnerClassesAttribute extends AttributeInfo { | |||
int i = innerClassIndex(nth); | |||
if (i == 0) | |||
return null; | |||
else | |||
return constPool.getClassInfo(i); | |||
return constPool.getClassInfo(i); | |||
} | |||
/** | |||
@@ -102,8 +101,7 @@ public class InnerClassesAttribute extends AttributeInfo { | |||
int i = outerClassIndex(nth); | |||
if (i == 0) | |||
return null; | |||
else | |||
return constPool.getClassInfo(i); | |||
return constPool.getClassInfo(i); | |||
} | |||
/** | |||
@@ -131,8 +129,7 @@ public class InnerClassesAttribute extends AttributeInfo { | |||
int i = innerNameIndex(nth); | |||
if (i == 0) | |||
return null; | |||
else | |||
return constPool.getUtf8Info(i); | |||
return constPool.getUtf8Info(i); | |||
} | |||
/** | |||
@@ -257,7 +254,8 @@ public class InnerClassesAttribute extends AttributeInfo { | |||
* @param classnames pairs of replaced and substituted | |||
* class names. | |||
*/ | |||
public AttributeInfo copy(ConstPool newCp, Map classnames) { | |||
@Override | |||
public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) { | |||
byte[] src = get(); | |||
byte[] dest = new byte[src.length]; | |||
ConstPool cp = getConstPool(); |
@@ -156,7 +156,8 @@ public class LineNumberAttribute extends AttributeInfo { | |||
* @param newCp the constant pool table used by the new copy. | |||
* @param classnames should be null. | |||
*/ | |||
public AttributeInfo copy(ConstPool newCp, Map classnames) { | |||
@Override | |||
public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) { | |||
byte[] src = info; | |||
int num = src.length; | |||
byte[] dest = new byte[num]; |
@@ -53,6 +53,7 @@ public class LocalVariableAttribute extends AttributeInfo { | |||
* @since 3.1 | |||
* @deprecated | |||
*/ | |||
@Deprecated | |||
public LocalVariableAttribute(ConstPool cp, String name) { | |||
super(cp, name, new byte[2]); | |||
ByteArray.write16bit(0, info, 0); | |||
@@ -93,6 +94,7 @@ public class LocalVariableAttribute extends AttributeInfo { | |||
info = newInfo; | |||
} | |||
@Override | |||
void renameClass(String oldname, String newname) { | |||
ConstPool cp = getConstPool(); | |||
int n = tableLength(); | |||
@@ -111,7 +113,8 @@ public class LocalVariableAttribute extends AttributeInfo { | |||
return Descriptor.rename(desc, oldname, newname); | |||
} | |||
void renameClass(Map classnames) { | |||
@Override | |||
void renameClass(Map<String,String> classnames) { | |||
ConstPool cp = getConstPool(); | |||
int n = tableLength(); | |||
for (int i = 0; i < n; ++i) { | |||
@@ -125,7 +128,7 @@ public class LocalVariableAttribute extends AttributeInfo { | |||
} | |||
} | |||
String renameEntry(String desc, Map classnames) { | |||
String renameEntry(String desc, Map<String,String> classnames) { | |||
return Descriptor.rename(desc, classnames); | |||
} | |||
@@ -291,7 +294,8 @@ public class LocalVariableAttribute extends AttributeInfo { | |||
* @param newCp the constant pool table used by the new copy. | |||
* @param classnames should be null. | |||
*/ | |||
public AttributeInfo copy(ConstPool newCp, Map classnames) { | |||
@Override | |||
public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) { | |||
byte[] src = get(); | |||
byte[] dest = new byte[src.length]; | |||
ConstPool cp = getConstPool(); |
@@ -49,14 +49,17 @@ public class LocalVariableTypeAttribute extends LocalVariableAttribute { | |||
super(cp, tag, dest); | |||
} | |||
@Override | |||
String renameEntry(String desc, String oldname, String newname) { | |||
return SignatureAttribute.renameClass(desc, oldname, newname); | |||
} | |||
String renameEntry(String desc, Map classnames) { | |||
@Override | |||
String renameEntry(String desc, Map<String,String> classnames) { | |||
return SignatureAttribute.renameClass(desc, classnames); | |||
} | |||
@Override | |||
LocalVariableAttribute makeThisAttr(ConstPool cp, byte[] dest) { | |||
return new LocalVariableTypeAttribute(cp, dest); | |||
} |
@@ -59,7 +59,7 @@ public class MethodInfo { | |||
int name; | |||
String cachedName; | |||
int descriptor; | |||
ArrayList attribute; // may be null | |||
List<AttributeInfo> attribute; // may be null | |||
/** | |||
* If this value is true, Javassist maintains a <code>StackMap</code> attribute | |||
@@ -129,7 +129,8 @@ public class MethodInfo { | |||
* @see Descriptor | |||
*/ | |||
public MethodInfo(ConstPool cp, String methodname, MethodInfo src, | |||
Map classnameMap) throws BadBytecode { | |||
Map<String,String> classnameMap) throws BadBytecode | |||
{ | |||
this(cp); | |||
read(src, methodname, classnameMap); | |||
} | |||
@@ -137,6 +138,7 @@ public class MethodInfo { | |||
/** | |||
* Returns a string representation of the object. | |||
*/ | |||
@Override | |||
public String toString() { | |||
return getName() + " " + getDescriptor(); | |||
} | |||
@@ -157,7 +159,7 @@ public class MethodInfo { | |||
} | |||
void prune(ConstPool cp) { | |||
ArrayList newAttributes = new ArrayList(); | |||
List<AttributeInfo> newAttributes = new ArrayList<AttributeInfo>(); | |||
AttributeInfo invisibleAnnotations | |||
= getAttribute(AnnotationsAttribute.invisibleTag); | |||
@@ -304,9 +306,9 @@ public class MethodInfo { | |||
* @return a list of <code>AttributeInfo</code> objects. | |||
* @see AttributeInfo | |||
*/ | |||
public List getAttributes() { | |||
public List<AttributeInfo> getAttributes() { | |||
if (attribute == null) | |||
attribute = new ArrayList(); | |||
attribute = new ArrayList<AttributeInfo>(); | |||
return attribute; | |||
} | |||
@@ -347,7 +349,7 @@ public class MethodInfo { | |||
*/ | |||
public void addAttribute(AttributeInfo info) { | |||
if (attribute == null) | |||
attribute = new ArrayList(); | |||
attribute = new ArrayList<AttributeInfo>(); | |||
AttributeInfo.remove(attribute, info.getName()); | |||
attribute.add(info); | |||
@@ -391,7 +393,7 @@ public class MethodInfo { | |||
public void setExceptionsAttribute(ExceptionsAttribute cattr) { | |||
removeExceptionsAttribute(); | |||
if (attribute == null) | |||
attribute = new ArrayList(); | |||
attribute = new ArrayList<AttributeInfo>(); | |||
attribute.add(cattr); | |||
} | |||
@@ -413,7 +415,7 @@ public class MethodInfo { | |||
public void setCodeAttribute(CodeAttribute cattr) { | |||
removeCodeAttribute(); | |||
if (attribute == null) | |||
attribute = new ArrayList(); | |||
attribute = new ArrayList<AttributeInfo>(); | |||
attribute.add(cattr); | |||
} | |||
@@ -536,8 +538,7 @@ public class MethodInfo { | |||
} | |||
} | |||
private void read(MethodInfo src, String methodname, Map classnames) | |||
throws BadBytecode { | |||
private void read(MethodInfo src, String methodname, Map<String,String> classnames) { | |||
ConstPool destCp = constPool; | |||
accessFlags = src.accessFlags; | |||
name = destCp.addUtf8Info(methodname); | |||
@@ -547,7 +548,7 @@ public class MethodInfo { | |||
String desc2 = Descriptor.rename(desc, classnames); | |||
descriptor = destCp.addUtf8Info(desc2); | |||
attribute = new ArrayList(); | |||
attribute = new ArrayList<AttributeInfo>(); | |||
ExceptionsAttribute eattr = src.getExceptionsAttribute(); | |||
if (eattr != null) | |||
attribute.add(eattr.copy(destCp, classnames)); | |||
@@ -562,7 +563,7 @@ public class MethodInfo { | |||
name = in.readUnsignedShort(); | |||
descriptor = in.readUnsignedShort(); | |||
int n = in.readUnsignedShort(); | |||
attribute = new ArrayList(); | |||
attribute = new ArrayList<AttributeInfo>(); | |||
for (int i = 0; i < n; ++i) | |||
attribute.add(AttributeInfo.read(constPool, in)); | |||
} |
@@ -72,7 +72,8 @@ public class MethodParametersAttribute extends AttributeInfo { | |||
* @param newCp the constant pool table used by the new copy. | |||
* @param classnames ignored. | |||
*/ | |||
public AttributeInfo copy(ConstPool newCp, Map classnames) { | |||
@Override | |||
public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) { | |||
int s = size(); | |||
ConstPool cp = getConstPool(); | |||
String[] names = new String[s]; |
@@ -104,7 +104,8 @@ public class ParameterAnnotationsAttribute extends AttributeInfo { | |||
/** | |||
* Copies this attribute and returns a new copy. | |||
*/ | |||
public AttributeInfo copy(ConstPool newCp, Map classnames) { | |||
@Override | |||
public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) { | |||
Copier copier = new Copier(info, constPool, newCp, classnames); | |||
try { | |||
copier.parameters(); | |||
@@ -150,10 +151,8 @@ public class ParameterAnnotationsAttribute extends AttributeInfo { | |||
ByteArrayOutputStream output = new ByteArrayOutputStream(); | |||
AnnotationsWriter writer = new AnnotationsWriter(output, constPool); | |||
try { | |||
int n = params.length; | |||
writer.numParameters(n); | |||
for (int i = 0; i < n; ++i) { | |||
Annotation[] anno = params[i]; | |||
writer.numParameters(params.length); | |||
for (Annotation[] anno:params) { | |||
writer.numAnnotations(anno.length); | |||
for (int j = 0; j < anno.length; ++j) | |||
anno[j].write(writer); | |||
@@ -172,13 +171,15 @@ public class ParameterAnnotationsAttribute extends AttributeInfo { | |||
* @param oldname a JVM class name. | |||
* @param newname a JVM class name. | |||
*/ | |||
@Override | |||
void renameClass(String oldname, String newname) { | |||
HashMap map = new HashMap(); | |||
Map<String,String> map = new HashMap<String,String>(); | |||
map.put(oldname, newname); | |||
renameClass(map); | |||
} | |||
void renameClass(Map classnames) { | |||
@Override | |||
void renameClass(Map<String,String> classnames) { | |||
Renamer renamer = new Renamer(info, getConstPool(), classnames); | |||
try { | |||
renamer.parameters(); | |||
@@ -187,29 +188,23 @@ public class ParameterAnnotationsAttribute extends AttributeInfo { | |||
} | |||
} | |||
void getRefClasses(Map classnames) { renameClass(classnames); } | |||
@Override | |||
void getRefClasses(Map<String,String> classnames) { renameClass(classnames); } | |||
/** | |||
* Returns a string representation of this object. | |||
*/ | |||
@Override | |||
public String toString() { | |||
Annotation[][] aa = getAnnotations(); | |||
StringBuilder sbuf = new StringBuilder(); | |||
int k = 0; | |||
while (k < aa.length) { | |||
Annotation[] a = aa[k++]; | |||
int i = 0; | |||
while (i < a.length) { | |||
sbuf.append(a[i++].toString()); | |||
if (i != a.length) | |||
sbuf.append(" "); | |||
} | |||
for (Annotation[] a : aa) { | |||
for (Annotation i : a) | |||
sbuf.append(i.toString()).append(" "); | |||
if (k != aa.length) | |||
sbuf.append(", "); | |||
sbuf.append(", "); | |||
} | |||
return sbuf.toString(); | |||
return sbuf.toString().replaceAll(" (?=,)|, $",""); | |||
} | |||
} |
@@ -20,6 +20,9 @@ import java.io.DataInputStream; | |||
import java.io.IOException; | |||
import java.util.Map; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import javassist.CtClass; | |||
/** | |||
@@ -83,27 +86,30 @@ public class SignatureAttribute extends AttributeInfo { | |||
* @param classnames pairs of replaced and substituted | |||
* class names. | |||
*/ | |||
public AttributeInfo copy(ConstPool newCp, Map classnames) { | |||
@Override | |||
public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) { | |||
return new SignatureAttribute(newCp, getSignature()); | |||
} | |||
@Override | |||
void renameClass(String oldname, String newname) { | |||
String sig = renameClass(getSignature(), oldname, newname); | |||
setSignature(sig); | |||
} | |||
void renameClass(Map classnames) { | |||
@Override | |||
void renameClass(Map<String,String> classnames) { | |||
String sig = renameClass(getSignature(), classnames); | |||
setSignature(sig); | |||
} | |||
static String renameClass(String desc, String oldname, String newname) { | |||
Map map = new java.util.HashMap(); | |||
Map<String,String> map = new HashMap<String,String>(); | |||
map.put(oldname, newname); | |||
return renameClass(desc, map); | |||
} | |||
static String renameClass(String desc, Map map) { | |||
static String renameClass(String desc, Map<String,String> map) { | |||
if (map == null) | |||
return desc; | |||
@@ -132,7 +138,7 @@ public class SignatureAttribute extends AttributeInfo { | |||
catch (IndexOutOfBoundsException e) { break; } | |||
i = k + 1; | |||
String name = nameBuf.toString(); | |||
String name2 = (String)map.get(name); | |||
String name2 = map.get(name); | |||
if (name2 != null) { | |||
newdesc.append(desc.substring(head, j)); | |||
newdesc.append('L'); | |||
@@ -144,15 +150,14 @@ public class SignatureAttribute extends AttributeInfo { | |||
if (head == 0) | |||
return desc; | |||
else { | |||
int len = desc.length(); | |||
if (head < len) | |||
newdesc.append(desc.substring(head, len)); | |||
int len = desc.length(); | |||
if (head < len) | |||
newdesc.append(desc.substring(head, len)); | |||
return newdesc.toString(); | |||
} | |||
return newdesc.toString(); | |||
} | |||
@SuppressWarnings("unused") | |||
private static boolean isNamePart(int c) { | |||
return c != ';' && c != '<'; | |||
} | |||
@@ -164,10 +169,8 @@ public class SignatureAttribute extends AttributeInfo { | |||
int i = s.indexOf(ch, position); | |||
if (i < 0) | |||
throw error(s); | |||
else { | |||
position = i + 1; | |||
return i; | |||
} | |||
position = i + 1; | |||
return i; | |||
} | |||
} | |||
@@ -225,6 +228,7 @@ public class SignatureAttribute extends AttributeInfo { | |||
/** | |||
* Returns the string representation. | |||
*/ | |||
@Override | |||
public String toString() { | |||
StringBuffer sbuf = new StringBuffer(); | |||
@@ -314,6 +318,7 @@ public class SignatureAttribute extends AttributeInfo { | |||
/** | |||
* Returns the string representation. | |||
*/ | |||
@Override | |||
public String toString() { | |||
StringBuffer sbuf = new StringBuffer(); | |||
@@ -424,6 +429,7 @@ public class SignatureAttribute extends AttributeInfo { | |||
/** | |||
* Returns the string representation. | |||
*/ | |||
@Override | |||
public String toString() { | |||
StringBuffer sbuf = new StringBuffer(getName()); | |||
if (superClass != null) | |||
@@ -550,6 +556,7 @@ public class SignatureAttribute extends AttributeInfo { | |||
/** | |||
* Returns the string representation. | |||
*/ | |||
@Override | |||
public String toString() { | |||
if (wildcard == '*') | |||
return "?"; | |||
@@ -634,10 +641,12 @@ public class SignatureAttribute extends AttributeInfo { | |||
/** | |||
* Returns the string representation. | |||
*/ | |||
@Override | |||
public String toString() { | |||
return Descriptor.toClassName(Character.toString(descriptor)); | |||
} | |||
@Override | |||
void encode(StringBuffer sb) { | |||
sb.append(descriptor); | |||
} | |||
@@ -669,8 +678,7 @@ public class SignatureAttribute extends AttributeInfo { | |||
TypeArgument[] targs, ClassType parent) { | |||
if (parent == null) | |||
return new ClassType(s, b, e, targs); | |||
else | |||
return new NestedClassType(s, b, e, targs, parent); | |||
return new NestedClassType(s, b, e, targs, parent); | |||
} | |||
ClassType(String signature, int begin, int end, TypeArgument[] targs) { | |||
@@ -730,6 +738,7 @@ public class SignatureAttribute extends AttributeInfo { | |||
/** | |||
* Returns the string representation. | |||
*/ | |||
@Override | |||
public String toString() { | |||
StringBuffer sbuf = new StringBuffer(); | |||
ClassType parent = getDeclaringClass(); | |||
@@ -762,6 +771,7 @@ public class SignatureAttribute extends AttributeInfo { | |||
* For example, if the type is a nested class {@code foo.Bar.Baz}, | |||
* then {@code foo.Bar$Baz} is returned. | |||
*/ | |||
@Override | |||
public String jvmTypeName() { | |||
StringBuffer sbuf = new StringBuffer(); | |||
ClassType parent = getDeclaringClass(); | |||
@@ -771,6 +781,7 @@ public class SignatureAttribute extends AttributeInfo { | |||
return toString2(sbuf); | |||
} | |||
@Override | |||
void encode(StringBuffer sb) { | |||
sb.append('L'); | |||
encode2(sb); | |||
@@ -818,6 +829,7 @@ public class SignatureAttribute extends AttributeInfo { | |||
* Returns the class that declares this nested class. | |||
* This nested class is a member of that declaring class. | |||
*/ | |||
@Override | |||
public ClassType getDeclaringClass() { return parent; } | |||
} | |||
@@ -854,6 +866,7 @@ public class SignatureAttribute extends AttributeInfo { | |||
/** | |||
* Returns the string representation. | |||
*/ | |||
@Override | |||
public String toString() { | |||
StringBuffer sbuf = new StringBuffer(componentType.toString()); | |||
for (int i = 0; i < dim; i++) | |||
@@ -862,6 +875,7 @@ public class SignatureAttribute extends AttributeInfo { | |||
return sbuf.toString(); | |||
} | |||
@Override | |||
void encode(StringBuffer sb) { | |||
for (int i = 0; i < dim; i++) | |||
sb.append('['); | |||
@@ -899,10 +913,12 @@ public class SignatureAttribute extends AttributeInfo { | |||
/** | |||
* Returns the string representation. | |||
*/ | |||
@Override | |||
public String toString() { | |||
return name; | |||
} | |||
@Override | |||
void encode(StringBuffer sb) { | |||
sb.append('T').append(name).append(';'); | |||
} | |||
@@ -991,12 +1007,12 @@ public class SignatureAttribute extends AttributeInfo { | |||
TypeParameter[] tp = parseTypeParams(sig, cur); | |||
ClassType superClass = parseClassType(sig, cur); | |||
int sigLen = sig.length(); | |||
ArrayList ifArray = new ArrayList(); | |||
List<ClassType> ifArray = new ArrayList<ClassType>(); | |||
while (cur.position < sigLen && sig.charAt(cur.position) == 'L') | |||
ifArray.add(parseClassType(sig, cur)); | |||
ClassType[] ifs | |||
= (ClassType[])ifArray.toArray(new ClassType[ifArray.size()]); | |||
= ifArray.toArray(new ClassType[ifArray.size()]); | |||
return new ClassSignature(tp, superClass, ifs); | |||
} | |||
@@ -1008,7 +1024,7 @@ public class SignatureAttribute extends AttributeInfo { | |||
if (sig.charAt(cur.position++) != '(') | |||
throw error(sig); | |||
ArrayList params = new ArrayList(); | |||
List<Type> params = new ArrayList<Type>(); | |||
while (sig.charAt(cur.position) != ')') { | |||
Type t = parseType(sig, cur); | |||
params.add(t); | |||
@@ -1017,7 +1033,7 @@ public class SignatureAttribute extends AttributeInfo { | |||
cur.position++; | |||
Type ret = parseType(sig, cur); | |||
int sigLen = sig.length(); | |||
ArrayList exceptions = new ArrayList(); | |||
List<ObjectType> exceptions = new ArrayList<ObjectType>(); | |||
while (cur.position < sigLen && sig.charAt(cur.position) == '^') { | |||
cur.position++; | |||
ObjectType t = parseObjectType(sig, cur, false); | |||
@@ -1027,22 +1043,22 @@ public class SignatureAttribute extends AttributeInfo { | |||
exceptions.add(t); | |||
} | |||
Type[] p = (Type[])params.toArray(new Type[params.size()]); | |||
ObjectType[] ex = (ObjectType[])exceptions.toArray(new ObjectType[exceptions.size()]); | |||
Type[] p = params.toArray(new Type[params.size()]); | |||
ObjectType[] ex = exceptions.toArray(new ObjectType[exceptions.size()]); | |||
return new MethodSignature(tp, p, ret, ex); | |||
} | |||
private static TypeParameter[] parseTypeParams(String sig, Cursor cur) | |||
throws BadBytecode | |||
{ | |||
ArrayList typeParam = new ArrayList(); | |||
List<TypeParameter> typeParam = new ArrayList<TypeParameter>(); | |||
if (sig.charAt(cur.position) == '<') { | |||
cur.position++; | |||
while (sig.charAt(cur.position) != '>') { | |||
int nameBegin = cur.position; | |||
int nameEnd = cur.indexOf(sig, ':'); | |||
ObjectType classBound = parseObjectType(sig, cur, true); | |||
ArrayList ifBound = new ArrayList(); | |||
List<ObjectType> ifBound = new ArrayList<ObjectType>(); | |||
while (sig.charAt(cur.position) == ':') { | |||
cur.position++; | |||
ObjectType t = parseObjectType(sig, cur, false); | |||
@@ -1050,14 +1066,14 @@ public class SignatureAttribute extends AttributeInfo { | |||
} | |||
TypeParameter p = new TypeParameter(sig, nameBegin, nameEnd, | |||
classBound, (ObjectType[])ifBound.toArray(new ObjectType[ifBound.size()])); | |||
classBound, ifBound.toArray(new ObjectType[ifBound.size()])); | |||
typeParam.add(p); | |||
} | |||
cur.position++; | |||
} | |||
return (TypeParameter[])typeParam.toArray(new TypeParameter[typeParam.size()]); | |||
return typeParam.toArray(new TypeParameter[typeParam.size()]); | |||
} | |||
private static ObjectType parseObjectType(String sig, Cursor c, boolean dontThrow) | |||
@@ -1076,8 +1092,7 @@ public class SignatureAttribute extends AttributeInfo { | |||
default : | |||
if (dontThrow) | |||
return null; | |||
else | |||
throw error(sig); | |||
throw error(sig); | |||
} | |||
} | |||
@@ -1086,8 +1101,7 @@ public class SignatureAttribute extends AttributeInfo { | |||
{ | |||
if (sig.charAt(c.position) == 'L') | |||
return parseClassType2(sig, c, null); | |||
else | |||
throw error(sig); | |||
throw error(sig); | |||
} | |||
private static ClassType parseClassType2(String sig, Cursor c, ClassType parent) | |||
@@ -1112,12 +1126,11 @@ public class SignatureAttribute extends AttributeInfo { | |||
c.position--; | |||
return parseClassType2(sig, c, thisClass); | |||
} | |||
else | |||
return thisClass; | |||
return thisClass; | |||
} | |||
private static TypeArgument[] parseTypeArgs(String sig, Cursor c) throws BadBytecode { | |||
ArrayList args = new ArrayList(); | |||
List<TypeArgument> args = new ArrayList<TypeArgument>(); | |||
char t; | |||
while ((t = sig.charAt(c.position++)) != '>') { | |||
TypeArgument ta; | |||
@@ -1135,7 +1148,7 @@ public class SignatureAttribute extends AttributeInfo { | |||
args.add(ta); | |||
} | |||
return (TypeArgument[])args.toArray(new TypeArgument[args.size()]); | |||
return args.toArray(new TypeArgument[args.size()]); | |||
} | |||
private static ObjectType parseArray(String sig, Cursor c) throws BadBytecode { |
@@ -65,7 +65,8 @@ public class SourceFileAttribute extends AttributeInfo { | |||
* @param classnames pairs of replaced and substituted | |||
* class names. | |||
*/ | |||
public AttributeInfo copy(ConstPool newCp, Map classnames) { | |||
@Override | |||
public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) { | |||
return new SourceFileAttribute(newCp, getFileName()); | |||
} | |||
} |
@@ -22,9 +22,6 @@ import java.io.IOException; | |||
import java.util.Map; | |||
import javassist.CannotCompileException; | |||
import javassist.bytecode.StackMapTable.InsertLocal; | |||
import javassist.bytecode.StackMapTable.NewRemover; | |||
import javassist.bytecode.StackMapTable.Shifter; | |||
/** | |||
* Another <code>stack_map</code> attribute defined in CLDC 1.1 for J2ME. | |||
@@ -116,7 +113,8 @@ public class StackMap extends AttributeInfo { | |||
/** | |||
* Makes a copy. | |||
*/ | |||
public AttributeInfo copy(ConstPool newCp, Map classnames) { | |||
@Override | |||
public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) { | |||
Copier copier = new Copier(this, newCp, classnames); | |||
copier.visit(); | |||
return copier.getStackMap(); | |||
@@ -224,42 +222,47 @@ public class StackMap extends AttributeInfo { | |||
static class Copier extends Walker { | |||
byte[] dest; | |||
ConstPool srcCp, destCp; | |||
Map classnames; | |||
Map<String,String> classnames; | |||
Copier(StackMap map, ConstPool newCp, Map classnames) { | |||
Copier(StackMap map, ConstPool newCp, Map<String,String> classnames) { | |||
super(map); | |||
srcCp = map.getConstPool(); | |||
dest = new byte[info.length]; | |||
destCp = newCp; | |||
this.classnames = classnames; | |||
} | |||
@Override | |||
public void visit() { | |||
int num = ByteArray.readU16bit(info, 0); | |||
ByteArray.write16bit(num, dest, 0); | |||
super.visit(); | |||
} | |||
@Override | |||
public int locals(int pos, int offset, int num) { | |||
ByteArray.write16bit(offset, dest, pos - 4); | |||
return super.locals(pos, offset, num); | |||
} | |||
@Override | |||
public int typeInfoArray(int pos, int offset, int num, boolean isLocals) { | |||
ByteArray.write16bit(num, dest, pos - 2); | |||
return super.typeInfoArray(pos, offset, num, isLocals); | |||
} | |||
@Override | |||
public void typeInfo(int pos, byte tag) { | |||
dest[pos] = tag; | |||
} | |||
@Override | |||
public void objectVariable(int pos, int clazz) { | |||
dest[pos] = OBJECT; | |||
int newClazz = srcCp.copy(clazz, destCp, classnames); | |||
ByteArray.write16bit(newClazz, dest, pos + 1); | |||
} | |||
@Override | |||
public void uninitialized(int pos, int offset) { | |||
dest[pos] = UNINIT; | |||
ByteArray.write16bit(offset, dest, pos + 1); | |||
@@ -305,30 +308,36 @@ public class StackMap extends AttributeInfo { | |||
return writer.toByteArray(); | |||
} | |||
@Override | |||
public void visit() { | |||
int num = ByteArray.readU16bit(info, 0); | |||
writer.write16bit(num); | |||
super.visit(); | |||
} | |||
@Override | |||
public int locals(int pos, int offset, int num) { | |||
writer.write16bit(offset); | |||
return super.locals(pos, offset, num); | |||
} | |||
@Override | |||
public int typeInfoArray(int pos, int offset, int num, boolean isLocals) { | |||
writer.write16bit(num); | |||
return super.typeInfoArray(pos, offset, num, isLocals); | |||
} | |||
@Override | |||
public void typeInfo(int pos, byte tag) { | |||
writer.writeVerifyTypeInfo(tag, 0); | |||
} | |||
@Override | |||
public void objectVariable(int pos, int clazz) { | |||
writer.writeVerifyTypeInfo(OBJECT, clazz); | |||
} | |||
@Override | |||
public void uninitialized(int pos, int offset) { | |||
writer.writeVerifyTypeInfo(UNINIT, offset); | |||
} | |||
@@ -345,6 +354,7 @@ public class StackMap extends AttributeInfo { | |||
this.varData = varData; | |||
} | |||
@Override | |||
public int typeInfoArray(int pos, int offset, int num, boolean isLocals) { | |||
if (!isLocals || num < varIndex) | |||
return super.typeInfoArray(pos, offset, num, isLocals); | |||
@@ -390,6 +400,7 @@ public class StackMap extends AttributeInfo { | |||
this.exclusive = exclusive; | |||
} | |||
@Override | |||
public int locals(int pos, int offset, int num) { | |||
if (exclusive ? where <= offset : where < offset) | |||
ByteArray.write16bit(offset + gap, info, pos - 4); | |||
@@ -397,6 +408,7 @@ public class StackMap extends AttributeInfo { | |||
return super.locals(pos, offset, num); | |||
} | |||
@Override | |||
public void uninitialized(int pos, int offset) { | |||
if (where <= offset) | |||
ByteArray.write16bit(offset + gap, info, pos + 1); | |||
@@ -419,6 +431,7 @@ public class StackMap extends AttributeInfo { | |||
this.gap = gap; | |||
} | |||
@Override | |||
public int locals(int pos, int offset, int num) { | |||
if (where == pos + offset) | |||
ByteArray.write16bit(offset - gap, info, pos - 4); | |||
@@ -451,6 +464,7 @@ public class StackMap extends AttributeInfo { | |||
posOfNew = where; | |||
} | |||
@Override | |||
public int stack(int pos, int offset, int num) { | |||
return stackTypeInfoArray(pos, offset, num); | |||
} | |||
@@ -519,6 +533,7 @@ public class StackMap extends AttributeInfo { | |||
visit(); | |||
} | |||
@Override | |||
public int locals(int pos, int offset, int num) { | |||
writer.println(" * offset " + offset); | |||
return super.locals(pos, offset, num); |
@@ -62,7 +62,8 @@ public class StackMapTable extends AttributeInfo { | |||
* <code>RuntimeCopyException</code>. | |||
* | |||
*/ | |||
public AttributeInfo copy(ConstPool newCp, Map classnames) | |||
@Override | |||
public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) | |||
throws RuntimeCopyException | |||
{ | |||
try { | |||
@@ -90,6 +91,7 @@ public class StackMapTable extends AttributeInfo { | |||
} | |||
} | |||
@Override | |||
void write(DataOutputStream out) throws IOException { | |||
super.write(out); | |||
} | |||
@@ -341,8 +343,8 @@ public class StackMapTable extends AttributeInfo { | |||
* @param stackData <code>stack[i].cpool_index</code> | |||
* or <code>stack[i].offset</code> | |||
*/ | |||
public void fullFrame(int pos, int offsetDelta, int[] localTags, int[] localData, | |||
int[] stackTags, int[] stackData) | |||
public void fullFrame(int pos, int offsetDelta, int[] localTags, | |||
int[] localData, int[] stackTags, int[] stackData) | |||
throws BadBytecode {} | |||
private int verifyTypeInfo(int pos, int n, int[] tags, int[] data) { | |||
@@ -383,22 +385,27 @@ public class StackMapTable extends AttributeInfo { | |||
return writer.toByteArray(); | |||
} | |||
@Override | |||
public void sameFrame(int pos, int offsetDelta) { | |||
writer.sameFrame(offsetDelta); | |||
} | |||
@Override | |||
public void sameLocals(int pos, int offsetDelta, int stackTag, int stackData) { | |||
writer.sameLocals(offsetDelta, stackTag, copyData(stackTag, stackData)); | |||
} | |||
@Override | |||
public void chopFrame(int pos, int offsetDelta, int k) { | |||
writer.chopFrame(offsetDelta, k); | |||
} | |||
@Override | |||
public void appendFrame(int pos, int offsetDelta, int[] tags, int[] data) { | |||
writer.appendFrame(offsetDelta, tags, copyData(tags, data)); | |||
} | |||
@Override | |||
public void fullFrame(int pos, int offsetDelta, int[] localTags, int[] localData, | |||
int[] stackTags, int[] stackData) { | |||
writer.fullFrame(offsetDelta, localTags, copyData(localTags, localData), | |||
@@ -416,22 +423,23 @@ public class StackMapTable extends AttributeInfo { | |||
static class Copier extends SimpleCopy { | |||
private ConstPool srcPool, destPool; | |||
private Map classnames; | |||
private Map<String,String> classnames; | |||
public Copier(ConstPool src, byte[] data, ConstPool dest, Map names) { | |||
public Copier(ConstPool src, byte[] data, ConstPool dest, Map<String,String> names) { | |||
super(data); | |||
srcPool = src; | |||
destPool = dest; | |||
classnames = names; | |||
} | |||
@Override | |||
protected int copyData(int tag, int data) { | |||
if (tag == OBJECT) | |||
return srcPool.copy(data, destPool, classnames); | |||
else | |||
return data; | |||
return srcPool.copy(data, destPool, classnames); | |||
return data; | |||
} | |||
@Override | |||
protected int[] copyData(int[] tags, int[] data) { | |||
int[] newData = new int[data.length]; | |||
for (int i = 0; i < data.length; i++) | |||
@@ -507,6 +515,7 @@ public class StackMapTable extends AttributeInfo { | |||
this.varData = varData; | |||
} | |||
@Override | |||
public void fullFrame(int pos, int offsetDelta, int[] localTags, int[] localData, | |||
int[] stackTags, int[] stackData) { | |||
int len = localTags.length; | |||
@@ -731,22 +740,26 @@ public class StackMapTable extends AttributeInfo { | |||
offset = -1; | |||
} | |||
@Override | |||
public void sameFrame(int pos, int offsetDelta) { | |||
offset += offsetDelta + 1; | |||
writer.println(offset + " same frame: " + offsetDelta); | |||
} | |||
@Override | |||
public void sameLocals(int pos, int offsetDelta, int stackTag, int stackData) { | |||
offset += offsetDelta + 1; | |||
writer.println(offset + " same locals: " + offsetDelta); | |||
printTypeInfo(stackTag, stackData); | |||
} | |||
@Override | |||
public void chopFrame(int pos, int offsetDelta, int k) { | |||
offset += offsetDelta + 1; | |||
writer.println(offset + " chop frame: " + offsetDelta + ", " + k + " last locals"); | |||
} | |||
@Override | |||
public void appendFrame(int pos, int offsetDelta, int[] tags, int[] data) { | |||
offset += offsetDelta + 1; | |||
writer.println(offset + " append frame: " + offsetDelta); | |||
@@ -754,6 +767,7 @@ public class StackMapTable extends AttributeInfo { | |||
printTypeInfo(tags[i], data[i]); | |||
} | |||
@Override | |||
public void fullFrame(int pos, int offsetDelta, int[] localTags, int[] localData, | |||
int[] stackTags, int[] stackData) { | |||
offset += offsetDelta + 1; | |||
@@ -820,7 +834,8 @@ public class StackMapTable extends AttributeInfo { | |||
this.gap = gap; | |||
} | |||
public void objectOrUninitialized(int tag, int data, int pos) { | |||
@Override | |||
public void objectOrUninitialized(int tag, int data, int pos) { | |||
if (tag == UNINIT) | |||
if (where <= data) | |||
ByteArray.write16bit(data + gap, info, pos); | |||
@@ -850,10 +865,12 @@ public class StackMapTable extends AttributeInfo { | |||
stackMap.set(updatedInfo); | |||
} | |||
@Override | |||
public void sameFrame(int pos, int offsetDelta) { | |||
update(pos, offsetDelta, 0, 251); | |||
} | |||
@Override | |||
public void sameLocals(int pos, int offsetDelta, int stackTag, int stackData) { | |||
update(pos, offsetDelta, 64, 247); | |||
} | |||
@@ -892,14 +909,17 @@ public class StackMapTable extends AttributeInfo { | |||
return newinfo; | |||
} | |||
@Override | |||
public void chopFrame(int pos, int offsetDelta, int k) { | |||
update(pos, offsetDelta); | |||
} | |||
@Override | |||
public void appendFrame(int pos, int offsetDelta, int[] tags, int[] data) { | |||
update(pos, offsetDelta); | |||
} | |||
@Override | |||
public void fullFrame(int pos, int offsetDelta, int[] localTags, int[] localData, | |||
int[] stackTags, int[] stackData) { | |||
update(pos, offsetDelta); | |||
@@ -934,6 +954,7 @@ public class StackMapTable extends AttributeInfo { | |||
super(smt, where, gap, false); | |||
} | |||
@Override | |||
void update(int pos, int offsetDelta, int base, int entry) { | |||
int oldPos = position; | |||
position = oldPos + offsetDelta + (oldPos == 0 ? 0 : 1); | |||
@@ -974,6 +995,7 @@ public class StackMapTable extends AttributeInfo { | |||
return newinfo; | |||
} | |||
@Override | |||
void update(int pos, int offsetDelta) { | |||
int oldPos = position; | |||
position = oldPos + offsetDelta + (oldPos == 0 ? 0 : 1); | |||
@@ -1016,6 +1038,7 @@ public class StackMapTable extends AttributeInfo { | |||
posOfNew = pos; | |||
} | |||
@Override | |||
public void sameLocals(int pos, int offsetDelta, int stackTag, int stackData) { | |||
if (stackTag == UNINIT && stackData == posOfNew) | |||
super.sameFrame(pos, offsetDelta); | |||
@@ -1023,6 +1046,7 @@ public class StackMapTable extends AttributeInfo { | |||
super.sameLocals(pos, offsetDelta, stackTag, stackData); | |||
} | |||
@Override | |||
public void fullFrame(int pos, int offsetDelta, int[] localTags, int[] localData, | |||
int[] stackTags, int[] stackData) { | |||
int n = stackTags.length - 1; |
@@ -50,7 +50,8 @@ public class SyntheticAttribute extends AttributeInfo { | |||
* @param newCp the constant pool table used by the new copy. | |||
* @param classnames should be null. | |||
*/ | |||
public AttributeInfo copy(ConstPool newCp, Map classnames) { | |||
@Override | |||
public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) { | |||
return new SyntheticAttribute(newCp); | |||
} | |||
} |
@@ -57,7 +57,8 @@ public class TypeAnnotationsAttribute extends AttributeInfo { | |||
/** | |||
* Copies this attribute and returns a new copy. | |||
*/ | |||
public AttributeInfo copy(ConstPool newCp, Map classnames) { | |||
@Override | |||
public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) { | |||
Copier copier = new Copier(info, constPool, newCp, classnames); | |||
try { | |||
copier.annotationArray(); | |||
@@ -72,13 +73,15 @@ public class TypeAnnotationsAttribute extends AttributeInfo { | |||
* @param oldname a JVM class name. | |||
* @param newname a JVM class name. | |||
*/ | |||
@Override | |||
void renameClass(String oldname, String newname) { | |||
HashMap map = new HashMap(); | |||
Map<String,String> map = new HashMap<String,String>(); | |||
map.put(oldname, newname); | |||
renameClass(map); | |||
} | |||
void renameClass(Map classnames) { | |||
@Override | |||
void renameClass(Map<String,String> classnames) { | |||
Renamer renamer = new Renamer(info, getConstPool(), classnames); | |||
try { | |||
renamer.annotationArray(); | |||
@@ -87,7 +90,8 @@ public class TypeAnnotationsAttribute extends AttributeInfo { | |||
} | |||
} | |||
void getRefClasses(Map classnames) { renameClass(classnames); } | |||
@Override | |||
void getRefClasses(Map<String,String> classnames) { renameClass(classnames); } | |||
/** | |||
* To visit each elements of the type annotation attribute, | |||
@@ -103,6 +107,7 @@ public class TypeAnnotationsAttribute extends AttributeInfo { | |||
subWalker = new SubWalker(attrInfo); | |||
} | |||
@Override | |||
int annotationArray(int pos, int num) throws Exception { | |||
for (int i = 0; i < num; i++) { | |||
int targetType = info[pos] & 0xff; | |||
@@ -130,7 +135,7 @@ public class TypeAnnotationsAttribute extends AttributeInfo { | |||
typeParameterTarget(pos, type, index); | |||
return pos + 1; } | |||
case 0x10: { | |||
int index = ByteArray.readU16bit(info, pos); | |||
int index = ByteArray.readU16bit(info, pos); | |||
supertypeTarget(pos, index); | |||
return pos + 2; } | |||
case 0x11: | |||
@@ -149,22 +154,22 @@ public class TypeAnnotationsAttribute extends AttributeInfo { | |||
formalParameterTarget(pos, index); | |||
return pos + 1; } | |||
case 0x17: { | |||
int index = ByteArray.readU16bit(info, pos); | |||
int index = ByteArray.readU16bit(info, pos); | |||
throwsTarget(pos, index); | |||
return pos + 2; } | |||
case 0x40: | |||
case 0x41: { | |||
int len = ByteArray.readU16bit(info, pos); | |||
int len = ByteArray.readU16bit(info, pos); | |||
return localvarTarget(pos + 2, type, len); } | |||
case 0x42: { | |||
int index = ByteArray.readU16bit(info, pos); | |||
int index = ByteArray.readU16bit(info, pos); | |||
catchTarget(pos, index); | |||
return pos + 2; } | |||
case 0x43: | |||
case 0x44: | |||
case 0x45: | |||
case 0x46: { | |||
int offset = ByteArray.readU16bit(info, pos); | |||
int offset = ByteArray.readU16bit(info, pos); | |||
offsetTarget(pos, type, offset); | |||
return pos + 2; } | |||
case 0x47: | |||
@@ -239,11 +244,12 @@ public class TypeAnnotationsAttribute extends AttributeInfo { | |||
static class Renamer extends AnnotationsAttribute.Renamer { | |||
SubWalker sub; | |||
Renamer(byte[] attrInfo, ConstPool cp, Map map) { | |||
Renamer(byte[] attrInfo, ConstPool cp, Map<String,String> map) { | |||
super(attrInfo, cp, map); | |||
sub = new SubWalker(attrInfo); | |||
} | |||
@Override | |||
int annotationArray(int pos, int num) throws Exception { | |||
for (int i = 0; i < num; i++) { | |||
int targetType = info[pos] & 0xff; | |||
@@ -259,13 +265,14 @@ public class TypeAnnotationsAttribute extends AttributeInfo { | |||
static class Copier extends AnnotationsAttribute.Copier { | |||
SubCopier sub; | |||
Copier(byte[] attrInfo, ConstPool src, ConstPool dest, Map map) { | |||
Copier(byte[] attrInfo, ConstPool src, ConstPool dest, Map<String,String> map) { | |||
super(attrInfo, src, dest, map, false); | |||
TypeAnnotationsWriter w = new TypeAnnotationsWriter(output, dest); | |||
writer = w; | |||
sub = new SubCopier(attrInfo, src, dest, map, w); | |||
} | |||
@Override | |||
int annotationArray(int pos, int num) throws Exception { | |||
writer.numAnnotations(num); | |||
for (int i = 0; i < num; i++) { | |||
@@ -281,11 +288,11 @@ public class TypeAnnotationsAttribute extends AttributeInfo { | |||
static class SubCopier extends SubWalker { | |||
ConstPool srcPool, destPool; | |||
Map classnames; | |||
Map<String,String> classnames; | |||
TypeAnnotationsWriter writer; | |||
SubCopier(byte[] attrInfo, ConstPool src, ConstPool dest, Map map, | |||
TypeAnnotationsWriter w) | |||
SubCopier(byte[] attrInfo, ConstPool src, ConstPool dest, | |||
Map<String,String> map, TypeAnnotationsWriter w) | |||
{ | |||
super(attrInfo); | |||
srcPool = src; | |||
@@ -294,16 +301,19 @@ public class TypeAnnotationsAttribute extends AttributeInfo { | |||
writer = w; | |||
} | |||
@Override | |||
void typeParameterTarget(int pos, int targetType, int typeParameterIndex) | |||
throws Exception | |||
{ | |||
writer.typeParameterTarget(targetType, typeParameterIndex); | |||
writer.typeParameterTarget(targetType, typeParameterIndex); | |||
} | |||
@Override | |||
void supertypeTarget(int pos, int superTypeIndex) throws Exception { | |||
writer.supertypeTarget(superTypeIndex); | |||
} | |||
@Override | |||
void typeParameterBoundTarget(int pos, int targetType, int typeParameterIndex, | |||
int boundIndex) | |||
throws Exception | |||
@@ -311,48 +321,58 @@ public class TypeAnnotationsAttribute extends AttributeInfo { | |||
writer.typeParameterBoundTarget(targetType, typeParameterIndex, boundIndex); | |||
} | |||
@Override | |||
void emptyTarget(int pos, int targetType) throws Exception { | |||
writer.emptyTarget(targetType); | |||
} | |||
@Override | |||
void formalParameterTarget(int pos, int formalParameterIndex) throws Exception { | |||
writer.formalParameterTarget(formalParameterIndex); | |||
} | |||
@Override | |||
void throwsTarget(int pos, int throwsTypeIndex) throws Exception { | |||
writer.throwsTarget(throwsTypeIndex); | |||
} | |||
@Override | |||
int localvarTarget(int pos, int targetType, int tableLength) throws Exception { | |||
writer.localVarTarget(targetType, tableLength); | |||
return super.localvarTarget(pos, targetType, tableLength); | |||
} | |||
@Override | |||
void localvarTarget(int pos, int targetType, int startPc, int length, int index) | |||
throws Exception | |||
{ | |||
writer.localVarTargetTable(startPc, length, index); | |||
} | |||
@Override | |||
void catchTarget(int pos, int exceptionTableIndex) throws Exception { | |||
writer.catchTarget(exceptionTableIndex); | |||
} | |||
@Override | |||
void offsetTarget(int pos, int targetType, int offset) throws Exception { | |||
writer.offsetTarget(targetType, offset); | |||
} | |||
@Override | |||
void typeArgumentTarget(int pos, int targetType, int offset, int typeArgumentIndex) | |||
throws Exception | |||
{ | |||
writer.typeArgumentTarget(targetType, offset, typeArgumentIndex); | |||
} | |||
@Override | |||
int typePath(int pos, int pathLength) throws Exception { | |||
writer.typePath(pathLength); | |||
return super.typePath(pos, pathLength); | |||
} | |||
@Override | |||
void typePath(int pos, int typePathKind, int typeArgumentIndex) throws Exception { | |||
writer.typePathPath(typePathKind, typeArgumentIndex); | |||
} |
@@ -15,8 +15,6 @@ | |||
*/ | |||
package javassist.bytecode.analysis; | |||
import java.util.Iterator; | |||
import javassist.ClassPool; | |||
import javassist.CtClass; | |||
import javassist.CtMethod; | |||
@@ -363,9 +361,7 @@ public class Analyzer implements Opcode { | |||
if (subroutine == null) | |||
throw new BadBytecode("Ret on no subroutine! [pos = " + pos + "]"); | |||
Iterator callerIter = subroutine.callers().iterator(); | |||
while (callerIter.hasNext()) { | |||
int caller = ((Integer) callerIter.next()).intValue(); | |||
for (int caller:subroutine.callers()) { | |||
int returnLoc = getNext(iter, caller, pos); | |||
boolean changed = false; | |||
@@ -377,8 +373,7 @@ public class Analyzer implements Opcode { | |||
changed = old.mergeStack(frame); | |||
} | |||
for (Iterator i = subroutine.accessed().iterator(); i.hasNext(); ) { | |||
int index = ((Integer)i.next()).intValue(); | |||
for (int index:subroutine.accessed()) { | |||
Type oldType = old.getLocal(index); | |||
Type newType = frame.getLocal(index); | |||
if (oldType != newType) { |
@@ -17,6 +17,8 @@ | |||
package javassist.bytecode.analysis; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import javassist.CtClass; | |||
import javassist.CtMethod; | |||
import javassist.bytecode.BadBytecode; | |||
@@ -64,9 +66,11 @@ public class ControlFlow { | |||
methodInfo = minfo; | |||
frames = null; | |||
basicBlocks = (Block[])new BasicBlock.Maker() { | |||
@Override | |||
protected BasicBlock makeBlock(int pos) { | |||
return new Block(pos, methodInfo); | |||
} | |||
@Override | |||
protected BasicBlock[] makeArray(int size) { | |||
return new Block[size]; | |||
} | |||
@@ -156,7 +160,9 @@ public class ControlFlow { | |||
} | |||
Access access = new Access(nodes) { | |||
@Override | |||
BasicBlock[] exits(Node n) { return n.block.getExit(); } | |||
@Override | |||
BasicBlock[] entrances(Node n) { return n.block.entrances; } | |||
}; | |||
nodes[0].makeDepth1stTree(null, visited, 0, distance, access); | |||
@@ -202,7 +208,9 @@ public class ControlFlow { | |||
} | |||
Access access = new Access(nodes) { | |||
@Override | |||
BasicBlock[] exits(Node n) { return n.block.entrances; } | |||
@Override | |||
BasicBlock[] entrances(Node n) { return n.block.getExit(); } | |||
}; | |||
@@ -252,6 +260,7 @@ public class ControlFlow { | |||
method = minfo; | |||
} | |||
@Override | |||
protected void toString2(StringBuffer sbuf) { | |||
super.toString2(sbuf); | |||
sbuf.append(", incoming{"); | |||
@@ -314,14 +323,14 @@ public class ControlFlow { | |||
* in this block. | |||
*/ | |||
public Catcher[] catchers() { | |||
ArrayList catchers = new ArrayList(); | |||
List<Catcher> catchers = new ArrayList<Catcher>(); | |||
BasicBlock.Catch c = toCatch; | |||
while (c != null) { | |||
catchers.add(new Catcher(c)); | |||
c = c.next; | |||
} | |||
return (Catcher[])catchers.toArray(new Catcher[catchers.size()]); | |||
return catchers.toArray(new Catcher[catchers.size()]); | |||
} | |||
} | |||
@@ -349,6 +358,7 @@ public class ControlFlow { | |||
/** | |||
* Returns a <code>String</code> representation. | |||
*/ | |||
@Override | |||
public String toString() { | |||
StringBuffer sbuf = new StringBuffer(); | |||
sbuf.append("Node[pos=").append(block().position()); | |||
@@ -473,7 +483,7 @@ public class ControlFlow { | |||
Node n = all[i]; | |||
Node p = n.parent; | |||
if (p != null) | |||
p.children[nchildren[p.block.index]++] = n; | |||
p.children[nchildren[p.block.index]++] = n; | |||
} | |||
} | |||
} |
@@ -229,6 +229,7 @@ public class Frame { | |||
return changed; | |||
} | |||
@Override | |||
public String toString() { | |||
StringBuffer buffer = new StringBuffer(); | |||
@@ -34,6 +34,7 @@ public class MultiArrayType extends Type { | |||
this.dims = dims; | |||
} | |||
@Override | |||
public CtClass getCtClass() { | |||
CtClass clazz = component.getCtClass(); | |||
if (clazz == null) | |||
@@ -52,30 +53,37 @@ public class MultiArrayType extends Type { | |||
} | |||
} | |||
@Override | |||
boolean popChanged() { | |||
return component.popChanged(); | |||
} | |||
@Override | |||
public int getDimensions() { | |||
return dims; | |||
} | |||
@Override | |||
public Type getComponent() { | |||
return dims == 1 ? (Type)component : new MultiArrayType(component, dims - 1); | |||
} | |||
@Override | |||
public int getSize() { | |||
return 1; | |||
} | |||
@Override | |||
public boolean isArray() { | |||
return true; | |||
} | |||
@Override | |||
public boolean isAssignableFrom(Type type) { | |||
throw new UnsupportedOperationException("Not implemented"); | |||
} | |||
@Override | |||
public boolean isReference() { | |||
return true; | |||
} | |||
@@ -115,12 +123,13 @@ public class MultiArrayType extends Type { | |||
return component.isAssignableTo(typeRoot); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return component.hashCode() + dims; | |||
} | |||
@Override | |||
public boolean equals(Object o) { | |||
if (! (o instanceof MultiArrayType)) | |||
return false; | |||
@@ -129,6 +138,7 @@ public class MultiArrayType extends Type { | |||
return component.equals(multi.component) && dims == multi.dims; | |||
} | |||
@Override | |||
public String toString() { | |||
// follows the same detailed formating scheme as component | |||
return arrayName(component.toString(), dims); |
@@ -16,7 +16,6 @@ | |||
package javassist.bytecode.analysis; | |||
import java.util.HashMap; | |||
import java.util.Iterator; | |||
import java.util.Map; | |||
import javassist.CtClass; | |||
@@ -47,17 +46,17 @@ import javassist.CtClass; | |||
* changes, and somehow communicating assignment changes to the Analyzer | |||
*/ | |||
public class MultiType extends Type { | |||
private Map interfaces; | |||
private Map<String,CtClass> interfaces; | |||
private Type resolved; | |||
private Type potentialClass; | |||
private MultiType mergeSource; | |||
private boolean changed = false; | |||
public MultiType(Map interfaces) { | |||
public MultiType(Map<String,CtClass> interfaces) { | |||
this(interfaces, null); | |||
} | |||
public MultiType(Map interfaces, Type potentialClass) { | |||
public MultiType(Map<String,CtClass> interfaces, Type potentialClass) { | |||
super(null); | |||
this.interfaces = interfaces; | |||
this.potentialClass = potentialClass; | |||
@@ -67,6 +66,7 @@ public class MultiType extends Type { | |||
* Gets the class that corresponds with this type. If this information | |||
* is not yet known, java.lang.Object will be returned. | |||
*/ | |||
@Override | |||
public CtClass getCtClass() { | |||
if (resolved != null) | |||
return resolved.getCtClass(); | |||
@@ -77,6 +77,7 @@ public class MultiType extends Type { | |||
/** | |||
* Always returns null since this type is never used for an array. | |||
*/ | |||
@Override | |||
public Type getComponent() { | |||
return null; | |||
} | |||
@@ -84,6 +85,7 @@ public class MultiType extends Type { | |||
/** | |||
* Always returns 1, since this type is a reference. | |||
*/ | |||
@Override | |||
public int getSize() { | |||
return 1; | |||
} | |||
@@ -91,6 +93,7 @@ public class MultiType extends Type { | |||
/** | |||
* Always reutnrs false since this type is never used for an array | |||
*/ | |||
@Override | |||
public boolean isArray() { | |||
return false; | |||
} | |||
@@ -98,12 +101,14 @@ public class MultiType extends Type { | |||
/** | |||
* Returns true if the internal state has changed. | |||
*/ | |||
@Override | |||
boolean popChanged() { | |||
boolean changed = this.changed; | |||
this.changed = false; | |||
return changed; | |||
} | |||
@Override | |||
public boolean isAssignableFrom(Type type) { | |||
throw new UnsupportedOperationException("Not implemented"); | |||
} | |||
@@ -118,11 +123,11 @@ public class MultiType extends Type { | |||
if (potentialClass != null && !type.isAssignableFrom(potentialClass)) | |||
potentialClass = null; | |||
Map map = mergeMultiAndSingle(this, type); | |||
Map<String,CtClass> map = mergeMultiAndSingle(this, type); | |||
if (map.size() == 1 && potentialClass == null) { | |||
// Update previous merge paths to the same resolved type | |||
resolved = Type.get((CtClass)map.values().iterator().next()); | |||
resolved = Type.get(map.values().iterator().next()); | |||
propogateResolved(); | |||
return true; | |||
@@ -168,16 +173,15 @@ public class MultiType extends Type { | |||
* | |||
* @return true | |||
*/ | |||
@Override | |||
public boolean isReference() { | |||
return true; | |||
} | |||
private Map getAllMultiInterfaces(MultiType type) { | |||
Map map = new HashMap(); | |||
private Map<String,CtClass> getAllMultiInterfaces(MultiType type) { | |||
Map<String,CtClass> map = new HashMap<String,CtClass>(); | |||
Iterator iter = type.interfaces.values().iterator(); | |||
while (iter.hasNext()) { | |||
CtClass intf = (CtClass)iter.next(); | |||
for (CtClass intf:type.interfaces.values()) { | |||
map.put(intf.getName(), intf); | |||
getAllInterfaces(intf, map); | |||
} | |||
@@ -186,16 +190,16 @@ public class MultiType extends Type { | |||
} | |||
private Map mergeMultiInterfaces(MultiType type1, MultiType type2) { | |||
Map map1 = getAllMultiInterfaces(type1); | |||
Map map2 = getAllMultiInterfaces(type2); | |||
private Map<String,CtClass> mergeMultiInterfaces(MultiType type1, MultiType type2) { | |||
Map<String,CtClass> map1 = getAllMultiInterfaces(type1); | |||
Map<String,CtClass> map2 = getAllMultiInterfaces(type2); | |||
return findCommonInterfaces(map1, map2); | |||
} | |||
private Map mergeMultiAndSingle(MultiType multi, Type single) { | |||
Map map1 = getAllMultiInterfaces(multi); | |||
Map map2 = getAllInterfaces(single.getCtClass(), null); | |||
private Map<String,CtClass> mergeMultiAndSingle(MultiType multi, Type single) { | |||
Map<String,CtClass> map1 = getAllMultiInterfaces(multi); | |||
Map<String,CtClass> map2 = getAllInterfaces(single.getCtClass(), null); | |||
return findCommonInterfaces(map1, map2); | |||
} | |||
@@ -211,6 +215,7 @@ public class MultiType extends Type { | |||
return false; | |||
} | |||
@Override | |||
public Type merge(Type type) { | |||
if (this == type) | |||
return this; | |||
@@ -235,7 +240,7 @@ public class MultiType extends Type { | |||
} | |||
} | |||
Map merged; | |||
Map<String,CtClass> merged; | |||
if (type instanceof MultiType) { | |||
MultiType multi = (MultiType)type; | |||
@@ -254,14 +259,13 @@ public class MultiType extends Type { | |||
// Keep all previous merge paths up to date | |||
if (merged.size() > 1 || (merged.size() == 1 && potentialClass != null)) { | |||
// Check for changes | |||
if (merged.size() != interfaces.size()) { | |||
if (merged.size() != interfaces.size()) | |||
changed = true; | |||
} else if (changed == false){ | |||
Iterator iter = merged.keySet().iterator(); | |||
while (iter.hasNext()) | |||
if (! interfaces.containsKey(iter.next())) | |||
else if (changed == false) | |||
for (String key:merged.keySet()) | |||
if (!interfaces.containsKey(key)) | |||
changed = true; | |||
} | |||
interfaces = merged; | |||
propogateState(); | |||
@@ -269,27 +273,27 @@ public class MultiType extends Type { | |||
return this; | |||
} | |||
if (merged.size() == 1) { | |||
resolved = Type.get((CtClass) merged.values().iterator().next()); | |||
} else if (potentialClass != null){ | |||
if (merged.size() == 1) | |||
resolved = Type.get(merged.values().iterator().next()); | |||
else if (potentialClass != null) | |||
resolved = potentialClass; | |||
} else { | |||
else | |||
resolved = OBJECT; | |||
} | |||
propogateResolved(); | |||
return resolved; | |||
} | |||
@Override | |||
public int hashCode() { | |||
if (resolved != null) | |||
return resolved.hashCode(); | |||
return interfaces.keySet().hashCode(); | |||
} | |||
@Override | |||
public boolean equals(Object o) { | |||
if (! (o instanceof MultiType)) | |||
return false; | |||
@@ -303,19 +307,18 @@ public class MultiType extends Type { | |||
return interfaces.keySet().equals(multi.interfaces.keySet()); | |||
} | |||
@Override | |||
public String toString() { | |||
if (resolved != null) | |||
return resolved.toString(); | |||
StringBuffer buffer = new StringBuffer("{"); | |||
Iterator iter = interfaces.keySet().iterator(); | |||
while (iter.hasNext()) { | |||
buffer.append(iter.next()); | |||
buffer.append(", "); | |||
} | |||
buffer.setLength(buffer.length() - 2); | |||
for (String key:interfaces.keySet()) | |||
buffer.append(key).append(", "); | |||
if (potentialClass != null) | |||
buffer.append(", *").append(potentialClass.toString()); | |||
buffer.append("*").append(potentialClass.toString()); | |||
else | |||
buffer.setLength(buffer.length() - 2); | |||
buffer.append("}"); | |||
return buffer.toString(); | |||
} |
@@ -28,17 +28,17 @@ import java.util.Set; | |||
*/ | |||
public class Subroutine { | |||
//private Set callers = new HashSet(); | |||
private List callers = new ArrayList(); | |||
private Set access = new HashSet(); | |||
private List<Integer> callers = new ArrayList<Integer>(); | |||
private Set<Integer> access = new HashSet<Integer>(); | |||
private int start; | |||
public Subroutine(int start, int caller) { | |||
this.start = start; | |||
callers.add(Integer.valueOf(caller)); | |||
callers.add(caller); | |||
} | |||
public void addCaller(int caller) { | |||
callers.add(Integer.valueOf(caller)); | |||
callers.add(caller); | |||
} | |||
public int start() { | |||
@@ -46,21 +46,22 @@ public class Subroutine { | |||
} | |||
public void access(int index) { | |||
access.add(Integer.valueOf(index)); | |||
access.add(index); | |||
} | |||
public boolean isAccessed(int index) { | |||
return access.contains(Integer.valueOf(index)); | |||
return access.contains(index); | |||
} | |||
public Collection accessed() { | |||
public Collection<Integer> accessed() { | |||
return access; | |||
} | |||
public Collection callers() { | |||
public Collection<Integer> callers() { | |||
return callers; | |||
} | |||
@Override | |||
public String toString() { | |||
return "start = " + start + " callers = " + callers.toString(); | |||
} |
@@ -35,8 +35,8 @@ import javassist.bytecode.Opcode; | |||
public class SubroutineScanner implements Opcode { | |||
private Subroutine[] subroutines; | |||
Map subTable = new HashMap(); | |||
Set done = new HashSet(); | |||
Map<Integer,Subroutine> subTable = new HashMap<Integer,Subroutine>(); | |||
Set<Integer> done = new HashSet<Integer>(); | |||
public Subroutine[] scan(MethodInfo method) throws BadBytecode { | |||
@@ -62,10 +62,10 @@ public class SubroutineScanner implements Opcode { | |||
private void scan(int pos, CodeIterator iter, Subroutine sub) throws BadBytecode { | |||
// Skip already processed blocks | |||
if (done.contains(Integer.valueOf(pos))) | |||
if (done.contains(pos)) | |||
return; | |||
done.add(Integer.valueOf(pos)); | |||
done.add(pos); | |||
int old = iter.lookAhead(); | |||
iter.move(pos); | |||
@@ -103,10 +103,10 @@ public class SubroutineScanner implements Opcode { | |||
if (Util.isJumpInstruction(opcode)) { | |||
int target = Util.getJumpTarget(pos, iter); | |||
if (opcode == JSR || opcode == JSR_W) { | |||
Subroutine s = (Subroutine) subTable.get(Integer.valueOf(target)); | |||
Subroutine s = subTable.get(target); | |||
if (s == null) { | |||
s = new Subroutine(target, pos); | |||
subTable.put(Integer.valueOf(target), s); | |||
subTable.put(target, s); | |||
scan(target, iter, s); | |||
} else { | |||
s.addCaller(pos); |
@@ -15,10 +15,8 @@ | |||
*/ | |||
package javassist.bytecode.analysis; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import java.util.IdentityHashMap; | |||
import java.util.Iterator; | |||
import java.util.Map; | |||
import javassist.ClassPool; | |||
@@ -44,7 +42,7 @@ public class Type { | |||
private final CtClass clazz; | |||
private final boolean special; | |||
private static final Map prims = new IdentityHashMap(); | |||
private static final Map<CtClass,Type> prims = new IdentityHashMap<CtClass,Type>(); | |||
/** Represents the double primitive type */ | |||
public static final Type DOUBLE = new Type(CtClass.doubleType); | |||
/** Represents the boolean primitive type */ | |||
@@ -451,7 +449,7 @@ public class Type { | |||
// If its Object, then try and find a common interface(s) | |||
if (superClass.getSuperclass() == null) { | |||
Map interfaces = findCommonInterfaces(type); | |||
Map<String,CtClass> interfaces = findCommonInterfaces(type); | |||
if (interfaces.size() == 1) | |||
return new Type((CtClass) interfaces.values().iterator().next()); | |||
if (interfaces.size() > 1) | |||
@@ -462,7 +460,7 @@ public class Type { | |||
} | |||
// Check for a common interface that is not on the found supertype | |||
Map commonDeclared = findExclusiveDeclaredInterfaces(type, superClass); | |||
Map<String,CtClass> commonDeclared = findExclusiveDeclaredInterfaces(type, superClass); | |||
if (commonDeclared.size() > 0) { | |||
return new MultiType(commonDeclared, new Type(superClass)); | |||
} | |||
@@ -470,21 +468,19 @@ public class Type { | |||
return new Type(superClass); | |||
} | |||
private Map findCommonInterfaces(Type type) { | |||
Map typeMap = getAllInterfaces(type.clazz, null); | |||
Map thisMap = getAllInterfaces(this.clazz, null); | |||
private Map<String,CtClass> findCommonInterfaces(Type type) { | |||
Map<String,CtClass> typeMap = getAllInterfaces(type.clazz, null); | |||
Map<String,CtClass> thisMap = getAllInterfaces(this.clazz, null); | |||
return findCommonInterfaces(typeMap, thisMap); | |||
} | |||
private Map findExclusiveDeclaredInterfaces(Type type, CtClass exclude) { | |||
Map typeMap = getDeclaredInterfaces(type.clazz, null); | |||
Map thisMap = getDeclaredInterfaces(this.clazz, null); | |||
Map excludeMap = getAllInterfaces(exclude, null); | |||
private Map<String,CtClass> findExclusiveDeclaredInterfaces(Type type, CtClass exclude) { | |||
Map<String,CtClass> typeMap = getDeclaredInterfaces(type.clazz, null); | |||
Map<String,CtClass> thisMap = getDeclaredInterfaces(this.clazz, null); | |||
Map<String,CtClass> excludeMap = getAllInterfaces(exclude, null); | |||
Iterator i = excludeMap.keySet().iterator(); | |||
while (i.hasNext()) { | |||
Object intf = i.next(); | |||
for (String intf:excludeMap.keySet()) { | |||
typeMap.remove(intf); | |||
thisMap.remove(intf); | |||
} | |||
@@ -493,19 +489,21 @@ public class Type { | |||
} | |||
Map findCommonInterfaces(Map typeMap, Map alterMap) { | |||
Iterator i = alterMap.keySet().iterator(); | |||
while (i.hasNext()) { | |||
if (! typeMap.containsKey(i.next())) | |||
i.remove(); | |||
} | |||
Map<String,CtClass> findCommonInterfaces(Map<String,CtClass> typeMap, Map<String,CtClass> alterMap) { | |||
if (alterMap == null) | |||
alterMap = new HashMap<String,CtClass>(); | |||
if (typeMap == null||typeMap.isEmpty()) | |||
alterMap.clear(); | |||
for (String name:alterMap.keySet()) | |||
if (!typeMap.containsKey(name)) | |||
alterMap.remove(name); | |||
// Reduce to subinterfaces | |||
// This does not need to be recursive since we make a copy, | |||
// and that copy contains all super types for the whole hierarchy | |||
i = new ArrayList(alterMap.values()).iterator(); | |||
while (i.hasNext()) { | |||
CtClass intf = (CtClass) i.next(); | |||
for (CtClass intf:alterMap.values()) { | |||
CtClass[] interfaces; | |||
try { | |||
interfaces = intf.getInterfaces(); | |||
@@ -513,24 +511,23 @@ public class Type { | |||
throw new RuntimeException(e); | |||
} | |||
for (int c = 0; c < interfaces.length; c++) | |||
alterMap.remove(interfaces[c].getName()); | |||
for (CtClass c:interfaces) | |||
alterMap.remove(c.getName()); | |||
} | |||
return alterMap; | |||
} | |||
Map getAllInterfaces(CtClass clazz, Map map) { | |||
Map<String,CtClass> getAllInterfaces(CtClass clazz, Map<String,CtClass> map) { | |||
if (map == null) | |||
map = new HashMap(); | |||
map = new HashMap<String,CtClass>(); | |||
if (clazz.isInterface()) | |||
map.put(clazz.getName(), clazz); | |||
do { | |||
try { | |||
CtClass[] interfaces = clazz.getInterfaces(); | |||
for (int i = 0; i < interfaces.length; i++) { | |||
CtClass intf = interfaces[i]; | |||
for (CtClass intf:interfaces) { | |||
map.put(intf.getName(), intf); | |||
getAllInterfaces(intf, map); | |||
} | |||
@@ -544,9 +541,9 @@ public class Type { | |||
return map; | |||
} | |||
Map getDeclaredInterfaces(CtClass clazz, Map map) { | |||
Map<String,CtClass> getDeclaredInterfaces(CtClass clazz, Map<String,CtClass> map) { | |||
if (map == null) | |||
map = new HashMap(); | |||
map = new HashMap<String,CtClass>(); | |||
if (clazz.isInterface()) | |||
map.put(clazz.getName(), clazz); | |||
@@ -558,8 +555,7 @@ public class Type { | |||
throw new RuntimeException(e); | |||
} | |||
for (int i = 0; i < interfaces.length; i++) { | |||
CtClass intf = interfaces[i]; | |||
for (CtClass intf:interfaces) { | |||
map.put(intf.getName(), intf); | |||
getDeclaredInterfaces(intf, map); | |||
} | |||
@@ -572,6 +568,7 @@ public class Type { | |||
return getClass().hashCode() + clazz.hashCode(); | |||
} | |||
@Override | |||
public boolean equals(Object o) { | |||
if (! (o instanceof Type)) | |||
return false; | |||
@@ -583,6 +580,7 @@ public class Type { | |||
return one == two || (one != null && two != null && one.getName().equals(two.getName())); | |||
} | |||
@Override | |||
public String toString() { | |||
if (this == BOGUS) | |||
return "BOGUS"; |
@@ -25,8 +25,8 @@ import javassist.NotFoundException; | |||
import java.io.IOException; | |||
import java.util.LinkedHashMap; | |||
import java.util.Map; | |||
import java.util.Set; | |||
import java.util.Iterator; | |||
/** | |||
* The <code>annotation</code> structure. | |||
@@ -53,7 +53,7 @@ public class Annotation { | |||
ConstPool pool; | |||
int typeIndex; | |||
LinkedHashMap members; // this sould be LinkedHashMap | |||
Map<String,Pair> members; // this sould be LinkedHashMap | |||
// but it is not supported by JDK 1.3. | |||
/** | |||
@@ -106,17 +106,13 @@ public class Annotation { | |||
throw new RuntimeException( | |||
"Only interfaces are allowed for Annotation creation."); | |||
CtMethod methods[] = clazz.getDeclaredMethods(); | |||
if (methods.length > 0) { | |||
members = new LinkedHashMap(); | |||
} | |||
CtMethod[] methods = clazz.getDeclaredMethods(); | |||
if (methods.length > 0) | |||
members = new LinkedHashMap<String,Pair>(); | |||
for (int i = 0; i < methods.length; i++) { | |||
CtClass returnType = methods[i].getReturnType(); | |||
addMemberValue(methods[i].getName(), | |||
createMemberValue(cp, returnType)); | |||
} | |||
for (CtMethod m:methods) | |||
addMemberValue(m.getName(), | |||
createMemberValue(cp, m.getReturnType())); | |||
} | |||
/** | |||
@@ -196,7 +192,7 @@ public class Annotation { | |||
p.name = pool.addUtf8Info(name); | |||
p.value = value; | |||
if (members == null) | |||
members = new LinkedHashMap(); | |||
members = new LinkedHashMap<String,Pair>(); | |||
members.put(name, p); | |||
} | |||
@@ -204,7 +200,7 @@ public class Annotation { | |||
private void addMemberValue(Pair pair) { | |||
String name = pool.getUtf8Info(pair.name); | |||
if (members == null) | |||
members = new LinkedHashMap(); | |||
members = new LinkedHashMap<String,Pair>(); | |||
members.put(name, pair); | |||
} | |||
@@ -212,18 +208,18 @@ public class Annotation { | |||
/** | |||
* Returns a string representation of the annotation. | |||
*/ | |||
@Override | |||
public String toString() { | |||
StringBuffer buf = new StringBuffer("@"); | |||
buf.append(getTypeName()); | |||
if (members != null) { | |||
buf.append("("); | |||
Iterator mit = members.keySet().iterator(); | |||
while (mit.hasNext()) { | |||
String name = (String)mit.next(); | |||
buf.append(name).append("=").append(getMemberValue(name)); | |||
if (mit.hasNext()) | |||
buf.append(", "); | |||
for (String name:members.keySet()) { | |||
buf.append(name).append("=") | |||
.append(getMemberValue(name)) | |||
.append(", "); | |||
} | |||
buf.setLength(buf.length()-2); | |||
buf.append(")"); | |||
} | |||
@@ -244,11 +240,10 @@ public class Annotation { | |||
* | |||
* @return null if no members are defined. | |||
*/ | |||
public Set getMemberNames() { | |||
public Set<String> getMemberNames() { | |||
if (members == null) | |||
return null; | |||
else | |||
return members.keySet(); | |||
return members.keySet(); | |||
} | |||
/** | |||
@@ -267,15 +262,9 @@ public class Annotation { | |||
* @see javassist.bytecode.AnnotationDefaultAttribute | |||
*/ | |||
public MemberValue getMemberValue(String name) { | |||
if (members == null) | |||
if (members == null||members.get(name) == null) | |||
return null; | |||
else { | |||
Pair p = (Pair)members.get(name); | |||
if (p == null) | |||
return null; | |||
else | |||
return p.value; | |||
} | |||
return members.get(name).value; | |||
} | |||
/** | |||
@@ -292,9 +281,9 @@ public class Annotation { | |||
public Object toAnnotationType(ClassLoader cl, ClassPool cp) | |||
throws ClassNotFoundException, NoSuchClassError | |||
{ | |||
Class clazz = MemberValue.loadClass(cl, getTypeName()); | |||
Class<?> clazz = MemberValue.loadClass(cl, getTypeName()); | |||
try { | |||
return AnnotationImpl.make(cl, clazz, cp, this); | |||
return AnnotationImpl.make(cl, clazz, cp, this); | |||
} | |||
catch (IllegalArgumentException e) { | |||
/* AnnotationImpl.make() may throw this exception | |||
@@ -323,9 +312,7 @@ public class Annotation { | |||
} | |||
writer.annotation(typeName, members.size()); | |||
Iterator it = members.values().iterator(); | |||
while (it.hasNext()) { | |||
Pair pair = (Pair)it.next(); | |||
for (Pair pair:members.values()) { | |||
writer.memberValuePair(pair.name); | |||
pair.value.write(writer); | |||
} | |||
@@ -333,7 +320,7 @@ public class Annotation { | |||
@Override | |||
public int hashCode() { | |||
return getTypeName().hashCode() + | |||
return getTypeName().hashCode() + | |||
(members == null ? 0 : members.hashCode()); | |||
} | |||
@@ -341,18 +328,19 @@ public class Annotation { | |||
* Returns true if the given object represents the same annotation | |||
* as this object. The equality test checks the member values. | |||
*/ | |||
@Override | |||
public boolean equals(Object obj) { | |||
if (obj == this) | |||
return true; | |||
if (obj == null || obj instanceof Annotation == false) | |||
return false; | |||
Annotation other = (Annotation) obj; | |||
if (getTypeName().equals(other.getTypeName()) == false) | |||
return false; | |||
LinkedHashMap otherMembers = other.members; | |||
Map<String,Pair> otherMembers = other.members; | |||
if (members == otherMembers) | |||
return true; | |||
else if (members == null) |
@@ -38,24 +38,24 @@ import javassist.bytecode.MethodInfo; | |||
public class AnnotationImpl implements InvocationHandler { | |||
private static final String JDK_ANNOTATION_CLASS_NAME = "java.lang.annotation.Annotation"; | |||
private static Method JDK_ANNOTATION_TYPE_METHOD = null; | |||
private Annotation annotation; | |||
private ClassPool pool; | |||
private ClassLoader classLoader; | |||
private transient Class annotationType; | |||
private transient Class<?> annotationType; | |||
private transient int cachedHashCode = Integer.MIN_VALUE; | |||
static { | |||
// Try to resolve the JDK annotation type method | |||
try { | |||
Class clazz = Class.forName(JDK_ANNOTATION_CLASS_NAME); | |||
Class<?> clazz = Class.forName(JDK_ANNOTATION_CLASS_NAME); | |||
JDK_ANNOTATION_TYPE_METHOD = clazz.getMethod("annotationType", (Class[])null); | |||
} | |||
catch (Exception ignored) { | |||
// Probably not JDK5+ | |||
} | |||
} | |||
/** | |||
* Constructs an annotation object. | |||
* | |||
@@ -66,14 +66,14 @@ public class AnnotationImpl implements InvocationHandler { | |||
* @param anon the annotation. | |||
* @return the annotation | |||
*/ | |||
public static Object make(ClassLoader cl, Class clazz, ClassPool cp, | |||
public static Object make(ClassLoader cl, Class<?> clazz, ClassPool cp, | |||
Annotation anon) | |||
throws IllegalArgumentException | |||
{ | |||
AnnotationImpl handler = new AnnotationImpl(anon, cp, cl); | |||
return Proxy.newProxyInstance(cl, new Class[] { clazz }, handler); | |||
} | |||
private AnnotationImpl(Annotation a, ClassPool cp, ClassLoader loader) { | |||
annotation = a; | |||
pool = cp; | |||
@@ -95,7 +95,7 @@ public class AnnotationImpl implements InvocationHandler { | |||
* @return the annotation class | |||
* @throws NoClassDefFoundError when the class could not loaded | |||
*/ | |||
private Class getAnnotationType() { | |||
private Class<?> getAnnotationType() { | |||
if (annotationType == null) { | |||
String typeName = annotation.getTypeName(); | |||
try { | |||
@@ -109,7 +109,7 @@ public class AnnotationImpl implements InvocationHandler { | |||
} | |||
return annotationType; | |||
} | |||
/** | |||
* Obtains the internal data structure representing the annotation. | |||
* | |||
@@ -126,6 +126,7 @@ public class AnnotationImpl implements InvocationHandler { | |||
* <code>AnnotationImpl</code>. The <code>annotationType()</code> method | |||
* is also available on the proxy instance. | |||
*/ | |||
@Override | |||
public Object invoke(Object proxy, Method method, Object[] args) | |||
throws Throwable | |||
{ | |||
@@ -147,10 +148,9 @@ public class AnnotationImpl implements InvocationHandler { | |||
MemberValue mv = annotation.getMemberValue(name); | |||
if (mv == null) | |||
return getDefault(name, method); | |||
else | |||
return mv.getValue(classLoader, pool, method); | |||
return mv.getValue(classLoader, pool, method); | |||
} | |||
private Object getDefault(String name, Method method) | |||
throws ClassNotFoundException, RuntimeException | |||
{ | |||
@@ -183,6 +183,7 @@ public class AnnotationImpl implements InvocationHandler { | |||
/** | |||
* Returns a hash code value for this object. | |||
*/ | |||
@Override | |||
public int hashCode() { | |||
if (cachedHashCode == Integer.MIN_VALUE) { | |||
int hashCode = 0; | |||
@@ -217,15 +218,15 @@ public class AnnotationImpl implements InvocationHandler { | |||
valueHashCode = arrayHashCode(value); | |||
else | |||
valueHashCode = value.hashCode(); | |||
} | |||
} | |||
hashCode += 127 * name.hashCode() ^ valueHashCode; | |||
} | |||
cachedHashCode = hashCode; | |||
} | |||
return cachedHashCode; | |||
} | |||
/** | |||
* Check that another annotation equals ourselves. | |||
* | |||
@@ -246,10 +247,10 @@ public class AnnotationImpl implements InvocationHandler { | |||
} | |||
} | |||
Class otherAnnotationType = (Class) JDK_ANNOTATION_TYPE_METHOD.invoke(obj, (Object[])null); | |||
Class<?> otherAnnotationType = (Class<?>) JDK_ANNOTATION_TYPE_METHOD.invoke(obj); | |||
if (getAnnotationType().equals(otherAnnotationType) == false) | |||
return false; | |||
Method[] methods = annotationType.getDeclaredMethods(); | |||
for (int i = 0; i < methods.length; ++ i) { | |||
String name = methods[i].getName(); | |||
@@ -263,7 +264,7 @@ public class AnnotationImpl implements InvocationHandler { | |||
value = mv.getValue(classLoader, pool, methods[i]); | |||
if (value == null) | |||
value = getDefault(name, methods[i]); | |||
otherValue = methods[i].invoke(obj, (Object[])null); | |||
otherValue = methods[i].invoke(obj); | |||
} | |||
catch (RuntimeException e) { | |||
throw e; | |||
@@ -277,7 +278,7 @@ public class AnnotationImpl implements InvocationHandler { | |||
if (value != null && value.equals(otherValue) == false) | |||
return false; | |||
} | |||
return true; | |||
} | |||
@@ -294,7 +295,7 @@ public class AnnotationImpl implements InvocationHandler { | |||
return 0; | |||
int result = 1; | |||
Object[] array = (Object[]) object; | |||
for (int i = 0; i < array.length; ++i) { | |||
int elementHashCode = 0; |
@@ -45,17 +45,18 @@ public class AnnotationMemberValue extends MemberValue { | |||
value = a; | |||
} | |||
@Override | |||
Object getValue(ClassLoader cl, ClassPool cp, Method m) | |||
throws ClassNotFoundException | |||
{ | |||
return AnnotationImpl.make(cl, getType(cl), cp, value); | |||
} | |||
Class getType(ClassLoader cl) throws ClassNotFoundException { | |||
@Override | |||
Class<?> getType(ClassLoader cl) throws ClassNotFoundException { | |||
if (value == null) | |||
throw new ClassNotFoundException("no type specified"); | |||
else | |||
return loadClass(cl, value.getTypeName()); | |||
return loadClass(cl, value.getTypeName()); | |||
} | |||
/** | |||
@@ -75,6 +76,7 @@ public class AnnotationMemberValue extends MemberValue { | |||
/** | |||
* Obtains the string representation of this object. | |||
*/ | |||
@Override | |||
public String toString() { | |||
return value.toString(); | |||
} | |||
@@ -82,6 +84,7 @@ public class AnnotationMemberValue extends MemberValue { | |||
/** | |||
* Writes the value. | |||
*/ | |||
@Override | |||
public void write(AnnotationsWriter writer) throws IOException { | |||
writer.annotationValue(); | |||
value.write(writer); | |||
@@ -90,6 +93,7 @@ public class AnnotationMemberValue extends MemberValue { | |||
/** | |||
* Accepts a visitor. | |||
*/ | |||
@Override | |||
public void accept(MemberValueVisitor visitor) { | |||
visitor.visitAnnotationMemberValue(this); | |||
} |
@@ -51,6 +51,7 @@ public class ArrayMemberValue extends MemberValue { | |||
values = null; | |||
} | |||
@Override | |||
Object getValue(ClassLoader cl, ClassPool cp, Method method) | |||
throws ClassNotFoundException | |||
{ | |||
@@ -59,7 +60,7 @@ public class ArrayMemberValue extends MemberValue { | |||
"no array elements found: " + method.getName()); | |||
int size = values.length; | |||
Class clazz; | |||
Class<?> clazz; | |||
if (type == null) { | |||
clazz = method.getReturnType().getComponentType(); | |||
if (clazz == null || size > 0) | |||
@@ -76,7 +77,8 @@ public class ArrayMemberValue extends MemberValue { | |||
return a; | |||
} | |||
Class getType(ClassLoader cl) throws ClassNotFoundException { | |||
@Override | |||
Class<?> getType(ClassLoader cl) throws ClassNotFoundException { | |||
if (type == null) | |||
throw new ClassNotFoundException("no array type specified"); | |||
@@ -112,6 +114,7 @@ public class ArrayMemberValue extends MemberValue { | |||
/** | |||
* Obtains the string representation of this object. | |||
*/ | |||
@Override | |||
public String toString() { | |||
StringBuffer buf = new StringBuffer("{"); | |||
if (values != null) { | |||
@@ -129,6 +132,7 @@ public class ArrayMemberValue extends MemberValue { | |||
/** | |||
* Writes the value. | |||
*/ | |||
@Override | |||
public void write(AnnotationsWriter writer) throws IOException { | |||
int num = values == null ? 0 : values.length; | |||
writer.arrayValue(num); | |||
@@ -139,6 +143,7 @@ public class ArrayMemberValue extends MemberValue { | |||
/** | |||
* Accepts a visitor. | |||
*/ | |||
@Override | |||
public void accept(MemberValueVisitor visitor) { | |||
visitor.visitArrayMemberValue(this); | |||
} |
@@ -58,11 +58,13 @@ public class BooleanMemberValue extends MemberValue { | |||
setValue(false); | |||
} | |||
@Override | |||
Object getValue(ClassLoader cl, ClassPool cp, Method m) { | |||
return Boolean.valueOf(getValue()); | |||
} | |||
Class getType(ClassLoader cl) { | |||
@Override | |||
Class<?> getType(ClassLoader cl) { | |||
return boolean.class; | |||
} | |||
@@ -83,6 +85,7 @@ public class BooleanMemberValue extends MemberValue { | |||
/** | |||
* Obtains the string representation of this object. | |||
*/ | |||
@Override | |||
public String toString() { | |||
return getValue() ? "true" : "false"; | |||
} | |||
@@ -90,6 +93,7 @@ public class BooleanMemberValue extends MemberValue { | |||
/** | |||
* Writes the value. | |||
*/ | |||
@Override | |||
public void write(AnnotationsWriter writer) throws IOException { | |||
writer.constValueIndex(getValue()); | |||
} | |||
@@ -97,6 +101,7 @@ public class BooleanMemberValue extends MemberValue { | |||
/** | |||
* Accepts a visitor. | |||
*/ | |||
@Override | |||
public void accept(MemberValueVisitor visitor) { | |||
visitor.visitBooleanMemberValue(this); | |||
} |
@@ -58,11 +58,13 @@ public class ByteMemberValue extends MemberValue { | |||
setValue((byte)0); | |||
} | |||
@Override | |||
Object getValue(ClassLoader cl, ClassPool cp, Method m) { | |||
return Byte.valueOf(getValue()); | |||
} | |||
Class getType(ClassLoader cl) { | |||
@Override | |||
Class<?> getType(ClassLoader cl) { | |||
return byte.class; | |||
} | |||
@@ -83,6 +85,7 @@ public class ByteMemberValue extends MemberValue { | |||
/** | |||
* Obtains the string representation of this object. | |||
*/ | |||
@Override | |||
public String toString() { | |||
return Byte.toString(getValue()); | |||
} | |||
@@ -90,6 +93,7 @@ public class ByteMemberValue extends MemberValue { | |||
/** | |||
* Writes the value. | |||
*/ | |||
@Override | |||
public void write(AnnotationsWriter writer) throws IOException { | |||
writer.constValueIndex(getValue()); | |||
} | |||
@@ -97,6 +101,7 @@ public class ByteMemberValue extends MemberValue { | |||
/** | |||
* Accepts a visitor. | |||
*/ | |||
@Override | |||
public void accept(MemberValueVisitor visitor) { | |||
visitor.visitByteMemberValue(this); | |||
} |
@@ -59,11 +59,13 @@ public class CharMemberValue extends MemberValue { | |||
setValue('\0'); | |||
} | |||
@Override | |||
Object getValue(ClassLoader cl, ClassPool cp, Method m) { | |||
return Character.valueOf(getValue()); | |||
} | |||
Class getType(ClassLoader cl) { | |||
@Override | |||
Class<?> getType(ClassLoader cl) { | |||
return char.class; | |||
} | |||
@@ -84,6 +86,7 @@ public class CharMemberValue extends MemberValue { | |||
/** | |||
* Obtains the string representation of this object. | |||
*/ | |||
@Override | |||
public String toString() { | |||
return Character.toString(getValue()); | |||
} | |||
@@ -91,6 +94,7 @@ public class CharMemberValue extends MemberValue { | |||
/** | |||
* Writes the value. | |||
*/ | |||
@Override | |||
public void write(AnnotationsWriter writer) throws IOException { | |||
writer.constValueIndex(getValue()); | |||
} | |||
@@ -98,6 +102,7 @@ public class CharMemberValue extends MemberValue { | |||
/** | |||
* Accepts a visitor. | |||
*/ | |||
@Override | |||
public void accept(MemberValueVisitor visitor) { | |||
visitor.visitCharMemberValue(this); | |||
} |
@@ -64,6 +64,7 @@ public class ClassMemberValue extends MemberValue { | |||
setValue("java.lang.Class"); | |||
} | |||
@Override | |||
Object getValue(ClassLoader cl, ClassPool cp, Method m) | |||
throws ClassNotFoundException { | |||
final String classname = getValue(); | |||
@@ -89,7 +90,8 @@ public class ClassMemberValue extends MemberValue { | |||
return loadClass(cl, classname); | |||
} | |||
Class getType(ClassLoader cl) throws ClassNotFoundException { | |||
@Override | |||
Class<?> getType(ClassLoader cl) throws ClassNotFoundException { | |||
return loadClass(cl, "java.lang.Class"); | |||
} | |||
@@ -120,6 +122,7 @@ public class ClassMemberValue extends MemberValue { | |||
/** | |||
* Obtains the string representation of this object. | |||
*/ | |||
@Override | |||
public String toString() { | |||
return getValue().replace('$', '.') + ".class"; | |||
} | |||
@@ -127,6 +130,7 @@ public class ClassMemberValue extends MemberValue { | |||
/** | |||
* Writes the value. | |||
*/ | |||
@Override | |||
public void write(AnnotationsWriter writer) throws IOException { | |||
writer.classInfoIndex(cp.getUtf8Info(valueIndex)); | |||
} | |||
@@ -134,6 +138,7 @@ public class ClassMemberValue extends MemberValue { | |||
/** | |||
* Accepts a visitor. | |||
*/ | |||
@Override | |||
public void accept(MemberValueVisitor visitor) { | |||
visitor.visitClassMemberValue(this); | |||
} |
@@ -60,11 +60,13 @@ public class DoubleMemberValue extends MemberValue { | |||
setValue(0.0); | |||
} | |||
@Override | |||
Object getValue(ClassLoader cl, ClassPool cp, Method m) { | |||
return Double.valueOf(getValue()); | |||
} | |||
Class getType(ClassLoader cl) { | |||
@Override | |||
Class<?> getType(ClassLoader cl) { | |||
return double.class; | |||
} | |||
@@ -85,6 +87,7 @@ public class DoubleMemberValue extends MemberValue { | |||
/** | |||
* Obtains the string representation of this object. | |||
*/ | |||
@Override | |||
public String toString() { | |||
return Double.toString(getValue()); | |||
} | |||
@@ -92,6 +95,7 @@ public class DoubleMemberValue extends MemberValue { | |||
/** | |||
* Writes the value. | |||
*/ | |||
@Override | |||
public void write(AnnotationsWriter writer) throws IOException { | |||
writer.constValueIndex(getValue()); | |||
} | |||
@@ -99,6 +103,7 @@ public class DoubleMemberValue extends MemberValue { | |||
/** | |||
* Accepts a visitor. | |||
*/ | |||
@Override | |||
public void accept(MemberValueVisitor visitor) { | |||
visitor.visitDoubleMemberValue(this); | |||
} |
@@ -56,6 +56,7 @@ public class EnumMemberValue extends MemberValue { | |||
typeIndex = valueIndex = 0; | |||
} | |||
@Override | |||
Object getValue(ClassLoader cl, ClassPool cp, Method m) | |||
throws ClassNotFoundException | |||
{ | |||
@@ -70,7 +71,8 @@ public class EnumMemberValue extends MemberValue { | |||
} | |||
} | |||
Class getType(ClassLoader cl) throws ClassNotFoundException { | |||
@Override | |||
Class<?> getType(ClassLoader cl) throws ClassNotFoundException { | |||
return loadClass(cl, getType()); | |||
} | |||
@@ -86,7 +88,7 @@ public class EnumMemberValue extends MemberValue { | |||
/** | |||
* Changes the enum type name. | |||
* | |||
* @param typename a fully-qualified type name. | |||
* @param typename a fully-qualified type name. | |||
*/ | |||
public void setType(String typename) { | |||
typeIndex = cp.addUtf8Info(Descriptor.of(typename)); | |||
@@ -106,6 +108,7 @@ public class EnumMemberValue extends MemberValue { | |||
valueIndex = cp.addUtf8Info(name); | |||
} | |||
@Override | |||
public String toString() { | |||
return getType() + "." + getValue(); | |||
} | |||
@@ -113,6 +116,7 @@ public class EnumMemberValue extends MemberValue { | |||
/** | |||
* Writes the value. | |||
*/ | |||
@Override | |||
public void write(AnnotationsWriter writer) throws IOException { | |||
writer.enumConstValue(cp.getUtf8Info(typeIndex), getValue()); | |||
} | |||
@@ -120,6 +124,7 @@ public class EnumMemberValue extends MemberValue { | |||
/** | |||
* Accepts a visitor. | |||
*/ | |||
@Override | |||
public void accept(MemberValueVisitor visitor) { | |||
visitor.visitEnumMemberValue(this); | |||
} |
@@ -60,11 +60,13 @@ public class FloatMemberValue extends MemberValue { | |||
setValue(0.0F); | |||
} | |||
@Override | |||
Object getValue(ClassLoader cl, ClassPool cp, Method m) { | |||
return Float.valueOf(getValue()); | |||
} | |||
Class getType(ClassLoader cl) { | |||
@Override | |||
Class<?> getType(ClassLoader cl) { | |||
return float.class; | |||
} | |||
@@ -85,6 +87,7 @@ public class FloatMemberValue extends MemberValue { | |||
/** | |||
* Obtains the string representation of this object. | |||
*/ | |||
@Override | |||
public String toString() { | |||
return Float.toString(getValue()); | |||
} | |||
@@ -92,6 +95,7 @@ public class FloatMemberValue extends MemberValue { | |||
/** | |||
* Writes the value. | |||
*/ | |||
@Override | |||
public void write(AnnotationsWriter writer) throws IOException { | |||
writer.constValueIndex(getValue()); | |||
} | |||
@@ -99,6 +103,7 @@ public class FloatMemberValue extends MemberValue { | |||
/** | |||
* Accepts a visitor. | |||
*/ | |||
@Override | |||
public void accept(MemberValueVisitor visitor) { | |||
visitor.visitFloatMemberValue(this); | |||
} |
@@ -65,11 +65,13 @@ public class IntegerMemberValue extends MemberValue { | |||
setValue(0); | |||
} | |||
@Override | |||
Object getValue(ClassLoader cl, ClassPool cp, Method m) { | |||
return Integer.valueOf(getValue()); | |||
} | |||
Class getType(ClassLoader cl) { | |||
@Override | |||
Class<?> getType(ClassLoader cl) { | |||
return int.class; | |||
} | |||
@@ -90,6 +92,7 @@ public class IntegerMemberValue extends MemberValue { | |||
/** | |||
* Obtains the string representation of this object. | |||
*/ | |||
@Override | |||
public String toString() { | |||
return Integer.toString(getValue()); | |||
} | |||
@@ -97,6 +100,7 @@ public class IntegerMemberValue extends MemberValue { | |||
/** | |||
* Writes the value. | |||
*/ | |||
@Override | |||
public void write(AnnotationsWriter writer) throws IOException { | |||
writer.constValueIndex(getValue()); | |||
} | |||
@@ -104,6 +108,7 @@ public class IntegerMemberValue extends MemberValue { | |||
/** | |||
* Accepts a visitor. | |||
*/ | |||
@Override | |||
public void accept(MemberValueVisitor visitor) { | |||
visitor.visitIntegerMemberValue(this); | |||
} |
@@ -59,11 +59,13 @@ public class LongMemberValue extends MemberValue { | |||
setValue(0L); | |||
} | |||
@Override | |||
Object getValue(ClassLoader cl, ClassPool cp, Method m) { | |||
return Long.valueOf(getValue()); | |||
} | |||
Class getType(ClassLoader cl) { | |||
@Override | |||
Class<?> getType(ClassLoader cl) { | |||
return long.class; | |||
} | |||
@@ -84,6 +86,7 @@ public class LongMemberValue extends MemberValue { | |||
/** | |||
* Obtains the string representation of this object. | |||
*/ | |||
@Override | |||
public String toString() { | |||
return Long.toString(getValue()); | |||
} | |||
@@ -91,6 +94,7 @@ public class LongMemberValue extends MemberValue { | |||
/** | |||
* Writes the value. | |||
*/ | |||
@Override | |||
public void write(AnnotationsWriter writer) throws IOException { | |||
writer.constValueIndex(getValue()); | |||
} | |||
@@ -98,6 +102,7 @@ public class LongMemberValue extends MemberValue { | |||
/** | |||
* Accepts a visitor. | |||
*/ | |||
@Override | |||
public void accept(MemberValueVisitor visitor) { | |||
visitor.visitLongMemberValue(this); | |||
} |
@@ -47,9 +47,9 @@ public abstract class MemberValue { | |||
abstract Object getValue(ClassLoader cl, ClassPool cp, Method m) | |||
throws ClassNotFoundException; | |||
abstract Class getType(ClassLoader cl) throws ClassNotFoundException; | |||
abstract Class<?> getType(ClassLoader cl) throws ClassNotFoundException; | |||
static Class loadClass(ClassLoader cl, String classname) | |||
static Class<?> loadClass(ClassLoader cl, String classname) | |||
throws ClassNotFoundException, NoSuchClassError | |||
{ | |||
try { | |||
@@ -59,10 +59,10 @@ public abstract class MemberValue { | |||
throw new NoSuchClassError(classname, e); | |||
} | |||
} | |||
private static String convertFromArray(String classname) | |||
{ | |||
int index = classname.indexOf("[]"); | |||
int index = classname.indexOf("[]"); | |||
if (index != -1) { | |||
String rawType = classname.substring(0, index); | |||
StringBuffer sb = new StringBuffer(Descriptor.of(rawType)); |
@@ -59,11 +59,13 @@ public class ShortMemberValue extends MemberValue { | |||
setValue((short)0); | |||
} | |||
@Override | |||
Object getValue(ClassLoader cl, ClassPool cp, Method m) { | |||
return Short.valueOf(getValue()); | |||
} | |||
Class getType(ClassLoader cl) { | |||
@Override | |||
Class<?> getType(ClassLoader cl) { | |||
return short.class; | |||
} | |||
@@ -84,6 +86,7 @@ public class ShortMemberValue extends MemberValue { | |||
/** | |||
* Obtains the string representation of this object. | |||
*/ | |||
@Override | |||
public String toString() { | |||
return Short.toString(getValue()); | |||
} | |||
@@ -91,6 +94,7 @@ public class ShortMemberValue extends MemberValue { | |||
/** | |||
* Writes the value. | |||
*/ | |||
@Override | |||
public void write(AnnotationsWriter writer) throws IOException { | |||
writer.constValueIndex(getValue()); | |||
} | |||
@@ -98,6 +102,7 @@ public class ShortMemberValue extends MemberValue { | |||
/** | |||
* Accepts a visitor. | |||
*/ | |||
@Override | |||
public void accept(MemberValueVisitor visitor) { | |||
visitor.visitShortMemberValue(this); | |||
} |
@@ -59,11 +59,13 @@ public class StringMemberValue extends MemberValue { | |||
setValue(""); | |||
} | |||
@Override | |||
Object getValue(ClassLoader cl, ClassPool cp, Method m) { | |||
return getValue(); | |||
} | |||
Class getType(ClassLoader cl) { | |||
@Override | |||
Class<?> getType(ClassLoader cl) { | |||
return String.class; | |||
} | |||
@@ -84,6 +86,7 @@ public class StringMemberValue extends MemberValue { | |||
/** | |||
* Obtains the string representation of this object. | |||
*/ | |||
@Override | |||
public String toString() { | |||
return "\"" + getValue() + "\""; | |||
} | |||
@@ -91,6 +94,7 @@ public class StringMemberValue extends MemberValue { | |||
/** | |||
* Writes the value. | |||
*/ | |||
@Override | |||
public void write(AnnotationsWriter writer) throws IOException { | |||
writer.constValueIndex(getValue()); | |||
} | |||
@@ -98,6 +102,7 @@ public class StringMemberValue extends MemberValue { | |||
/** | |||
* Accepts a visitor. | |||
*/ | |||
@Override | |||
public void accept(MemberValueVisitor visitor) { | |||
visitor.visitStringMemberValue(this); | |||
} |
@@ -28,6 +28,7 @@ public class TypeAnnotationsWriter extends AnnotationsWriter { | |||
* {@code Runtime(In)VisibleTypeAnnotations_attribute}. | |||
* It must be followed by {@code num} instances of {@code type_annotation}. | |||
*/ | |||
@Override | |||
public void numAnnotations(int num) throws IOException { | |||
super.numAnnotations(num); | |||
} |
@@ -18,7 +18,10 @@ package javassist.bytecode.stackmap; | |||
import javassist.bytecode.*; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
/** | |||
* A basic block is a sequence of bytecode that does not contain jump/branch | |||
@@ -49,11 +52,9 @@ public class BasicBlock { | |||
public static BasicBlock find(BasicBlock[] blocks, int pos) | |||
throws BadBytecode | |||
{ | |||
for (int i = 0; i < blocks.length; i++) { | |||
int iPos = blocks[i].position; | |||
if (iPos <= pos && pos < iPos + blocks[i].length) | |||
return blocks[i]; | |||
} | |||
for (BasicBlock b:blocks) | |||
if (b.position <= pos && pos < b.position + b.length) | |||
return b; | |||
throw new BadBytecode("no basic block at " + pos); | |||
} | |||
@@ -69,6 +70,7 @@ public class BasicBlock { | |||
} | |||
} | |||
@Override | |||
public String toString() { | |||
StringBuffer sbuf = new StringBuffer(); | |||
String cname = this.getClass().getName(); | |||
@@ -84,10 +86,9 @@ public class BasicBlock { | |||
sbuf.append("pos=").append(position).append(", len=") | |||
.append(length).append(", in=").append(incoming) | |||
.append(", exit{"); | |||
if (exit != null) { | |||
for (int i = 0; i < exit.length; i++) | |||
sbuf.append(exit[i].position).append(","); | |||
} | |||
if (exit != null) | |||
for (BasicBlock b:exit) | |||
sbuf.append(b.position).append(","); | |||
sbuf.append("}, {"); | |||
Catch th = toCatch; | |||
@@ -104,7 +105,7 @@ public class BasicBlock { | |||
* A Mark indicates the position of a branch instruction | |||
* or a branch target. | |||
*/ | |||
static class Mark implements Comparable { | |||
static class Mark implements Comparable<Mark> { | |||
int position; | |||
BasicBlock block; | |||
BasicBlock[] jump; | |||
@@ -121,13 +122,11 @@ public class BasicBlock { | |||
catcher = null; | |||
} | |||
public int compareTo(Object obj) { | |||
if (obj instanceof Mark) { | |||
int pos = ((Mark)obj).position; | |||
return position - pos; | |||
} | |||
return -1; | |||
@Override | |||
public int compareTo(Mark obj) { | |||
if (null == obj) | |||
return -1; | |||
return position - obj.position; | |||
} | |||
void setJump(BasicBlock[] bb, int s, boolean always) { | |||
@@ -175,7 +174,7 @@ public class BasicBlock { | |||
ExceptionTable et) | |||
throws BadBytecode | |||
{ | |||
HashMap marks = makeMarks(ci, begin, end, et); | |||
Map<Integer,Mark> marks = makeMarks(ci, begin, end, et); | |||
BasicBlock[] bb = makeBlocks(marks); | |||
addCatchers(bb, et); | |||
return bb; | |||
@@ -183,24 +182,24 @@ public class BasicBlock { | |||
/* Branch target | |||
*/ | |||
private Mark makeMark(HashMap table, int pos) { | |||
private Mark makeMark(Map<Integer,Mark> table, int pos) { | |||
return makeMark0(table, pos, true, true); | |||
} | |||
/* Branch instruction. | |||
* size > 0 | |||
*/ | |||
private Mark makeMark(HashMap table, int pos, BasicBlock[] jump, | |||
private Mark makeMark(Map<Integer,Mark> table, int pos, BasicBlock[] jump, | |||
int size, boolean always) { | |||
Mark m = makeMark0(table, pos, false, false); | |||
m.setJump(jump, size, always); | |||
return m; | |||
} | |||
private Mark makeMark0(HashMap table, int pos, | |||
private Mark makeMark0(Map<Integer,Mark> table, int pos, | |||
boolean isBlockBegin, boolean isTarget) { | |||
Integer p = Integer.valueOf(pos); | |||
Mark m = (Mark)table.get(p); | |||
Integer p = pos; | |||
Mark m = table.get(p); | |||
if (m == null) { | |||
m = new Mark(pos); | |||
table.put(p, m); | |||
@@ -217,13 +216,13 @@ public class BasicBlock { | |||
return m; | |||
} | |||
private HashMap makeMarks(CodeIterator ci, int begin, int end, | |||
private Map<Integer,Mark> makeMarks(CodeIterator ci, int begin, int end, | |||
ExceptionTable et) | |||
throws BadBytecode | |||
{ | |||
ci.begin(); | |||
ci.move(begin); | |||
HashMap marks = new HashMap(); | |||
Map<Integer,Mark> marks = new HashMap<Integer,Mark>(); | |||
while (ci.hasNext()) { | |||
int index = ci.next(); | |||
if (index >= end) | |||
@@ -299,7 +298,7 @@ public class BasicBlock { | |||
return marks; | |||
} | |||
private void makeGoto(HashMap marks, int pos, int target, int size) { | |||
private void makeGoto(Map<Integer,Mark> marks, int pos, int target, int size) { | |||
Mark to = makeMark(marks, target); | |||
BasicBlock[] jumps = makeArray(to.block); | |||
makeMark(marks, pos, jumps, size, true); | |||
@@ -309,7 +308,7 @@ public class BasicBlock { | |||
* We could ignore JSR since Java 7 or later does not allow it. | |||
* See The JVM Spec. Sec. 4.10.2.5. | |||
*/ | |||
protected void makeJsr(HashMap marks, int pos, int target, int size) throws BadBytecode { | |||
protected void makeJsr(Map<Integer,Mark> marks, int pos, int target, int size) throws BadBytecode { | |||
/* | |||
Mark to = makeMark(marks, target); | |||
Mark next = makeMark(marks, pos + size); | |||
@@ -319,11 +318,10 @@ public class BasicBlock { | |||
throw new JsrBytecode(); | |||
} | |||
private BasicBlock[] makeBlocks(HashMap markTable) { | |||
Mark[] marks = (Mark[])markTable.values() | |||
.toArray(new Mark[markTable.size()]); | |||
java.util.Arrays.sort(marks); | |||
ArrayList blocks = new ArrayList(); | |||
private BasicBlock[] makeBlocks(Map<Integer,Mark> markTable) { | |||
Mark[] marks = markTable.values().toArray(new Mark[markTable.size()]); | |||
Arrays.sort(marks); | |||
List<BasicBlock> blocks = new ArrayList<BasicBlock>(); | |||
int i = 0; | |||
BasicBlock prev; | |||
if (marks.length > 0 && marks[0].position == 0 && marks[0].block != null) | |||
@@ -373,7 +371,7 @@ public class BasicBlock { | |||
} | |||
} | |||
return (BasicBlock[])blocks.toArray(makeArray(blocks.size())); | |||
return blocks.toArray(makeArray(blocks.size())); | |||
} | |||
private static BasicBlock getBBlock(Mark m) { |
@@ -17,8 +17,9 @@ | |||
package javassist.bytecode.stackmap; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import javassist.ClassPool; | |||
import javassist.CtClass; | |||
import javassist.NotFoundException; | |||
import javassist.bytecode.*; | |||
@@ -379,7 +380,7 @@ public class MapMaker extends Tracer { | |||
* their types are also fixed when they are found. | |||
*/ | |||
private void fixTypes(byte[] code, TypedBlock[] blocks) throws NotFoundException, BadBytecode { | |||
ArrayList preOrder = new ArrayList(); | |||
List<TypeData> preOrder = new ArrayList<TypeData>(); | |||
int len = blocks.length; | |||
int index = 0; | |||
for (int i = 0; i < len; i++) { | |||
@@ -522,8 +523,7 @@ public class MapMaker extends Tracer { | |||
return diffSize(newTd, len, newTdLen); | |||
else | |||
return -diffSize(oldTd, len, oldTdLen); | |||
else | |||
return -100; | |||
return -100; | |||
} | |||
private static boolean stackMapEq(TypeData[] oldTd, TypeData[] newTd, int len) { |
@@ -69,16 +69,13 @@ public abstract class Tracer implements TypeTag { | |||
protected int doOpcode(int pos, byte[] code) throws BadBytecode { | |||
try { | |||
int op = code[pos] & 0xff; | |||
if (op < 54) | |||
return doOpcode0_53(pos, code, op); | |||
if (op < 96) | |||
if (op < 54) | |||
return doOpcode0_53(pos, code, op); | |||
else | |||
return doOpcode54_95(pos, code, op); | |||
else | |||
if (op < 148) | |||
return doOpcode96_147(pos, code, op); | |||
else | |||
return doOpcode148_201(pos, code, op); | |||
return doOpcode54_95(pos, code, op); | |||
if (op < 148) | |||
return doOpcode96_147(pos, code, op); | |||
return doOpcode148_201(pos, code, op); | |||
} | |||
catch (ArrayIndexOutOfBoundsException e) { | |||
throw new BadBytecode("inconsistent stack height " + e.getMessage(), e); |
@@ -25,6 +25,8 @@ import javassist.bytecode.StackMapTable; | |||
import javassist.bytecode.BadBytecode; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Set; | |||
import java.util.ArrayList; | |||
public abstract class TypeData { | |||
@@ -49,6 +51,7 @@ public abstract class TypeData { | |||
* | |||
* @param className dot-separated name unless the type is an array type. | |||
*/ | |||
@SuppressWarnings("unused") | |||
private static void setType(TypeData td, String className, ClassPool cp) throws BadBytecode { | |||
td.setType(className, cp); | |||
} | |||
@@ -89,7 +92,7 @@ public abstract class TypeData { | |||
* @param order a node stack in the order in which nodes are visited. | |||
* @param index the index used by the algorithm. | |||
*/ | |||
public int dfs(ArrayList order, int index, ClassPool cp) | |||
public int dfs(List<TypeData> order, int index, ClassPool cp) | |||
throws NotFoundException | |||
{ | |||
return index; | |||
@@ -107,11 +110,12 @@ public abstract class TypeData { | |||
// see UninitTypeVar and UninitData | |||
public void constructorCalled(int offset) {} | |||
@Override | |||
public String toString() { | |||
return super.toString() + "(" + toString2(new HashSet()) + ")"; | |||
return super.toString() + "(" + toString2(new HashSet<TypeData>()) + ")"; | |||
} | |||
abstract String toString2(HashSet set); | |||
abstract String toString2(Set<TypeData> set); | |||
/** | |||
* Primitive types. | |||
@@ -127,31 +131,38 @@ public abstract class TypeData { | |||
decodedName = decoded; | |||
} | |||
@Override | |||
public int getTypeTag() { return typeTag; } | |||
@Override | |||
public int getTypeData(ConstPool cp) { return 0; } | |||
@Override | |||
public TypeData join() { | |||
if (this == TypeTag.TOP) | |||
return this; | |||
else | |||
return super.join(); | |||
return super.join(); | |||
} | |||
@Override | |||
public BasicType isBasicType() { return this; } | |||
@Override | |||
public boolean is2WordType() { | |||
return typeTag == StackMapTable.LONG | |||
|| typeTag == StackMapTable.DOUBLE; | |||
} | |||
@Override | |||
public boolean eq(TypeData d) { return this == d; } | |||
@Override | |||
public String getName() { | |||
return name; | |||
} | |||
public char getDecodedName() { return decodedName; } | |||
@Override | |||
public void setType(String s, ClassPool cp) throws BadBytecode { | |||
throw new BadBytecode("conflict: " + name + " and " + s); | |||
} | |||
@@ -159,6 +170,7 @@ public abstract class TypeData { | |||
/** | |||
* @param dim array dimension. It may be negative. | |||
*/ | |||
@Override | |||
public TypeData getArrayType(int dim) throws NotFoundException { | |||
if (this == TypeTag.TOP) | |||
return this; | |||
@@ -176,103 +188,109 @@ public abstract class TypeData { | |||
} | |||
} | |||
String toString2(HashSet set) { return name; } | |||
@Override | |||
String toString2(Set<TypeData> set) { return name; } | |||
} | |||
// a type variable | |||
public static abstract class AbsTypeVar extends TypeData { | |||
public AbsTypeVar() {} | |||
public abstract void merge(TypeData t); | |||
@Override | |||
public int getTypeTag() { return StackMapTable.OBJECT; } | |||
@Override | |||
public int getTypeData(ConstPool cp) { | |||
return cp.addClassInfo(getName()); | |||
} | |||
@Override | |||
public boolean eq(TypeData d) { return getName().equals(d.getName()); } | |||
} | |||
/* a type variable representing a class type or a basic type. | |||
*/ | |||
public static class TypeVar extends AbsTypeVar { | |||
protected ArrayList lowers; // lower bounds of this type. ArrayList<TypeData> | |||
protected ArrayList usedBy; // reverse relations of lowers | |||
protected ArrayList uppers; // upper bounds of this type. | |||
protected List<TypeData> lowers;// lower bounds of this type. ArrayList<TypeData> | |||
protected List<TypeData> usedBy;// reverse relations of lowers | |||
protected List<String> uppers; // upper bounds of this type. | |||
protected String fixedType; | |||
private boolean is2WordType; // cache | |||
public TypeVar(TypeData t) { | |||
uppers = null; | |||
lowers = new ArrayList(2); | |||
usedBy = new ArrayList(2); | |||
lowers = new ArrayList<TypeData>(2); | |||
usedBy = new ArrayList<TypeData>(2); | |||
merge(t); | |||
fixedType = null; | |||
is2WordType = t.is2WordType(); | |||
} | |||
@Override | |||
public String getName() { | |||
if (fixedType == null) | |||
return ((TypeData)lowers.get(0)).getName(); | |||
else | |||
return fixedType; | |||
return lowers.get(0).getName(); | |||
return fixedType; | |||
} | |||
@Override | |||
public BasicType isBasicType() { | |||
if (fixedType == null) | |||
return ((TypeData)lowers.get(0)).isBasicType(); | |||
else | |||
return null; | |||
return lowers.get(0).isBasicType(); | |||
return null; | |||
} | |||
@Override | |||
public boolean is2WordType() { | |||
if (fixedType == null) { | |||
return is2WordType; | |||
// return ((TypeData)lowers.get(0)).is2WordType(); | |||
} | |||
else | |||
return false; | |||
return false; | |||
} | |||
@Override | |||
public boolean isNullType() { | |||
if (fixedType == null) | |||
return ((TypeData)lowers.get(0)).isNullType(); | |||
else | |||
return false; | |||
return lowers.get(0).isNullType(); | |||
return false; | |||
} | |||
@Override | |||
public boolean isUninit() { | |||
if (fixedType == null) | |||
return ((TypeData)lowers.get(0)).isUninit(); | |||
else | |||
return false; | |||
return lowers.get(0).isUninit(); | |||
return false; | |||
} | |||
@Override | |||
public void merge(TypeData t) { | |||
lowers.add(t); | |||
if (t instanceof TypeVar) | |||
((TypeVar)t).usedBy.add(this); | |||
} | |||
@Override | |||
public int getTypeTag() { | |||
/* If fixedType is null after calling dfs(), then this | |||
type is NULL, Uninit, or a basic type. So call | |||
getTypeTag() on the first element of lowers. */ | |||
if (fixedType == null) | |||
return ((TypeData)lowers.get(0)).getTypeTag(); | |||
else | |||
return super.getTypeTag(); | |||
return lowers.get(0).getTypeTag(); | |||
return super.getTypeTag(); | |||
} | |||
@Override | |||
public int getTypeData(ConstPool cp) { | |||
if (fixedType == null) | |||
return ((TypeData)lowers.get(0)).getTypeData(cp); | |||
else | |||
return super.getTypeData(cp); | |||
return lowers.get(0).getTypeData(cp); | |||
return super.getTypeData(cp); | |||
} | |||
@Override | |||
public void setType(String typeName, ClassPool cp) throws BadBytecode { | |||
if (uppers == null) | |||
uppers = new ArrayList(); | |||
uppers = new ArrayList<String>(); | |||
uppers.add(typeName); | |||
} | |||
@@ -282,6 +300,7 @@ public abstract class TypeData { | |||
private boolean inList = false; | |||
private int dimension = 0; | |||
@Override | |||
protected TypeVar toTypeVar(int dim) { | |||
dimension = dim; | |||
return this; | |||
@@ -290,23 +309,22 @@ public abstract class TypeData { | |||
/* When fixTypes() is called, getName() will return the correct | |||
* (i.e. fixed) type name. | |||
*/ | |||
@Override | |||
public TypeData getArrayType(int dim) throws NotFoundException { | |||
if (dim == 0) | |||
return this; | |||
else { | |||
BasicType bt = isBasicType(); | |||
if (bt == null) | |||
if (isNullType()) | |||
return new NullType(); | |||
else | |||
return new ClassName(getName()).getArrayType(dim); | |||
BasicType bt = isBasicType(); | |||
if (bt == null) | |||
if (isNullType()) | |||
return new NullType(); | |||
else | |||
return bt.getArrayType(dim); | |||
} | |||
return new ClassName(getName()).getArrayType(dim); | |||
return bt.getArrayType(dim); | |||
} | |||
// depth-first serach | |||
public int dfs(ArrayList preOrder, int index, ClassPool cp) throws NotFoundException { | |||
@Override | |||
public int dfs(List<TypeData> preOrder, int index, ClassPool cp) throws NotFoundException { | |||
if (visited > 0) | |||
return index; // MapMaker.make() may call an already visited node. | |||
@@ -315,7 +333,7 @@ public abstract class TypeData { | |||
inList = true; | |||
int n = lowers.size(); | |||
for (int i = 0; i < n; i++) { | |||
TypeVar child = ((TypeData)lowers.get(i)).toTypeVar(dimension); | |||
TypeVar child = lowers.get(i).toTypeVar(dimension); | |||
if (child != null) | |||
if (child.visited == 0) { | |||
index = child.dfs(preOrder, index, cp); | |||
@@ -328,7 +346,7 @@ public abstract class TypeData { | |||
} | |||
if (visited == smallest) { | |||
ArrayList scc = new ArrayList(); // strongly connected component | |||
List<TypeData> scc = new ArrayList<TypeData>(); // strongly connected component | |||
TypeVar cv; | |||
do { | |||
cv = (TypeVar)preOrder.remove(preOrder.size() - 1); | |||
@@ -341,17 +359,17 @@ public abstract class TypeData { | |||
return index; | |||
} | |||
private void fixTypes(ArrayList scc, ClassPool cp) throws NotFoundException { | |||
HashSet lowersSet = new HashSet(); | |||
private void fixTypes(List<TypeData> scc, ClassPool cp) throws NotFoundException { | |||
Set<String> lowersSet = new HashSet<String>(); | |||
boolean isBasicType = false; | |||
TypeData kind = null; | |||
int size = scc.size(); | |||
for (int i = 0; i < size; i++) { | |||
TypeVar tvar = (TypeVar)scc.get(i); | |||
ArrayList tds = tvar.lowers; | |||
List<TypeData> tds = tvar.lowers; | |||
int size2 = tds.size(); | |||
for (int j = 0; j < size2; j++) { | |||
TypeData td = (TypeData)tds.get(j); | |||
TypeData td = tds.get(j); | |||
TypeData d = td.getArrayType(tvar.dimension); | |||
BasicType bt = d.isBasicType(); | |||
if (kind == null) { | |||
@@ -393,7 +411,7 @@ public abstract class TypeData { | |||
} | |||
} | |||
private void fixTypes1(ArrayList scc, TypeData kind) throws NotFoundException { | |||
private void fixTypes1(List<TypeData> scc, TypeData kind) throws NotFoundException { | |||
int size = scc.size(); | |||
for (int i = 0; i < size; i++) { | |||
TypeVar cv = (TypeVar)scc.get(i); | |||
@@ -408,24 +426,24 @@ public abstract class TypeData { | |||
} | |||
} | |||
private String fixTypes2(ArrayList scc, HashSet lowersSet, ClassPool cp) throws NotFoundException { | |||
Iterator it = lowersSet.iterator(); | |||
private String fixTypes2(List<TypeData> scc, Set<String> lowersSet, ClassPool cp) throws NotFoundException { | |||
Iterator<String> it = lowersSet.iterator(); | |||
if (lowersSet.size() == 0) | |||
return null; // only NullType | |||
else if (lowersSet.size() == 1) | |||
return (String)it.next(); | |||
return it.next(); | |||
else { | |||
CtClass cc = cp.get((String)it.next()); | |||
CtClass cc = cp.get(it.next()); | |||
while (it.hasNext()) | |||
cc = commonSuperClassEx(cc, cp.get((String)it.next())); | |||
cc = commonSuperClassEx(cc, cp.get(it.next())); | |||
if (cc.getSuperclass() == null || isObjectArray(cc)) | |||
cc = fixByUppers(scc, cp, new HashSet(), cc); | |||
cc = fixByUppers(scc, cp, new HashSet<TypeData>(), cc); | |||
if (cc.isArray()) | |||
return Descriptor.toJvmName(cc); | |||
else | |||
return cc.getName(); | |||
return cc.getName(); | |||
} | |||
} | |||
@@ -433,7 +451,7 @@ public abstract class TypeData { | |||
return cc.isArray() && cc.getComponentType().getSuperclass() == null; | |||
} | |||
private CtClass fixByUppers(ArrayList users, ClassPool cp, HashSet visited, CtClass type) | |||
private CtClass fixByUppers(List<TypeData> users, ClassPool cp, Set<TypeData> visited, CtClass type) | |||
throws NotFoundException | |||
{ | |||
if (users == null) | |||
@@ -448,7 +466,7 @@ public abstract class TypeData { | |||
if (t.uppers != null) { | |||
int s = t.uppers.size(); | |||
for (int k = 0; k < s; k++) { | |||
CtClass cc = cp.get((String)t.uppers.get(k)); | |||
CtClass cc = cp.get(t.uppers.get(k)); | |||
if (cc.subtypeOf(type)) | |||
type = cc; | |||
} | |||
@@ -460,13 +478,13 @@ public abstract class TypeData { | |||
return type; | |||
} | |||
String toString2(HashSet hash) { | |||
@Override | |||
String toString2(Set<TypeData> hash) { | |||
hash.add(this); | |||
if (lowers.size() > 0) { | |||
TypeData e = (TypeData)lowers.get(0); | |||
if (e != null && !hash.contains(e)) { | |||
TypeData e = lowers.get(0); | |||
if (e != null && !hash.contains(e)) | |||
return e.toString2(hash); | |||
} | |||
} | |||
return "?"; | |||
@@ -494,7 +512,7 @@ public abstract class TypeData { | |||
} | |||
else if (one.isPrimitive() || two.isPrimitive()) | |||
return null; // TOP | |||
else if (one.isArray() || two.isArray()) // but !(one.isArray() && two.isArray()) | |||
else if (one.isArray() || two.isArray()) // but !(one.isArray() && two.isArray()) | |||
return one.getClassPool().get("java.lang.Object"); | |||
else | |||
return commonSuperClass(one, two); | |||
@@ -605,6 +623,7 @@ public abstract class TypeData { | |||
throw new BadBytecode("bad AASTORE: " + element); | |||
} | |||
@Override | |||
public void merge(TypeData t) { | |||
try { | |||
if (!t.isNullType()) | |||
@@ -616,13 +635,16 @@ public abstract class TypeData { | |||
} | |||
} | |||
@Override | |||
public String getName() { | |||
return typeName(element.getName()); | |||
} | |||
public AbsTypeVar elementType() { return element; } | |||
@Override | |||
public BasicType isBasicType() { return null; } | |||
@Override | |||
public boolean is2WordType() { return false; } | |||
/* elementType must be a class name. Basic type names | |||
@@ -631,25 +653,29 @@ public abstract class TypeData { | |||
public static String typeName(String elementType) { | |||
if (elementType.charAt(0) == '[') | |||
return "[" + elementType; | |||
else | |||
return "[L" + elementType.replace('.', '/') + ";"; | |||
return "[L" + elementType.replace('.', '/') + ";"; | |||
} | |||
@Override | |||
public void setType(String s, ClassPool cp) throws BadBytecode { | |||
element.setType(ArrayElement.typeName(s), cp); | |||
} | |||
@Override | |||
protected TypeVar toTypeVar(int dim) { return element.toTypeVar(dim + 1); } | |||
@Override | |||
public TypeData getArrayType(int dim) throws NotFoundException { | |||
return element.getArrayType(dim + 1); | |||
} | |||
public int dfs(ArrayList order, int index, ClassPool cp) throws NotFoundException { | |||
@Override | |||
public int dfs(List<TypeData> order, int index, ClassPool cp) throws NotFoundException { | |||
return element.dfs(order, index, cp); | |||
} | |||
String toString2(HashSet set) { | |||
@Override | |||
String toString2(Set<TypeData> set) { | |||
return "[" + element.toString2(set); | |||
} | |||
} | |||
@@ -659,7 +685,7 @@ public abstract class TypeData { | |||
*/ | |||
public static class ArrayElement extends AbsTypeVar { | |||
private AbsTypeVar array; | |||
private ArrayElement(AbsTypeVar a) { // a is never null | |||
array = a; | |||
} | |||
@@ -676,6 +702,7 @@ public abstract class TypeData { | |||
throw new BadBytecode("bad AASTORE: " + array); | |||
} | |||
@Override | |||
public void merge(TypeData t) { | |||
try { | |||
if (!t.isNullType()) | |||
@@ -687,6 +714,7 @@ public abstract class TypeData { | |||
} | |||
} | |||
@Override | |||
public String getName() { | |||
return typeName(array.getName()); | |||
} | |||
@@ -697,8 +725,10 @@ public abstract class TypeData { | |||
* not allowed. | |||
*/ | |||
@Override | |||
public BasicType isBasicType() { return null; } | |||
@Override | |||
public boolean is2WordType() { return false; } | |||
private static String typeName(String arrayType) { | |||
@@ -713,21 +743,26 @@ public abstract class TypeData { | |||
return "java.lang.Object"; // the array type may be NullType | |||
} | |||
@Override | |||
public void setType(String s, ClassPool cp) throws BadBytecode { | |||
array.setType(ArrayType.typeName(s), cp); | |||
} | |||
@Override | |||
protected TypeVar toTypeVar(int dim) { return array.toTypeVar(dim - 1); } | |||
@Override | |||
public TypeData getArrayType(int dim) throws NotFoundException { | |||
return array.getArrayType(dim - 1); | |||
} | |||
public int dfs(ArrayList order, int index, ClassPool cp) throws NotFoundException { | |||
@Override | |||
public int dfs(List<TypeData> order, int index, ClassPool cp) throws NotFoundException { | |||
return array.dfs(order, index, cp); | |||
} | |||
String toString2(HashSet set) { | |||
@Override | |||
String toString2(Set<TypeData> set) { | |||
return "*" + array.toString2(set); | |||
} | |||
} | |||
@@ -736,26 +771,38 @@ public abstract class TypeData { | |||
protected TypeData type; // UninitData or TOP | |||
public UninitTypeVar(UninitData t) { type = t; } | |||
@Override | |||
public int getTypeTag() { return type.getTypeTag(); } | |||
@Override | |||
public int getTypeData(ConstPool cp) { return type.getTypeData(cp); } | |||
@Override | |||
public BasicType isBasicType() { return type.isBasicType(); } | |||
@Override | |||
public boolean is2WordType() { return type.is2WordType(); } | |||
@Override | |||
public boolean isUninit() { return type.isUninit(); } | |||
@Override | |||
public boolean eq(TypeData d) { return type.eq(d); } | |||
@Override | |||
public String getName() { return type.getName(); } | |||
@Override | |||
protected TypeVar toTypeVar(int dim) { return null; } | |||
@Override | |||
public TypeData join() { return type.join(); } | |||
@Override | |||
public void setType(String s, ClassPool cp) throws BadBytecode { | |||
type.setType(s, cp); | |||
} | |||
@Override | |||
public void merge(TypeData t) { | |||
if (!t.eq(type)) | |||
type = TypeTag.TOP; | |||
} | |||
@Override | |||
public void constructorCalled(int offset) { | |||
type.constructorCalled(offset); | |||
} | |||
@@ -763,15 +810,16 @@ public abstract class TypeData { | |||
public int offset() { | |||
if (type instanceof UninitData) | |||
return ((UninitData)type).offset; | |||
else // if type == TypeTag.TOP | |||
throw new RuntimeException("not available"); | |||
throw new RuntimeException("not available"); | |||
} | |||
@Override | |||
public TypeData getArrayType(int dim) throws NotFoundException { | |||
return type.getArrayType(dim); | |||
} | |||
String toString2(HashSet set) { return ""; } | |||
@Override | |||
String toString2(Set<TypeData> set) { return ""; } | |||
} | |||
/** | |||
@@ -784,24 +832,32 @@ public abstract class TypeData { | |||
name = n; | |||
} | |||
@Override | |||
public String getName() { | |||
return name; | |||
} | |||
@Override | |||
public BasicType isBasicType() { return null; } | |||
@Override | |||
public boolean is2WordType() { return false; } | |||
@Override | |||
public int getTypeTag() { return StackMapTable.OBJECT; } | |||
@Override | |||
public int getTypeData(ConstPool cp) { | |||
return cp.addClassInfo(getName()); | |||
} | |||
@Override | |||
public boolean eq(TypeData d) { return name.equals(d.getName()); } | |||
@Override | |||
public void setType(String typeName, ClassPool cp) throws BadBytecode {} | |||
@Override | |||
public TypeData getArrayType(int dim) throws NotFoundException { | |||
if (dim == 0) | |||
return this; | |||
@@ -825,7 +881,7 @@ public abstract class TypeData { | |||
if (type == '[') | |||
return new ClassName(name.substring(-dim)); | |||
else if (type == 'L') | |||
return new ClassName(name.substring(-dim + 1, name.length() - 1).replace('/', '.')); | |||
return new ClassName(name.substring(-dim + 1, name.length() - 1).replace('/', '.')); | |||
else if (type == TypeTag.DOUBLE.decodedName) | |||
return TypeTag.DOUBLE; | |||
else if (type == TypeTag.FLOAT.decodedName) | |||
@@ -837,7 +893,8 @@ public abstract class TypeData { | |||
} | |||
} | |||
String toString2(HashSet set) { | |||
@Override | |||
String toString2(Set<TypeData> set) { | |||
return name; | |||
} | |||
} | |||
@@ -852,13 +909,17 @@ public abstract class TypeData { | |||
super("null-type"); // type name | |||
} | |||
@Override | |||
public int getTypeTag() { | |||
return StackMapTable.NULL; | |||
} | |||
@Override | |||
public boolean isNullType() { return true; } | |||
@Override | |||
public int getTypeData(ConstPool cp) { return 0; } | |||
@Override | |||
public TypeData getArrayType(int dim) { return this; } | |||
} | |||
@@ -877,40 +938,45 @@ public abstract class TypeData { | |||
public UninitData copy() { return new UninitData(offset, getName()); } | |||
@Override | |||
public int getTypeTag() { | |||
return StackMapTable.UNINIT; | |||
} | |||
@Override | |||
public int getTypeData(ConstPool cp) { | |||
return offset; | |||
} | |||
@Override | |||
public TypeData join() { | |||
if (initialized) | |||
return new TypeVar(new ClassName(getName())); | |||
else | |||
return new UninitTypeVar(copy()); | |||
return new UninitTypeVar(copy()); | |||
} | |||
@Override | |||
public boolean isUninit() { return true; } | |||
@Override | |||
public boolean eq(TypeData d) { | |||
if (d instanceof UninitData) { | |||
UninitData ud = (UninitData)d; | |||
return offset == ud.offset && getName().equals(ud.getName()); | |||
} | |||
else | |||
return false; | |||
return false; | |||
} | |||
public int offset() { return offset; } | |||
@Override | |||
public void constructorCalled(int offset) { | |||
if (offset == this.offset) | |||
initialized = true; | |||
} | |||
String toString2(HashSet set) { return getName() + "," + offset; } | |||
@Override | |||
String toString2(Set<TypeData> set) { return getName() + "," + offset; } | |||
} | |||
public static class UninitThis extends UninitData { | |||
@@ -918,16 +984,20 @@ public abstract class TypeData { | |||
super(-1, className); | |||
} | |||
@Override | |||
public UninitData copy() { return new UninitThis(getName()); } | |||
@Override | |||
public int getTypeTag() { | |||
return StackMapTable.THIS; | |||
} | |||
@Override | |||
public int getTypeData(ConstPool cp) { | |||
return 0; | |||
} | |||
String toString2(HashSet set) { return "uninit:this"; } | |||
@Override | |||
String toString2(Set<TypeData> set) { return "uninit:this"; } | |||
} | |||
} |
@@ -54,6 +54,7 @@ public class TypedBlock extends BasicBlock { | |||
localsTypes = null; | |||
} | |||
@Override | |||
protected void toString2(StringBuffer sbuf) { | |||
super.toString2(sbuf); | |||
sbuf.append(",\n stack={"); | |||
@@ -110,10 +111,12 @@ public class TypedBlock extends BasicBlock { | |||
} | |||
public static class Maker extends BasicBlock.Maker { | |||
@Override | |||
protected BasicBlock makeBlock(int pos) { | |||
return new TypedBlock(pos); | |||
} | |||
@Override | |||
protected BasicBlock[] makeArray(int size) { | |||
return new TypedBlock[size]; | |||
} |
@@ -19,6 +19,7 @@ package javassist.compiler; | |||
import javassist.*; | |||
import javassist.bytecode.*; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
/** | |||
* AccessorMaker maintains accessors to private members of an enclosing | |||
@@ -27,14 +28,14 @@ import java.util.HashMap; | |||
public class AccessorMaker { | |||
private CtClass clazz; | |||
private int uniqueNumber; | |||
private HashMap accessors; | |||
private Map<String,Object> accessors; | |||
static final String lastParamType = "javassist.runtime.Inner"; | |||
public AccessorMaker(CtClass c) { | |||
clazz = c; | |||
uniqueNumber = 1; | |||
accessors = new HashMap(); | |||
accessors = new HashMap<String,Object>(); | |||
} | |||
public String getConstructor(CtClass c, String desc, MethodInfo orig) |
@@ -18,10 +18,12 @@ package javassist.compiler; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import javassist.compiler.ast.*; | |||
import javassist.bytecode.*; | |||
/* The code generator is implemeted by three files: | |||
/* The code generator is implemented by three files: | |||
* CodeGen.java, MemberCodeGen.java, and JvstCodeGen. | |||
* I just wanted to split a big file into three smaller ones. | |||
*/ | |||
@@ -47,7 +49,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
*/ | |||
public boolean inStaticMethod; | |||
protected ArrayList breakList, continueList; | |||
protected List<Integer> breakList, continueList; | |||
/** | |||
* doit() in ReturnHook is called from atReturn(). | |||
@@ -171,18 +173,16 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
if (dim == 0) | |||
return name; | |||
else { | |||
StringBuffer sbuf = new StringBuffer(); | |||
int d = dim; | |||
while (d-- > 0) | |||
sbuf.append('['); | |||
StringBuffer sbuf = new StringBuffer(); | |||
int d = dim; | |||
while (d-- > 0) | |||
sbuf.append('['); | |||
sbuf.append('L'); | |||
sbuf.append(name); | |||
sbuf.append(';'); | |||
sbuf.append('L'); | |||
sbuf.append(name); | |||
sbuf.append(';'); | |||
return sbuf.toString(); | |||
} | |||
return sbuf.toString(); | |||
} | |||
protected static String toJvmTypeName(int type, int dim) { | |||
@@ -242,16 +242,21 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
expr.accept(typeChecker); | |||
} | |||
@Override | |||
public void atASTList(ASTList n) throws CompileError { fatal(); } | |||
@Override | |||
public void atPair(Pair n) throws CompileError { fatal(); } | |||
@Override | |||
public void atSymbol(Symbol n) throws CompileError { fatal(); } | |||
@Override | |||
public void atFieldDecl(FieldDecl field) throws CompileError { | |||
field.getInit().accept(this); | |||
} | |||
@Override | |||
public void atMethodDecl(MethodDecl method) throws CompileError { | |||
ASTList mods = method.getModifiers(); | |||
setMaxLocals(1); | |||
@@ -263,7 +268,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
inStaticMethod = true; | |||
} | |||
} | |||
ASTList params = method.getParams(); | |||
while (params != null) { | |||
atDeclarator((Declarator)params.head()); | |||
@@ -320,6 +325,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
protected abstract void insertDefaultSuperCall() throws CompileError; | |||
@Override | |||
public void atStmnt(Stmnt st) throws CompileError { | |||
if (st == null) | |||
return; // empty | |||
@@ -417,10 +423,10 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
} | |||
private void atWhileStmnt(Stmnt st, boolean notDo) throws CompileError { | |||
ArrayList prevBreakList = breakList; | |||
ArrayList prevContList = continueList; | |||
breakList = new ArrayList(); | |||
continueList = new ArrayList(); | |||
List<Integer> prevBreakList = breakList; | |||
List<Integer> prevContList = continueList; | |||
breakList = new ArrayList<Integer>(); | |||
continueList = new ArrayList<Integer>(); | |||
ASTree expr = st.head(); | |||
Stmnt body = (Stmnt)st.tail(); | |||
@@ -454,19 +460,16 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
hasReturned = alwaysBranch; | |||
} | |||
protected void patchGoto(ArrayList list, int targetPc) { | |||
int n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
int pc = ((Integer)list.get(i)).intValue(); | |||
protected void patchGoto(List<Integer> list, int targetPc) { | |||
for (int pc:list) | |||
bytecode.write16bit(pc, targetPc - pc + 1); | |||
} | |||
} | |||
private void atForStmnt(Stmnt st) throws CompileError { | |||
ArrayList prevBreakList = breakList; | |||
ArrayList prevContList = continueList; | |||
breakList = new ArrayList(); | |||
continueList = new ArrayList(); | |||
List<Integer> prevBreakList = breakList; | |||
List<Integer> prevContList = continueList; | |||
breakList = new ArrayList<Integer>(); | |||
continueList = new ArrayList<Integer>(); | |||
Stmnt init = (Stmnt)st.head(); | |||
ASTList p = st.tail(); | |||
@@ -517,8 +520,8 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
private void atSwitchStmnt(Stmnt st) throws CompileError { | |||
compileExpr(st.head()); | |||
ArrayList prevBreakList = breakList; | |||
breakList = new ArrayList(); | |||
List<Integer> prevBreakList = breakList; | |||
breakList = new ArrayList<Integer>(); | |||
int opcodePc = bytecode.currentPc(); | |||
bytecode.addOpcode(LOOKUPSWITCH); | |||
int npads = 3 - (opcodePc & 3); | |||
@@ -583,8 +586,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
expr = TypeChecker.stripPlusExpr(expr); | |||
if (expr instanceof IntConst) | |||
return (int)((IntConst)expr).get(); | |||
else | |||
throw new CompileError("bad case label"); | |||
throw new CompileError("bad case label"); | |||
} | |||
private void atBreakStmnt(Stmnt st, boolean notCont) | |||
@@ -672,6 +674,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
bc.addOpcode(MONITORENTER); | |||
ReturnHook rh = new ReturnHook(this) { | |||
@Override | |||
protected boolean doit(Bytecode b, int opcode) { | |||
b.addAload(var); | |||
b.addOpcode(MONITOREXIT); | |||
@@ -711,7 +714,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
"sorry, cannot break/continue in synchronized block"); | |||
} | |||
private static int getListSize(ArrayList list) { | |||
private static int getListSize(List<Integer> list) { | |||
return list == null ? 0 : list.size(); | |||
} | |||
@@ -724,6 +727,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
return false; | |||
} | |||
@Override | |||
public void atDeclarator(Declarator d) throws CompileError { | |||
d.setLocalVar(getMaxLocals()); | |||
d.setClassName(resolveClassName(d.getClassName())); | |||
@@ -745,10 +749,13 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
} | |||
} | |||
@Override | |||
public abstract void atNewExpr(NewExpr n) throws CompileError; | |||
@Override | |||
public abstract void atArrayInit(ArrayInit init) throws CompileError; | |||
@Override | |||
public void atAssignExpr(AssignExpr expr) throws CompileError { | |||
atAssignExpr(expr, true); | |||
} | |||
@@ -931,6 +938,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
return false; | |||
} | |||
@Override | |||
public void atCondExpr(CondExpr expr) throws CompileError { | |||
if (booleanExpr(false, expr.condExpr())) | |||
expr.elseExpr().accept(this); | |||
@@ -974,6 +982,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
return -1; | |||
} | |||
@Override | |||
public void atBinExpr(BinExpr expr) throws CompileError { | |||
int token = expr.getOperator(); | |||
@@ -1136,7 +1145,6 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
arrayDim = 0; | |||
return true; | |||
} | |||
else { | |||
int pc = bytecode.currentPc(); | |||
bytecode.addIndex(0); // correct later | |||
if (booleanExpr(isAndAnd, bexpr.oprand2())) | |||
@@ -1147,7 +1155,6 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
bytecode.addIndex(6); // skip GOTO instruction | |||
bytecode.addOpcode(Opcode.GOTO); | |||
} | |||
} | |||
} | |||
else if (isAlwaysBranch(expr, branchIf)) { | |||
// Opcode.GOTO is not added here. The caller must add it. | |||
@@ -1207,8 +1214,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
if (type1 == NULL) | |||
return exprType; | |||
else | |||
return type1; | |||
return type1; | |||
} | |||
private static final int ifOp[] = { EQ, IF_ICMPEQ, IF_ICMPNE, | |||
@@ -1390,6 +1396,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
bytecode.addOpcode(op); | |||
} | |||
@Override | |||
public void atCastExpr(CastExpr expr) throws CompileError { | |||
String cname = resolveClassName(expr.getClassName()); | |||
String toClass = checkCastExpr(expr, cname); | |||
@@ -1403,6 +1410,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
bytecode.addCheckcast(toClass); | |||
} | |||
@Override | |||
public void atInstanceOfExpr(InstanceOfExpr expr) throws CompileError { | |||
String cname = resolveClassName(expr.getClassName()); | |||
String toClass = checkCastExpr(expr, cname); | |||
@@ -1443,7 +1451,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
{ | |||
if (srcType == destType) | |||
return; | |||
int op, op2; | |||
int stype = typePrecedence(srcType); | |||
int dtype = typePrecedence(destType); | |||
@@ -1475,6 +1483,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
bytecode.addOpcode(op2); | |||
} | |||
@Override | |||
public void atExpr(Expr expr) throws CompileError { | |||
// array access, member access, | |||
// (unary) +, (unary) -, ++, --, !, ~ | |||
@@ -1483,7 +1492,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
ASTree oprand = expr.oprand1(); | |||
if (token == '.') { | |||
String member = ((Symbol)expr.oprand2()).get(); | |||
if (member.equals("class")) | |||
if (member.equals("class")) | |||
atClassObject(expr); // .class | |||
else | |||
atFieldRead(expr); | |||
@@ -1560,6 +1569,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
throw new CompileError("invalid type for " + expr.getName()); | |||
} | |||
@Override | |||
public abstract void atCallExpr(CallExpr expr) throws CompileError; | |||
protected abstract void atFieldRead(ASTree expr) throws CompileError; | |||
@@ -1749,7 +1759,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
if (doDup && isPost) | |||
bytecode.addOpcode(DUP2); | |||
bytecode.addLconst((long)1); | |||
bytecode.addLconst(1); | |||
bytecode.addOpcode(token == PLUSPLUS ? LADD : LSUB); | |||
if (doDup && !isPost) | |||
bytecode.addOpcode(DUP2); | |||
@@ -1835,7 +1845,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
exprType = INT; | |||
} | |||
else if (t == LONG) { | |||
bytecode.addLconst((long)1); | |||
bytecode.addLconst(1); | |||
bytecode.addOpcode(token == PLUSPLUS ? LADD : LSUB); | |||
} | |||
else if (t == FLOAT) { | |||
@@ -1856,8 +1866,10 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
protected abstract void atFieldPlusPlus(int token, boolean isPost, | |||
ASTree oprand, Expr expr, boolean doDup) throws CompileError; | |||
@Override | |||
public abstract void atMember(Member n) throws CompileError; | |||
@Override | |||
public void atVariable(Variable v) throws CompileError { | |||
Declarator d = v.getDeclarator(); | |||
exprType = d.getType(); | |||
@@ -1887,6 +1899,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
} | |||
} | |||
@Override | |||
public void atKeyword(Keyword k) throws CompileError { | |||
arrayDim = 0; | |||
int token = k.get(); | |||
@@ -1914,13 +1927,14 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
if (token == THIS) | |||
className = getThisName(); | |||
else | |||
className = getSuperName(); | |||
className = getSuperName(); | |||
break; | |||
default : | |||
fatal(); | |||
} | |||
} | |||
@Override | |||
public void atStringL(StringL s) throws CompileError { | |||
exprType = CLASS; | |||
arrayDim = 0; | |||
@@ -1928,6 +1942,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
bytecode.addLdc(s.get()); | |||
} | |||
@Override | |||
public void atIntConst(IntConst i) throws CompileError { | |||
arrayDim = 0; | |||
long value = i.get(); | |||
@@ -1942,6 +1957,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
} | |||
} | |||
@Override | |||
public void atDoubleConst(DoubleConst d) throws CompileError { | |||
arrayDim = 0; | |||
if (d.getType() == DoubleConstant) { |
@@ -45,10 +45,12 @@ public class CompileError extends Exception { | |||
public Lex getLex() { return lex; } | |||
@Override | |||
public String getMessage() { | |||
return reason; | |||
} | |||
@Override | |||
public String toString() { | |||
return "compile error: " + reason; | |||
} |
@@ -91,14 +91,12 @@ public class Javac { | |||
try { | |||
if (mem instanceof FieldDecl) | |||
return compileField((FieldDecl)mem); | |||
else { | |||
CtBehavior cb = compileMethod(p, (MethodDecl)mem); | |||
CtClass decl = cb.getDeclaringClass(); | |||
cb.getMethodInfo2() | |||
.rebuildStackMapIf6(decl.getClassPool(), | |||
decl.getClassFile2()); | |||
return cb; | |||
} | |||
CtBehavior cb = compileMethod(p, (MethodDecl)mem); | |||
CtClass decl = cb.getDeclaringClass(); | |||
cb.getMethodInfo2() | |||
.rebuildStackMapIf6(decl.getClassPool(), | |||
decl.getClassFile2()); | |||
return cb; | |||
} | |||
catch (BadBytecode bb) { | |||
throw new CompileError(bb.getMessage()); | |||
@@ -120,6 +118,7 @@ public class Javac { | |||
protected void setInit(ASTree i) { init = i; } | |||
@Override | |||
protected ASTree getInitAST() { | |||
return init; | |||
} | |||
@@ -158,24 +157,22 @@ public class Javac { | |||
cons.setExceptionTypes(tlist); | |||
return cons; | |||
} | |||
else { | |||
Declarator r = md.getReturn(); | |||
CtClass rtype = gen.resolver.lookupClass(r); | |||
recordReturnType(rtype, false); | |||
CtMethod method = new CtMethod(rtype, r.getVariable().get(), | |||
plist, gen.getThisClass()); | |||
method.setModifiers(mod); | |||
gen.setThisMethod(method); | |||
md.accept(gen); | |||
if (md.getBody() != null) | |||
method.getMethodInfo().setCodeAttribute( | |||
bytecode.toCodeAttribute()); | |||
else | |||
method.setModifiers(mod | Modifier.ABSTRACT); | |||
Declarator r = md.getReturn(); | |||
CtClass rtype = gen.resolver.lookupClass(r); | |||
recordReturnType(rtype, false); | |||
CtMethod method = new CtMethod(rtype, r.getVariable().get(), | |||
plist, gen.getThisClass()); | |||
method.setModifiers(mod); | |||
gen.setThisMethod(method); | |||
md.accept(gen); | |||
if (md.getBody() != null) | |||
method.getMethodInfo().setCodeAttribute( | |||
bytecode.toCodeAttribute()); | |||
else | |||
method.setModifiers(mod | Modifier.ABSTRACT); | |||
method.setExceptionTypes(tlist); | |||
return method; | |||
} | |||
method.setExceptionTypes(tlist); | |||
return method; | |||
} | |||
catch (NotFoundException e) { | |||
throw new CompileError(e.toString()); | |||
@@ -437,6 +434,7 @@ public class Javac { | |||
final String m = method; | |||
ProceedHandler h = new ProceedHandler() { | |||
@Override | |||
public void doit(JvstCodeGen gen, Bytecode b, ASTList args) | |||
throws CompileError | |||
{ | |||
@@ -449,6 +447,7 @@ public class Javac { | |||
gen.addNullIfVoid(); | |||
} | |||
@Override | |||
public void setReturnType(JvstTypeChecker check, ASTList args) | |||
throws CompileError | |||
{ | |||
@@ -481,6 +480,7 @@ public class Javac { | |||
final String m = method; | |||
ProceedHandler h = new ProceedHandler() { | |||
@Override | |||
public void doit(JvstCodeGen gen, Bytecode b, ASTList args) | |||
throws CompileError | |||
{ | |||
@@ -491,6 +491,7 @@ public class Javac { | |||
gen.addNullIfVoid(); | |||
} | |||
@Override | |||
public void setReturnType(JvstTypeChecker check, ASTList args) | |||
throws CompileError | |||
{ | |||
@@ -525,12 +526,14 @@ public class Javac { | |||
final ASTree texpr = p.parseExpression(stable); | |||
ProceedHandler h = new ProceedHandler() { | |||
@Override | |||
public void doit(JvstCodeGen gen, Bytecode b, ASTList args) | |||
throws CompileError | |||
{ | |||
gen.compileInvokeSpecial(texpr, methodIndex, descriptor, args); | |||
} | |||
@Override | |||
public void setReturnType(JvstTypeChecker c, ASTList args) | |||
throws CompileError | |||
{ |
@@ -36,6 +36,7 @@ public class JvstCodeGen extends MemberCodeGen { | |||
private CtClass dollarType = null; | |||
CtClass returnType = null; | |||
String returnCastName = null; | |||
@SuppressWarnings("unused") | |||
private String returnVarName = null; // null if $_ is not used. | |||
public static final String wrapperCastName = "$w"; | |||
String proceedName = null; | |||
@@ -78,6 +79,7 @@ public class JvstCodeGen extends MemberCodeGen { | |||
/* To support $args, $sig, and $type. | |||
* $args is an array of parameter list. | |||
*/ | |||
@Override | |||
public void atMember(Member mem) throws CompileError { | |||
String name = mem.get(); | |||
if (name.equals(paramArrayName)) { | |||
@@ -120,6 +122,7 @@ public class JvstCodeGen extends MemberCodeGen { | |||
className = "java/lang/Class"; | |||
} | |||
@Override | |||
protected void atFieldAssign(Expr expr, int op, ASTree left, | |||
ASTree right, boolean doDup) throws CompileError | |||
{ | |||
@@ -158,6 +161,7 @@ public class JvstCodeGen extends MemberCodeGen { | |||
} | |||
} | |||
@Override | |||
public void atCastExpr(CastExpr expr) throws CompileError { | |||
ASTList classname = expr.getClassName(); | |||
if (classname != null && expr.getArrayDim() == 0) { | |||
@@ -227,6 +231,7 @@ public class JvstCodeGen extends MemberCodeGen { | |||
/* Delegates to a ProcHandler object if the method call is | |||
* $proceed(). It may process $cflow(). | |||
*/ | |||
@Override | |||
public void atCallExpr(CallExpr expr) throws CompileError { | |||
ASTree method = expr.oprand1(); | |||
if (method instanceof Member) { | |||
@@ -301,8 +306,7 @@ public class JvstCodeGen extends MemberCodeGen { | |||
return (left instanceof Member | |||
&& ((Member)left).get().equals(paramListName)); | |||
} | |||
else | |||
return false; | |||
return false; | |||
} | |||
/* | |||
@@ -314,6 +318,7 @@ public class JvstCodeGen extends MemberCodeGen { | |||
} | |||
*/ | |||
@Override | |||
public int getMethodArgsLength(ASTList args) { | |||
String pname = paramListName; | |||
int n = 0; | |||
@@ -332,6 +337,7 @@ public class JvstCodeGen extends MemberCodeGen { | |||
return n; | |||
} | |||
@Override | |||
public void atMethodArgs(ASTList args, int[] types, int[] dims, | |||
String[] cnames) throws CompileError { | |||
CtClass[] params = paramTypeList; | |||
@@ -409,6 +415,7 @@ public class JvstCodeGen extends MemberCodeGen { | |||
/* | |||
* Makes it valid to write "return <expr>;" for a void method. | |||
*/ | |||
@Override | |||
protected void atReturnStmnt(Stmnt st) throws CompileError { | |||
ASTree result = st.getLeft(); | |||
if (result != null && returnType == CtClass.voidType) { | |||
@@ -442,12 +449,10 @@ public class JvstCodeGen extends MemberCodeGen { | |||
returnVarName = resultName; | |||
if (resultName == null) | |||
return -1; | |||
else { | |||
int varNo = getMaxLocals(); | |||
int locals = varNo + recordVar(type, resultName, varNo, tbl); | |||
setMaxLocals(locals); | |||
return varNo; | |||
} | |||
int varNo = getMaxLocals(); | |||
int locals = varNo + recordVar(type, resultName, varNo, tbl); | |||
setMaxLocals(locals); | |||
return varNo; | |||
} | |||
/** | |||
@@ -537,12 +542,10 @@ public class JvstCodeGen extends MemberCodeGen { | |||
{ | |||
if (varName == null) | |||
return -1; | |||
else { | |||
int varNo = getMaxLocals(); | |||
int locals = varNo + recordVar(type, varName, varNo, tbl); | |||
setMaxLocals(locals); | |||
return varNo; | |||
} | |||
int varNo = getMaxLocals(); | |||
int locals = varNo + recordVar(type, varName, varNo, tbl); | |||
setMaxLocals(locals); | |||
return varNo; | |||
} | |||
private int recordVar(CtClass cc, String varName, int varNo, | |||
@@ -608,36 +611,34 @@ public class JvstCodeGen extends MemberCodeGen { | |||
code.addAnewarray(javaLangObject); // anewarray Object | |||
return 1; | |||
} | |||
else { | |||
CtClass[] args = new CtClass[1]; | |||
int n = params.length; | |||
code.addIconst(n); // iconst_<n> | |||
code.addAnewarray(javaLangObject); // anewarray Object | |||
for (int i = 0; i < n; ++i) { | |||
code.addOpcode(Bytecode.DUP); // dup | |||
code.addIconst(i); // iconst_<i> | |||
if (params[i].isPrimitive()) { | |||
CtPrimitiveType pt = (CtPrimitiveType)params[i]; | |||
String wrapper = pt.getWrapperName(); | |||
code.addNew(wrapper); // new <wrapper> | |||
code.addOpcode(Bytecode.DUP); // dup | |||
int s = code.addLoad(regno, pt); // ?load <regno> | |||
regno += s; | |||
args[0] = pt; | |||
code.addInvokespecial(wrapper, "<init>", | |||
Descriptor.ofMethod(CtClass.voidType, args)); | |||
// invokespecial | |||
} | |||
else { | |||
code.addAload(regno); // aload <regno> | |||
++regno; | |||
} | |||
code.addOpcode(Bytecode.AASTORE); // aastore | |||
CtClass[] args = new CtClass[1]; | |||
int n = params.length; | |||
code.addIconst(n); // iconst_<n> | |||
code.addAnewarray(javaLangObject); // anewarray Object | |||
for (int i = 0; i < n; ++i) { | |||
code.addOpcode(Bytecode.DUP); // dup | |||
code.addIconst(i); // iconst_<i> | |||
if (params[i].isPrimitive()) { | |||
CtPrimitiveType pt = (CtPrimitiveType)params[i]; | |||
String wrapper = pt.getWrapperName(); | |||
code.addNew(wrapper); // new <wrapper> | |||
code.addOpcode(Bytecode.DUP); // dup | |||
int s = code.addLoad(regno, pt); // ?load <regno> | |||
regno += s; | |||
args[0] = pt; | |||
code.addInvokespecial(wrapper, "<init>", | |||
Descriptor.ofMethod(CtClass.voidType, args)); | |||
// invokespecial | |||
} | |||
else { | |||
code.addAload(regno); // aload <regno> | |||
++regno; | |||
} | |||
return 8; | |||
code.addOpcode(Bytecode.AASTORE); // aastore | |||
} | |||
return 8; | |||
} | |||
protected void compileUnwrapValue(CtClass type, Bytecode code) |
@@ -44,6 +44,7 @@ public class JvstTypeChecker extends TypeChecker { | |||
/* To support $args, $sig, and $type. | |||
* $args is an array of parameter list. | |||
*/ | |||
@Override | |||
public void atMember(Member mem) throws CompileError { | |||
String name = mem.get(); | |||
if (name.equals(codeGen.paramArrayName)) { | |||
@@ -66,6 +67,7 @@ public class JvstTypeChecker extends TypeChecker { | |||
super.atMember(mem); | |||
} | |||
@Override | |||
protected void atFieldAssign(Expr expr, int op, ASTree left, ASTree right) | |||
throws CompileError | |||
{ | |||
@@ -84,6 +86,7 @@ public class JvstTypeChecker extends TypeChecker { | |||
super.atFieldAssign(expr, op, left, right); | |||
} | |||
@Override | |||
public void atCastExpr(CastExpr expr) throws CompileError { | |||
ASTList classname = expr.getClassName(); | |||
if (classname != null && expr.getArrayDim() == 0) { | |||
@@ -138,6 +141,7 @@ public class JvstTypeChecker extends TypeChecker { | |||
/* Delegates to a ProcHandler object if the method call is | |||
* $proceed(). It may process $cflow(). | |||
*/ | |||
@Override | |||
public void atCallExpr(CallExpr expr) throws CompileError { | |||
ASTree method = expr.oprand1(); | |||
if (method instanceof Member) { | |||
@@ -175,10 +179,10 @@ public class JvstTypeChecker extends TypeChecker { | |||
return (left instanceof Member | |||
&& ((Member)left).get().equals(codeGen.paramListName)); | |||
} | |||
else | |||
return false; | |||
return false; | |||
} | |||
@Override | |||
public int getMethodArgsLength(ASTList args) { | |||
String pname = codeGen.paramListName; | |||
int n = 0; | |||
@@ -197,6 +201,7 @@ public class JvstTypeChecker extends TypeChecker { | |||
return n; | |||
} | |||
@Override | |||
public void atMethodArgs(ASTList args, int[] types, int[] dims, | |||
String[] cnames) throws CompileError { | |||
CtClass[] params = codeGen.paramTypeList; |
@@ -16,21 +16,19 @@ | |||
package javassist.compiler; | |||
public final class KeywordTable extends java.util.HashMap { | |||
import java.util.HashMap; | |||
public final class KeywordTable extends HashMap<String,Integer> { | |||
/** default serialVersionUID */ | |||
private static final long serialVersionUID = 1L; | |||
public KeywordTable() { super(); } | |||
public int lookup(String name) { | |||
Object found = get(name); | |||
if (found == null) | |||
return -1; | |||
else | |||
return ((Integer)found).intValue(); | |||
return containsKey(name) ? get(name) : -1; | |||
} | |||
public void append(String name, int t) { | |||
put(name, Integer.valueOf(t)); | |||
put(name, t); | |||
} | |||
} |
@@ -32,6 +32,7 @@ public class Lex implements TokenId { | |||
private Token lookAheadTokens; | |||
private String input; | |||
@SuppressWarnings("unused") | |||
private int position, maxlen, lineNumber; | |||
/** | |||
@@ -52,12 +53,10 @@ public class Lex implements TokenId { | |||
public int get() { | |||
if (lookAheadTokens == null) | |||
return get(currentToken); | |||
else { | |||
Token t; | |||
currentToken = t = lookAheadTokens; | |||
lookAheadTokens = lookAheadTokens.next; | |||
return t.tokenId; | |||
} | |||
Token t; | |||
currentToken = t = lookAheadTokens; | |||
lookAheadTokens = lookAheadTokens.next; | |||
return t.tokenId; | |||
} | |||
/** | |||
@@ -129,15 +128,12 @@ public class Lex implements TokenId { | |||
tbuf.append('.'); | |||
return readDouble(tbuf, c, token); | |||
} | |||
else{ | |||
ungetc(c); | |||
return readSeparator('.'); | |||
} | |||
ungetc(c); | |||
return readSeparator('.'); | |||
} | |||
else if (Character.isJavaIdentifierStart((char)c)) | |||
return readIdentifier(c, token); | |||
else | |||
return readSeparator(c); | |||
return readSeparator(c); | |||
} | |||
private int getNextNonWhiteChar() { | |||
@@ -249,19 +245,17 @@ public class Lex implements TokenId { | |||
for (;;) { | |||
c = getc(); | |||
if ('0' <= c && c <= '9') | |||
value = value * 16 + (long)(c - '0'); | |||
value = value * 16 + (c - '0'); | |||
else if ('A' <= c && c <= 'F') | |||
value = value * 16 + (long)(c - 'A' + 10); | |||
value = value * 16 + (c - 'A' + 10); | |||
else if ('a' <= c && c <= 'f') | |||
value = value * 16 + (long)(c - 'a' + 10); | |||
value = value * 16 + (c - 'a' + 10); | |||
else { | |||
token.longValue = value; | |||
if (c == 'L' || c == 'l') | |||
return LongConstant; | |||
else { | |||
ungetc(c); | |||
return IntConstant; | |||
} | |||
ungetc(c); | |||
return IntConstant; | |||
} | |||
} | |||
else if ('0' <= c2 && c2 <= '7') { | |||
@@ -269,15 +263,13 @@ public class Lex implements TokenId { | |||
for (;;) { | |||
c = getc(); | |||
if ('0' <= c && c <= '7') | |||
value = value * 8 + (long)(c - '0'); | |||
value = value * 8 + (c - '0'); | |||
else { | |||
token.longValue = value; | |||
if (c == 'L' || c == 'l') | |||
return LongConstant; | |||
else { | |||
ungetc(c); | |||
return IntConstant; | |||
} | |||
ungetc(c); | |||
return IntConstant; | |||
} | |||
} | |||
} | |||
@@ -290,7 +282,7 @@ public class Lex implements TokenId { | |||
token.longValue = value; | |||
if (c2 == 'F' || c2 == 'f') { | |||
token.doubleValue = (double)value; | |||
token.doubleValue = value; | |||
return FloatConstant; | |||
} | |||
else if (c2 == 'E' || c2 == 'e' | |||
@@ -343,12 +335,10 @@ public class Lex implements TokenId { | |||
if (c == 'F' || c == 'f') | |||
return FloatConstant; | |||
else { | |||
if (c != 'D' && c != 'd') | |||
ungetc(c); | |||
if (c != 'D' && c != 'd') | |||
ungetc(c); | |||
return DoubleConstant; | |||
} | |||
return DoubleConstant; | |||
} | |||
// !"#$%&'( )*+,-./0 12345678 9:;<=>? | |||
@@ -362,51 +352,45 @@ public class Lex implements TokenId { | |||
int c2, c3; | |||
if ('!' <= c && c <= '?') { | |||
int t = equalOps[c - '!']; | |||
if (t == 0) | |||
if (t == 0) | |||
return c; | |||
else { | |||
c2 = getc(); | |||
if (c == c2) | |||
switch (c) { | |||
case '=' : | |||
return EQ; | |||
case '+' : | |||
return PLUSPLUS; | |||
case '-' : | |||
return MINUSMINUS; | |||
case '&' : | |||
return ANDAND; | |||
case '<' : | |||
c3 = getc(); | |||
if (c3 == '=') | |||
return LSHIFT_E; | |||
else { | |||
ungetc(c3); | |||
return LSHIFT; | |||
} | |||
case '>' : | |||
c2 = getc(); | |||
if (c == c2) | |||
switch (c) { | |||
case '=' : | |||
return EQ; | |||
case '+' : | |||
return PLUSPLUS; | |||
case '-' : | |||
return MINUSMINUS; | |||
case '&' : | |||
return ANDAND; | |||
case '<' : | |||
c3 = getc(); | |||
if (c3 == '=') | |||
return LSHIFT_E; | |||
ungetc(c3); | |||
return LSHIFT; | |||
case '>' : | |||
c3 = getc(); | |||
if (c3 == '=') | |||
return RSHIFT_E; | |||
else if (c3 == '>') { | |||
c3 = getc(); | |||
if (c3 == '=') | |||
return RSHIFT_E; | |||
else if (c3 == '>') { | |||
c3 = getc(); | |||
if (c3 == '=') | |||
return ARSHIFT_E; | |||
else { | |||
ungetc(c3); | |||
return ARSHIFT; | |||
} | |||
} | |||
else { | |||
ungetc(c3); | |||
return RSHIFT; | |||
} | |||
default : | |||
break; | |||
return ARSHIFT_E; | |||
ungetc(c3); | |||
return ARSHIFT; | |||
} | |||
else if (c2 == '=') | |||
return t; | |||
} | |||
else { | |||
ungetc(c3); | |||
return RSHIFT; | |||
} | |||
default : | |||
break; | |||
} | |||
else if (c2 == '=') | |||
return t; | |||
} | |||
else if (c == '^') { | |||
c2 = getc(); | |||
@@ -442,17 +426,15 @@ public class Lex implements TokenId { | |||
int t = ktable.lookup(name); | |||
if (t >= 0) | |||
return t; | |||
else { | |||
/* tbuf.toString() is executed quickly since it does not | |||
* need memory copy. Using a hand-written extensible | |||
* byte-array class instead of StringBuffer is not a good idea | |||
* for execution speed. Converting a byte array to a String | |||
* object is very slow. Using an extensible char array | |||
* might be OK. | |||
*/ | |||
token.textValue = name; | |||
return Identifier; | |||
} | |||
/* tbuf.toString() is executed quickly since it does not | |||
* need memory copy. Using a hand-written extensible | |||
* byte-array class instead of StringBuffer is not a good idea | |||
* for execution speed. Converting a byte array to a String | |||
* object is very slow. Using an extensible char array | |||
* might be OK. | |||
*/ | |||
token.textValue = name; | |||
return Identifier; | |||
} | |||
private static final KeywordTable ktable = new KeywordTable(); | |||
@@ -516,6 +498,7 @@ public class Lex implements TokenId { | |||
|| c == '\n'; | |||
} | |||
@SuppressWarnings("unused") | |||
private static boolean isDigit(int c) { | |||
return '0' <= c && c <= '9'; | |||
} | |||
@@ -542,10 +525,8 @@ public class Lex implements TokenId { | |||
return input.charAt(position++); | |||
else | |||
return -1; | |||
else { | |||
int c = lastChar; | |||
lastChar = -1; | |||
return c; | |||
} | |||
int c = lastChar; | |||
lastChar = -1; | |||
return c; | |||
} | |||
} |
@@ -21,6 +21,7 @@ import javassist.bytecode.*; | |||
import javassist.compiler.ast.*; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
/* Code generator methods depending on javassist.* classes. | |||
*/ | |||
@@ -46,8 +47,7 @@ public class MemberCodeGen extends CodeGen { | |||
ClassFile cf = thisClass.getClassFile2(); | |||
if (cf == null) | |||
return ClassFile.MAJOR_VERSION; // JDK 1.3 | |||
else | |||
return cf.getMajorVersion(); | |||
return cf.getMajorVersion(); | |||
} | |||
/** | |||
@@ -64,6 +64,7 @@ public class MemberCodeGen extends CodeGen { | |||
/** | |||
* Returns the JVM-internal representation of this class name. | |||
*/ | |||
@Override | |||
protected String getThisName() { | |||
return MemberResolver.javaToJvmName(thisClass.getName()); | |||
} | |||
@@ -71,11 +72,13 @@ public class MemberCodeGen extends CodeGen { | |||
/** | |||
* Returns the JVM-internal representation of this super class name. | |||
*/ | |||
@Override | |||
protected String getSuperName() throws CompileError { | |||
return MemberResolver.javaToJvmName( | |||
MemberResolver.getSuperclass(thisClass).getName()); | |||
} | |||
@Override | |||
protected void insertDefaultSuperCall() throws CompileError { | |||
bytecode.addAload(0); | |||
bytecode.addInvokespecial(MemberResolver.getSuperclass(thisClass), | |||
@@ -83,13 +86,13 @@ public class MemberCodeGen extends CodeGen { | |||
} | |||
static class JsrHook extends ReturnHook { | |||
ArrayList jsrList; | |||
List<int[]> jsrList; | |||
CodeGen cgen; | |||
int var; | |||
JsrHook(CodeGen gen) { | |||
super(gen); | |||
jsrList = new ArrayList(); | |||
jsrList = new ArrayList<int[]>(); | |||
cgen = gen; | |||
var = -1; | |||
} | |||
@@ -109,6 +112,7 @@ public class MemberCodeGen extends CodeGen { | |||
b.addIndex(0); | |||
} | |||
@Override | |||
protected boolean doit(Bytecode b, int opcode) { | |||
switch (opcode) { | |||
case Opcode.RETURN : | |||
@@ -157,6 +161,7 @@ public class MemberCodeGen extends CodeGen { | |||
var = retTarget[1]; | |||
} | |||
@Override | |||
protected boolean doit(Bytecode b, int opcode) { | |||
switch (opcode) { | |||
case Opcode.RETURN : | |||
@@ -186,6 +191,7 @@ public class MemberCodeGen extends CodeGen { | |||
} | |||
} | |||
@Override | |||
protected void atTryStmnt(Stmnt st) throws CompileError { | |||
Bytecode bc = bytecode; | |||
Stmnt body = (Stmnt)st.getLeft(); | |||
@@ -194,7 +200,7 @@ public class MemberCodeGen extends CodeGen { | |||
ASTList catchList = (ASTList)st.getRight().getLeft(); | |||
Stmnt finallyBlock = (Stmnt)st.getRight().getRight().getLeft(); | |||
ArrayList gotoList = new ArrayList(); | |||
List<Integer> gotoList = new ArrayList<Integer>(); | |||
JsrHook jsrHook = null; | |||
if (finallyBlock != null) | |||
@@ -209,7 +215,7 @@ public class MemberCodeGen extends CodeGen { | |||
boolean tryNotReturn = !hasReturned; | |||
if (tryNotReturn) { | |||
bc.addOpcode(Opcode.GOTO); | |||
gotoList.add(Integer.valueOf(bc.currentPc())); | |||
gotoList.add(bc.currentPc()); | |||
bc.addIndex(0); // correct later | |||
} | |||
@@ -235,7 +241,7 @@ public class MemberCodeGen extends CodeGen { | |||
if (!hasReturned) { | |||
bc.addOpcode(Opcode.GOTO); | |||
gotoList.add(Integer.valueOf(bc.currentPc())); | |||
gotoList.add(bc.currentPc()); | |||
bc.addIndex(0); // correct later | |||
tryNotReturn = true; | |||
} | |||
@@ -270,13 +276,11 @@ public class MemberCodeGen extends CodeGen { | |||
/** | |||
* Adds a finally clause for earch return statement. | |||
*/ | |||
private void addFinally(ArrayList returnList, Stmnt finallyBlock) | |||
private void addFinally(List<int[]> returnList, Stmnt finallyBlock) | |||
throws CompileError | |||
{ | |||
Bytecode bc = bytecode; | |||
int n = returnList.size(); | |||
for (int i = 0; i < n; ++i) { | |||
final int[] ret = (int[])returnList.get(i); | |||
for (final int[] ret:returnList) { | |||
int pc = ret[0]; | |||
bc.write16bit(pc, bc.currentPc() - pc + 1); | |||
ReturnHook hook = new JsrHook2(this, ret); | |||
@@ -289,6 +293,7 @@ public class MemberCodeGen extends CodeGen { | |||
} | |||
} | |||
@Override | |||
public void atNewExpr(NewExpr expr) throws CompileError { | |||
if (expr.isArray()) | |||
atNewArrayExpr(expr); | |||
@@ -408,11 +413,13 @@ public class MemberCodeGen extends CodeGen { | |||
throw new CompileError("bad new expression"); | |||
} | |||
@Override | |||
protected void atArrayVariableAssign(ArrayInit init, int varType, | |||
int varArray, String varClass) throws CompileError { | |||
atNewArrayExpr2(varType, null, varClass, init); | |||
} | |||
@Override | |||
public void atArrayInit(ArrayInit init) throws CompileError { | |||
throw new CompileError("array initializer is not supported"); | |||
} | |||
@@ -446,6 +453,7 @@ public class MemberCodeGen extends CodeGen { | |||
bytecode.addMultiNewarray(desc, count); | |||
} | |||
@Override | |||
public void atCallExpr(CallExpr expr) throws CompileError { | |||
String mname = null; | |||
CtClass targetClass = null; | |||
@@ -472,8 +480,7 @@ public class MemberCodeGen extends CodeGen { | |||
targetClass = thisClass; | |||
if (inStaticMethod) | |||
throw new CompileError("a constructor cannot be static"); | |||
else | |||
bytecode.addAload(0); // this | |||
bytecode.addAload(0); // this | |||
if (((Keyword)method).get() == SUPER) | |||
targetClass = MemberResolver.getSuperclass(targetClass); | |||
@@ -563,6 +570,7 @@ public class MemberCodeGen extends CodeGen { | |||
isStatic = true; | |||
} | |||
@SuppressWarnings("unused") | |||
int stack = bytecode.getStackDepth(); | |||
// generate code for evaluating arguments. | |||
@@ -784,6 +792,7 @@ public class MemberCodeGen extends CodeGen { | |||
} | |||
} | |||
@Override | |||
protected void atFieldAssign(Expr expr, int op, ASTree left, | |||
ASTree right, boolean doDup) throws CompileError | |||
{ | |||
@@ -842,7 +851,7 @@ public class MemberCodeGen extends CodeGen { | |||
bytecode.add(PUTFIELD); | |||
bytecode.growStack(is2byte ? -3 : -2); | |||
} | |||
bytecode.addIndex(fi); | |||
} | |||
else { | |||
@@ -858,10 +867,12 @@ public class MemberCodeGen extends CodeGen { | |||
/* overwritten in JvstCodeGen. | |||
*/ | |||
@Override | |||
public void atMember(Member mem) throws CompileError { | |||
atFieldRead(mem); | |||
} | |||
@Override | |||
protected void atFieldRead(ASTree expr) throws CompileError | |||
{ | |||
CtField f = fieldAccess(expr, true); | |||
@@ -904,20 +915,18 @@ public class MemberCodeGen extends CodeGen { | |||
minfo.getDescriptor()); | |||
return 0; | |||
} | |||
int fi = addFieldrefInfo(f, finfo); | |||
if (isStatic) { | |||
bytecode.add(GETSTATIC); | |||
bytecode.growStack(is2byte ? 2 : 1); | |||
} | |||
else { | |||
int fi = addFieldrefInfo(f, finfo); | |||
if (isStatic) { | |||
bytecode.add(GETSTATIC); | |||
bytecode.growStack(is2byte ? 2 : 1); | |||
} | |||
else { | |||
bytecode.add(GETFIELD); | |||
bytecode.growStack(is2byte ? 1 : 0); | |||
} | |||
bytecode.addIndex(fi); | |||
return fi; | |||
bytecode.add(GETFIELD); | |||
bytecode.growStack(is2byte ? 1 : 0); | |||
} | |||
bytecode.addIndex(fi); | |||
return fi; | |||
} | |||
/** | |||
@@ -929,18 +938,15 @@ public class MemberCodeGen extends CodeGen { | |||
throws CompileError | |||
{ | |||
if (AccessFlag.isPrivate(finfo.getAccessFlags()) | |||
&& f.getDeclaringClass() != thisClass) { | |||
CtClass declClass = f.getDeclaringClass(); | |||
&& f.getDeclaringClass() != thisClass) { | |||
CtClass declClass = f.getDeclaringClass(); | |||
if (isEnclosing(declClass, thisClass)) { | |||
AccessorMaker maker = declClass.getAccessorMaker(); | |||
if (maker != null) | |||
return maker; | |||
else | |||
throw new CompileError("fatal error. bug?"); | |||
} | |||
else | |||
throw new CompileError("Field " + f.getName() + " in " | |||
+ declClass.getName() + " is private."); | |||
throw new CompileError("Field " + f.getName() + " in " | |||
+ declClass.getName() + " is private."); | |||
} | |||
return null; // accessible field | |||
@@ -983,6 +989,7 @@ public class MemberCodeGen extends CodeGen { | |||
return cp.addFieldrefInfo(ci, name, type); | |||
} | |||
@Override | |||
protected void atClassObject2(String cname) throws CompileError { | |||
if (getMajorVersion() < ClassFile.JAVA_5) | |||
super.atClassObject2(cname); | |||
@@ -990,6 +997,7 @@ public class MemberCodeGen extends CodeGen { | |||
bytecode.addLdc(bytecode.getConstPool().addClassInfo(cname)); | |||
} | |||
@Override | |||
protected void atFieldPlusPlus(int token, boolean isPost, | |||
ASTree oprand, Expr expr, boolean doDup) | |||
throws CompileError | |||
@@ -1130,16 +1138,14 @@ public class MemberCodeGen extends CodeGen { | |||
ASTList list = md.getThrows(); | |||
if (list == null) | |||
return null; | |||
else { | |||
int i = 0; | |||
clist = new CtClass[list.length()]; | |||
while (list != null) { | |||
clist[i++] = resolver.lookupClassByName((ASTList)list.head()); | |||
list = list.tail(); | |||
} | |||
return clist; | |||
int i = 0; | |||
clist = new CtClass[list.length()]; | |||
while (list != null) { | |||
clist[i++] = resolver.lookupClassByName((ASTList)list.head()); | |||
list = list.tail(); | |||
} | |||
return clist; | |||
} | |||
/* Converts a class name into a JVM-internal representation. | |||
@@ -1147,6 +1153,7 @@ public class MemberCodeGen extends CodeGen { | |||
* It may also expand a simple class name to java.lang.*. | |||
* For example, this converts Object into java/lang/Object. | |||
*/ | |||
@Override | |||
protected String resolveClassName(ASTList name) throws CompileError { | |||
return resolver.resolveClassName(name); | |||
} | |||
@@ -1154,6 +1161,7 @@ public class MemberCodeGen extends CodeGen { | |||
/* Expands a simple class name to java.lang.*. | |||
* For example, this converts Object into java/lang/Object. | |||
*/ | |||
@Override | |||
protected String resolveClassName(String jvmName) throws CompileError { | |||
return resolver.resolveJvmClassName(jvmName); | |||
} |
@@ -17,9 +17,11 @@ | |||
package javassist.compiler; | |||
import java.util.Hashtable; | |||
import java.lang.ref.Reference; | |||
import java.lang.ref.WeakReference; | |||
import java.util.WeakHashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Iterator; | |||
import javassist.*; | |||
@@ -77,8 +79,7 @@ public class MemberResolver implements TokenId { | |||
Method r = new Method(clazz, current, res); | |||
if (res == YES) | |||
return r; | |||
else | |||
maybe = r; | |||
maybe = r; | |||
} | |||
} | |||
@@ -86,8 +87,7 @@ public class MemberResolver implements TokenId { | |||
argClassNames, maybe != null); | |||
if (m != null) | |||
return m; | |||
else | |||
return maybe; | |||
return maybe; | |||
} | |||
private Method lookupMethod(CtClass clazz, String methodName, | |||
@@ -100,10 +100,8 @@ public class MemberResolver implements TokenId { | |||
// If the class is an array type, the class file is null. | |||
// If so, search the super class java.lang.Object for clone() etc. | |||
if (cf != null) { | |||
List list = cf.getMethods(); | |||
int n = list.size(); | |||
for (int i = 0; i < n; ++i) { | |||
MethodInfo minfo = (MethodInfo)list.get(i); | |||
List<MethodInfo> list = cf.getMethods(); | |||
for (MethodInfo minfo:list) { | |||
if (minfo.getName().equals(methodName) | |||
&& (minfo.getAccessFlags() & AccessFlag.BRIDGE) == 0) { | |||
int res = compareSignature(minfo.getDescriptor(), | |||
@@ -143,9 +141,8 @@ public class MemberResolver implements TokenId { | |||
try { | |||
CtClass[] ifs = clazz.getInterfaces(); | |||
int size = ifs.length; | |||
for (int i = 0; i < size; ++i) { | |||
Method r = lookupMethod(ifs[i], methodName, | |||
for (CtClass intf:ifs) { | |||
Method r = lookupMethod(intf, methodName, | |||
argTypes, argDims, argClassNames, | |||
onlyExact); | |||
if (r != null) | |||
@@ -396,13 +393,13 @@ public class MemberResolver implements TokenId { | |||
public CtClass lookupClass(String name, boolean notCheckInner) | |||
throws CompileError | |||
{ | |||
Hashtable cache = getInvalidNames(); | |||
Object found = cache.get(name); | |||
Map<String,String> cache = getInvalidNames(); | |||
String found = cache.get(name); | |||
if (found == INVALID) | |||
throw new CompileError("no such class: " + name); | |||
else if (found != null) | |||
try { | |||
return classPool.get((String)found); | |||
return classPool.get(found); | |||
} | |||
catch (NotFoundException e) {} | |||
@@ -419,23 +416,24 @@ public class MemberResolver implements TokenId { | |||
} | |||
private static final String INVALID = "<invalid>"; | |||
private static WeakHashMap invalidNamesMap = new WeakHashMap(); | |||
private Hashtable invalidNames = null; | |||
private static Map<ClassPool, Reference<Map<String,String>>> invalidNamesMap = | |||
new WeakHashMap<ClassPool, Reference<Map<String,String>>>(); | |||
private Map<String,String> invalidNames = null; | |||
// for unit tests | |||
public static int getInvalidMapSize() { return invalidNamesMap.size(); } | |||
private Hashtable getInvalidNames() { | |||
Hashtable ht = invalidNames; | |||
private Map<String,String> getInvalidNames() { | |||
Map<String,String> ht = invalidNames; | |||
if (ht == null) { | |||
synchronized (MemberResolver.class) { | |||
WeakReference ref = (WeakReference)invalidNamesMap.get(classPool); | |||
Reference<Map<String,String>> ref = invalidNamesMap.get(classPool); | |||
if (ref != null) | |||
ht = (Hashtable)ref.get(); | |||
ht = ref.get(); | |||
if (ht == null) { | |||
ht = new Hashtable(); | |||
invalidNamesMap.put(classPool, new WeakReference(ht)); | |||
ht = new Hashtable<String,String>(); | |||
invalidNamesMap.put(classPool, new WeakReference<Map<String,String>>(ht)); | |||
} | |||
} | |||
@@ -449,10 +447,10 @@ public class MemberResolver implements TokenId { | |||
throws CompileError | |||
{ | |||
if (orgName.indexOf('.') < 0) { | |||
Iterator it = classPool.getImportedPackages(); | |||
Iterator<String> it = classPool.getImportedPackages(); | |||
while (it.hasNext()) { | |||
String pac = (String)it.next(); | |||
String fqName = pac + '.' + orgName; | |||
String pac = it.next(); | |||
String fqName = pac.replaceAll("\\.$","") + "." + orgName; | |||
try { | |||
return classPool.get(fqName); | |||
} | |||
@@ -482,11 +480,9 @@ public class MemberResolver implements TokenId { | |||
int i = classname.lastIndexOf('.'); | |||
if (notCheckInner || i < 0) | |||
throw e; | |||
else { | |||
StringBuffer sbuf = new StringBuffer(classname); | |||
sbuf.setCharAt(i, '$'); | |||
classname = sbuf.toString(); | |||
} | |||
StringBuffer sbuf = new StringBuffer(classname); | |||
sbuf.setCharAt(i, '$'); | |||
classname = sbuf.toString(); | |||
} | |||
} while (cc == null); | |||
return cc; | |||
@@ -500,8 +496,7 @@ public class MemberResolver implements TokenId { | |||
public String resolveClassName(ASTList name) throws CompileError { | |||
if (name == null) | |||
return null; | |||
else | |||
return javaToJvmName(lookupClassByName(name).getName()); | |||
return javaToJvmName(lookupClassByName(name).getName()); | |||
} | |||
/* Expands a simple class name to java.lang.*. | |||
@@ -510,8 +505,7 @@ public class MemberResolver implements TokenId { | |||
public String resolveJvmClassName(String jvmName) throws CompileError { | |||
if (jvmName == null) | |||
return null; | |||
else | |||
return javaToJvmName(lookupClassByJvmName(jvmName).getName()); | |||
return javaToJvmName(lookupClassByJvmName(jvmName).getName()); | |||
} | |||
public static CtClass getSuperclass(CtClass c) throws CompileError { |
@@ -34,8 +34,7 @@ public final class Parser implements TokenId { | |||
ASTList mem = parseMember1(tbl); | |||
if (mem instanceof MethodDecl) | |||
return parseMethod2(tbl, (MethodDecl)mem); | |||
else | |||
return mem; | |||
return mem; | |||
} | |||
/* A method body is not parsed. | |||
@@ -63,8 +62,7 @@ public final class Parser implements TokenId { | |||
d.setVariable(new Symbol(name)); | |||
if (isConstructor || lex.lookAhead() == '(') | |||
return parseMethod1(tbl, isConstructor, mods, d); | |||
else | |||
return parseField(tbl, mods, d); | |||
return parseField(tbl, mods, d); | |||
} | |||
/* field.declaration | |||
@@ -188,11 +186,9 @@ public final class Parser implements TokenId { | |||
int dim = parseArrayDimension(); | |||
return new Declarator(t, dim); | |||
} | |||
else { | |||
ASTList name = parseClassType(tbl); | |||
int dim = parseArrayDimension(); | |||
return new Declarator(name, dim); | |||
} | |||
ASTList name = parseClassType(tbl); | |||
int dim = parseArrayDimension(); | |||
return new Declarator(name, dim); | |||
} | |||
private static boolean isBuiltinType(int t) { | |||
@@ -294,8 +290,7 @@ public final class Parser implements TokenId { | |||
lex.get(); // '}' | |||
if (body == null) | |||
return new Stmnt(BLOCK); // empty block | |||
else | |||
return body; | |||
return body; | |||
} | |||
/* if.statement : IF "(" expression ")" statement | |||
@@ -654,8 +649,7 @@ public final class Parser implements TokenId { | |||
private ASTree parseInitializer(SymbolTable tbl) throws CompileError { | |||
if (lex.lookAhead() == '{') | |||
return parseArrayInitializer(tbl); | |||
else | |||
return parseExpression(tbl); | |||
return parseExpression(tbl); | |||
} | |||
/* array.initializer : | |||
@@ -726,8 +720,7 @@ public final class Parser implements TokenId { | |||
ASTree elseExpr = parseExpression(tbl); | |||
return new CondExpr(cond, thenExpr, elseExpr); | |||
} | |||
else | |||
return cond; | |||
return cond; | |||
} | |||
/* logical.or.expr 10 (operator precedence) | |||
@@ -778,8 +771,7 @@ public final class Parser implements TokenId { | |||
int p = getOpPrecedence(t); | |||
if (p == 0) | |||
return expr; | |||
else | |||
expr = binaryExpr2(tbl, expr, p); | |||
expr = binaryExpr2(tbl, expr, p); | |||
} | |||
} | |||
@@ -792,11 +784,9 @@ public final class Parser implements TokenId { | |||
int dim = parseArrayDimension(); | |||
return new InstanceOfExpr(t, dim, expr); | |||
} | |||
else { | |||
ASTList name = parseClassType(tbl); | |||
int dim = parseArrayDimension(); | |||
return new InstanceOfExpr(name, dim, expr); | |||
} | |||
ASTList name = parseClassType(tbl); | |||
int dim = parseArrayDimension(); | |||
return new InstanceOfExpr(name, dim, expr); | |||
} | |||
private ASTree binaryExpr2(SymbolTable tbl, ASTree expr, int prec) | |||
@@ -922,6 +912,7 @@ public final class Parser implements TokenId { | |||
} | |||
private boolean nextIsBuiltinCast() { | |||
@SuppressWarnings("unused") | |||
int t; | |||
int i = 2; | |||
while ((t = lex.lookAhead(i++)) == '[') | |||
@@ -949,6 +940,7 @@ public final class Parser implements TokenId { | |||
} | |||
private int nextIsClassType(int i) { | |||
@SuppressWarnings("unused") | |||
int t; | |||
while (lex.lookAhead(++i) == '.') | |||
if (lex.lookAhead(++i) != Identifier) | |||
@@ -1117,43 +1109,41 @@ public final class Parser implements TokenId { | |||
String cname = CodeGen.toJvmTypeName(builtinType, dim); | |||
return Expr.make('.', new Symbol(cname), new Member("class")); | |||
} | |||
else { | |||
String cname; | |||
switch(builtinType) { | |||
case BOOLEAN : | |||
cname = "java.lang.Boolean"; | |||
break; | |||
case BYTE : | |||
cname = "java.lang.Byte"; | |||
break; | |||
case CHAR : | |||
cname = "java.lang.Character"; | |||
break; | |||
case SHORT : | |||
cname = "java.lang.Short"; | |||
break; | |||
case INT : | |||
cname = "java.lang.Integer"; | |||
break; | |||
case LONG : | |||
cname = "java.lang.Long"; | |||
break; | |||
case FLOAT : | |||
cname = "java.lang.Float"; | |||
break; | |||
case DOUBLE : | |||
cname = "java.lang.Double"; | |||
break; | |||
case VOID : | |||
cname = "java.lang.Void"; | |||
break; | |||
default : | |||
throw new CompileError("invalid builtin type: " | |||
+ builtinType); | |||
} | |||
return Expr.make(MEMBER, new Symbol(cname), new Member("TYPE")); | |||
String cname; | |||
switch(builtinType) { | |||
case BOOLEAN : | |||
cname = "java.lang.Boolean"; | |||
break; | |||
case BYTE : | |||
cname = "java.lang.Byte"; | |||
break; | |||
case CHAR : | |||
cname = "java.lang.Character"; | |||
break; | |||
case SHORT : | |||
cname = "java.lang.Short"; | |||
break; | |||
case INT : | |||
cname = "java.lang.Integer"; | |||
break; | |||
case LONG : | |||
cname = "java.lang.Long"; | |||
break; | |||
case FLOAT : | |||
cname = "java.lang.Float"; | |||
break; | |||
case DOUBLE : | |||
cname = "java.lang.Double"; | |||
break; | |||
case VOID : | |||
cname = "java.lang.Void"; | |||
break; | |||
default : | |||
throw new CompileError("invalid builtin type: " | |||
+ builtinType); | |||
} | |||
return Expr.make(MEMBER, new Symbol(cname), new Member("TYPE")); | |||
} | |||
/* method.call : method.expr "(" argument.list ")" | |||
@@ -1236,8 +1226,7 @@ public final class Parser implements TokenId { | |||
decl = tbl.lookup(name); | |||
if (decl == null) | |||
return new Member(name); // this or static member | |||
else | |||
return new Variable(name, decl); // local variable | |||
return new Variable(name, decl); // local variable | |||
case StringL : | |||
return new StringL(lex.getString()); | |||
case NEW : | |||
@@ -1246,8 +1235,7 @@ public final class Parser implements TokenId { | |||
expr = parseExpression(tbl); | |||
if (lex.get() == ')') | |||
return expr; | |||
else | |||
throw new CompileError(") is missing", lex); | |||
throw new CompileError(") is missing", lex); | |||
default : | |||
if (isBuiltinType(t) || t == VOID) { | |||
int dim = parseArrayDimension(); | |||
@@ -1311,13 +1299,11 @@ public final class Parser implements TokenId { | |||
lex.get(); | |||
return null; | |||
} | |||
else { | |||
ASTree index = parseExpression(tbl); | |||
if (lex.get() != ']') | |||
throw new CompileError("] is missing", lex); | |||
ASTree index = parseExpression(tbl); | |||
if (lex.get() != ']') | |||
throw new CompileError("] is missing", lex); | |||
return index; | |||
} | |||
return index; | |||
} | |||
/* argument.list : "(" [ expression [ "," expression ]* ] ")" |
@@ -19,7 +19,7 @@ package javassist.compiler; | |||
import java.util.HashMap; | |||
import javassist.compiler.ast.Declarator; | |||
public final class SymbolTable extends HashMap { | |||
public final class SymbolTable extends HashMap<String,Declarator> { | |||
/** default serialVersionUID */ | |||
private static final long serialVersionUID = 1L; | |||
private SymbolTable parent; | |||
@@ -34,11 +34,10 @@ public final class SymbolTable extends HashMap { | |||
public SymbolTable getParent() { return parent; } | |||
public Declarator lookup(String name) { | |||
Declarator found = (Declarator)get(name); | |||
Declarator found = get(name); | |||
if (found == null && parent != null) | |||
return parent.lookup(name); | |||
else | |||
return found; | |||
return found; | |||
} | |||
public void append(String name, Declarator value) { |
@@ -139,6 +139,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
return resolver.resolveJvmClassName(jvmName); | |||
} | |||
@Override | |||
public void atNewExpr(NewExpr expr) throws CompileError { | |||
if (expr.isArray()) | |||
atNewArrayExpr(expr); | |||
@@ -177,6 +178,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
} | |||
} | |||
@Override | |||
public void atArrayInit(ArrayInit init) throws CompileError { | |||
ASTList list = init; | |||
while (list != null) { | |||
@@ -190,6 +192,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
protected void atMultiNewArray(int type, ASTList classname, ASTList size) | |||
throws CompileError | |||
{ | |||
@SuppressWarnings("unused") | |||
int count, dim; | |||
dim = size.length(); | |||
for (count = 0; size != null; size = size.tail()) { | |||
@@ -209,6 +212,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
className = null; | |||
} | |||
@Override | |||
public void atAssignExpr(AssignExpr expr) throws CompileError { | |||
// =, %=, &=, *=, /=, +=, -=, ^=, |=, <<=, >>=, >>>= | |||
int op = expr.getOperator(); | |||
@@ -279,11 +283,13 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
className = cname; | |||
} | |||
@Override | |||
public void atCondExpr(CondExpr expr) throws CompileError { | |||
booleanExpr(expr.condExpr()); | |||
expr.thenExpr().accept(this); | |||
int type1 = exprType; | |||
int dim1 = arrayDim; | |||
@SuppressWarnings("unused") | |||
String cname1 = className; | |||
expr.elseExpr().accept(this); | |||
@@ -302,6 +308,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
* (if the original is not '+') and sets the new expression to the | |||
* left-hand-side expression and null to the right-hand-side expression. | |||
*/ | |||
@Override | |||
public void atBinExpr(BinExpr expr) throws CompileError { | |||
int token = expr.getOperator(); | |||
int k = CodeGen.lookupBinOp(token); | |||
@@ -384,10 +391,8 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
className = "java/lang/StringBuffer"; | |||
return makeAppendCall(makeAppendCall(e, left), right); | |||
} | |||
else { | |||
computeBinExprType(expr, '+', type1); | |||
return null; | |||
} | |||
computeBinExprType(expr, '+', type1); | |||
return null; | |||
} | |||
private boolean isConstant(BinExpr expr, int op, ASTree left, | |||
@@ -406,13 +411,11 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
if (newExpr == null) | |||
return false; // not a constant expression | |||
else { | |||
expr.setOperator('+'); | |||
expr.setOprand1(newExpr); | |||
expr.setOprand2(null); | |||
newExpr.accept(this); // for setting exprType, arrayDim, ... | |||
return true; | |||
} | |||
expr.setOperator('+'); | |||
expr.setOprand1(newExpr); | |||
expr.setOprand2(null); | |||
newExpr.accept(this); // for setting exprType, arrayDim, ... | |||
return true; | |||
} | |||
/* CodeGen.atSwitchStmnt() also calls stripPlusExpr(). | |||
@@ -542,6 +545,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
exprType = type1; | |||
} | |||
@Override | |||
public void atCastExpr(CastExpr expr) throws CompileError { | |||
String cname = resolveClassName(expr.getClassName()); | |||
expr.getOprand().accept(this); | |||
@@ -550,12 +554,14 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
className = cname; | |||
} | |||
@Override | |||
public void atInstanceOfExpr(InstanceOfExpr expr) throws CompileError { | |||
expr.getOprand().accept(this); | |||
exprType = BOOLEAN; | |||
arrayDim = 0; | |||
} | |||
@Override | |||
public void atExpr(Expr expr) throws CompileError { | |||
// array access, member access, | |||
// (unary) +, (unary) -, ++, --, !, ~ | |||
@@ -572,14 +578,14 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
// length might be a class or package name. | |||
atFieldRead(expr); | |||
} | |||
else if (member.equals("class")) | |||
else if (member.equals("class")) | |||
atClassObject(expr); // .class | |||
else | |||
atFieldRead(expr); | |||
} | |||
else if (token == MEMBER) { // field read | |||
String member = ((Symbol)expr.oprand2()).get(); | |||
if (member.equals("class")) | |||
if (member.equals("class")) | |||
atClassObject(expr); // .class | |||
else | |||
atFieldRead(expr); | |||
@@ -629,6 +635,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
return true; | |||
} | |||
@Override | |||
public void atCallExpr(CallExpr expr) throws CompileError { | |||
String mname = null; | |||
CtClass targetClass = null; | |||
@@ -739,7 +746,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
mname, types, dims, cnames); | |||
if (found == null) { | |||
String clazz = targetClass.getName(); | |||
String signature = argTypesToString(types, dims, cnames); | |||
String signature = argTypesToString(types, dims, cnames); | |||
String msg; | |||
if (mname.equals(MethodInfo.nameInit)) | |||
msg = "cannot find constructor " + clazz + signature; | |||
@@ -896,7 +903,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
* often inconvenient, this compiler allows it. The following | |||
* code is for that. | |||
*/ | |||
ASTree oprnd1 = e.oprand1(); | |||
ASTree oprnd1 = e.oprand1(); | |||
if (oprnd1 instanceof Symbol) | |||
return fieldAccess2(e, ((Symbol)oprnd1).get()); | |||
@@ -984,10 +991,12 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
exprType = INT; | |||
} | |||
@Override | |||
public void atMember(Member mem) throws CompileError { | |||
atFieldRead(mem); | |||
} | |||
@Override | |||
public void atVariable(Variable v) throws CompileError { | |||
Declarator d = v.getDeclarator(); | |||
exprType = d.getType(); | |||
@@ -995,6 +1004,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
className = d.getClassName(); | |||
} | |||
@Override | |||
public void atKeyword(Keyword k) throws CompileError { | |||
arrayDim = 0; | |||
int token = k.get(); | |||
@@ -1012,19 +1022,21 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
if (token == THIS) | |||
className = getThisName(); | |||
else | |||
className = getSuperName(); | |||
className = getSuperName(); | |||
break; | |||
default : | |||
fatal(); | |||
} | |||
} | |||
@Override | |||
public void atStringL(StringL s) throws CompileError { | |||
exprType = CLASS; | |||
arrayDim = 0; | |||
className = jvmJavaLangString; | |||
} | |||
@Override | |||
public void atIntConst(IntConst i) throws CompileError { | |||
arrayDim = 0; | |||
int type = i.getType(); | |||
@@ -1034,6 +1046,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
exprType = LONG; | |||
} | |||
@Override | |||
public void atDoubleConst(DoubleConst d) throws CompileError { | |||
arrayDim = 0; | |||
if (d.getType() == DoubleConstant) |
@@ -42,12 +42,16 @@ public class ASTList extends ASTree { | |||
return new ASTList(e1, new ASTList(e2, new ASTList(e3))); | |||
} | |||
@Override | |||
public ASTree getLeft() { return left; } | |||
@Override | |||
public ASTree getRight() { return right; } | |||
@Override | |||
public void setLeft(ASTree _left) { left = _left; } | |||
@Override | |||
public void setRight(ASTree _right) { | |||
right = (ASTList)_right; | |||
} | |||
@@ -70,8 +74,10 @@ public class ASTList extends ASTree { | |||
right = _tail; | |||
} | |||
@Override | |||
public void accept(Visitor v) throws CompileError { v.atASTList(this); } | |||
@Override | |||
public String toString() { | |||
StringBuffer sbuf = new StringBuffer(); | |||
sbuf.append("(<"); | |||
@@ -150,13 +156,11 @@ public class ASTList extends ASTree { | |||
public static ASTList concat(ASTList a, ASTList b) { | |||
if (a == null) | |||
return b; | |||
else { | |||
ASTList list = a; | |||
while (list.right != null) | |||
list = list.right; | |||
ASTList list = a; | |||
while (list.right != null) | |||
list = list.right; | |||
list.right = b; | |||
return a; | |||
} | |||
list.right = b; | |||
return a; | |||
} | |||
} |
@@ -43,6 +43,7 @@ public abstract class ASTree implements Serializable { | |||
*/ | |||
public abstract void accept(Visitor v) throws CompileError; | |||
@Override | |||
public String toString() { | |||
StringBuffer sbuf = new StringBuffer(); | |||
sbuf.append('<'); |
@@ -29,7 +29,9 @@ public class ArrayInit extends ASTList { | |||
super(firstElement); | |||
} | |||
@Override | |||
public void accept(Visitor v) throws CompileError { v.atArrayInit(this); } | |||
@Override | |||
public String getTag() { return "array"; } | |||
} |