Package org.jpox.enhancer.bcel

Source Code of org.jpox.enhancer.bcel.BCELUtils

/**********************************************************************
Copyright (c) 2004 Kikuchi Kousuke and others. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Contributors:
    ...
**********************************************************************/
package org.jpox.enhancer.bcel;

import javax.jdo.JDOFatalException;

import org.apache.bcel.Constants;
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.Attribute;
import org.apache.bcel.classfile.Field;
import org.apache.bcel.classfile.FieldOrMethod;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.classfile.Synthetic;
import org.apache.bcel.generic.ArrayType;
import org.apache.bcel.generic.BIPUSH;
import org.apache.bcel.generic.BasicType;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.Instruction;
import org.apache.bcel.generic.InstructionConstants;
import org.apache.bcel.generic.ObjectType;
import org.apache.bcel.generic.SIPUSH;
import org.apache.bcel.generic.Type;
import org.jpox.enhancer.ClassEnhancer;
import org.jpox.util.ClassUtils;
import org.jpox.util.JPOXLogger;
import org.jpox.util.Localiser;

/**
* Enhancer utility class for BCEL.
*
* @version $Revision: 1.10 $
*/
public final class BCELUtils
{
    /** Localiser for messages. */
    protected static Localiser LOCALISER = Localiser.getInstance("org.jpox.enhancer.Localisation",ClassEnhancer.class.getClassLoader());

    /**
     * private constructor to prevent instantiation.
     */
    private BCELUtils()
    {
    }

    /**
     * convert string to first upper string.
     * test -> Test
     * @param s original string
     * @return first upper string
     */
    public static String firstUpper(final String s)
    {
        return s.substring(0, 1).toUpperCase() + s.substring(1, s.length());
    }

    /**
     * create setter name from Field
     * @param f field
     * @return setter name
     */
    public static String getSetterName(final Field f)
    {
        String fieldName = f.getName();
        return "Set" + fieldName;
    }

    /**
     * create setter name from Field
     * @param fieldName Name of field
     * @return setter name
     */
    public static String getSetterName(final String fieldName)
    {
        return "Set" + fieldName;
    }
   
    /**
     * create getter name from Field
     * @param f field
     * @return getter name
     */
    public static String getGetterName(final Field f)
    {
        String fieldName = f.getName();
        // JDO2 spec dictates only jdoGetXXX methods, although java beans suggests jdoIsXXX for boolean fields
//        String prefix = (f.getType().equals(Type.BOOLEAN)) ? "Is" : "Get";
//        return prefix + fieldName;
        return "Get" + fieldName;
    }
   
    /**
     * create getter name from Field
     * @param fieldName field
     * @return getter name
     */
    public static String getGetterName(final String fieldName)
    {
        // JDO2 spec dictates only jdoGetXXX methods, although java beans suggests jdoIsXXX for boolean fields
//        String prefix = (f.getType().equals(Type.BOOLEAN)) ? "Is" : "Get";
//        return prefix + fieldName;
        return "Get" + fieldName;
    }   

    /**
     * find method
     * @param targetClasGen target class
     * @param name method name
     * @param signature method signature
     * @return target method. return null if method not found.
     */
    public static Method findMethod(
        final ClassGen targetClasGen,
        final String name,
        final String signature)
    {
        Method f[] = targetClasGen.getMethods();
        for (int i = 0; i < f.length; i++)
        {
            Method m = f[i];
            if (name.equals(m.getName()))
            {
                String methodSignature = m.getSignature();
                if (signature.equals(methodSignature))
                {
                    return m;
                }
            }
        }
        return null;
    }

    /**
     * Return JDO method BCEL's type from BCEL's field type.
     *
     * <br>
     * <table border=1>
     * <tr><th>Original Type</th><th>Return Type</th></tr>
     * <tr>
     <td align="center">Type.BOOLEAN</td>
     <td align="center">Type.BOOLEAN</td>
     * </tr>
     * <tr>
     <td align="center">Type.BYTE</td>
     <td align="center">Type.BYTE</td>
     * </tr>
     * <tr>
     <td align="center">Type.CHAR</td>
     <td align="center">Type.CHAR</td>
     * </tr>
     * <tr>
     <td align="center">Type.DOUBLE</td>
     <td align="center">Type.DOUBLE</td>
     * </tr>
     * <tr>
     <td align="center">Type.FLOAT</td>
     <td align="center">Type.FLOAT</td>
     * </tr>
     * <tr>
     <td align="center">Type.INT</td>
     <td align="center">Type.INT</td>
     * </tr>
     * <tr>
     <td align="center">Type.LONG</td>
     <td align="center">Type.LONG</td>
     * </tr>
     * <tr>
     <td align="center">Type.SHORT</td>
     <td align="center">Type.SHORT</td>
     * </tr>
     * <tr>
     <td align="center">Type.STRING</td>
     <td align="center">Type.STRING</td>
     * </tr>
     * <tr>
     <td align="center">[OTHER]</td>
     <td align="center">Type.OBJECT</td>
     * </tr>
     * </table>
     * @param t original type
     * @return method type
     */
    public static Type getJDOMethodType(Type t)
    {
        if (t.equals(Type.BOOLEAN))
        {
            return Type.BOOLEAN;
        }
        else if (t == Type.BYTE)
        {
            return Type.BYTE;
        }
        else if (t == Type.CHAR)
        {
            return Type.CHAR;
        }
        else if (t == Type.DOUBLE)
        {
            return Type.DOUBLE;
        }
        else if (t == Type.FLOAT)
        {
            return Type.FLOAT;
        }
        else if (t == Type.INT)
        {
            return Type.INT;
        }
        else if (t == Type.LONG)
        {
            return Type.LONG;
        }
        else if (t == Type.SHORT)
        {
            return Type.SHORT;
        }
        else if (t.equals(Type.STRING))
        {
            return Type.STRING;
        }
        else
        {
            return Type.OBJECT;
        }
    }

    public static String getJDOMethodName(Field f)
    {
        return f.getName();
    }
   
    /**
     * return JDO method type name by type.
     * <br>
     * <br>
     * <table border=1>
     * <tr><th>Original Type</th><th>Return String</th></tr>
     * <tr>
     <td align="center">Type.BOOLEAN</td>
     <td align="center">Boolean</td>
     * </tr>
     * <tr>
     <td align="center">Type.BYTE</td>
     <td align="center">Byte</td>
     * </tr>
     * <tr>
     <td align="center">Type.CHAR</td>
     <td align="center">Char</td>
     * </tr>
     * <tr>
     <td align="center">Type.DOUBLE</td>
     <td align="center">Double</td>
     * </tr>
     * <tr>
     <td align="center">Type.FLOAT</td>
     <td align="center">Float</td>
     * </tr>
     * <tr>
     <td align="center">Type.INT</td>
     <td align="center">Int</td>
     * </tr>
     * <tr>
     <td align="center">Type.LONG</td>
     <td align="center">Long</td>
     * </tr>
     * <tr>
     <td align="center">Type.SHORT</td>
     <td align="center">Short</td>
     * </tr>
     * <tr>
     <td align="center">Type.STRING</td>
     <td align="center">String</td>
     * </tr>
     * <tr>
     <td align="center">[OTHER]</td>
     <td align="center">Object</td>
     * </tr>
     * </table>
     * @param t original type
     * @return method type name
     */
    public static String getJDOMethodName(Type t)
    {
        if (t instanceof BasicType)
        {
            if (t.equals(Type.BOOLEAN))
            {
                return "Boolean";
            }
            else if (t == Type.BYTE)
            {
                return "Byte";
            }
            else if (t == Type.CHAR)
            {
                return "Char";
            }
            else if (t == Type.DOUBLE)
            {
                return "Double";
            }
            else if (t == Type.FLOAT)
            {
                return "Float";
            }
            else if (t == Type.INT)
            {
                return "Int";
            }
            else if (t == Type.LONG)
            {
                return "Long";
            }
            else if (t == Type.SHORT)
            {
                return "Short";
            }
            else
            {
                throw new RuntimeException("unknown type" + t);
            }
        }
        else if (t.equals(Type.STRING))
        {
            return "String";
        }
        return "Object";
    }

    /**
     * Provide the BCEL Type given the java class name.
     * @param typeName The type of the field
     * @return The ObjectType
     */
    public static Type getBCELTypeFromJavaType(String typeName)
    {
        if (typeName.equals("int"))
        {
            return Type.INT;
        }
        else if (typeName.equals("boolean"))
        {
            return Type.BOOLEAN;
        }
        else if (typeName.equals("byte"))
        {
            return Type.BYTE;
        }
        else if (typeName.equals("char"))
        {
            return Type.CHAR;
        }
        else if (typeName.equals("double"))
        {
            return Type.DOUBLE;
        }
        else if (typeName.equals("float"))
        {
            return Type.FLOAT;
        }
        else if (typeName.equals("long"))
        {
            return Type.LONG;
        }
        else if (typeName.equals("short"))
        {
            return Type.SHORT;
        }
        else
        {
            return new ObjectType(typeName);
        }
    }

    /**
     * return perfect for instruction of type for const int push operand.
     * @param i push num
     * @return push instruction
     */
    public static Instruction getBIPUSH(final int i)
    {
        Instruction result = null;
        if (i < 6)
        {
            switch (i)
            {
                case 0 :
                    result = InstructionConstants.ICONST_0;
                    break;
                case 1 :
                    result = InstructionConstants.ICONST_1;
                    break;
                case 2 :
                    result = InstructionConstants.ICONST_2;
                    break;
                case 3 :
                    result = InstructionConstants.ICONST_3;
                    break;
                case 4 :
                    result = InstructionConstants.ICONST_4;
                    break;
                case 5 :
                    result = InstructionConstants.ICONST_5;
                    break;
            }
        }
        else if (i < Byte.MAX_VALUE)
        {
            result = new BIPUSH((byte)i);
        }
        else if (i < Short.MAX_VALUE)
        {
            result = new SIPUSH((short)i);
        }
        return result;
    }

    /**
     * return primitive wraper type.
     * @param bt original type
     * @return wrapper type
     */
    public static ObjectType getPrimitiveWrapperType(BasicType bt)
    {
        if (bt.equals(Type.BOOLEAN))
        {
            return new ObjectType(Boolean.class.getName());
        }
        else if (bt.equals(Type.BYTE))
        {
            return new ObjectType(Byte.class.getName());
        }
        else if (bt.equals(Type.DOUBLE))
        {
            return new ObjectType(Double.class.getName());
        }
        else if (bt.equals(Type.FLOAT))
        {
            return new ObjectType(Float.class.getName());
        }
        else if (bt.equals(Type.INT))
        {
            return new ObjectType(Integer.class.getName());
        }
        else if (bt.equals(Type.LONG))
        {
            return new ObjectType(Long.class.getName());
        }
        else if (bt.equals(Type.SHORT))
        {
            return new ObjectType(Short.class.getName());
        }
        else if (bt.equals(Type.CHAR))
        {
            return new ObjectType(Character.class.getName());
        }

        return new ObjectType("java.lang.Object");
    }

    public static String getBcelType2JavaTypeString(final Type t)
    {
        String result = null;
        if (t instanceof ObjectType)
        {
            result = ((ObjectType)t).getClassName();
        }
        else if (t instanceof ArrayType)
        {
            result = "java.lang.Object";
        }
        else if (Type.BOOLEAN.getType() == t.getType())
        {
            result = "boolean";
        }
        else if (Type.BYTE.getType() == t.getType())
        {
            result = "byte";
        }
        else if (Type.CHAR.getType() == t.getType())
        {
            result = "char";
        }
        else if (Type.DOUBLE.getType() == t.getType())
        {
            result = "double";
        }
        else if (Type.FLOAT.getType() == t.getType())
        {
            result = "float";
        }
        else if (Type.INT.getType() == t.getType())
        {
            result = "int";
        }
        else if (Type.LONG.getType() == t.getType())
        {
            result = "long";
        }
        else if (Type.SHORT.getType() == t.getType())
        {
            result = "short";
        }
        else if (Type.STRING.getType() == t.getType())
        {
            result = "java.lang.String";
        }
        else if (Type.STRINGBUFFER.getType() == t.getType())
        {
            result = "java.lang.StringBuffer";
        }
        else if (Type.THROWABLE.getType() == t.getType())
        {
            result = "java.lang.Throwable";
        }
        else if (Type.OBJECT.getType() == t.getType())
        {
            result = "java.lang.Object";
        }
        else
        {
            if (t != null)
            {
                System.out.println("unkown Type " + t.getClass().getName() + " " + t);
            }
        }
        return result;
    }

    /**
     * find Field object by name
     * @param fieldName field name
     * @param classGen class gen
     * @return field object. return null if field not found.
     */
    public static Field getFieldByName(final String fieldName, final ClassGen classGen)
    {
        Field f[] = classGen.getFields();
        if( classGen == null )
        {
            return null;
        }
        for (int i = 0; i < f.length; i++)
        {
            if (fieldName.equals(f[i].getName()))
            {
                return f[i];
            }
        }
        ClassGen scg = classGen;
       
        if( scg.getSuperclassName() == null )
        {
            return null;
        }     
        JavaClass jc = Repository.getRepository().findClass(scg.getSuperclassName());
        while( jc != null )
        {
            scg = new ClassGen(jc);
            f = scg.getFields();
            for (int i = 0; i < f.length; i++)
            {
                if (fieldName.equals(f[i].getName()))
                {
                    return f[i];
                }
            }         
            if( scg.getSuperclassName() == null )
            {
                return null;
            }
            else if( scg.getSuperclassName().equals("java.lang.Object") )
            {
                return null;
            }           
            jc = Repository.getRepository().findClass(scg.getSuperclassName());
        }

       
        return null;
    }
   
    /**
     * find Field object by name
     * @param fieldName field name
     * @param classGen class gen
     * @return field object. return null if field not found.
     */
    public static Method getGetterByName(final String fieldName, final ClassGen classGen)
    {
        Method m[] = classGen.getMethods();
        if( classGen == null )
        {
            return null;
        }
        String booleanGetterName = ClassUtils.getJavaBeanGetterName(fieldName, true);
        String nonBooleanGetterName = ClassUtils.getJavaBeanGetterName(fieldName, false);

        for (int i = 0; i < m.length; i++)
        {
            if (nonBooleanGetterName.equals(m[i].getName()) || booleanGetterName.equals(m[i].getName()) )
            {
                return m[i];
            }
        }
        ClassGen scg = classGen;
       
        if( scg.getSuperclassName() == null )
        {
            return null;
        }     
        JavaClass jc = Repository.getRepository().findClass(scg.getSuperclassName());
        while( jc != null )
        {
            scg = new ClassGen(jc);
            m = scg.getMethods();
            for (int i = 0; i < m.length; i++)
            {
                if (nonBooleanGetterName.equals(m[i].getName()) || booleanGetterName.equals(m[i].getName()) )
                {
                    return m[i];
                }
            }         
            if( scg.getSuperclassName() == null )
            {
                return null;
            }
            else if( scg.getSuperclassName().equals("java.lang.Object") )
            {
                return null;
            }           
            jc = Repository.getRepository().findClass(scg.getSuperclassName());
        }

       
        return null;
    }

    /**
     * find Field object by name
     * @param fieldName field name
     * @param classGen class gen
     * @return field object. return null if field not found.
     */
    public static Field getFieldByName(final String fieldName, final JavaClass classGen)
    {
        Field f[] = classGen.getFields();
        if( classGen == null )
        {
            return null;
        }
        for (int i = 0; i < f.length; i++)
        {
            if (fieldName.equals(f[i].getName()))
            {
                return f[i];
            }
        }
        JavaClass jc = classGen;
       
        if( jc.getSuperclassName() == null )
        {
            return null;
        }     
        if( jc.getSuperclassName().equals("java.lang.Object") )
        {
            return null;
        }

        try
        {
            jc = jc.getSuperClass();
            while( jc != null )
            {
                f = jc.getFields();
                for (int i = 0; i < f.length; i++)
                {
                    if (fieldName.equals(f[i].getName()))
                    {
                        return f[i];
                    }
                }         
                if( jc.getSuperclassName() == null )
                {
                    return null;
                }
                else if( jc.getSuperclassName().equals("java.lang.Object") )
                {
                    return null;
                }           
                jc = jc.getSuperClass();
            }
        }
        catch(Throwable ex)
        {
            //catch Throwable, so it is compatible with latest BCEL changes in methods signature.
            //It nows raises ClassNotFoundException. In order to be able to compible this code
            //with bcel-5.1 or bcel-5.1+, we catch as throwable
            JPOXLogger.ENHANCER.error(LOCALISER.msg("Enhancer.ClassNotFound",ex));
            throw new JDOFatalException(LOCALISER.msg("Enhancer.ClassNotFound",ex));
        }
      
        return null;
    }

    /**
     * find Field object by name
     * @param fieldName field name
     * @param classGen class gen
     * @return field object. return null if field not found.
     */
    public static ClassGen getClassByFieldByName(final String fieldName, final ClassGen classGen)
    {
        Field f[] = classGen.getFields();
        for (int i = 0; i < f.length; i++)
        {
            if (fieldName.equals(f[i].getName()))
            {
                return classGen;
            }
        }
        ClassGen scg = classGen;
       
        if( scg.getSuperclassName() == null )
        {
            return null;
        }
        JavaClass jc = Repository.getRepository().findClass(scg.getSuperclassName());
        while( jc != null )
        {
            scg = new ClassGen(jc);
            f = scg.getFields();
            for (int i = 0; i < f.length; i++)
            {
                if (fieldName.equals(f[i].getName()))
                {
                    return scg;
                }
            }         
            if( scg.getSuperclassName() == null )
            {
                return scg;
            }
            jc = Repository.getRepository().findClass(scg.getSuperclassName());
        }

       
        return null;
    }    

    /**
     * find Field object by name
     * @param fieldName field name
     * @param classGen class gen
     * @return field object. return null if field not found.
     */
    public static ClassGen getClassByFieldByName(final String fieldName, final JavaClass classGen)
    {
        Field f[] = classGen.getFields();
        for (int i = 0; i < f.length; i++)
        {
            if (fieldName.equals(f[i].getName()))
            {
                return new ClassGen(classGen);
            }
        }
        ClassGen scg = new ClassGen(classGen);
       
        if( scg.getSuperclassName() == null )
        {
            return null;
        }
        JavaClass jc = Repository.getRepository().findClass(scg.getSuperclassName());
        while( jc != null )
        {
            scg = new ClassGen(jc);
            f = scg.getFields();
            for (int i = 0; i < f.length; i++)
            {
                if (fieldName.equals(f[i].getName()))
                {
                    return scg;
                }
            }         
            if( scg.getSuperclassName() == null )
            {
                return scg;
            }
            jc = Repository.getRepository().findClass(scg.getSuperclassName());
        }

       
        return null;
    }    
   
    /**
     * add synthetic attribute
     * @param m method or field
     * @param constantPoolGen target ConstantPoolGen instance
     */
    public static void addSynthetic(FieldOrMethod m, ConstantPoolGen constantPoolGen)
    {
        int index = constantPoolGen.addUtf8("Synthetic");
        Synthetic syn =
            new Synthetic(index, 0, new byte[] { Constants.ATTR_SYNTHETIC }, m.getConstantPool());

        Attribute originalAttrs[] = m.getAttributes();
        Attribute attrs[];
        if ((originalAttrs == null) || (originalAttrs.length == 0))
        {
            attrs = new Attribute[] { syn };
        }
        else
        {
            for (int i = 0; i < originalAttrs.length; i++)
            {
                if (originalAttrs[i] instanceof Synthetic)
                {
                    return;
                }
            }
            attrs = new Attribute[originalAttrs.length + 1];
            System.arraycopy(originalAttrs, 0, attrs, 0, originalAttrs.length);
            attrs[originalAttrs.length] = syn;
        }
        m.setAttributes(attrs);
    }

    /**
     * Check method or field is synthetic.
     * @param m field or method
     * @return Return true if method or field is synthetic.
     */
    public static boolean isSynthetic(FieldOrMethod m)
    {
        if (m == null)
        {
            return false;
        }
        Attribute attrs[] = m.getAttributes();
        return isSynthetic(attrs);
     }

    /**
     * Check method or field is synthetic.
     * @param attrs Attributes of Field or Method
     * @return Return true if method or field is synthetic.
     */
    public static boolean isSynthetic(Attribute[] attrs)
    {
        boolean result = false;
        if (attrs == null)
        {
            result = false;
        }
        for (int i = 0; i < attrs.length; i++)
        {
            Attribute a = attrs[i];
            // Constant c = m.getConstantPool().getConstant(a.getNameIndex());
            // if(c instanceof ConstantUtf8)
            if (a instanceof Synthetic)
            {
                result = true;
            }
        }

        // System.out.println(m.getName()+" synthetic="+result);
        return result;
    }
   
    /**
     * Same result targetClass.newInstance instanceof interfaceClass
     * @param targetClass Target class instance
     * @param interfaceClass Check class instance
     * @return return true if targetInstance.newInstance() instanceof interfaseClass.
     * @throws ClassNotFoundException
     */
    public static boolean isInstanceof(JavaClass targetClass, Class interfaceClass) throws ClassNotFoundException
    {
        if (interfaceClass == null)
        {
            return false;
        }
       
        boolean doNext = true;
        JavaClass t = targetClass;
        while (doNext)
        {
            JavaClass c[] = t.getInterfaces();
            String superClassName = interfaceClass.getName();
            if (c == null)
            {
                return false;
            }
            for (int i = 0; i < c.length; i++)
            {
                if (c[i].getClassName().equals(superClassName))
                {
                    return true;
                }
            }
            t = t.getSuperClass();
            if (t == null)
            {
                doNext = false;
            }
        }
        return false;
    }
}
TOP

Related Classes of org.jpox.enhancer.bcel.BCELUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.