From: Bill B. <pat...@us...> - 2003-03-24 23:19:40
|
User: patriot1burke Date: 03/03/24 15:19:36 Added: javassist/javassist/src/src/javassist/expr Cast.java Expr.java ExprEditor.java FieldAccess.java Instanceof.java MethodCall.java NewExpr.java Log: added javassist source code until we can set it up at sourceforge Revision Changes Path 1.1 thirdparty/javassist/javassist/src/src/javassist/expr/Cast.java Index: Cast.java =================================================================== /* * This file is part of the Javassist toolkit. * * 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. You may obtain a copy of the License at * either http://www.mozilla.org/MPL/. * * 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. * * The Original Code is Javassist. * * The Initial Developer of the Original Code is Shigeru Chiba. Portions * created by Shigeru Chiba are Copyright (C) 1999-2003 Shigeru Chiba. * All Rights Reserved. * * Contributor(s): * * The development of this software is supported in part by the PRESTO * program (Sakigake Kenkyu 21) of Japan Science and Technology Corporation. */ package javassist.expr; import javassist.*; import javassist.bytecode.*; import javassist.compiler.*; import javassist.compiler.ast.ASTList; /** * Explicit type cast. */ public class Cast extends Expr { /** * Undocumented constructor. Do not use; internal-use only. */ Cast(int pos, CodeIterator i, CtClass declaring, MethodInfo m) { super(pos, i, declaring, m); } /** * Returns the method or constructor containing the type cast * expression represented by this object. */ public CtBehavior where() { return super.where(); } /** * Returns the line number of the source line containing the * type-cast expression. * * @return -1 if this information is not available. */ public int getLineNumber() { return super.getLineNumber(); } /** * Returns the source file containing the type-cast expression. * * @return null if this information is not available. */ public String getFileName() { return super.getFileName(); } /** * Returns the <code>CtClass</code> object representing * the type specified by the cast. */ public CtClass getType() throws NotFoundException { ConstPool cp = getConstPool(); int pos = currentPos; int index = iterator.u16bitAt(pos + 1); String name = cp.getClassInfo(index); return Descriptor.toCtClass(name, thisClass.getClassPool()); } /** * Returns the list of exceptions that the expression may throw. * This list includes both the exceptions that the try-catch statements * including the expression can catch and the exceptions that * the throws declaration allows the method to throw. */ public CtClass[] mayThrow() { return super.mayThrow(); } /** * Replaces the explicit cast operator with the bytecode derived from * the given source text. * * <p>$0 is available but the value is <code>null</code>. * * @param statement a Java statement. */ public void replace(String statement) throws CannotCompileException { ConstPool constPool = getConstPool(); int pos = currentPos; int index = iterator.u16bitAt(pos + 1); Javac jc = new Javac(thisClass); ClassPool cp = thisClass.getClassPool(); CodeAttribute ca = iterator.get(); try { CtClass[] params = new CtClass[] { cp.get(javaLangObject) }; CtClass retType = getType(); int paramVar = ca.getMaxLocals(); jc.recordParams(javaLangObject, params, true, paramVar, withinStatic()); int retVar = jc.recordReturnType(retType, true); jc.recordProceed(new ProceedForCast(index, retType)); /* Is $_ included in the source code? */ checkResultValue(retType, statement); Bytecode bytecode = jc.getBytecode(); storeStack(params, true, paramVar, bytecode); jc.compileStmnt(statement); bytecode.addLoad(retVar, retType); replace0(pos, bytecode, 3); } catch (CompileError e) { throw new CannotCompileException(e); } catch (NotFoundException e) { throw new CannotCompileException(e); } catch (BadBytecode e) { throw new CannotCompileException("broken method"); } } /* <type> $proceed(Object obj) */ static class ProceedForCast implements ProceedHandler { int index; CtClass retType; ProceedForCast(int i, CtClass t) { index = i; retType = t; } public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args) throws CompileError { if (gen.atMethodArgsLength(args) != 1) throw new CompileError(Javac.proceedName + "() cannot take more than one parameter " + "for cast"); gen.atMethodArgs(args, new int[1], new int[1], new String[1]); bytecode.addOpcode(Opcode.CHECKCAST); bytecode.addIndex(index); gen.setType(retType); } } } 1.1 thirdparty/javassist/javassist/src/src/javassist/expr/Expr.java Index: Expr.java =================================================================== /* * This file is part of the Javassist toolkit. * * 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. You may obtain a copy of the License at * either http://www.mozilla.org/MPL/. * * 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. * * The Original Code is Javassist. * * The Initial Developer of the Original Code is Shigeru Chiba. Portions * created by Shigeru Chiba are Copyright (C) 1999-2003 Shigeru Chiba. * All Rights Reserved. * * Contributor(s): * * The development of this software is supported in part by the PRESTO * program (Sakigake Kenkyu 21) of Japan Science and Technology Corporation. */ package javassist.expr; import javassist.*; import javassist.bytecode.*; import javassist.compiler.*; import java.util.LinkedList; import java.util.Iterator; /** * Caller-side expression. */ abstract class Expr implements Opcode { int currentPos; CodeIterator iterator; CtClass thisClass; MethodInfo thisMethod; boolean edited; int maxLocals, maxStack; static final String javaLangObject = "java.lang.Object"; Expr(int pos, CodeIterator i, CtClass declaring, MethodInfo m) { currentPos = pos; iterator = i; thisClass = declaring; thisMethod = m; } final ConstPool getConstPool() { return thisMethod.getConstPool(); } final boolean edited() { return edited; } final int locals() { return maxLocals; } final int stack() { return maxStack; } /** * Returns true if this method is static. */ final boolean withinStatic() { return (thisMethod.getAccessFlags() & AccessFlag.STATIC) != 0; } /** * Returns the constructor or method containing the expression. */ public CtBehavior where() { MethodInfo mi = thisMethod; CtBehavior[] cb = thisClass.getDeclaredBehaviors(); for (int i = cb.length - 1; i >= 0; --i) if (cb[i].getMethodInfo() == mi) return cb[i]; throw new RuntimeException("fatal: not found"); } /** * Returns the list of exceptions that the expression may throw. * This list includes both the exceptions that the try-catch statements * including the expression can catch and the exceptions that * the throws declaration allows the method to throw. */ public CtClass[] mayThrow() { ClassPool pool = thisClass.getClassPool(); ConstPool cp = thisMethod.getConstPool(); LinkedList list = new LinkedList(); try { CodeAttribute ca = thisMethod.getCodeAttribute(); ExceptionTable et = ca.getExceptionTable(); int pos = currentPos; int n = et.size(); for (int i = 0; i < n; ++i) if (et.startPc(i) <= pos && pos < et.endPc(i)) { int t = et.catchType(i); if (t > 0) try { addClass(list, pool.get(cp.getClassInfo(t))); } catch (NotFoundException e) {} } } catch (NullPointerException e) {} ExceptionsAttribute ea = thisMethod.getExceptionsAttribute(); if (ea != null) { String[] exceptions = ea.getExceptions(); if (exceptions != null) { int n = exceptions.length; for (int i = 0; i < n; ++i) try { addClass(list, pool.get(exceptions[i])); } catch (NotFoundException e) {} } } return (CtClass[])list.toArray(new CtClass[list.size()]); } private static void addClass(LinkedList list, CtClass c) { Iterator it = list.iterator(); while (it.hasNext()) if (it.next() == c) return; list.add(c); } /** * Returns the line number of the source line containing the * expression. * * @return -1 if this information is not available. */ public int getLineNumber() { return thisMethod.getLineNumber(currentPos); } /** * Returns the source file containing the expression. * * @return null if this information is not available. */ public String getFileName() { ClassFile cf = thisClass.getClassFile2(); if (cf == null) return null; else return cf.getSourceFile(); } static final boolean checkResultValue(CtClass retType, String prog) throws CannotCompileException { /* Is $_ included in the source code? */ boolean hasIt = (prog.indexOf(Javac.resultVarName) >= 0); if (!hasIt && retType != CtClass.voidType) throw new CannotCompileException( "the resulting value is not stored in " + Javac.resultVarName); return hasIt; } /* If isStaticCall is true, null is assigned to $0. So $0 must * be declared by calling Javac.recordParams(). * * After executing this method, the current stack depth might * be less than 0. */ static final void storeStack(CtClass[] params, boolean isStaticCall, int regno, Bytecode bytecode) { storeStack0(0, params.length, params, regno + 1, bytecode); if (isStaticCall) bytecode.addOpcode(ACONST_NULL); bytecode.addAstore(regno); } private static void storeStack0(int i, int n, CtClass[] params, int regno, Bytecode bytecode) { if (i >= n) return; else { CtClass c = params[i]; int size; if (c instanceof CtPrimitiveType) size = ((CtPrimitiveType)c).getDataSize(); else size = 1; storeStack0(i + 1, n, params, regno + size, bytecode); bytecode.addStore(regno, c); } } protected void replace0(int pos, Bytecode bytecode, int size) throws BadBytecode { byte[] code = bytecode.get(); edited = true; int gap = code.length - size; if (gap > 0) iterator.insertGap(pos, gap); else for (int i = 0; i < size; ++i) iterator.writeByte(NOP, pos + i); iterator.write(code, pos); iterator.insert(bytecode.getExceptionTable(), pos); maxLocals = bytecode.getMaxLocals(); maxStack = bytecode.getMaxStack(); } } 1.1 thirdparty/javassist/javassist/src/src/javassist/expr/ExprEditor.java Index: ExprEditor.java =================================================================== /* * This file is part of the Javassist toolkit. * * 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. You may obtain a copy of the License at * either http://www.mozilla.org/MPL/. * * 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. * * The Original Code is Javassist. * * The Initial Developer of the Original Code is Shigeru Chiba. Portions * created by Shigeru Chiba are Copyright (C) 1999-2003 Shigeru Chiba. * All Rights Reserved. * * Contributor(s): * * The development of this software is supported in part by the PRESTO * program (Sakigake Kenkyu 21) of Japan Science and Technology Corporation. */ package javassist.expr; import javassist.bytecode.*; import javassist.CtClass; import javassist.CannotCompileException; /** * A translator of method bodies. * * <p>The users can define a subclass of this class to customize how to * modify a method body. The overall architecture is similar to the * strategy pattern. * * <p>If <code>instrument()</code> is called in * <code>CtMethod</code>, the method body is scanned from the beginning * to the end. * Whenever an expression, such as a method call and a <tt>new</tt> * expression (object creation), * is found, <code>edit()</code> is called in <code>ExprEdit</code>. * <code>edit()</code> can inspect and modify the given expression. * The modification is reflected on the original method body. If * <code>edit()</code> does nothing, the original method body is not * changed. * * <p>The following code is an example: * * <ul><pre> * CtMethod cm = ...; * cm.instrument(new ExprEditor() { * public void edit(MethodCall m) throws CannotCompileException { * if (m.getClassName().equals("Point")) { * System.out.println(m.getMethodName() + " line: " * + m.getLineNumber()); * } * }); * </pre></ul> * * <p>This code inspects all method calls appearing in the method represented * by <code>cm</code> and it prints the names and the line numbers of the * methods declared in class <code>Point</code>. This code does not modify * the body of the method represented by <code>cm</code>. If the method * body must be modified, call <code>replace()</code> * in <code>MethodCall</code>. * * @see javassist.CtClass#instrument(ExprEditor) * @see javassist.CtMethod#instrument(ExprEditor) * @see javassist.CtConstructor#instrument(ExprEditor) * @see MethodCall * @see NewExpr * @see FieldAccess * * @see javassist.CodeConverter */ public class ExprEditor { /** * Default constructor. It does nothing. */ public ExprEditor() {} static class NewOp { NewOp next; int pos; String type; NewOp(NewOp n, int p, String t) { next = n; pos = p; type = t; } } /** * Undocumented method. Do not use; internal-use only. */ public boolean doit(CtClass clazz, MethodInfo minfo) throws CannotCompileException { CodeAttribute codeAttr = minfo.getCodeAttribute(); if (codeAttr == null) return false; CodeIterator iterator = codeAttr.iterator(); boolean edited = false; int maxLocals = codeAttr.getMaxLocals(); int maxStack = 0; NewOp newList = null; ConstPool cp = minfo.getConstPool(); while (iterator.hasNext()) try { Expr expr = null; int pos = iterator.next(); int c = iterator.byteAt(pos); if (c == Opcode.INVOKESTATIC || c == Opcode.INVOKEINTERFACE || c == Opcode.INVOKEVIRTUAL) { expr = new MethodCall(pos, iterator, clazz, minfo); edit((MethodCall)expr); } else if (c == Opcode.GETFIELD || c == Opcode.GETSTATIC || c == Opcode.PUTFIELD || c == Opcode.PUTSTATIC) { expr = new FieldAccess(pos, iterator, clazz, minfo, c); edit((FieldAccess)expr); } else if (c == Opcode.NEW) { int index = iterator.u16bitAt(pos + 1); newList = new NewOp(newList, pos, cp.getClassInfo(index)); } else if (c == Opcode.INVOKESPECIAL) { if (newList != null && cp.isConstructor(newList.type, iterator.u16bitAt(pos + 1)) > 0) { expr = new NewExpr(pos, iterator, clazz, minfo, newList.type, newList.pos); edit((NewExpr)expr); newList = newList.next; } else { expr = new MethodCall(pos, iterator, clazz, minfo); MethodCall mcall = (MethodCall)expr; if (!mcall.getMethodName().equals( MethodInfo.nameInit)) edit(mcall); } } else if (c == Opcode.INSTANCEOF) { expr = new Instanceof(pos, iterator, clazz, minfo); edit((Instanceof)expr); } else if (c == Opcode.CHECKCAST) { expr = new Cast(pos, iterator, clazz, minfo); edit((Cast)expr); } if (expr != null && expr.edited()) { edited = true; if (maxLocals < expr.locals()) maxLocals = expr.locals(); if (maxStack < expr.stack()) maxStack = expr.stack(); } } catch (BadBytecode e) { throw new CannotCompileException(e); } codeAttr.setMaxLocals(maxLocals); codeAttr.setMaxStack(codeAttr.getMaxStack() + maxStack); return edited; } /** * Edits a <tt>new</tt> expression (overridable). * The default implementation performs nothing. * * @param e the <tt>new</tt> expression creating an object. */ public void edit(NewExpr e) throws CannotCompileException {} /** * Edits a method call (overridable). * The default implementation performs nothing. */ public void edit(MethodCall m) throws CannotCompileException {} /** * Edits a field-access expression (overridable). * Field access means both read and write. * The default implementation performs nothing. */ public void edit(FieldAccess f) throws CannotCompileException {} /** * Edits an instanceof expression (overridable). * The default implementation performs nothing. */ public void edit(Instanceof i) throws CannotCompileException {} /** * Edits an expression for explicit type casting (overridable). * The default implementation performs nothing. */ public void edit(Cast c) throws CannotCompileException {} } 1.1 thirdparty/javassist/javassist/src/src/javassist/expr/FieldAccess.java Index: FieldAccess.java =================================================================== /* * This file is part of the Javassist toolkit. * * 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. You may obtain a copy of the License at * either http://www.mozilla.org/MPL/. * * 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. * * The Original Code is Javassist. * * The Initial Developer of the Original Code is Shigeru Chiba. Portions * created by Shigeru Chiba are Copyright (C) 1999-2003 Shigeru Chiba. * All Rights Reserved. * * Contributor(s): * * The development of this software is supported in part by the PRESTO * program (Sakigake Kenkyu 21) of Japan Science and Technology Corporation. */ package javassist.expr; import javassist.*; import javassist.bytecode.*; import javassist.compiler.*; import javassist.compiler.ast.ASTList; /** * Expression for accessing a field. */ public class FieldAccess extends Expr { int opcode; FieldAccess(int pos, CodeIterator i, CtClass declaring, MethodInfo m, int op) { super(pos, i, declaring, m); opcode = op; } /** * Returns the method or constructor containing the field-access * expression represented by this object. */ public CtBehavior where() { return super.where(); } /** * Returns the line number of the source line containing the * field access. * * @return -1 if this information is not available. */ public int getLineNumber() { return super.getLineNumber(); } /** * Returns the source file containing the field access. * * @return null if this information is not available. */ public String getFileName() { return super.getFileName(); } /** * Returns true if the field is static. */ public boolean isStatic() { return isStatic(opcode); } static boolean isStatic(int c) { return c == Opcode.GETSTATIC || c == Opcode.PUTSTATIC; } /** * Returns true if the field is read. */ public boolean isReader() { return opcode == Opcode.GETFIELD || opcode == Opcode.GETSTATIC; } /** * Returns true if the field is written in. */ public boolean isWriter() { return opcode == Opcode.PUTFIELD || opcode == Opcode.PUTSTATIC; } /** * Returns the class in which the field is declared. */ private CtClass getCtClass() throws NotFoundException { return thisClass.getClassPool().get(getClassName()); } /** * Returns the name of the class in which the field is declared. */ public String getClassName() { int index = iterator.u16bitAt(currentPos + 1); return getConstPool().getFieldrefClassName(index); } /** * Returns the name of the field. */ public String getFieldName() { int index = iterator.u16bitAt(currentPos + 1); return getConstPool().getFieldrefName(index); } /** * Returns the field accessed by this expression. */ public CtField getField() throws NotFoundException { CtClass cc = getCtClass(); return cc.getField(getFieldName()); } /** * Returns the list of exceptions that the expression may throw. * This list includes both the exceptions that the try-catch statements * including the expression can catch and the exceptions that * the throws declaration allows the method to throw. */ public CtClass[] mayThrow() { return super.mayThrow(); } /* * Returns the type of the field. public CtClass getFieldType() throws NotFoundException { int index = iterator.u16bitAt(currentPos + 1); String type = getConstPool().getFieldrefType(index); return Descriptor.toCtClass(type, thisClass.getClassPool()); } */ /** * Replaces the method call with the bytecode derived from * the given source text. * * <p>$0 is available even if the called method is static. * If the field access is writing, $_ is available but the value * of $_ is ignored. * * @param statement a Java statement. */ public void replace(String statement) throws CannotCompileException { ConstPool constPool = getConstPool(); int pos = currentPos; int index = iterator.u16bitAt(pos + 1); Javac jc = new Javac(thisClass); CodeAttribute ca = iterator.get(); try { CtClass[] params; CtClass retType; CtClass fieldType = Descriptor.toCtClass(constPool.getFieldrefType(index), thisClass.getClassPool()); boolean read = isReader(); if (read) { params = new CtClass[0]; retType = fieldType; } else { params = new CtClass[1]; params[0] = fieldType; retType = CtClass.voidType; } int paramVar = ca.getMaxLocals(); jc.recordParams(constPool.getFieldrefClassName(index), params, true, paramVar, withinStatic()); /* Is $_ included in the source code? */ boolean included = checkResultValue(retType, statement); int retVar = jc.recordReturnType(retType, included); if (read) jc.recordProceed(new ProceedForRead(retType, opcode, index, paramVar)); else { // because $type is not the return type... jc.recordType(fieldType); jc.recordProceed(new ProceedForWrite(params[0], opcode, index, paramVar)); } Bytecode bytecode = jc.getBytecode(); storeStack(params, isStatic(), paramVar, bytecode); jc.compileStmnt(statement); if (read) bytecode.addLoad(retVar, retType); replace0(pos, bytecode, 3); } catch (CompileError e) { throw new CannotCompileException(e); } catch (NotFoundException e) { throw new CannotCompileException(e); } catch (BadBytecode e) { throw new CannotCompileException("broken method"); } } /* <field type> $proceed() */ static class ProceedForRead implements ProceedHandler { CtClass fieldType; int opcode; int targetVar, index; ProceedForRead(CtClass type, int op, int i, int var) { fieldType = type; targetVar = var; opcode = op; index = i; } public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args) throws CompileError { if (args != null && !gen.isParamListName(args)) throw new CompileError(Javac.proceedName + "() cannot take a parameter for field reading"); int stack; if (isStatic(opcode)) stack = 0; else { stack = -1; bytecode.addAload(targetVar); } if (fieldType instanceof CtPrimitiveType) stack += ((CtPrimitiveType)fieldType).getDataSize(); else ++stack; bytecode.add(opcode); bytecode.addIndex(index); bytecode.growStack(stack); gen.setType(fieldType); } } /* void $proceed(<field type>) * the return type is not the field type but void. */ static class ProceedForWrite implements ProceedHandler { CtClass fieldType; int opcode; int targetVar, index; ProceedForWrite(CtClass type, int op, int i, int var) { fieldType = type; targetVar = var; opcode = op; index = i; } public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args) throws CompileError { if (gen.atMethodArgsLength(args) != 1) throw new CompileError(Javac.proceedName + "() cannot take more than one parameter " + "for field writing"); int stack; if (isStatic(opcode)) stack = 0; else { stack = -1; bytecode.addAload(targetVar); } gen.atMethodArgs(args, new int[1], new int[1], new String[1]); gen.doNumCast(fieldType); if (fieldType instanceof CtPrimitiveType) stack -= ((CtPrimitiveType)fieldType).getDataSize(); else --stack; bytecode.add(opcode); bytecode.addIndex(index); bytecode.growStack(stack); gen.setType(CtClass.voidType); gen.addNullIfVoid(); } } } 1.1 thirdparty/javassist/javassist/src/src/javassist/expr/Instanceof.java Index: Instanceof.java =================================================================== /* * This file is part of the Javassist toolkit. * * 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. You may obtain a copy of the License at * either http://www.mozilla.org/MPL/. * * 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. * * The Original Code is Javassist. * * The Initial Developer of the Original Code is Shigeru Chiba. Portions * created by Shigeru Chiba are Copyright (C) 1999-2003 Shigeru Chiba. * All Rights Reserved. * * Contributor(s): * * The development of this software is supported in part by the PRESTO * program (Sakigake Kenkyu 21) of Japan Science and Technology Corporation. */ package javassist.expr; import javassist.*; import javassist.bytecode.*; import javassist.compiler.*; import javassist.compiler.ast.ASTList; /** * Instanceof operator. */ public class Instanceof extends Expr { /** * Undocumented constructor. Do not use; internal-use only. */ Instanceof(int pos, CodeIterator i, CtClass declaring, MethodInfo m) { super(pos, i, declaring, m); } /** * Returns the method or constructor containing the instanceof * expression represented by this object. */ public CtBehavior where() { return super.where(); } /** * Returns the line number of the source line containing the * instanceof expression. * * @return -1 if this information is not available. */ public int getLineNumber() { return super.getLineNumber(); } /** * Returns the source file containing the * instanceof expression. * * @return null if this information is not available. */ public String getFileName() { return super.getFileName(); } /** * Returns the <code>CtClass</code> object representing * the type name on the right hand side * of the instanceof operator. */ public CtClass getType() throws NotFoundException { ConstPool cp = getConstPool(); int pos = currentPos; int index = iterator.u16bitAt(pos + 1); String name = cp.getClassInfo(index); return Descriptor.toCtClass(name, thisClass.getClassPool()); } /** * Returns the list of exceptions that the expression may throw. * This list includes both the exceptions that the try-catch statements * including the expression can catch and the exceptions that * the throws declaration allows the method to throw. */ public CtClass[] mayThrow() { return super.mayThrow(); } /** * Replaces the instanceof operator with the bytecode derived from * the given source text. * * <p>$0 is available but the value is <code>null</code>. * * @param statement a Java statement. */ public void replace(String statement) throws CannotCompileException { ConstPool constPool = getConstPool(); int pos = currentPos; int index = iterator.u16bitAt(pos + 1); Javac jc = new Javac(thisClass); ClassPool cp = thisClass.getClassPool(); CodeAttribute ca = iterator.get(); try { CtClass[] params = new CtClass[] { cp.get(javaLangObject) }; CtClass retType = CtClass.booleanType; int paramVar = ca.getMaxLocals(); jc.recordParams(javaLangObject, params, true, paramVar, withinStatic()); int retVar = jc.recordReturnType(retType, true); jc.recordProceed(new ProceedForInstanceof(index)); // because $type is not the return type... jc.recordType(getType()); /* Is $_ included in the source code? */ checkResultValue(retType, statement); Bytecode bytecode = jc.getBytecode(); storeStack(params, true, paramVar, bytecode); jc.compileStmnt(statement); bytecode.addLoad(retVar, retType); replace0(pos, bytecode, 3); } catch (CompileError e) { throw new CannotCompileException(e); } catch (NotFoundException e) { throw new CannotCompileException(e); } catch (BadBytecode e) { throw new CannotCompileException("broken method"); } } /* boolean $proceed(Object obj) */ static class ProceedForInstanceof implements ProceedHandler { int index; ProceedForInstanceof(int i) { index = i; } public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args) throws CompileError { if (gen.atMethodArgsLength(args) != 1) throw new CompileError(Javac.proceedName + "() cannot take more than one parameter " + "for instanceof"); gen.atMethodArgs(args, new int[1], new int[1], new String[1]); bytecode.addOpcode(Opcode.INSTANCEOF); bytecode.addIndex(index); gen.setType(CtClass.booleanType); } } } 1.1 thirdparty/javassist/javassist/src/src/javassist/expr/MethodCall.java Index: MethodCall.java =================================================================== /* * This file is part of the Javassist toolkit. * * 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. You may obtain a copy of the License at * either http://www.mozilla.org/MPL/. * * 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. * * The Original Code is Javassist. * * The Initial Developer of the Original Code is Shigeru Chiba. Portions * created by Shigeru Chiba are Copyright (C) 1999-2003 Shigeru Chiba. * All Rights Reserved. * * Contributor(s): * * The development of this software is supported in part by the PRESTO * program (Sakigake Kenkyu 21) of Japan Science and Technology Corporation. */ package javassist.expr; import javassist.*; import javassist.bytecode.*; import javassist.compiler.*; /** * Method invocation (caller-side expression). */ public class MethodCall extends Expr { /** * Undocumented constructor. Do not use; internal-use only. */ MethodCall(int pos, CodeIterator i, CtClass declaring, MethodInfo m) { super(pos, i, declaring, m); } private int getNameAndType(ConstPool cp) { String cname; int pos = currentPos; int c = iterator.byteAt(pos); int index = iterator.u16bitAt(pos + 1); if (c == INVOKEINTERFACE) return cp.getInterfaceMethodrefNameAndType(index); else return cp.getMethodrefNameAndType(index); } /** * Returns the method or constructor containing the method-call * expression represented by this object. */ public CtBehavior where() { return super.where(); } /** * Returns the line number of the source line containing the * method call. * * @return -1 if this information is not available. */ public int getLineNumber() { return super.getLineNumber(); } /** * Returns the source file containing the method call. * * @return null if this information is not available. */ public String getFileName() { return super.getFileName(); } /** * Returns the class of the target object, * which the method is called on. */ private CtClass getCtClass() throws NotFoundException { return thisClass.getClassPool().get(getClassName()); } /** * Returns the class name of the target object, * which the method is called on. */ public String getClassName() { String cname; ConstPool cp = getConstPool(); int pos = currentPos; int c = iterator.byteAt(pos); int index = iterator.u16bitAt(pos + 1); if (c == INVOKEINTERFACE) cname = cp.getInterfaceMethodrefClassName(index); else cname = cp.getMethodrefClassName(index); return cname; } /** * Returns the name of the called method. */ public String getMethodName() { ConstPool cp = getConstPool(); int nt = getNameAndType(cp); return cp.getUtf8Info(cp.getNameAndTypeName(nt)); } /** * Returns the called method. */ public CtMethod getMethod() throws NotFoundException { return getCtClass().getMethod(getMethodName(), getMethodDesc()); } private String getMethodDesc() { ConstPool cp = getConstPool(); int nt = getNameAndType(cp); return cp.getUtf8Info(cp.getNameAndTypeDescriptor(nt)); } /** * Returns the list of exceptions that the expression may throw. * This list includes both the exceptions that the try-catch statements * including the expression can catch and the exceptions that * the throws declaration allows the method to throw. */ public CtClass[] mayThrow() { return super.mayThrow(); } /* * Returns the parameter types of the called method. public CtClass[] getParameterTypes() throws NotFoundException { return Descriptor.getParameterTypes(getMethodDesc(), thisClass.getClassPool()); } */ /* * Returns the return type of the called method. public CtClass getReturnType() throws NotFoundException { return Descriptor.getReturnType(getMethodDesc(), thisClass.getClassPool()); } */ /** * Replaces the method call with the bytecode derived from * the given source text. * * <p>$0 is available even if the called method is static. * * @param statement a Java statement. */ public void replace(String statement) throws CannotCompileException { ConstPool constPool = getConstPool(); int pos = currentPos; int index = iterator.u16bitAt(pos + 1); String classname, methodname, signature; int opcodeSize; int c = iterator.byteAt(pos); if (c == INVOKEINTERFACE) { opcodeSize = 5; classname = constPool.getInterfaceMethodrefClassName(index); methodname = constPool.getInterfaceMethodrefName(index); signature = constPool.getInterfaceMethodrefType(index); } else if (c == INVOKESTATIC || c == INVOKESPECIAL || c == INVOKEVIRTUAL) { opcodeSize = 3; classname = constPool.getMethodrefClassName(index); methodname = constPool.getMethodrefName(index); signature = constPool.getMethodrefType(index); } else throw new CannotCompileException("not method invocation"); Javac jc = new Javac(thisClass); ClassPool cp = thisClass.getClassPool(); CodeAttribute ca = iterator.get(); try { CtClass[] params = Descriptor.getParameterTypes(signature, cp); CtClass retType = Descriptor.getReturnType(signature, cp); int paramVar = ca.getMaxLocals(); jc.recordParams(classname, params, true, paramVar, withinStatic()); int retVar = jc.recordReturnType(retType, true); jc.recordProceed(Javac.param0Name, methodname); /* Is $_ included in the source code? */ checkResultValue(retType, statement); Bytecode bytecode = jc.getBytecode(); storeStack(params, c == INVOKESTATIC, paramVar, bytecode); jc.compileStmnt(statement); if (retType != CtClass.voidType) bytecode.addLoad(retVar, retType); replace0(pos, bytecode, opcodeSize); } catch (CompileError e) { throw new CannotCompileException(e); } catch (NotFoundException e) { throw new CannotCompileException(e); } catch (BadBytecode e) { throw new CannotCompileException("broken method"); } } } 1.1 thirdparty/javassist/javassist/src/src/javassist/expr/NewExpr.java Index: NewExpr.java =================================================================== /* * This file is part of the Javassist toolkit. * * 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. You may obtain a copy of the License at * either http://www.mozilla.org/MPL/. * * 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. * * The Original Code is Javassist. * * The Initial Developer of the Original Code is Shigeru Chiba. Portions * created by Shigeru Chiba are Copyright (C) 1999-2003 Shigeru Chiba. * All Rights Reserved. * * Contributor(s): * * The development of this software is supported in part by the PRESTO * program (Sakigake Kenkyu 21) of Japan Science and Technology Corporation. */ package javassist.expr; import javassist.*; import javassist.bytecode.*; import javassist.compiler.*; import javassist.compiler.ast.ASTree; import javassist.compiler.ast.ASTList; /** * Object creation (<tt>new</tt> expression). */ public class NewExpr extends Expr { String newTypeName; int newPos; /** * Undocumented constructor. Do not use; internal-use only. */ NewExpr(int pos, CodeIterator i, CtClass declaring, MethodInfo m, String type, int np) { super(pos, i, declaring, m); newTypeName = type; newPos = np; } private int getNameAndType(ConstPool cp) { String cname; int pos = currentPos; int c = iterator.byteAt(pos); int index = iterator.u16bitAt(pos + 1); if (c == INVOKEINTERFACE) return cp.getInterfaceMethodrefNameAndType(index); else return cp.getMethodrefNameAndType(index); } /** * Returns the method or constructor containing the <tt>new</tt> * expression represented by this object. */ public CtBehavior where() { return super.where(); } /** * Returns the line number of the source line containing the * <tt>new</tt> expression. * * @return -1 if this information is not available. */ public int getLineNumber() { return super.getLineNumber(); } /** * Returns the source file containing the <tt>new</tt> expression. * * @return null if this information is not available. */ public String getFileName() { return super.getFileName(); } /** * Returns the class of the created object. */ private CtClass getCtClass() throws NotFoundException { return thisClass.getClassPool().get(newTypeName); } /** * Returns the class name of the created object. */ public String getClassName() { return newTypeName; } /** * Returns the constructor called for creating the object. */ public CtConstructor getConstructor() throws NotFoundException { ConstPool cp = getConstPool(); int index = iterator.u16bitAt(currentPos + 1); String desc = cp.getMethodrefType(index); return getCtClass().getConstructor(desc); } /** * Returns the list of exceptions that the expression may throw. * This list includes both the exceptions that the try-catch statements * including the expression can catch and the exceptions that * the throws declaration allows the method to throw. */ public CtClass[] mayThrow() { return super.mayThrow(); } /* * Returns the parameter types of the constructor. public CtClass[] getParameterTypes() throws NotFoundException { ConstPool cp = getConstPool(); int index = iterator.u16bitAt(currentPos + 1); String desc = cp.getMethodrefType(index); return Descriptor.getParameterTypes(desc, thisClass.getClassPool()); } */ private int canReplace() throws CannotCompileException { int op = iterator.byteAt(newPos + 3); if (op == Opcode.DUP) return 4; else if (op == Opcode.DUP_X1 && iterator.byteAt(newPos + 4) == Opcode.SWAP) return 5; else throw new CannotCompileException( "sorry, cannot edit NEW followed by no DUP"); } /** * Replaces the <tt>new</tt> expression with the bytecode derived from * the given source text. * * <p>$0 is available but the value is null. * * @param statement a Java statement. */ public void replace(String statement) throws CannotCompileException { final int bytecodeSize = 3; int pos = newPos; int newIndex = iterator.u16bitAt(pos + 1); /* delete the preceding NEW and DUP (or DUP_X1, SWAP) instructions. */ int end = pos + canReplace(); for (int i = pos; i < end; ++i) iterator.writeByte(NOP, i); ConstPool constPool = getConstPool(); pos = currentPos; int methodIndex = iterator.u16bitAt(pos + 1); // constructor String signature = constPool.getMethodrefType(methodIndex); Javac jc = new Javac(thisClass); ClassPool cp = thisClass.getClassPool(); CodeAttribute ca = iterator.get(); try { CtClass[] params = Descriptor.getParameterTypes(signature, cp); CtClass newType = cp.get(newTypeName); int paramVar = ca.getMaxLocals(); jc.recordParams(newTypeName, params, true, paramVar, withinStatic()); int retVar = jc.recordReturnType(newType, true); jc.recordProceed(new ProceedForNew(newType, newIndex, methodIndex)); /* Is $_ included in the source code? */ checkResultValue(newType, statement); Bytecode bytecode = jc.getBytecode(); storeStack(params, true, paramVar, bytecode); jc.compileStmnt(statement); bytecode.addAload(retVar); replace0(pos, bytecode, bytecodeSize); } catch (CompileError e) { throw new CannotCompileException(e); } catch (NotFoundException e) { throw new CannotCompileException(e); } catch (BadBytecode e) { throw new CannotCompileException("broken method"); } } static class ProceedForNew implements ProceedHandler { CtClass newType; int newIndex, methodIndex; ProceedForNew(CtClass nt, int ni, int mi) { newType = nt; newIndex = ni; methodIndex = mi; } public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args) throws CompileError { bytecode.addOpcode(NEW); bytecode.addIndex(newIndex); bytecode.addOpcode(DUP); gen.atMethodCall2(newType, MethodInfo.nameInit, args, false, true); gen.setType(newType); } } } |