All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.feilong.lib.javassist.expr.NewExpr Maven / Gradle / Ivy

Go to download

feilong is a suite of core and expanded libraries that include utility classes, http, excel,cvs, io classes, and much much more.

There is a newer version: 4.3.0
Show newest version
/*
 * Javassist, a Java-bytecode translator toolkit.
 * Copyright (C) 1999- 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,
 * or the Apache License Version 2.0.
 *
 * 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 com.feilong.lib.javassist.expr;

import com.feilong.lib.javassist.CannotCompileException;
import com.feilong.lib.javassist.ClassPool;
import com.feilong.lib.javassist.CtBehavior;
import com.feilong.lib.javassist.CtClass;
import com.feilong.lib.javassist.CtConstructor;
import com.feilong.lib.javassist.NotFoundException;
import com.feilong.lib.javassist.bytecode.BadBytecode;
import com.feilong.lib.javassist.bytecode.Bytecode;
import com.feilong.lib.javassist.bytecode.CodeAttribute;
import com.feilong.lib.javassist.bytecode.CodeIterator;
import com.feilong.lib.javassist.bytecode.ConstPool;
import com.feilong.lib.javassist.bytecode.Descriptor;
import com.feilong.lib.javassist.bytecode.MethodInfo;
import com.feilong.lib.javassist.bytecode.Opcode;
import com.feilong.lib.javassist.compiler.CompileError;
import com.feilong.lib.javassist.compiler.Javac;
import com.feilong.lib.javassist.compiler.JvstCodeGen;
import com.feilong.lib.javassist.compiler.JvstTypeChecker;
import com.feilong.lib.javassist.compiler.ProceedHandler;
import com.feilong.lib.javassist.compiler.ast.ASTList;

/**
 * Object creation (new expression).
 */
public class NewExpr extends Expr{

    String newTypeName;

    int    newPos;

    /**
     * Undocumented constructor. Do not use; internal-use only.
     */
    protected NewExpr(int pos, CodeIterator i, CtClass declaring, MethodInfo m, String type, int np){
        super(pos, i, declaring, m);
        newTypeName = type;
        newPos = np;
    }

    /*
     * Not used
     * 
     * private int getNameAndType(ConstPool cp) {
     * 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 new
     * expression represented by this object.
     */
    @Override
    public CtBehavior where(){
        return super.where();
    }

    /**
     * Returns the line number of the source line containing the
     * new expression.
     *
     * @return -1 if this information is not available.
     */
    @Override
    public int getLineNumber(){
        return super.getLineNumber();
    }

    /**
     * Returns the source file containing the new expression.
     *
     * @return null if this information is not available.
     */
    @Override
    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;
    }

    /**
     * Get the signature of the constructor
     *
     * The signature is represented by a character string
     * called method descriptor, which is defined in the JVM specification.
     *
     * @see com.feilong.lib.javassist.CtBehavior#getSignature()
     * @see com.feilong.lib.javassist.bytecode.Descriptor
     * @return the signature
     */
    public String getSignature(){
        ConstPool constPool = getConstPool();
        int methodIndex = iterator.u16bitAt(currentPos + 1); // constructor
        return constPool.getMethodrefType(methodIndex);
    }

    /**
     * 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.
     */
    @Override
    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 ((iterator.byteAt(newPos + 4) == Opcode.DUP2_X2 && iterator.byteAt(newPos + 5) == Opcode.POP2)) ? 6 : 4;
        }else if (op == Opcode.DUP_X1 && iterator.byteAt(newPos + 4) == Opcode.SWAP){
            return 5;
        }else{
            return 3; // for Eclipse.  The generated code may include no DUP.
            // throw new CannotCompileException(
            //            "sorry, cannot edit NEW followed by no DUP");
        }
    }

    /**
     * Replaces the new expression with the bytecode derived from
     * the given source text.
     *
     * 

* $0 is available but the value is null. * * @param statement * a Java statement except try-catch. */ @Override public void replace(String statement) throws CannotCompileException{ thisClass.getClassFile(); // to call checkModify(). 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 codeSize = canReplace(); int end = pos + codeSize; 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.recordLocalVariables(ca, pos); bytecode.addConstZero(newType); bytecode.addStore(retVar, newType); // initialize $_ jc.compileStmnt(statement); if (codeSize > 3){ 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; } @Override public void doit(JvstCodeGen gen,Bytecode bytecode,ASTList args) throws CompileError{ bytecode.addOpcode(NEW); bytecode.addIndex(newIndex); bytecode.addOpcode(DUP); gen.atMethodCallCore(newType, MethodInfo.nameInit, args, false, true, -1, null); gen.setType(newType); } @Override public void setReturnType(JvstTypeChecker c,ASTList args) throws CompileError{ c.atMethodCallCore(newType, MethodInfo.nameInit, args); c.setType(newType); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy