⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 methodbuilder.java

📁 对xml很好的java处理引擎,编译中绑定xml
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/*Copyright (c) 2003-2005, Dennis M. SosnoskiAll rights reserved.Redistribution and use in source and binary forms, with or without modification,are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this   list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice,   this list of conditions and the following disclaimer in the documentation   and/or other materials provided with the distribution. * Neither the name of JiBX nor the names of its contributors may be used   to endorse or promote products derived from this software without specific   prior written permission.THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ANDANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIEDWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FORANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ONANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THISSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/package org.jibx.binding.classes;import java.util.ArrayList;import java.util.HashMap;import org.apache.bcel.Constants;import org.apache.bcel.classfile.Method;import org.apache.bcel.classfile.Utility;import org.apache.bcel.generic.ANEWARRAY;import org.apache.bcel.generic.BranchHandle;import org.apache.bcel.generic.CompoundInstruction;import org.apache.bcel.generic.GOTO;import org.apache.bcel.generic.IFEQ;import org.apache.bcel.generic.IFGE;import org.apache.bcel.generic.IFLT;import org.apache.bcel.generic.IFNE;import org.apache.bcel.generic.IFNONNULL;import org.apache.bcel.generic.IFNULL;import org.apache.bcel.generic.IF_ICMPNE;import org.apache.bcel.generic.IINC;import org.apache.bcel.generic.Instruction;import org.apache.bcel.generic.InstructionConstants;import org.apache.bcel.generic.InstructionFactory;import org.apache.bcel.generic.InstructionHandle;import org.apache.bcel.generic.InstructionList;import org.apache.bcel.generic.LocalVariableGen;import org.apache.bcel.generic.MULTIANEWARRAY;import org.apache.bcel.generic.MethodGen;import org.apache.bcel.generic.NEWARRAY;import org.apache.bcel.generic.ReferenceType;import org.apache.bcel.generic.Type;import org.jibx.binding.util.StringStack;import org.jibx.runtime.JiBXException;/** * Method builder. Organizes and tracks the creation of a method, providing * convenience methods for common operations. This is customized for the needs * of JiBX, with some predetermined settings as appropriate. It supplies hash * code and equality checking based on the method signature and actual byte * code of the generated method, ignoring the method name. * * @author Dennis M. Sosnoski * @version 1.0 */public abstract class MethodBuilder extends BindingMethod{    //    // Constants for code generation.        public static final String FRAMEWORK_EXCEPTION_CLASS =        "org.jibx.runtime.JiBXException";        public static final String EXCEPTION_CONSTRUCTOR_SIGNATURE1 =        "(Ljava/lang/String;)V";        public static final String EXCEPTION_CONSTRUCTOR_SIGNATURE2 =        "(Ljava/lang/String;Ljava/lang/Throwable;)V";        public static final int SYNTHETIC_ACCESS_FLAG = 0x1000;        //    // Static data.        /** Table of argument name lists (generated as needed). */    protected static ArrayList s_argNameLists = new ArrayList();        /** Zero-length string array. */    protected static String[] EMPTY_STRING_ARRAY = new String[0];        //    // Actual instance data        /** Builder for class instructions. */    protected InstructionBuilder m_instructionBuilder;        /** List of instructions in method definition. */    private InstructionList m_instructionList;        /** List of types currently on stack. */    private StringStack m_stackState;        /** Generator for constructing method. */    protected MethodGen m_generator;        /** Actual generated method information. */    protected Method m_method;        /** Method class item information. */    protected ClassItem m_item;        /** Value types associated with local variable slots. */    private ArrayList m_localTypes;        /** Exceptions needing to be handled in method (lazy create,     <code>null</code> if not used). */    protected ArrayList m_exceptions;        /** Accumulated hash code from adding instructions. */    protected int m_hashCode;        /** Branch to be aimed at next appended instruction. */    protected BranchWrapper[] m_targetBranches;        /** Map for initialized properties (lazy create, <code>null</code> if not     used). */    protected HashMap m_valueMap;    /**     * Constructor. This sets up for constructing a method with public access.     *     * @param name method name to be built     * @param ret method return type     * @param args types of arguments     * @param cf owning class file information     * @param access flags for method access     * @throws JiBXException on error in constructing method     */    protected MethodBuilder(String name, Type ret, Type[] args,        ClassFile cf, int access) throws JiBXException {        super(cf);                // make sure the dummy argument names are defined        if (args.length >= s_argNameLists.size()) {                        // append to end of argument names list            for (int i = s_argNameLists.size(); i <= args.length; i++) {                String[] list = new String[i];                if (i > 0) {                    Object last = s_argNameLists.get(i-1);                    System.arraycopy(last, 0, list, 0, i-1);                    list[i-1] = "arg" + i;                }                s_argNameLists.add(list);            }                    }                // create the method generator with empty instruction list        String[] names = (String[])s_argNameLists.get(args.length);        m_instructionList = new InstructionList();        m_stackState = new StringStack();        m_instructionBuilder = cf.getInstructionBuilder();        m_generator = new MethodGen(access | SYNTHETIC_ACCESS_FLAG, ret, args,            names, name, cf.getName(), m_instructionList, cf.getConstPoolGen());                // initialize local variables for method parameters        m_localTypes = new ArrayList();        if ((access & Constants.ACC_STATIC) == 0) {            m_localTypes.add(cf.getName());        }        for (int i = 0; i < args.length; i++) {            m_localTypes.add(args[i].toString());            if (args[i].getSize() > 1) {                m_localTypes.add(null);            }        }    }    /**     * Get name of method being constructed.     *     * @return name of method being constructed     */    public String getName() {        return m_generator.getName();    }        /**     * Get signature.     *     * @return signature for method     */    public String getSignature() {        return m_generator.getSignature();    }        /**     * Get access flags.     *     * @return flags for access type of method     */    public int getAccessFlags() {        return m_generator.getAccessFlags();    }        /**     * Set access flags.     *     * @param flags access type to be set     */    public void setAccessFlags(int flags) {        m_generator.setAccessFlags(flags);    }        /**     * Get the actual method. This can only be called once code generation is     * completed (after the {@link #codeComplete(boolean)} method is called).     *     * @return constructed method information     */    public Method getMethod() {        if (m_method == null) {            throw new IllegalStateException("Method still under construction");        } else {            return m_method;        }    }        /**     * Add keyed value to method definition.     *     * @param key retrieval key     * @param value keyed value     * @return prior value for key     */    public Object setKeyValue(Object key, Object value) {        if (m_valueMap == null) {            m_valueMap = new HashMap();        }        return m_valueMap.put(key, value);    }        /**     * Get local variable for object.     *      * @param key object key for local variable     * @return local variable     */    public Object getKeyValue(Object key) {        return m_valueMap == null ? null : m_valueMap.get(key);    }    /**     * Add exception to those needing handling.     *     * @param name fully qualified name of exception class     */    public void addException(String name) {        if (m_exceptions == null) {            m_exceptions = new ArrayList();        }        if (!m_exceptions.contains(name)) {            m_exceptions.add(name);        }    }    /**     * Add exceptions thrown by called method to those needing handling.     *     * @param method information for method to be handled     */    public void addMethodExceptions(ClassItem method) {        String[] excepts = method.getExceptions();        if (excepts != null) {            for (int i = 0; i < excepts.length; i++) {                addException(excepts[i]);            }        }    }    /**     * Get first instruction in method.     *     * @return handle for first instruction in method     */    protected InstructionHandle getFirstInstruction() {        return m_instructionList.getStart();    }    /**     * Get last instruction in method.     *     * @return handle for last instruction in method     */    protected InstructionHandle getLastInstruction() {        return m_instructionList.getEnd();    }    /**     * Target branches if pending. This implements setting the target of     * branch instructions supplied using the {@link #targetNext} method.     *     * @param inst handle for appended instruction     */    protected final void setTarget(InstructionHandle inst) {        if (m_targetBranches != null) {                        // TODO: fix this ugly kludge with code rewrite            // adjust stack with POPs if need to match size            String[] types = m_stackState.toArray();            if (m_targetBranches.length > 0) {                boolean match = true;                int depth = m_targetBranches[0].getStackState().length;                for (int i = 1; i < m_targetBranches.length; i++) {                    if (depth != m_targetBranches[i].getStackState().length) {                        match = false;                        break;                    }                }                if (match) {                    if (depth > types.length) {                        BranchWrapper merge = new BranchWrapper                            (m_instructionList.insert(inst, new GOTO(null)),                            types, this);                        String[] stack = m_targetBranches[0].getStackState();                        m_stackState = new StringStack(stack);                        InstructionHandle poph = m_instructionList.                            insert(inst, InstructionConstants.POP);                        for (int i = 0; i < m_targetBranches.length; i++) {                            m_targetBranches[i].setTarget(poph, stack, this);                        }                        m_stackState.pop();                        while (m_stackState.size() > types.length) {                            m_instructionList.insert(inst,                                InstructionConstants.POP);                            m_stackState.pop();                        }                        merge.setTarget(inst, m_stackState.toArray(), this);                        m_targetBranches = null;                        return;                    } else {                        while (depth < types.length) {                            m_instructionList.insert(inst,                                InstructionConstants.POP);                            m_stackState.pop();                            types = m_stackState.toArray();                        }                    }                }            }                        // set all branch targets            for (int i = 0; i < m_targetBranches.length; i++) {                m_targetBranches[i].setTarget(inst, types, this);            }            m_targetBranches = null;        }    }        /**     * Generate description of current stack state.     *     * @return stack state description     */    private String describeStack() {        StringBuffer buff = new StringBuffer();        String[] types = m_stackState.toArray();        for (int i = 0; i < types.length; i++) {            buff.append("  ");            buff.append(i);            buff.append(": ");            buff.append(types[i]);            buff.append('\n');        }        return buff.toString();    }    /**     * Verify that a pair of value types represent compatible types. This checks     * for equal types or downcast object types.     *     * @param type actual known type of value     * @param need type needed     */    private void verifyCompatible(String type, String need) {        if (!need.equals(type)) {            try {                if ("<null>".equals(type)) {                    if (ClassItem.isPrimitive(need)) {                        throw new IllegalStateException                            ("Internal error: Expected " + need +                            " on stack , found null");                    }                } else if ("java.lang.Object".equals(need)) {                    if (ClassItem.isPrimitive(type)) {                        throw new IllegalStateException("Internal error: " +                            "Expected object reference on stack, found " +                            type + "\n full stack:\n" + describeStack());                    }                } else {                    boolean match = false;                    if ("int".equals(need)) {                        match = "boolean".equals(type) ||                            "short".equals(type) || "char".equals(type) ||                            "byte".equals(type);                    } else if ("int".equals(type)) {                        match = "boolean".equals(need) ||                            "short".equals(need) || "char".equals(need) ||                            "byte".equals(need);                    }                    if (!match && !ClassItem.isAssignable(type, need)) {                        throw new IllegalStateException                            ("Internal error: Expected " + need +                            " on stack, found " + type + "\n full stack:\n" +                            describeStack());                    }                }            } catch (JiBXException e) {                throw new RuntimeException                    ("Internal error: Attempting to compare types " + need +                    " and " + type);            }        }    }    /**     * Verify that at least the specified number of items are present on the     * stack.     *     * @param count minimum number of items required     */    private void verifyStackDepth(int count) {        if (m_stackState.size() < count) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -