alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 *
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2001 Sun
 * Microsystems, Inc. All Rights Reserved.
 */
package org.netbeans.mdr.handlers.gen;

import org.netbeans.lib.jmi.util.ClassFileGenerator;
import org.netbeans.mdr.storagemodel.*;
import org.netbeans.mdr.util.DebugException;
import org.netbeans.mdr.util.Logger;
import org.netbeans.mdr.util.MOFConstants;
import javax.jmi.model.MultiplicityType;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;

/**
 * Abstract base class for handler generators.
 * @author	Martin Matula, Dusan Balek
 * @version	0.1
 */
public abstract class HandlerGenerator extends ClassFileGenerator {

    /* -------------------------------------------------------------------- */
    /* -- Private static constants ---------------------------------------- */
    /* -------------------------------------------------------------------- */
    
    private static final String PRE_TYPE = "Ljava/lang/Object;"; //NOI18N
    private static final String POST_DESCRIPTOR = "Ljava/lang/Object;Z)V"; //NOI18N
    private static final String POST_VOID_DESCRIPTOR = "(Ljava/lang/Object;Z)V"; //NOI18N
    
    /* -------------------------------------------------------------------- */
    /* -- Protected static constants ---------------------------------------- */
    /* -------------------------------------------------------------------- */

    protected static final String DT_MULTIVALUED = "java.util.Collection"; //NOI18N
    protected static final String DT_ORDERED = "java.util.List"; //NOI18N
    protected static final String PRE_PREFIX = "_pre"; //NOI18N
    protected static final String POST_PREFIX = "_post"; //NOI18N
    protected static final String HANDLE_PREFIX = "_handle"; //NOI18N
    protected static final String CUSTOM_PREFIX = "super_"; //NOI18N
    
    /* -------------------------------------------------------------------- */
    /* -- Static methods (public) ----------------------------------------- */
    /* -------------------------------------------------------------------- */

    /**
     * Generate a handler class given a name, interface and storable object to
     * be wrapped by a handler object.
     */
    public static byte[] generateHandler(final String name, Class ifc, StorableBaseObject storable) {
        HandlerGenerator gen;
        try {
            if (storable instanceof StorableAssociation) {
                gen = new AssociationGenerator(name, ifc, ((StorableAssociation)storable).getAssociationSuperclass(), (StorableAssociation)storable, ((StorableAssociation)storable).getAssociationCustomImpl());
            } else if (storable instanceof StorableClass) {
                gen = new ClassGenerator(name, ifc, ((StorableClass) storable).getClassSuperclass(), (StorableClass)storable, ((StorableClass) storable).getClassCustomImpl());
            } else if (storable instanceof StorablePackage) {
                gen = new PackageGenerator(name, ifc, ((StorablePackage) storable).getPackageSuperclass(), (StorablePackage)storable, ((StorablePackage) storable).getPackageCustomImpl());
            } else if (storable instanceof StorableObject) {
                gen = new InstanceGenerator(name, ifc, ((StorableObject) storable).getClassProxy().getInstanceSuperclass(), (StorableObject)storable, ((StorableObject) storable).getClassProxy().getInstanceCustomImpl());
            } else {
                throw new InternalError("Unknow dispatcher type."); //NOI18N
            }
        } catch (Exception e) {
            throw (DebugException) Logger.getDefault().annotate(new DebugException(), e);
        }
        
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        gen.generateClassFile(bout);
        return bout.toByteArray();
    }
    
    public static boolean customImplContainsMethod(Class customImpl, String name, String descriptor) {
        if (customImpl == null)
            return false;
        synchronized (customImplInfos) {
            HashSet methods = (HashSet)customImplInfos.get(customImpl);
            if (methods == null) {
                methods = new HashSet();
                Method[] m = customImpl.getMethods();
                for (int i = 0; i < m.length; i++) {
                    if (Modifier.isAbstract(m[i].getModifiers()))
                        continue;
                    ArrayList params = new ArrayList();
                    Class[] p = m[i].getParameterTypes();
                    for(int j = 0; j < p.length; j++)
                        params.add(p[j].getName());
                    methods.add(m[i].getName() + getMethodDescriptor((String [])params.toArray(new String[params.size()]), m[i].getReturnType().getName()));
                }
                customImplInfos.put(customImpl, methods);
            }
            return methods.contains(name + descriptor);
        }
    }

    /* -------------------------------------------------------------------- */
    /* -- Static attributes ----------------------------------------------- */
    /* -------------------------------------------------------------------- */

    private static Map customImplInfos = new LinkedHashMap(10, .5f, true) {
        private static final int MAX_SIZE = 5;
        
        protected boolean removeEldestEntry(Map.Entry entry) {
            return size() > MAX_SIZE;
        }
    };

    /* -------------------------------------------------------------------- */
    /* -- Attributes ------------------------------------------------------ */
    /* -------------------------------------------------------------------- */

    protected final StorableBaseObject obj;
    protected final Class customImpl;
    protected final HashMap dispatchMethods = new HashMap();
    
    /* -------------------------------------------------------------------- */
    /* -- Constructor ----------------------------------------------------- */
    /* -------------------------------------------------------------------- */

    /**
     * Construct a HandlerGenerator to generate a handler class with the
     * specified name and for the given interfaces.
     */
    protected HandlerGenerator(String className, Class ifc, Class handler, StorableBaseObject storable, Class custom) {
        super(className, new String[] {ifc.getName()}, handler.getName(), ACC_PUBLIC | ACC_FINAL | ACC_SUPER);
        obj = storable;
        customImpl = custom;
    }
    

    
    protected FieldInfo[] generateFields() throws IOException {
        return new FieldInfo[0];
    }

    /**
     * Generate the constructor method for the proxy class.
     */
    protected MethodInfo generateConstructor() throws IOException {
        MethodInfo minfo = new MethodInfo(
        "", getConstructorDescriptor(), //NOI18N
        ACC_PUBLIC);
        
        DataOutputStream out = new DataOutputStream(minfo.getCodeStream());
        
        code_aload(0, out);
        code_aload(1, out);
        
        // just call super.(String);
        out.writeByte(opc_invokespecial);
        out.writeShort(cp.getMethodRef(dotToSlash(superclassName), "", getConstructorDescriptor())); //NOI18N
        
        out.writeByte(opc_return);
        
        minfo.setMaxStack((short)2);
        minfo.setMaxLocals((short)2);
        return minfo;
    }
    
    protected abstract String getConstructorDescriptor();
    
    protected short getHandlerIndex(String methodName, String methodDescriptor, String methodType) {
        return cp.getMethodRef(dotToSlash(superclassName), HANDLE_PREFIX + methodName, methodDescriptor + methodType);
    }
    
    protected short getPreIndex(String methodName, String methodDescriptor) {
        return cp.getMethodRef(dotToSlash(superclassName), PRE_PREFIX + methodName, methodDescriptor + PRE_TYPE);
    }
    
    protected short getPostIndex(String methodName, String methodType) {
        return cp.getMethodRef(dotToSlash(superclassName), POST_PREFIX + methodName, (methodType.equals("V") ? POST_VOID_DESCRIPTOR : ("(" + methodType + POST_DESCRIPTOR))); //NOI18N
    }
    
    protected Collection getHandlerMethod(String methodName, String[] parameterTypes, String returnType, String handlerName, String handlerDescriptor, String handlerType, String featureName) throws IOException {
        short delegateMethod = getHandlerIndex(handlerName, handlerDescriptor, handlerType);
        short preMethod = getPreIndex(handlerName, handlerDescriptor);
        short postMethod = getPostIndex(handlerName, handlerType);
        String methodDescriptor = getMethodDescriptor(parameterTypes, returnType);
        boolean isCustom = customImplContainsMethod(customImpl, methodName, methodDescriptor);

        int[] parameterSlot = new int[parameterTypes.length];
        int nextSlot = 1;
        for (int i = 0; i < parameterSlot.length; i++) {
            parameterSlot[i] = nextSlot;
            nextSlot += getWordsPerType(parameterTypes[i]);
        }
        int localSlot0 = nextSlot;
        
        short fail = (short) localSlot0;
        short extraInfo = (short) (localSlot0 + 1);
        short result = (short) (localSlot0 + 2);
        short addr = (short) (localSlot0 + 3);
        short exception = (short) (localSlot0 + 4);
        short customResult = (short) (localSlot0 + 5);
        
        MethodInfo minfo = new MethodInfo(methodName, methodDescriptor, ACC_PUBLIC | ACC_FINAL);
        DataOutputStream out = new DataOutputStream(minfo.getCodeStream());
        MethodInfo cminfo = null;
        DataOutputStream cout = null;
        if (isCustom) {
            cminfo = new MethodInfo(CUSTOM_PREFIX + methodName, methodDescriptor, ACC_PUBLIC | ACC_FINAL);
            cout = new DataOutputStream(cminfo.getCodeStream());
        }
        
        // store "true" in the fail variable
        out.writeByte(opc_iconst_1);
        code_istore(fail, out);
        // store "null" in the extraInfo variable
        out.writeByte(opc_aconst_null);
        out.writeByte(opc_dup);
        code_astore(extraInfo, out);
        // store "null" in result variable
        code_astore(result, out);

        // I'll pass this instance as the first parameter
        code_aload(0, out);
        
        if (featureName != null)
            // feature name as the second parameter
            code_ldc(cp.getString(featureName), out);
        
        // The rest of parameters follows
        for (int i = 0; i < parameterTypes.length; i++) {
            codeWrapArgument(parameterTypes[i], parameterSlot[i], out);
        }
        
        // call the _pre method
        out.writeByte(opc_invokespecial);
        out.writeShort(preMethod);

        // start of the try block
        short tryStart = (short) out.size();

        // store the returned object in a local variable
        code_astore(extraInfo, out);
        
        if (isCustom) {
            // I'll pass this instance as the first parameter
            code_aload(0, out);

            // The rest of parameters follows
            for (int i = 0; i < parameterTypes.length; i++) {
                codeLoad(parameterSlot[i], parameterTypes[i], out);
            }

            // call the custom method
            out.writeByte(opc_invokespecial);
            out.writeShort(cp.getMethodRef(dotToSlash(superclassName), methodName, methodDescriptor));

            if (!returnType.equals("void")) { //NOI18N
                if (PrimitiveTypeInfo.get(returnType) == null)
                    code_astore(result, out);
                else {
                    codeStore(customResult, returnType, out);
                    codeWrapArgument(returnType, customResult, out);
                    code_astore(result, out);
                }
            }
            
            // I'll pass this instance as the first parameter
            code_aload(0, cout);

            if (featureName != null)
                // feature name as the second parameter
                code_ldc(cp.getString(featureName), cout);

            // The rest of parameters follows
            for (int i = 0; i < parameterTypes.length; i++) {
                codeWrapArgument(parameterTypes[i], parameterSlot[i], cout);
            }

            // call the delegate method
            cout.writeByte(opc_invokespecial);
            cout.writeShort(delegateMethod);

            if (returnType.equals("void")) //NOI18N
                cout.writeByte(opc_return);
            else
                codeUnwrapReturnValue(returnType, cout);
        }
        else {
            // I'll pass this instance as the first parameter
            code_aload(0, out);

            if (featureName != null)
                // feature name as the second parameter
                code_ldc(cp.getString(featureName), out);

            // The rest of parameters follows
            for (int i = 0; i < parameterTypes.length; i++) {
                codeWrapArgument(parameterTypes[i], parameterSlot[i], out);
            }

            // call the delegate method
            out.writeByte(opc_invokespecial);
            out.writeShort(delegateMethod);

            if (!returnType.equals("void")) { //NOI18N
                code_astore(result, out);
            }
        }        
        // change value of fail to "false"
        out.writeByte(opc_iconst_0);
        code_istore(fail, out);
        
        // call the finally block and return
        out.writeByte(opc_jsr);
        if (returnType.equals("void")) { //NOI18N
            out.writeShort(3 + 1 + 2*getBytesForLoadOrStore(exception) + 4);
            out.writeByte(opc_return);
        } else {
            if (isCustom) {
                if (PrimitiveTypeInfo.get(returnType) != null) {
                    out.writeShort(3 + getBytesForLoadOrStore(customResult) + 1 + 2*getBytesForLoadOrStore(exception) + 4);
                    codeLoad(customResult, returnType, out);
                    if (returnType.equals("int") || returnType.equals("boolean") || returnType.equals("byte") || returnType.equals("char") || returnType.equals("short")) //NOI18N
                        out.writeByte(opc_ireturn);
                    else if (returnType.equals("long")) //NOI18N
                        out.writeByte(opc_lreturn);
                    else if (returnType.equals("float")) //NOI18N
                        out.writeByte(opc_freturn);
                    else if (returnType.equals("double")) //NOI18N
                        out.writeByte(opc_dreturn);
                    else
                        _assert(false);
                } else {
                    out.writeShort(3 + getBytesForLoadOrStore(result) + 1 + 2*getBytesForLoadOrStore(exception) + 4);
                    code_aload(result, out);
                    out.writeByte(opc_areturn);
                }
            }
            else {
                out.writeShort(3 + getBytesForLoadOrStore(result) + getBytesForUnwrapReturn(returnType) + 2*getBytesForLoadOrStore(exception) + 4);
                // load the returned value
                code_aload(result, out);
                // convert it to the result type
                codeUnwrapReturnValue(returnType, out);
            }
        }
        // start of catch block
        short catchStart = (short) out.size();
        
        // store exception
        code_astore(exception, out);
        
        // call finally
        out.writeByte(opc_jsr);
        out.writeShort(3 + getBytesForLoadOrStore(exception) + 1);
        
        // load exception
        code_aload(exception, out);
        
        // rethrow exception
        out.writeByte(opc_athrow);
        
        // start of finally block
        // store the return address
        code_astore(addr, out);
        
        // load parameters
        code_aload(0, out);
        if (!returnType.equals("void")) { //NOI18N
            code_aload(result, out);
        }
        code_aload(extraInfo, out);
        code_iload(fail, out);
        
        // call the _post method
        out.writeByte(opc_invokespecial);
        out.writeShort(postMethod);
        
        // return from finally
        out.writeByte(opc_ret);
        out.writeByte(addr);
        
        minfo.getExceptionTable().add(new ExceptionTableEntry(tryStart, catchStart, catchStart, (short) 0));
        
        minfo.setMaxStack((short)15);
        minfo.setMaxLocals((short)(localSlot0 + 6));
        
        if (isCustom) {
            cminfo.setMaxStack((short)15);
            cminfo.setMaxLocals((short)(localSlot0 + 5));
        }            
        
        ArrayList ret = new ArrayList();
        ret.add(minfo);
        if (isCustom)
            ret.add(cminfo);
        return ret;
    }
    
    protected MethodInfo getDerivedMethod(String methodName, String[] parameterTypes, String returnType) throws IOException {
        String desc = getMethodDescriptor(parameterTypes, returnType);
        MethodInfo minfo = new MethodInfo(methodName, desc, ACC_PUBLIC | ACC_FINAL);
        int[] parameterSlot = new int[parameterTypes.length];
        int nextSlot = 1;
        for (int i = 0; i < parameterSlot.length; i++) {
            parameterSlot[i] = nextSlot;
            nextSlot += getWordsPerType(parameterTypes[i]);
        }
        int localSlot0 = nextSlot;
        
        DataOutputStream out = new DataOutputStream(minfo.getCodeStream());
        
        // I'll pass this instance as the first parameter
        code_aload(0, out);
        
        // Load the rest of parameters
        for (int i = 0; i < parameterTypes.length; i++) {
            codeLoad(parameterSlot[i], parameterTypes[i], out);
        }
        
        // call the delegate method
        out.writeByte(opc_invokespecial);
        out.writeShort(cp.getMethodRef(dotToSlash(superclassName), methodName, desc));
        
        if (returnType.equals("void")) //NOI18N
            out.writeByte(opc_return);
        else if (PrimitiveTypeInfo.get(returnType) != null) {
            if (returnType.equals("int") || returnType.equals("boolean") || returnType.equals("byte") || returnType.equals("char") || returnType.equals("short")) //NOI18N
                out.writeByte(opc_ireturn);
            else if (returnType.equals("long")) //NOI18N
                out.writeByte(opc_lreturn);
            else if (returnType.equals("float")) //NOI18N
                out.writeByte(opc_freturn);
            else if (returnType.equals("double")) //NOI18N
                out.writeByte(opc_dreturn);
            else
                _assert(false);
        } else
            out.writeByte(opc_areturn);
        
        minfo.setMaxStack((short)10);
        minfo.setMaxLocals((short)(localSlot0 + 2));
        
        return minfo;
    }
    
    protected void codeStore(int index, String type, DataOutputStream out) throws IOException {
        if (type.equals("int") || type.equals("boolean") || type.equals("byte") || type.equals("char") || type.equals("short")) //NOI18N
            code_istore(index, out);
        else if (type.equals("long")) //NOI18N
            code_lstore(index, out);
        else if (type.equals("float")) //NOI18N
            code_fstore(index, out);
        else if (type.equals("double")) //NOI18N
            code_dstore(index, out);
        else
            code_astore(index, out);
    }
    
    protected void codeLoad(int index, String type, DataOutputStream out) throws IOException {
        if (type.equals("int") || type.equals("boolean") || type.equals("byte") || type.equals("char") || type.equals("short")) //NOI18N
            code_iload(index, out);
        else if (type.equals("long")) //NOI18N
            code_lload(index, out);
        else if (type.equals("float")) //NOI18N
            code_fload(index, out);
        else if (type.equals("double")) //NOI18N
            code_dload(index, out);
        else
            code_aload(index, out);
    }
    
    protected int getBytesForLoadOrStore(int idx) {
        if (idx <= 3)
            return 1;
        if (idx <= 0xFF)
            return 2;
        return 4;
    }
    
    protected void codeWrapArgument(String typeName, int slot, DataOutputStream out) throws IOException {
        PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(typeName);
        if (prim != null) {
            out.writeByte(opc_new);
            out.writeShort(cp.getClass(prim.wrapperClassName));
            
            out.writeByte(opc_dup);
            
            if (typeName.equals("int") || typeName.equals("boolean") || typeName.equals("byte") || typeName.equals("char") || typeName.equals("short")) { //NOI18N
                code_iload(slot, out);
            } else if (typeName.equals("long")) { //NOI18N
                code_lload(slot, out);
            } else if (typeName.equals("float")) { //NOI18N
                code_fload(slot, out);
            } else if (typeName.equals("double")) { //NOI18N
                code_dload(slot, out);
            } else {
                _assert(false);
            }
            
            out.writeByte(opc_invokespecial);
            out.writeShort(cp.getMethodRef(prim.wrapperClassName, "", prim.wrapperConstructorDesc)); //NOI18N
        } else {
            code_aload(slot, out);
        }
    }
    
    protected void codeUnwrapReturnValue(String typeName, DataOutputStream out) throws IOException {
        PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(typeName);
        if (prim != null) {
            out.writeByte(opc_dup);
            out.writeByte(opc_ifnull);
            out.writeShort(10);
            
            out.writeByte(opc_checkcast);
            out.writeShort(cp.getClass(prim.wrapperClassName));
            
            out.writeByte(opc_invokevirtual);
            out.writeShort(cp.getMethodRef(prim.wrapperClassName, prim.unwrapMethodName, prim.unwrapMethodDesc));
            
            if (typeName.equals("int") || typeName.equals("boolean") || typeName.equals("byte") || typeName.equals("char") || typeName.equals("short")) { //NOI18N
                out.writeByte(opc_ireturn);
                out.writeByte(opc_iconst_0);
                out.writeByte(opc_ireturn);
            } else if (typeName.equals("long")) { //NOI18N
                out.writeByte(opc_lreturn);
                out.writeByte(opc_lconst_0);
                out.writeByte(opc_lreturn);
            } else if (typeName.equals("float")) { //NOI18N
                out.writeByte(opc_freturn);
                out.writeByte(opc_fconst_0);
                out.writeByte(opc_freturn);
            } else if (typeName.equals("double")) { //NOI18N
                out.writeByte(opc_dreturn);
                out.writeByte(opc_dconst_0);
                out.writeByte(opc_dreturn);
            } else {
                _assert(false);
            }
            
        } else {
            out.writeByte(opc_checkcast);
            out.writeShort(cp.getClass(dotToSlash(typeName)));
            
            out.writeByte(opc_areturn);
        }
    }
    
    protected int getBytesForUnwrapReturn(String typeName) {
        if (PrimitiveTypeInfo.get(typeName) != null) {
            return 13;
        } else {
            return 4;
        }
    }
    
    protected StorableObject getAttrType(StorableObject attr) {
        try {
            StorableObject curType = (StorableObject) attr.getReference(MOFConstants.SH_MODEL_TYPED_ELEMENT_TYPE);
            String typeName = (String) curType.getMetaObject().getAttribute(MOFConstants.SH_MODEL_MODEL_ELEMENT_NAME);
            if (typeName.equals(MOFConstants.SH_MODEL_ALIAS_TYPE))
                curType = getAttrType(curType);
            return curType;
        } catch (Exception e) {
            throw (DebugException) Logger.getDefault().annotate(new DebugException(), e);
        }
    }
    
    // returns correct type name for attribute (depending on the multiplicity type)
    protected String getAttrTypeName(StorableObject attr) {
        try {
            MultiplicityType mp = (MultiplicityType) attr.getAttribute(MOFConstants.SH_MODEL_STRUCTURAL_FEATURE_MULTIPLICITY);
            
            if (mp.getUpper() > 1 || mp.getUpper() == -1) {
                return (mp.isOrdered() ? DT_ORDERED : DT_MULTIVALUED);
            } else if (mp.getLower() < 1) {
                return TagSupport.getDataTypeName(getAttrType(attr));
            } else {
                return getTypeName2(attr);
            }
        } catch (Exception e) {
            throw (DebugException) Logger.getDefault().annotate(new DebugException(), e);
        }
    }
    
    protected String getTypeName2(StorableObject te) {
        return getPrimitiveName(TagSupport.getDataTypeName(getAttrType(te)));
    }
    
    // converts object type name to primitive type name
    protected String getPrimitiveName(String typeName) {
        String name = (String) objectToPrimitive.get(typeName);
        return name == null ? typeName : name;
    }
    
    // conversion table between object type names and primitive type names
    protected static final HashMap objectToPrimitive = new HashMap(7);
    static {
        objectToPrimitive.put("java.lang.Short", "short"); //NOI18N
        objectToPrimitive.put("java.lang.Integer", "int"); //NOI18N
        objectToPrimitive.put("java.lang.Float", "float"); //NOI18N
        objectToPrimitive.put("java.lang.Double", "double"); //NOI18N
        objectToPrimitive.put("java.lang.Boolean", "boolean"); //NOI18N
        objectToPrimitive.put("java.lang.Character", "char"); //NOI18N
        objectToPrimitive.put("java.lang.Long", "long"); //NOI18N
    }

    protected MethodInfo getDispatcherMethod(String methodName, String[] parameterTypes, String returnType, HashMap features) throws IOException {
        String desc = getMethodDescriptor(parameterTypes, returnType);
        MethodInfo minfo = new MethodInfo(methodName, desc, ACC_PUBLIC | ACC_FINAL);
        int[] parameterSlot = new int[parameterTypes.length];
        int nextSlot = 1;
        for (int i = 0; i < parameterSlot.length; i++) {
            parameterSlot[i] = nextSlot;
            nextSlot += getWordsPerType(parameterTypes[i]);
        }
        int localSlot0 = nextSlot;
        int maxStack = 0;
        
        DataOutputStream out = new DataOutputStream(minfo.getCodeStream());
        
        for (Iterator it = features.keySet().iterator(); it.hasNext();) {
            String featureName = (String) it.next();
            MethodDescHolder item = (MethodDescHolder) features.get(featureName);
            
            // load name of feature
            code_ldc(cp.getString(featureName), out);
            
            //compare it with passed name
            code_aload(1, out);
            out.writeByte(opc_invokevirtual);
            out.writeShort(cp.getMethodRef("java/lang/String", "equals", "(Ljava/lang/Object;)Z")); //NOI18N
            
            // if it is not equal, continue processing
            out.writeByte(opc_ifeq);
            out.writeShort(7 + getBytesForArgUnwrap(methodName, item.getParameterTypes()) + getBytesForReturn(methodName, item.getReturnType()) + getBytesForPreReturn(item.getReturnType()));
            // if it is equal, return result of a proper method
            codePreReturn(item.getReturnType(), out);
            out.writeByte(opc_aload_0);
            codeUnwrapArguments(methodName, item.getParameterTypes(), out);
            out.writeByte(opc_invokevirtual);
            out.writeShort(cp.getMethodRef(dotToSlash(className), item.getName(), getMethodDescriptor(item.getParameterTypes(), item.getReturnType())));
            codeReturn(methodName, item.getReturnType(), out);
            if (item.getParameterTypes().length > maxStack)
                maxStack = item.getParameterTypes().length;
        }
        short tryStop = (short) out.size();
        
        // if the field was not found, throw an exception
        out.writeByte(opc_new);            // new
        out.writeShort(cp.getClass("javax/jmi/reflect/InvalidNameException"));     //NOI18N
        out.writeByte(opc_dup);            // dup
        code_aload(1, out);
        out.writeByte(opc_invokespecial);
        out.writeShort(cp.getMethodRef("javax/jmi/reflect/InvalidNameException", "", "(Ljava/lang/String;)V")); //NOI18N
        out.writeByte(opc_athrow);

        if (tryStop != 0) {
            short catchStart = (short) out.size();

            code_astore(localSlot0, out);
            out.writeByte(opc_new);
            out.writeShort(cp.getClass("javax/jmi/reflect/TypeMismatchException")); //NOI18N
            out.writeByte(opc_dup);
            out.writeByte(opc_aconst_null);
            out.writeByte(opc_dup);
            out.writeByte(opc_dup);
            out.writeByte(opc_invokespecial);
            out.writeShort(cp.getMethodRef("javax/jmi/reflect/TypeMismatchException", "", "(Ljava/lang/Class;Ljava/lang/Object;Ljavax/jmi/reflect/RefObject;)V")); //NOI18N
            out.writeByte(opc_athrow);

            minfo.getExceptionTable().add(new ExceptionTableEntry((short)0, tryStop, catchStart, cp.getClass("java/lang/ClassCastException"))); //NOI18N
        }
        minfo.setMaxStack((short)(maxStack + 6));
        minfo.setMaxLocals((short) (localSlot0 + 2));
        
        return minfo;
    }
    
    protected void codeUnwrapArguments(String methodName, String[] paramTypeNames, DataOutputStream out) throws IOException {
        if (methodName.equals("_invokeOperation") || methodName.equals("_createStruct")) { //NOI18N
            code_aload(2, out);
            out.writeByte(opc_arraylength);
            code_ipush(paramTypeNames.length, out);
            out.writeByte(opc_if_icmpeq);
            out.writeShort(12);
            out.writeByte(opc_new);
            out.writeShort(cp.getClass("javax/jmi/reflect/WrongSizeException")); //NOI18N
            out.writeByte(opc_dup);
            out.writeByte(opc_aconst_null);
            out.writeByte(opc_invokespecial);
            out.writeShort(cp.getMethodRef("javax/jmi/reflect/WrongSizeException", "", "(Ljavax/jmi/reflect/RefObject;)V")); //NOI18N
            out.writeByte(opc_athrow);
            for (int i = 0; i < paramTypeNames.length; i++) {
                code_aload(2, out);
                out.writeByte(opc_sipush);
                out.writeShort(i & 0xFFFF);
                out.writeByte(opc_aaload);
                codeUnwrapArgument(paramTypeNames[i], out);
            }
        } else {
            for (int i = 0; i < paramTypeNames.length; i++) {
                out.writeByte(opc_aload);
                out.writeByte(i + 2);
                codeUnwrapArgument(paramTypeNames[i], out);
            }
        }
    }
    
    protected void codeUnwrapArgument(String typeName, DataOutputStream out) throws IOException {
        PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(typeName);
        if (prim != null) {
            out.writeByte(opc_checkcast);
            out.writeShort(cp.getClass(prim.wrapperClassName));
            
            out.writeByte(opc_invokevirtual);
            out.writeShort(cp.getMethodRef(
            prim.wrapperClassName,
            prim.unwrapMethodName, prim.unwrapMethodDesc));
        } else {
            out.writeByte(opc_checkcast);
            out.writeShort(cp.getClass(getParamType(typeName)));
        }
    }

    protected static String getParamType(String typeName) {
        if (typeName.endsWith("[]")) //NOI18N
            return "[" + getFieldType(typeName.substring(0, typeName.length()-2).trim()); //NOI18N
        else
            return dotToSlash(typeName);
    }

    
    protected int getBytesForArgUnwrap(String methodName, String[] parameterTypeNames) {
        int result = 0;
        if (methodName.equals("_invokeOperation") || methodName.equals("_createStruct")) { //NOI18N
            result += 14 + getBytesForIPush(parameterTypeNames.length);
            for (int i = 0; i < parameterTypeNames.length; i++) {
                result += 5;
                result += getBytesForOneArgUnwrap(parameterTypeNames[i]);
            }
        } else {
            for (int i = 0; i < parameterTypeNames.length; i++) {
                result += 2;
                result += getBytesForOneArgUnwrap(parameterTypeNames[i]);
            }
        }
        return result;
    }
    
    protected int getBytesForOneArgUnwrap(String typeName) {
        if (PrimitiveTypeInfo.get(typeName) != null)
            return 6;
        else
            return 3;
    }

    protected int getBytesForIPush(int value) {
        if (value >= -1 && value <= 5)
            return 1;
        if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE)
            return 2;
        return 3;
    }
    
    protected int getBytesForReturn(String methodName, String typeName) {
        if (typeName.equals("void")) //NOI18N
            return (methodName.equals("_invokeOperation") ? 2 : 1); //NOI18N
        else if (PrimitiveTypeInfo.get(typeName) != null)
            return 4;
        else
            return 1;
    }
    
    protected int getBytesForPreReturn(String typeName) {
        if ((!typeName.equals("void")) && (PrimitiveTypeInfo.get(typeName) != null)) //NOI18N
            return 4;
        else
            return 0;
    }
    
    protected void codePreReturn(String typeName, DataOutputStream out) throws IOException {
        PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(typeName);
        if ((!typeName.equals("void")) && (prim != null)) { //NOI18N
            out.writeByte(opc_new);
            out.writeShort(cp.getClass(prim.wrapperClassName));
            out.writeByte(opc_dup);
        }
    }
    
    protected void codeReturn(String methodName, String typeName, DataOutputStream out) throws IOException {
        if (typeName.equals("void")) { //NOI18N
            if (methodName.equals("_invokeOperation")) { //NOI18N
                out.writeByte(opc_aconst_null);
                out.writeByte(opc_areturn);
            } else {
                out.writeByte(opc_return);
            }
        } else {
            PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(typeName);
            if (prim != null) {
                out.writeByte(opc_invokespecial);
                out.writeShort(cp.getMethodRef(prim.wrapperClassName, "", prim.wrapperConstructorDesc)); //NOI18N
            }
            out.writeByte(opc_areturn);
        }
    }
    
    
    protected class MethodDescHolder {
        
        private String name;
        private String[] params;
        private String ret;
        
        public MethodDescHolder(String methodName, String []parameterTypes, String returnType) {
            name = methodName;
            params = parameterTypes;
            ret = returnType;
        }
        
        public String getName() {
            return name;
        }
        
        public String[] getParameterTypes() {
            return params;
        }
        
        public String getReturnType() {
            return ret;
        }
    }    
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.