Browse Source

changed the stuff related to ClassPool.


git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@76 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
tags/rel_3_17_1_ga
chiba 20 years ago
parent
commit
f56bd9e72f

+ 8
- 1
Readme.html View File

@@ -67,7 +67,12 @@ other editors.

<h2>How to run sample programs</h2>

<p>JDK 1.2.2 or later is needed.
<p>JDK 1.3 or later is needed.

<h3>0. If you have Apache Ant</h3>

<p>Run the sample-all task.
Otherwise, follow the instructions below.

<h3>1. Move to the directory where this Readme.html file is located.</h3>

@@ -253,6 +258,8 @@ see javassist.Dump.
<p>- version 2.7

<ul>
<li>javassist.bytecode.annotation has been added.

<li>Now local variables were made available in the source text passed to
CtBehavior.insertBefore(), MethodCall.replace(), etc.
<li>CtClass.main(), which prints the version number, has been added.

+ 73
- 6
build.xml View File

@@ -1,18 +1,21 @@
<?xml version="1.0"?>
<!-- ======================================================================= -->
<!-- JBoss build file -->
<!-- ======================================================================= -->
<!-- =================================================================== -->
<!-- JBoss build file -->
<!-- =================================================================== -->
<project name="javassist" default="jar" basedir=".">
<property name="dist-version" value="javassist-2.7"/>
<property environment="env"/>
<property name="target.jar" value="javassist.jar"/>
<property name="src.dir" value="${basedir}/src/main"/>
<property name="build.dir" value="${basedir}/build"/>
<property name="build.classes.dir" value="${build.dir}/classes"/>
<property name="run.dir" value="${build.classes.dir}"/>
<!-- Build classpath -->
<path id="classpath">
<pathelement location="${build.classes.dir}"/>
@@ -61,7 +64,7 @@ to ${build.classes.dir}.</echo>
</target>
<target name="jar" depends="compile">
<jar jarfile="javassist.jar" manifest="${src.dir}/META-INF/MANIFEST.MF">
<jar jarfile="${target.jar}" manifest="${src.dir}/META-INF/MANIFEST.MF">
<fileset dir="${build.classes.dir}">
<include name="**/*.class"/>
</fileset>
@@ -103,8 +106,72 @@ Copyright (C) 1999-2004 Shigeru Chiba. All Rights Reserved.</i>]]></bottom>
<target name="clean">
<delete dir="build"/>
<delete dir="html"/>
<delete file="javassist.jar"/>
<delete file="${target.jar}"/>
<delete file="${dist-version}.zip"/>
</target>
</project>
<!-- =================================================================== -->
<!-- Run samples -->
<!-- =================================================================== -->
<target name = "sample-all"
depends="sample-test,sample-reflect,sample-duplicate,sample-vector">
<echo>** please run sample-rmi and sample-evolve separately **</echo>
</target>
<target name = "sample-test" depends="sample" >
<java fork="true" dir="${run.dir}" classname="sample.Test">
<classpath refid="classpath"/>
</java>
</target>
<target name = "sample-reflect" depends="sample" >
<java fork="true" dir="${run.dir}" classname="javassist.reflect.Loader">
<classpath refid="classpath"/>
<arg line="sample.reflect.Main Joe" />
</java>
</target>
<target name = "sample-duplicate" depends="sample" >
<echo>run sample.duplicate.Viewer without reflection</echo>
<java fork="true" dir="${run.dir}" classname="sample.duplicate.Viewer">
<classpath refid="classpath"/>
</java>
<echo>run sample.duplicate.Viewer with reflection</echo>
<java fork="true" dir="${run.dir}" classname="sample.duplicate.Main">
<classpath refid="classpath"/>
</java>
</target>
<target name = "sample-vector" depends="sample" >
<echo>javassist.preproc.Compiler sample/vector/Test.j</echo>
<java fork="true" dir="${run.dir}" classname="javassist.preproc.Compiler">
<classpath refid="classpath"/>
<arg line="sample/vector/Test.j"/>
</java>
<echo>javac sample/vector/Test.java</echo>
<javac srcdir="${build.classes.dir}"
destdir="${build.classes.dir}"
includes="sample/vector/Test.java">
<classpath refid="classpath"/>
</javac>
<java fork="true" dir="${run.dir}" classname="sample.vector.Test" />
</target>
<target name = "sample-rmi" depends="sample" >
<echo>** Please open sample/rmi/webdemo.html with your browser **</echo>
<java fork="true" dir="${run.dir}" classname="sample.rmi.Counter">
<classpath refid="classpath"/>
<arg value="5001" />
</java>
</target>
<target name = "sample-evolve" depends="sample" >
<echo>** Please open http://localhost:5003/demo.html with your browser **</echo>
<java fork="true" dir="${run.dir}" classname="sample.evolve.DemoLoader">
<classpath refid="classpath"/>
<arg value="5003" />
</java>
</target>
</project>

+ 1
- 1
sample/Test.java View File

@@ -23,7 +23,7 @@ public class Test {
}
public static void main(String[] args) throws Exception {
ClassPool pool = ClassPool.getDefault(null);
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("sample.Test");
try {

+ 7
- 6
sample/evolve/DemoLoader.java View File

@@ -29,12 +29,13 @@ public class DemoLoader {
* updatable. Then it runs main() in sample.evolve.DemoServer.
*/
public static void main(String[] args) throws Throwable {
Evolution translator = new Evolution();
ClassPool cp = ClassPool.getDefault(translator);
Loader cl = new Loader();
cl.setClassPool(cp);
Evolution translator = new Evolution();
ClassPool cp = ClassPool.getDefault();
cp.insertTranslator(translator);
Loader cl = new Loader();
cl.setClassPool(cp);
translator.makeUpdatable("sample.evolve.WebPage");
cl.run("sample.evolve.DemoServer", args);
translator.makeUpdatable("sample.evolve.WebPage");
cl.run("sample.evolve.DemoServer", args);
}
}

+ 47
- 0
src/main/javassist/AbsClassPool.java View File

@@ -0,0 +1,47 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999-2004 Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package javassist;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.URL;
/**
* Abstract root of ClassPool and ClassPoolTail.
*/
abstract class AbsClassPool {
public abstract String toString();
public abstract void recordInvalidClassName(String name);
abstract byte[] readSource(String classname)
throws NotFoundException, IOException, CannotCompileException;
abstract boolean write0(String classname, DataOutputStream out,
boolean callback)
throws NotFoundException, CannotCompileException, IOException;
abstract URL find(String classname);
public abstract ClassPath appendSystemPath();
public abstract ClassPath insertClassPath(ClassPath cp);
public abstract ClassPath appendClassPath(ClassPath cp);
public abstract ClassPath insertClassPath(String pathname)
throws NotFoundException;
public abstract ClassPath appendClassPath(String pathname)
throws NotFoundException;
public abstract void removeClassPath(ClassPath cp);
}

+ 1
- 1
src/main/javassist/ClassPath.java View File

@@ -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
* so that the search is terminated.
* so that the search will be terminated.
*
* <p>This method should not modify the contents of the class file.
* Use <code>javassist.Translator</code> for modification.

+ 180
- 141
src/main/javassist/ClassPool.java View File

@@ -85,87 +85,63 @@ import java.util.Hashtable;
* @see javassist.ClassPath
* @see javassist.Translator
*/
public class ClassPool {
/* If this field is null, then the object must be an instance of
* ClassPoolTail.
*/
protected ClassPool source;

public class ClassPool extends AbsClassPool {
protected AbsClassPool source;
protected ClassPool parent;
protected Translator translator;

protected Hashtable classes; // should be synchronous

/**
* Provide a hook so that subclasses can do their own
* caching of classes
*
* @see #removeCached(String)
*/
protected CtClass getCached(String classname)
{
return (CtClass)classes.get(classname);
}

/**
* Provide a hook so that subclasses can do their own
* caching of classes
*
* @see #getCached(String)
*/
protected void removeCached(String classname)
{
classes.remove(classname);
}

/**
* Creates a class pool.
*
* @param src the source of class files. If it is null,
* the class search path is initially null.
* @see javassist.ClassPool#getDefault()
* Table of registered cflow variables.
*/
public ClassPool(ClassPool src) {
this(src, null);
}
private Hashtable cflow = null; // should be synchronous.

/**
* Creates a class pool.
*
* @param src the source of class files. If it is null,
* the class search path is initially null.
* @param trans the translator linked to this class pool.
* It may be null.
* @param p the parent of this class pool.
* @see javassist.ClassPool#getDefault()
*/
public ClassPool(ClassPool src, Translator trans)
throws RuntimeException
{
classes = new Hashtable();
CtClass[] pt = CtClass.primitiveTypes;
for (int i = 0; i < pt.length; ++i)
classes.put(pt[i].getName(), pt[i]);
public ClassPool(ClassPool p) {
this(new ClassPoolTail(), p);
}

if (src != null)
source = src;
else
source = new ClassPoolTail();
ClassPool(AbsClassPool src, ClassPool parent) {
this.classes = new Hashtable();
this.source = src;
this.parent = parent;
if (parent == null) {
// if this has no parent, it must include primitive types
// even if this.source is not a ClassPoolTail.
CtClass[] pt = CtClass.primitiveTypes;
for (int i = 0; i < pt.length; ++i)
classes.put(pt[i].getName(), pt[i]);
}

translator = trans;
if (trans != null)
try {
trans.start(this);
}
catch (Exception e) {
throw new RuntimeException(
"Translator.start() throws an exception: "
+ e.toString());
}
this.translator = null;
this.cflow = null;
}

protected ClassPool() {
source = null;
classes = null;
translator = null;
/**
* Inserts a new translator at the head of the translator chain.
*
* @param trans a new translator associated with this class pool.
* @throws RuntimeException if trans.start() throws an exception.
*/
public void insertTranslator(Translator trans) throws RuntimeException {
ClassPool next = new ClassPool(source, parent);
next.translator = trans;
source = next;
try {
trans.start(next);
}
catch (Exception e) {
throw new RuntimeException(
"Translator.start() throws an exception: "
+ e.toString());
}
}

/**
@@ -188,15 +164,11 @@ public class ClassPool {
*
* @param t null or the translator linked to the class pool.
*/
public static synchronized ClassPool getDefault(Translator t) {
public static synchronized ClassPool getDefault() {
if (defaultPool == null) {
ClassPoolTail tail = new ClassPoolTail();
tail.appendSystemPath();
defaultPool = new ClassPool(tail, t);
defaultPool = new ClassPool(null);
defaultPool.appendSystemPath();
}
else if (defaultPool.translator != t)
throw new RuntimeException(
"has been created with a different translator");

return defaultPool;
}
@@ -204,16 +176,26 @@ public class ClassPool {
private static ClassPool defaultPool = null;

/**
* Returns the default class pool.
* The returned object is always identical.
* Provide a hook so that subclasses can do their own
* caching of classes
*
* <p>This returns the result of <code>getDefault(null)</code>.
* @see #removeCached(String)
*/
protected CtClass getCached(String classname)
{
return (CtClass)classes.get(classname);
}

/**
* Provide a hook so that subclasses can do their own
* caching of classes
*
* @see #getDefault(Translator)
* @see #getCached(String)
*/
public static ClassPool getDefault() {
return getDefault(null);
}
protected void removeCached(String classname)
{
classes.remove(classname);
}

/**
* Returns the class search path.
@@ -223,8 +205,8 @@ public class ClassPool {
}

/**
* Records a name that never exists. For example, a package name
* can be recorded by this method.
* Records a name that never exists.
* For example, a package name can be recorded by this method.
* This would improve execution performance
* since <code>get()</code> does not search the class path at all
* if the given name is an invalid name recorded by this method.
@@ -239,13 +221,10 @@ public class ClassPool {
/**
* Returns the <code>Translator</code> object associated with
* this <code>ClassPool</code>.
*
* @deprecated
*/
public Translator getTranslator() { return translator; }

/**
* Table of registered cflow variables.
*/
private Hashtable cflow = null; // should be synchronous.
Translator getTranslator() { return translator; }

/**
* Records the <code>$cflow</code> variable for the field specified
@@ -425,7 +404,7 @@ public class ClassPool {

/**
* Returns a <code>java.lang.Class</code> object that has been loaded
* by <code>writeAsClass()</code>. That object cannot be
* by <code>writeAsClass()</code>. Such an object cannot be
* obtained by <code>java.lang.Class.forName()</code> because it has
* been loaded by an internal class loader of Javassist.
*
@@ -526,6 +505,17 @@ public class ClassPool {
boolean callback)
throws NotFoundException, CannotCompileException, IOException
{
if (!write0(classname, out, callback))
throw new NotFoundException(classname);
}

boolean write0(String classname, DataOutputStream out, boolean callback)
throws NotFoundException, CannotCompileException, IOException
{
// first, delegate to the parent.
if (parent != null && parent.write0(classname, out, callback))
return true;

CtClass clazz = (CtClass)getCached(classname);
if (callback && translator != null
&& (clazz == null || !clazz.isFrozen())) {
@@ -538,49 +528,76 @@ public class ClassPool {
if (clazz != null)
clazz.freeze();

source.write(classname, out);
return source.write0(classname, out, callback);
}
else
else {
clazz.toBytecode(out);
return true;
}
}

/* for CtClassType.getClassFile2()
/* for CtClassType.getClassFile2(). Don't delegate to the parent.
*/
byte[] readSource(String classname)
throws NotFoundException, IOException, CannotCompileException
{
return source.write(classname);
return source.readSource(classname);
}

/*
* Is invoked by CtClassType.setName().
* Is invoked by CtClassType.setName(). Don't delegate to the parent.
*/
synchronized void classNameChanged(String oldname, CtClass clazz) {
CtClass c = (CtClass)getCached(oldname);
if (c == clazz) // must check this equation
removeCached(oldname);
if (c == clazz) // must check this equation.
removeCached(oldname); // see getAndRename().

String newName = clazz.getName();
checkNotFrozen(newName, "the class with the new name is frozen.");
checkNotFrozen(newName);
classes.put(newName, clazz);
}

/*
* Is invoked by CtClassType.setName() and methods in this class.
* This method throws an exception if the class is already frozen or
* if this class pool cannot edit the class since it is in a parent
* class pool.
*/
void checkNotFrozen(String classname, String errmsg)
throws RuntimeException
{
CtClass c = getCached(classname);
void checkNotFrozen(String classname) throws RuntimeException {
CtClass c;
if (parent != null) {
try {
c = parent.get0(classname);
}
catch (NotFoundException e) { // some error happens.
throw new RuntimeException(e.toString());
}

if (c != null)
throw new RuntimeException(classname
+ " is in a parent ClassPool. Use the parent.");
}

c = getCached(classname);
if (c != null && c.isFrozen())
throw new RuntimeException(errmsg);
throw new RuntimeException(classname +
": frozen class (cannot edit)");
}

/**
* Reads a class file and constructs a <code>CtClass</code>
* object with a new name.
* This method is useful if that class file has been already
* loaded and the resulting class is frozen.
* This method is useful if you want to generate a new class as a copy
* of another class (except the class name). For example,
*
* <ul><pre>
* getAndRename("Point", "Pair")
* </pre></ul>
*
* returns a <code>CtClass</code> object representing <code>Pair</code>
* class. The definition of <code>Pair</code> is the same as that of
* <code>Point</code> class except the class name since <code>Pair</code>
* is defined by reading <code>Point.class</code>.
*
* @param orgName the original (fully-qualified) class name
* @param newName the new class name
@@ -588,7 +605,16 @@ public class ClassPool {
public CtClass getAndRename(String orgName, String newName)
throws NotFoundException
{
CtClass clazz = get0(orgName);
CtClass clazz = null;
if (parent != null)
clazz = parent.get1(orgName);

if (clazz == null)
clazz = get1(orgName);

if (clazz == null)
throw new NotFoundException(orgName);

clazz.setName(newName); // indirectly calls
// classNameChanged() in this class
return clazz;
@@ -610,25 +636,61 @@ public class ClassPool {
*
* @param classname a fully-qualified class name.
*/
public synchronized CtClass get(String classname)
public CtClass get(String classname) throws NotFoundException {
CtClass clazz = get0(classname);
if (clazz == null)
throw new NotFoundException(classname);
else
return clazz;
}

/**
* @return null if the class could not be found.
*/
private synchronized CtClass get0(String classname)
throws NotFoundException
{
CtClass clazz = getCached(classname);
CtClass clazz;
if (parent != null) {
clazz = parent.get0(classname);
if (clazz != null)
return clazz;
}

clazz = getCached(classname);
if (clazz == null) {
clazz = get0(classname);
classes.put(classname, clazz);
clazz = get1(classname);
if (clazz != null)
classes.put(classname, clazz);
}

return clazz;
}

protected CtClass get0(String classname) throws NotFoundException {
if (classname.endsWith("[]"))
return new CtArray(classname, this);
else {
checkClassName(classname);
return new CtClassType(classname, this);
private CtClass get1(String classname) throws NotFoundException {
if (classname.endsWith("[]")) {
String base = classname.substring(0, classname.indexOf('['));
if (getCached(base) == null && find(base) == null)
return null;
else
return new CtArray(classname, this);
}
else
if (find(classname) == null)
return null;
else
return new CtClassType(classname, this);
}

/**
* Obtains the URL of the class file specified by classname.
* This method does not delegate to the parent pool.
*
* @param classname a fully-qualified class name.
* @return null if the class file could not be found.
*/
URL find(String classname) {
return source.find(classname);
}

/**
@@ -670,7 +732,7 @@ public class ClassPool {
}

/**
* Creates a new class from the given class file.
* Creates a new class (or interface) from the given class file.
* If there already exists a class with the same name, the new class
* overwrites that previous class.
*
@@ -689,8 +751,7 @@ public class ClassPool {
CtClass clazz = new CtClassType(classfile, this);
clazz.checkModify();
String classname = clazz.getName();
checkNotFrozen(classname,
"there is a frozen class with the same name.");
checkNotFrozen(classname);
classes.put(classname, clazz);
return clazz;
}
@@ -719,8 +780,7 @@ public class ClassPool {
public synchronized CtClass makeClass(String classname, CtClass superclass)
throws RuntimeException
{
checkNotFrozen(classname,
"the class with the given name is frozen.");
checkNotFrozen(classname);
CtClass clazz = new CtNewClass(classname, this, false, superclass);
classes.put(classname, clazz);
return clazz;
@@ -750,33 +810,12 @@ public class ClassPool {
public synchronized CtClass makeInterface(String name, CtClass superclass)
throws RuntimeException
{
checkNotFrozen(name,
"the interface with the given name is frozen.");
checkNotFrozen(name);
CtClass clazz = new CtNewClass(name, this, true, superclass);
classes.put(name, clazz);
return clazz;
}

/**
* Throws an exception if the class with the specified name does not
* exist.
*/
void checkClassName(String classname)
throws NotFoundException
{
source.checkClassName(classname);
}

/**
* Obtains the URL of the class file specified by classname.
*
* @param classname a fully-qualified class name.
* @return null if the class file could not be found.
*/
public URL find(String classname) {
return source.find(classname);
}

/**
* Appends the system search path to the end of the
* search path. The system search path
@@ -854,7 +893,7 @@ public class ClassPool {
* The detached <code>ClassPath</code> object cannot be added
* to the pathagain.
*/
public synchronized void removeClassPath(ClassPath cp) {
public void removeClassPath(ClassPath cp) {
source.removeClassPath(cp);
}


+ 39
- 23
src/main/javassist/ClassPoolTail.java View File

@@ -163,14 +163,12 @@ final class JarClassPath implements ClassPath {
}
}

final class ClassPoolTail extends ClassPool {
final class ClassPoolTail extends AbsClassPool {
protected ClassPathList pathList;
private Class thisClass;
private Hashtable packages; // should be synchronized.

public ClassPoolTail() {
pathList = null;
thisClass = getClass();
packages = new Hashtable();
}

@@ -196,33 +194,44 @@ final class ClassPoolTail extends ClassPool {
packages.put(name, name);
}

public byte[] write(String classname)
throws NotFoundException, IOException
/**
* @return the contents of the class file.
* @throws NotFoundException if the file could not be found.
*/
byte[] readSource(String classname)
throws NotFoundException, IOException, CannotCompileException
{
return readClassfile(classname);
byte[] b = readClassfile(classname);
if (b == null)
throw new NotFoundException(classname);
else
return b;
}

public void write(String classname, DataOutputStream out)
/**
* @return null if the file could not be found.
* @throws NotFoundException if any error is reported by ClassPath.
*/
boolean write0(String classname, DataOutputStream out, boolean callback)
throws NotFoundException, CannotCompileException, IOException
{
byte[] b = write(classname);
out.write(b, 0, b.length);
}

public CtClass get(String classname) throws NotFoundException {
throw new RuntimeException("fatal error");
}

public CtClass makeClass(String classname) {
throw new RuntimeException("fatal error");
byte[] b = readClassfile(classname);
if (b == null)
return false; // not found
else {
out.write(b, 0, b.length);
return true;
}
}

/*
-- faster version --
void checkClassName(String classname) throws NotFoundException {
if (find(classname) == null)
throw new NotFoundException(classname);
}

/* slower version.
-- slower version --

void checkClassName(String classname) throws NotFoundException {
InputStream fin = openClassfile(classname);
@@ -303,11 +312,16 @@ final class ClassPoolTail extends ClassPool {
* specified by <code>classname</code>.
*
* @param classname a fully-qualified class name
* @return null if the file has not been found.
* @throws NotFoundException if any error is reported by ClassPath.
*/
byte[] readClassfile(String classname)
private byte[] readClassfile(String classname)
throws NotFoundException, IOException
{
InputStream fin = openClassfile(classname);
if (fin == null)
return null;

byte[] b;
try {
b = readStream(fin);
@@ -323,13 +337,15 @@ final class ClassPoolTail extends ClassPool {
* Opens the class file for the class specified by
* <code>classname</code>.
*
* @param classname a fully-qualified class name
* @param classname a fully-qualified class name
* @return null if the file has not been found.
* @throws NotFoundException if any error is reported by ClassPath.
*/
public InputStream openClassfile(String classname)
private InputStream openClassfile(String classname)
throws NotFoundException
{
if (packages.get(classname) != null)
throw new NotFoundException(classname);
return null; // not found

ClassPathList list = pathList;
InputStream ins = null;
@@ -352,7 +368,7 @@ final class ClassPoolTail extends ClassPool {
if (error != null)
throw error;
else
throw new NotFoundException(classname);
return null; // not found
}

/**

+ 4
- 4
src/main/javassist/CtClassType.java View File

@@ -180,8 +180,8 @@ class CtClassType extends CtClass {
if (name.equals(oldname))
return;

classPool.checkNotFrozen(name,
"the class with the new name is frozen");
// check this in advance although classNameChanged() below does.
classPool.checkNotFrozen(name);
ClassFile cf = getClassFile2();
super.setName(name);
cf.setName(name);
@@ -197,8 +197,8 @@ class CtClassType extends CtClass {
= (String)classnames.get(Descriptor.toJvmName(oldClassName));
if (newClassName != null) {
newClassName = Descriptor.toJavaName(newClassName);
classPool.checkNotFrozen(newClassName,
"the class " + newClassName + " is frozen");
// check this in advance although classNameChanged() below does.
classPool.checkNotFrozen(newClassName);
}

super.replaceClassName(classnames);

+ 1
- 1
src/main/javassist/Translator.java View File

@@ -43,7 +43,7 @@ public interface Translator {
* Is invoked by a <code>ClassPool</code> for notifying that
* a class is written out to an output stream.
*
* <p>If CtClass.frozen() is true, that is, if the class has been
* <p>If <code>CtClass.frozen()</code> is true, that is, if the class has been
* already modified and written, then onWrite() is not invoked.
*
* @param pool the <code>ClassPool</code> that this translator

+ 580
- 632
src/main/javassist/bytecode/ClassFile.java
File diff suppressed because it is too large
View File


+ 207
- 224
src/main/javassist/bytecode/FieldInfo.java View File

@@ -28,228 +28,211 @@ import java.util.LinkedList;
*
* @see javassist.CtField#getFieldInfo()
*/
public final class FieldInfo
{
ConstPool constPool;
int accessFlags;
int name;
int descriptor;
LinkedList attribute; // may be null.
AnnotationGroup runtimeInvisible;
AnnotationGroup runtimeVisible;

private FieldInfo(ConstPool cp)
{
constPool = cp;
accessFlags = 0;
attribute = null;
}

/**
* Constructs a <code>field_info</code> structure.
*
* @param cp a constant pool table
* @param fieldName field name
* @param desc field descriptor
*
* @see Descriptor
*/
public FieldInfo(ConstPool cp, String fieldName, String desc)
{
this(cp);
name = cp.addUtf8Info(fieldName);
descriptor = cp.addUtf8Info(desc);
}

FieldInfo(ConstPool cp, DataInputStream in) throws IOException
{
this(cp);
read(in);
}

/**
* Returns the constant pool table used
* by this <code>field_info</code>.
*/
public ConstPool getConstPool()
{
return constPool;
}

/**
* Returns the field name.
*/
public String getName()
{
return constPool.getUtf8Info(name);
}

/**
* Sets the field name.
*/
public void setName(String newName)
{
name = constPool.addUtf8Info(newName);
}

/**
* Returns the access flags.
*
* @see AccessFlag
*/
public int getAccessFlags()
{
return accessFlags;
}

/**
* Sets the access flags.
*
* @see AccessFlag
*/
public void setAccessFlags(int acc)
{
accessFlags = acc;
}

/**
* Returns the field descriptor.
*
* @see Descriptor
*/
public String getDescriptor()
{
return constPool.getUtf8Info(descriptor);
}

/**
* Sets the field descriptor.
*
* @see Descriptor
*/
public void setDescriptor(String desc)
{
if (!desc.equals(getDescriptor()))
descriptor = constPool.addUtf8Info(desc);
}

/**
* Returns all the attributes.
*
* @return a list of <code>AttributeInfo</code> objects.
* @see AttributeInfo
*/
public List getAttributes()
{
if (attribute == null)
attribute = new LinkedList();

return attribute;
}

/**
* Returns the attribute with the specified name.
*
* @param name attribute name
*/
public AttributeInfo getAttribute(String name)
{
return AttributeInfo.lookup(attribute, name);
}

/**
* Appends an attribute. If there is already an attribute with
* the same name, the new one substitutes for it.
*/
public void addAttribute(AttributeInfo info)
{
if (attribute == null)
attribute = new LinkedList();

AttributeInfo.remove(attribute, info.getName());
attribute.add(info);
}

/**
* Create an empty (null) attribute "RuntimeInvisibleAnnotations"
* Usually used so that you can start adding annotations to a particular thing
*/
public void createRuntimeInvisibleGroup()
{
if (runtimeInvisible == null)
{
AttributeInfo attr = new AttributeInfo(constPool, "RuntimeInvisibleAnnotations");
addAttribute(attr);
runtimeInvisible = new AnnotationGroup(attr);
}
}

/**
* Create an empty (null) attribute "RuntimeVisibleAnnotations"
* Usually used so that you can start adding annotations to a particular thing
*/
public void createRuntimeVisibleGroup()
{
if (runtimeVisible == null)
{
AttributeInfo attr = new AttributeInfo(constPool, "RuntimeVisibleAnnotations");
addAttribute(attr);
runtimeVisible = new AnnotationGroup(attr);
}
}

/**
* Return access object for getting info about annotations
* This returns runtime invisible annotations as pertains to the
* CLASS RetentionPolicy
* @return
*/
public AnnotationGroup getRuntimeInvisibleAnnotations()
{
if (runtimeInvisible != null) return runtimeInvisible;
AttributeInfo invisible = getAttribute("RuntimeInvisibleAnnotations");
if (invisible == null) return null;
runtimeInvisible = new AnnotationGroup(invisible);
return runtimeInvisible;
}

/**
* Return access object for getting info about annotations
* This returns runtime visible annotations as pertains to the
* RUNTIME RetentionPolicy
* @return
*/
public AnnotationGroup getRuntimeVisibleAnnotations()
{
if (runtimeVisible != null) return runtimeVisible;
AttributeInfo visible = getAttribute("RuntimeVisibleAnnotations");
if (visible == null) return null;
runtimeVisible = new AnnotationGroup(visible);
return runtimeVisible;
}

private void read(DataInputStream in) throws IOException
{
accessFlags = in.readUnsignedShort();
name = in.readUnsignedShort();
descriptor = in.readUnsignedShort();
int n = in.readUnsignedShort();
attribute = new LinkedList();
for (int i = 0; i < n; ++i)
attribute.add(AttributeInfo.read(constPool, in));
}

void write(DataOutputStream out) throws IOException
{
out.writeShort(accessFlags);
out.writeShort(name);
out.writeShort(descriptor);
if (attribute == null)
out.writeShort(0);
else
{
out.writeShort(attribute.size());
AttributeInfo.writeAll(attribute, out);
}
}
public final class FieldInfo {
ConstPool constPool;
int accessFlags;
int name;
int descriptor;
LinkedList attribute; // may be null.
AnnotationGroup runtimeInvisible;
AnnotationGroup runtimeVisible;

private FieldInfo(ConstPool cp) {
constPool = cp;
accessFlags = 0;
attribute = null;
}

/**
* Constructs a <code>field_info</code> structure.
*
* @param cp a constant pool table
* @param fieldName field name
* @param desc field descriptor
*
* @see Descriptor
*/
public FieldInfo(ConstPool cp, String fieldName, String desc) {
this(cp);
name = cp.addUtf8Info(fieldName);
descriptor = cp.addUtf8Info(desc);
}

FieldInfo(ConstPool cp, DataInputStream in) throws IOException {
this(cp);
read(in);
}

/**
* Returns the constant pool table used
* by this <code>field_info</code>.
*/
public ConstPool getConstPool() {
return constPool;
}

/**
* Returns the field name.
*/
public String getName() {
return constPool.getUtf8Info(name);
}

/**
* Sets the field name.
*/
public void setName(String newName) {
name = constPool.addUtf8Info(newName);
}

/**
* Returns the access flags.
*
* @see AccessFlag
*/
public int getAccessFlags() {
return accessFlags;
}

/**
* Sets the access flags.
*
* @see AccessFlag
*/
public void setAccessFlags(int acc) {
accessFlags = acc;
}

/**
* Returns the field descriptor.
*
* @see Descriptor
*/
public String getDescriptor() {
return constPool.getUtf8Info(descriptor);
}

/**
* Sets the field descriptor.
*
* @see Descriptor
*/
public void setDescriptor(String desc) {
if (!desc.equals(getDescriptor()))
descriptor = constPool.addUtf8Info(desc);
}

/**
* Returns all the attributes.
*
* @return a list of <code>AttributeInfo</code> objects.
* @see AttributeInfo
*/
public List getAttributes() {
if (attribute == null)
attribute = new LinkedList();

return attribute;
}

/**
* Returns the attribute with the specified name.
*
* @param name attribute name
*/
public AttributeInfo getAttribute(String name) {
return AttributeInfo.lookup(attribute, name);
}

/**
* Appends an attribute. If there is already an attribute with
* the same name, the new one substitutes for it.
*/
public void addAttribute(AttributeInfo info) {
if (attribute == null)
attribute = new LinkedList();

AttributeInfo.remove(attribute, info.getName());
attribute.add(info);
}

/**
* Create an empty (null) attribute "RuntimeInvisibleAnnotations"
* Usually used so that you can start adding annotations to a particular thing
*/
public void createRuntimeInvisibleGroup() {
if (runtimeInvisible == null) {
AttributeInfo attr =
new AttributeInfo(constPool, "RuntimeInvisibleAnnotations");
addAttribute(attr);
runtimeInvisible = new AnnotationGroup(attr);
}
}

/**
* Create an empty (null) attribute "RuntimeVisibleAnnotations"
* Usually used so that you can start adding annotations to a particular thing
*/
public void createRuntimeVisibleGroup() {
if (runtimeVisible == null) {
AttributeInfo attr =
new AttributeInfo(constPool, "RuntimeVisibleAnnotations");
addAttribute(attr);
runtimeVisible = new AnnotationGroup(attr);
}
}

/**
* Return access object for getting info about annotations
* This returns runtime invisible annotations as pertains to the
* CLASS RetentionPolicy
* @return
*/
public AnnotationGroup getRuntimeInvisibleAnnotations() {
if (runtimeInvisible != null)
return runtimeInvisible;
AttributeInfo invisible = getAttribute("RuntimeInvisibleAnnotations");
if (invisible == null)
return null;
runtimeInvisible = new AnnotationGroup(invisible);
return runtimeInvisible;
}

/**
* Return access object for getting info about annotations
* This returns runtime visible annotations as pertains to the
* RUNTIME RetentionPolicy
* @return
*/
public AnnotationGroup getRuntimeVisibleAnnotations() {
if (runtimeVisible != null)
return runtimeVisible;
AttributeInfo visible = getAttribute("RuntimeVisibleAnnotations");
if (visible == null)
return null;
runtimeVisible = new AnnotationGroup(visible);
return runtimeVisible;
}

private void read(DataInputStream in) throws IOException {
accessFlags = in.readUnsignedShort();
name = in.readUnsignedShort();
descriptor = in.readUnsignedShort();
int n = in.readUnsignedShort();
attribute = new LinkedList();
for (int i = 0; i < n; ++i)
attribute.add(AttributeInfo.read(constPool, in));
}

void write(DataOutputStream out) throws IOException {
out.writeShort(accessFlags);
out.writeShort(name);
out.writeShort(descriptor);
if (attribute == null)
out.writeShort(0);
else {
out.writeShort(attribute.size());
AttributeInfo.writeAll(attribute, out);
}
}
}

+ 410
- 440
src/main/javassist/bytecode/MethodInfo.java View File

@@ -30,444 +30,414 @@ import java.util.LinkedList;
* @see javassist.CtMethod#getMethodInfo()
* @see javassist.CtConstructor#getMethodInfo()
*/
public final class MethodInfo
{
ConstPool constPool;
int accessFlags;
int name;
int descriptor;
LinkedList attribute; // may be null
AnnotationGroup runtimeInvisible;
AnnotationGroup runtimeVisible;

/**
* The name of constructors: <code>&lt;init&gt</code>.
*/
public static final String nameInit = "<init>";

/**
* The name of class initializer (static initializer):
* <code>&lt;clinit&gt</code>.
*/
public static final String nameClinit = "<clinit>";

private MethodInfo(ConstPool cp)
{
constPool = cp;
attribute = null;
}

/**
* Constructs a <code>method_info</code> structure.
*
* @param cp a constant pool table
* @param methodname method name
* @param desc method descriptor
*
* @see Descriptor
*/
public MethodInfo(ConstPool cp, String methodname, String desc)
{
this(cp);
accessFlags = 0;
name = cp.addUtf8Info(methodname);
descriptor = constPool.addUtf8Info(desc);
}

MethodInfo(ConstPool cp, DataInputStream in) throws IOException
{
this(cp);
read(in);
}

/**
* Constructs a copy of <code>method_info</code> structure.
* Class names appearing in the source <code>method_info</code>
* are renamed according to <code>classnameMap</code>.
*
* <p>Note: only <code>Code</code> and <code>Exceptions</code>
* attributes are copied from the source. The other attributes
* are ignored.
*
* @param cp a constant pool table
* @param methodname a method name
* @param src a source <code>method_info</code>
* @param classnameMap specifies pairs of replaced and substituted
* name.
* @see Descriptor
*/
public MethodInfo(ConstPool cp, String methodname, MethodInfo src,
Map classnameMap) throws BadBytecode
{
this(cp);
read(src, methodname, classnameMap);
}

/**
* Returns a method name.
*/
public String getName()
{
return constPool.getUtf8Info(name);
}

/**
* Sets a method name.
*/
public void setName(String newName)
{
name = constPool.addUtf8Info(newName);
}

/**
* Returns true if this is not a constructor or a class initializer
* (static initializer).
*/
public boolean isMethod()
{
String n = getName();
return !n.equals(nameInit) && !n.equals(nameClinit);
}

/**
* Returns a constant pool table used by this method.
*/
public ConstPool getConstPool()
{
return constPool;
}

/**
* Returns true if this is a constructor.
*/
public boolean isConstructor()
{
return getName().equals(nameInit);
}

/**
* Returns true if this is a class initializer (static initializer).
*/
public boolean isStaticInitializer()
{
return getName().equals(nameClinit);
}

/**
* Returns access flags.
*
* @see AccessFlag
*/
public int getAccessFlags()
{
return accessFlags;
}

/**
* Sets access flags.
*
* @see AccessFlag
*/
public void setAccessFlags(int acc)
{
accessFlags = acc;
}

/**
* Returns a method descriptor.
*
* @see Descriptor
*/
public String getDescriptor()
{
return constPool.getUtf8Info(descriptor);
}

/**
* Sets a method descriptor.
*
* @see Descriptor
*/
public void setDescriptor(String desc)
{
if (!desc.equals(getDescriptor()))
descriptor = constPool.addUtf8Info(desc);
}

/**
* Returns all the attributes.
*
* @return a list of <code>AttributeInfo</code> objects.
* @see AttributeInfo
*/
public List getAttributes()
{
if (attribute == null)
attribute = new LinkedList();

return attribute;
}

/**
* Returns the attribute with the specified name.
* If it is not found, this method returns null.
*
* @param name attribute name
* @return an <code>AttributeInfo</code> object or null.
*/
public AttributeInfo getAttribute(String name)
{
return AttributeInfo.lookup(attribute, name);
}

/**
* Appends an attribute. If there is already an attribute with
* the same name, the new one substitutes for it.
*/
public void addAttribute(AttributeInfo info)
{
if (attribute == null)
attribute = new LinkedList();

AttributeInfo.remove(attribute, info.getName());
attribute.add(info);
}

/**
* Create an empty (null) attribute "RuntimeInvisibleAnnotations"
* Usually used so that you can start adding annotations to a particular thing
*/
public void createRuntimeInvisibleGroup()
{
if (runtimeInvisible == null)
{
AttributeInfo attr = new AttributeInfo(constPool, "RuntimeInvisibleAnnotations");
addAttribute(attr);
runtimeInvisible = new AnnotationGroup(attr);
}
}

/**
* Create an empty (null) attribute "RuntimeVisibleAnnotations"
* Usually used so that you can start adding annotations to a particular thing
*/
public void createRuntimeVisibleGroup()
{
if (runtimeVisible == null)
{
AttributeInfo attr = new AttributeInfo(constPool, "RuntimeVisibleAnnotations");
addAttribute(attr);
runtimeVisible = new AnnotationGroup(attr);
}
}

/**
* Return access object for getting info about annotations
* This returns runtime invisible annotations as pertains to the
* CLASS RetentionPolicy
* @return
*/
public AnnotationGroup getRuntimeInvisibleAnnotations()
{
if (runtimeInvisible != null) return runtimeInvisible;
AttributeInfo invisible = getAttribute("RuntimeInvisibleAnnotations");
if (invisible == null) return null;
runtimeInvisible = new AnnotationGroup(invisible);
return runtimeInvisible;
}

/**
* Return access object for getting info about annotations
* This returns runtime visible annotations as pertains to the
* RUNTIME RetentionPolicy
* @return
*/
public AnnotationGroup getRuntimeVisibleAnnotations()
{
if (runtimeVisible != null) return runtimeVisible;
AttributeInfo visible = getAttribute("RuntimeVisibleAnnotations");
if (visible == null) return null;
runtimeVisible = new AnnotationGroup(visible);
return runtimeVisible;
}

/**
* Returns an Exceptions attribute.
*
* @return an Exceptions attribute
* or null if it is not specified.
*/
public ExceptionsAttribute getExceptionsAttribute()
{
AttributeInfo info
= AttributeInfo.lookup(attribute, ExceptionsAttribute.class);
return (ExceptionsAttribute) info;
}

/**
* Returns a Code attribute.
*
* @return a Code attribute
* or null if it is not specified.
*/
public CodeAttribute getCodeAttribute()
{
AttributeInfo info
= AttributeInfo.lookup(attribute, CodeAttribute.class);
return (CodeAttribute) info;
}

/**
* Removes an Exception attribute.
*/
public void removeExceptionsAttribute()
{
AttributeInfo.remove(attribute, ExceptionsAttribute.class);
}

/**
* Adds an Exception attribute.
*
* <p>The added attribute must share the same constant pool table
* as this <code>method_info</code> structure.
*/
public void setExceptionsAttribute(ExceptionsAttribute cattr)
{
removeExceptionsAttribute();
if (attribute == null)
attribute = new LinkedList();

attribute.add(cattr);
}

/**
* Removes a Code attribute.
*/
public void removeCodeAttribute()
{
AttributeInfo.remove(attribute, CodeAttribute.class);
}

/**
* Adds a Code attribute.
*
* <p>The added attribute must share the same constant pool table
* as this <code>method_info</code> structure.
*/
public void setCodeAttribute(CodeAttribute cattr)
{
removeCodeAttribute();
if (attribute == null)
attribute = new LinkedList();

attribute.add(cattr);
}

/**
* Returns the line number of the source line corresponding to the
* specified bytecode contained in this method.
*
* @param pos the position of the bytecode (&gt;= 0).
* an index into the code array.
* @return -1 if this information is not available.
*/
public int getLineNumber(int pos)
{
CodeAttribute ca = getCodeAttribute();
if (ca == null)
return -1;

LineNumberAttribute ainfo
= (LineNumberAttribute) ca.getAttribute(LineNumberAttribute.tag);
if (ainfo == null)
return -1;

return ainfo.toLineNumber(pos);
}

/**
* Changes a super constructor called by this constructor.
*
* <p>This method modifies a call to <code>super()</code>,
* which should be at the
* head of a constructor body, so that a constructor in a different
* super class is called. This method does not change actural
* parameters. Hence the new super class must have a constructor
* with the same signature as the original one.
*
* <p>This method should be called when the super class
* of the class declaring this method is changed.
*
* <p>This method does not perform anything unless this
* <code>MethodInfo</code> represents a constructor.
*
* @param superclass the new super class
*/
public void setSuperclass(String superclass) throws BadBytecode
{
if (!isConstructor())
return;

CodeAttribute ca = getCodeAttribute();
byte[] code = ca.getCode();
CodeIterator iterator = ca.iterator();
int pos = iterator.skipSuperConstructor();
if (pos >= 0)
{ // not this()
ConstPool cp = constPool;
int mref = ByteArray.readU16bit(code, pos + 1);
int nt = cp.getMethodrefNameAndType(mref);
int sc = cp.addClassInfo(superclass);
int mref2 = cp.addMethodrefInfo(sc, nt);
ByteArray.write16bit(mref2, code, pos + 1);
}
}

private void read(MethodInfo src, String methodname, Map classnames)
throws BadBytecode
{
ConstPool destCp = constPool;
accessFlags = src.accessFlags;
name = destCp.addUtf8Info(methodname);

ConstPool srcCp = src.constPool;
String desc = srcCp.getUtf8Info(src.descriptor);
String desc2 = Descriptor.rename(desc, classnames);
descriptor = destCp.addUtf8Info(desc2);

attribute = new LinkedList();
ExceptionsAttribute eattr = src.getExceptionsAttribute();
if (eattr != null)
attribute.add(eattr.copy(destCp, classnames));

CodeAttribute cattr = src.getCodeAttribute();
if (cattr != null)
attribute.add(cattr.copy(destCp, classnames));
}

private void read(DataInputStream in) throws IOException
{
accessFlags = in.readUnsignedShort();
name = in.readUnsignedShort();
descriptor = in.readUnsignedShort();
int n = in.readUnsignedShort();
attribute = new LinkedList();
for (int i = 0; i < n; ++i)
attribute.add(AttributeInfo.read(constPool, in));
}

void write(DataOutputStream out) throws IOException
{
out.writeShort(accessFlags);
out.writeShort(name);
out.writeShort(descriptor);

if (attribute == null)
out.writeShort(0);
else
{
out.writeShort(attribute.size());
AttributeInfo.writeAll(attribute, out);
}
}
public final class MethodInfo {
ConstPool constPool;
int accessFlags;
int name;
int descriptor;
LinkedList attribute; // may be null
AnnotationGroup runtimeInvisible;
AnnotationGroup runtimeVisible;

/**
* The name of constructors: <code>&lt;init&gt</code>.
*/
public static final String nameInit = "<init>";

/**
* The name of class initializer (static initializer):
* <code>&lt;clinit&gt</code>.
*/
public static final String nameClinit = "<clinit>";

private MethodInfo(ConstPool cp) {
constPool = cp;
attribute = null;
}

/**
* Constructs a <code>method_info</code> structure.
*
* @param cp a constant pool table
* @param methodname method name
* @param desc method descriptor
*
* @see Descriptor
*/
public MethodInfo(ConstPool cp, String methodname, String desc) {
this(cp);
accessFlags = 0;
name = cp.addUtf8Info(methodname);
descriptor = constPool.addUtf8Info(desc);
}

MethodInfo(ConstPool cp, DataInputStream in) throws IOException {
this(cp);
read(in);
}

/**
* Constructs a copy of <code>method_info</code> structure.
* Class names appearing in the source <code>method_info</code>
* are renamed according to <code>classnameMap</code>.
*
* <p>Note: only <code>Code</code> and <code>Exceptions</code>
* attributes are copied from the source. The other attributes
* are ignored.
*
* @param cp a constant pool table
* @param methodname a method name
* @param src a source <code>method_info</code>
* @param classnameMap specifies pairs of replaced and substituted
* name.
* @see Descriptor
*/
public MethodInfo(ConstPool cp, String methodname, MethodInfo src,
Map classnameMap) throws BadBytecode {
this(cp);
read(src, methodname, classnameMap);
}

/**
* Returns a method name.
*/
public String getName() {
return constPool.getUtf8Info(name);
}

/**
* Sets a method name.
*/
public void setName(String newName) {
name = constPool.addUtf8Info(newName);
}

/**
* Returns true if this is not a constructor or a class initializer
* (static initializer).
*/
public boolean isMethod() {
String n = getName();
return !n.equals(nameInit) && !n.equals(nameClinit);
}

/**
* Returns a constant pool table used by this method.
*/
public ConstPool getConstPool() {
return constPool;
}

/**
* Returns true if this is a constructor.
*/
public boolean isConstructor() {
return getName().equals(nameInit);
}

/**
* Returns true if this is a class initializer (static initializer).
*/
public boolean isStaticInitializer() {
return getName().equals(nameClinit);
}

/**
* Returns access flags.
*
* @see AccessFlag
*/
public int getAccessFlags() {
return accessFlags;
}

/**
* Sets access flags.
*
* @see AccessFlag
*/
public void setAccessFlags(int acc) {
accessFlags = acc;
}

/**
* Returns a method descriptor.
*
* @see Descriptor
*/
public String getDescriptor() {
return constPool.getUtf8Info(descriptor);
}

/**
* Sets a method descriptor.
*
* @see Descriptor
*/
public void setDescriptor(String desc) {
if (!desc.equals(getDescriptor()))
descriptor = constPool.addUtf8Info(desc);
}

/**
* Returns all the attributes.
*
* @return a list of <code>AttributeInfo</code> objects.
* @see AttributeInfo
*/
public List getAttributes() {
if (attribute == null)
attribute = new LinkedList();

return attribute;
}

/**
* Returns the attribute with the specified name.
* If it is not found, this method returns null.
*
* @param name attribute name
* @return an <code>AttributeInfo</code> object or null.
*/
public AttributeInfo getAttribute(String name) {
return AttributeInfo.lookup(attribute, name);
}

/**
* Appends an attribute. If there is already an attribute with
* the same name, the new one substitutes for it.
*/
public void addAttribute(AttributeInfo info) {
if (attribute == null)
attribute = new LinkedList();

AttributeInfo.remove(attribute, info.getName());
attribute.add(info);
}

/**
* Create an empty (null) attribute "RuntimeInvisibleAnnotations"
* Usually used so that you can start adding annotations to a particular thing
*/
public void createRuntimeInvisibleGroup() {
if (runtimeInvisible == null) {
AttributeInfo attr =
new AttributeInfo(constPool, "RuntimeInvisibleAnnotations");
addAttribute(attr);
runtimeInvisible = new AnnotationGroup(attr);
}
}

/**
* Create an empty (null) attribute "RuntimeVisibleAnnotations"
* Usually used so that you can start adding annotations to a particular thing
*/
public void createRuntimeVisibleGroup() {
if (runtimeVisible == null) {
AttributeInfo attr =
new AttributeInfo(constPool, "RuntimeVisibleAnnotations");
addAttribute(attr);
runtimeVisible = new AnnotationGroup(attr);
}
}

/**
* Return access object for getting info about annotations
* This returns runtime invisible annotations as pertains to the
* CLASS RetentionPolicy
* @return
*/
public AnnotationGroup getRuntimeInvisibleAnnotations() {
if (runtimeInvisible != null)
return runtimeInvisible;
AttributeInfo invisible = getAttribute("RuntimeInvisibleAnnotations");
if (invisible == null)
return null;
runtimeInvisible = new AnnotationGroup(invisible);
return runtimeInvisible;
}

/**
* Return access object for getting info about annotations
* This returns runtime visible annotations as pertains to the
* RUNTIME RetentionPolicy
* @return
*/
public AnnotationGroup getRuntimeVisibleAnnotations() {
if (runtimeVisible != null)
return runtimeVisible;
AttributeInfo visible = getAttribute("RuntimeVisibleAnnotations");
if (visible == null)
return null;
runtimeVisible = new AnnotationGroup(visible);
return runtimeVisible;
}

/**
* Returns an Exceptions attribute.
*
* @return an Exceptions attribute
* or null if it is not specified.
*/
public ExceptionsAttribute getExceptionsAttribute() {
AttributeInfo info
= AttributeInfo.lookup(attribute, ExceptionsAttribute.class);
return (ExceptionsAttribute)info;
}

/**
* Returns a Code attribute.
*
* @return a Code attribute
* or null if it is not specified.
*/
public CodeAttribute getCodeAttribute() {
AttributeInfo info
= AttributeInfo.lookup(attribute, CodeAttribute.class);
return (CodeAttribute)info;
}

/**
* Removes an Exception attribute.
*/
public void removeExceptionsAttribute() {
AttributeInfo.remove(attribute, ExceptionsAttribute.class);
}

/**
* Adds an Exception attribute.
*
* <p>The added attribute must share the same constant pool table
* as this <code>method_info</code> structure.
*/
public void setExceptionsAttribute(ExceptionsAttribute cattr) {
removeExceptionsAttribute();
if (attribute == null)
attribute = new LinkedList();

attribute.add(cattr);
}

/**
* Removes a Code attribute.
*/
public void removeCodeAttribute() {
AttributeInfo.remove(attribute, CodeAttribute.class);
}

/**
* Adds a Code attribute.
*
* <p>The added attribute must share the same constant pool table
* as this <code>method_info</code> structure.
*/
public void setCodeAttribute(CodeAttribute cattr) {
removeCodeAttribute();
if (attribute == null)
attribute = new LinkedList();

attribute.add(cattr);
}

/**
* Returns the line number of the source line corresponding to the
* specified bytecode contained in this method.
*
* @param pos the position of the bytecode (&gt;= 0).
* an index into the code array.
* @return -1 if this information is not available.
*/
public int getLineNumber(int pos) {
CodeAttribute ca = getCodeAttribute();
if (ca == null)
return -1;

LineNumberAttribute ainfo =
(LineNumberAttribute)ca.getAttribute(LineNumberAttribute.tag);
if (ainfo == null)
return -1;

return ainfo.toLineNumber(pos);
}

/**
* Changes a super constructor called by this constructor.
*
* <p>This method modifies a call to <code>super()</code>,
* which should be at the
* head of a constructor body, so that a constructor in a different
* super class is called. This method does not change actural
* parameters. Hence the new super class must have a constructor
* with the same signature as the original one.
*
* <p>This method should be called when the super class
* of the class declaring this method is changed.
*
* <p>This method does not perform anything unless this
* <code>MethodInfo</code> represents a constructor.
*
* @param superclass the new super class
*/
public void setSuperclass(String superclass) throws BadBytecode {
if (!isConstructor())
return;

CodeAttribute ca = getCodeAttribute();
byte[] code = ca.getCode();
CodeIterator iterator = ca.iterator();
int pos = iterator.skipSuperConstructor();
if (pos >= 0) { // not this()
ConstPool cp = constPool;
int mref = ByteArray.readU16bit(code, pos + 1);
int nt = cp.getMethodrefNameAndType(mref);
int sc = cp.addClassInfo(superclass);
int mref2 = cp.addMethodrefInfo(sc, nt);
ByteArray.write16bit(mref2, code, pos + 1);
}
}

private void read(MethodInfo src, String methodname, Map classnames)
throws BadBytecode
{
ConstPool destCp = constPool;
accessFlags = src.accessFlags;
name = destCp.addUtf8Info(methodname);

ConstPool srcCp = src.constPool;
String desc = srcCp.getUtf8Info(src.descriptor);
String desc2 = Descriptor.rename(desc, classnames);
descriptor = destCp.addUtf8Info(desc2);

attribute = new LinkedList();
ExceptionsAttribute eattr = src.getExceptionsAttribute();
if (eattr != null)
attribute.add(eattr.copy(destCp, classnames));

CodeAttribute cattr = src.getCodeAttribute();
if (cattr != null)
attribute.add(cattr.copy(destCp, classnames));
}

private void read(DataInputStream in) throws IOException {
accessFlags = in.readUnsignedShort();
name = in.readUnsignedShort();
descriptor = in.readUnsignedShort();
int n = in.readUnsignedShort();
attribute = new LinkedList();
for (int i = 0; i < n; ++i)
attribute.add(AttributeInfo.read(constPool, in));
}

void write(DataOutputStream out) throws IOException {
out.writeShort(accessFlags);
out.writeShort(name);
out.writeShort(descriptor);

if (attribute == null)
out.writeShort(0);
else {
out.writeShort(attribute.size());
AttributeInfo.writeAll(attribute, out);
}
}
}

+ 2
- 1
src/main/javassist/reflect/Compiler.java View File

@@ -90,7 +90,8 @@ public class Compiler {
throws Exception
{
Reflection implementor = new Reflection();
ClassPool pool = ClassPool.getDefault(implementor);
ClassPool pool = ClassPool.getDefault();
pool.insertTranslator(implementor);

for (int i = 0; i < n; ++i) {
CtClass c = pool.get(entries[i].classname);

+ 3
- 1
src/main/javassist/reflect/Loader.java View File

@@ -133,7 +133,9 @@ public class Loader extends javassist.Loader {
delegateLoadingOf("javassist.reflect.Loader");

reflection = new Reflection();
setClassPool(ClassPool.getDefault(reflection));
ClassPool pool = ClassPool.getDefault();
pool.insertTranslator(reflection);
setClassPool(pool);
}

/**

+ 5
- 4
src/main/javassist/rmi/AppletServer.java View File

@@ -60,7 +60,7 @@ public class AppletServer extends Webserver {
public AppletServer(int port)
throws IOException, NotFoundException, CannotCompileException
{
this(ClassPool.getDefault(new StubGenerator()), port);
this(ClassPool.getDefault(), new StubGenerator(), port);
}

/**
@@ -72,16 +72,17 @@ public class AppletServer extends Webserver {
public AppletServer(int port, ClassPool src)
throws IOException, NotFoundException, CannotCompileException
{
this(new ClassPool(src, new StubGenerator()), port);
this(new ClassPool(src), new StubGenerator(), port);
}

private AppletServer(ClassPool loader, int port)
private AppletServer(ClassPool loader, StubGenerator gen, int port)
throws IOException, NotFoundException, CannotCompileException
{
super(port);
exportedNames = new Hashtable();
exportedObjects = new Vector();
stubGen = (StubGenerator)loader.getTranslator();
stubGen = gen;
loader.insertTranslator(gen);
setClassPool(loader);
}


Loading…
Cancel
Save