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

com.feilong.lib.ognl.ObjectPropertyAccessor 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.0.8
Show newest version
// --------------------------------------------------------------------------
// Copyright (c) 1998-2004, Drew Davidson and Luke Blanshard
// All 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 the Drew Davidson 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" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 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 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
// --------------------------------------------------------------------------
package com.feilong.lib.ognl;

import java.beans.IntrospectionException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;

import com.feilong.lib.ognl.enhance.ExpressionCompiler;
import com.feilong.lib.ognl.enhance.UnsupportedCompilationException;

/**
 * Implementation of PropertyAccessor that uses reflection on the target object's class to find a
 * field or a pair of set/get methods with the given property name.
 *
 * @author Luke Blanshard ([email protected])
 * @author Drew Davidson ([email protected])
 */
public class ObjectPropertyAccessor implements PropertyAccessor{

    /**
     * Returns OgnlRuntime.NotFound if the property does not exist.
     * 
     * @param context
     *            the current execution context.
     * @param target
     *            the object to get the property from.
     * @param name
     *            the name of the property to get.
     * @return the current value of the given property in the given object.
     * @throws OgnlException
     *             if there is an error locating the property in the given object.
     */
    public Object getPossibleProperty(Map context,Object target,String name) throws OgnlException{
        Object result;
        OgnlContext ognlContext = (OgnlContext) context;

        try{
            if ((result = OgnlRuntime.getMethodValue(ognlContext, target, name, true)) == OgnlRuntime.NotFound){
                result = OgnlRuntime.getFieldValue(ognlContext, target, name, true);
            }
        }catch (IntrospectionException ex){
            throw new OgnlException(name, ex);
        }catch (OgnlException ex){
            throw ex;
        }catch (Exception ex){
            throw new OgnlException(name, ex);
        }

        return result;
    }

    /**
     * Returns OgnlRuntime.NotFound if the property does not exist.
     * 
     * @param context
     *            the current execution context.
     * @param target
     *            the object to set the property in.
     * @param name
     *            the name of the property to set.
     * @param value
     *            the new value for the property.
     * @return the Object result of the property set operation.
     * @throws OgnlException
     *             if there is an error setting the property in the given object.
     */
    public Object setPossibleProperty(Map context,Object target,String name,Object value) throws OgnlException{
        Object result = null;
        OgnlContext ognlContext = (OgnlContext) context;

        try{
            if (!OgnlRuntime.setMethodValue(ognlContext, target, name, value, true)){
                result = OgnlRuntime.setFieldValue(ognlContext, target, name, value) ? null : OgnlRuntime.NotFound;
            }

            if (result == OgnlRuntime.NotFound){
                Method m = OgnlRuntime.getWriteMethod(target.getClass(), name);
                if (m != null){
                    result = m.invoke(target, new Object[] { value });
                }
            }
        }catch (IntrospectionException ex){
            throw new OgnlException(name, ex);
        }catch (OgnlException ex){
            throw ex;
        }catch (Exception ex){
            throw new OgnlException(name, ex);
        }

        return result;
    }

    public boolean hasGetProperty(OgnlContext context,Object target,Object oname) throws OgnlException{
        try{
            return OgnlRuntime.hasGetProperty(context, target, oname);
        }catch (IntrospectionException ex){
            throw new OgnlException("checking if " + target + " has gettable property " + oname, ex);
        }
    }

    public boolean hasGetProperty(Map context,Object target,Object oname) throws OgnlException{
        return hasGetProperty((OgnlContext) context, target, oname);
    }

    public boolean hasSetProperty(OgnlContext context,Object target,Object oname) throws OgnlException{
        try{
            return OgnlRuntime.hasSetProperty(context, target, oname);
        }catch (IntrospectionException ex){
            throw new OgnlException("checking if " + target + " has settable property " + oname, ex);
        }
    }

    public boolean hasSetProperty(Map context,Object target,Object oname) throws OgnlException{
        return hasSetProperty((OgnlContext) context, target, oname);
    }

    @Override
    public Object getProperty(Map context,Object target,Object oname) throws OgnlException{
        Object result = null;
        String name = oname.toString();

        result = getPossibleProperty(context, target, name);

        if (result == OgnlRuntime.NotFound){
            throw new NoSuchPropertyException(target, name);
        }

        return result;
    }

    @Override
    public void setProperty(Map context,Object target,Object oname,Object value) throws OgnlException{
        String name = oname.toString();

        Object result = setPossibleProperty(context, target, name, value);

        if (result == OgnlRuntime.NotFound){
            throw new NoSuchPropertyException(target, name);
        }
    }

    public Class getPropertyClass(OgnlContext context,Object target,Object index){
        try{
            Method m = OgnlRuntime.getReadMethod(target.getClass(), index.toString());

            if (m == null){

                if (String.class.isAssignableFrom(index.getClass()) && !target.getClass().isArray()){
                    String indexStr = (String) index;
                    String key = (indexStr.indexOf('"') >= 0) ? indexStr.replaceAll("\"", "") : indexStr;
                    try{
                        Field f = target.getClass().getField(key);
                        if (f != null){

                            return f.getType();
                        }
                    }catch (NoSuchFieldException e){
                        return null;
                    }
                }

                return null;
            }

            return m.getReturnType();

        }catch (Throwable t){
            throw OgnlOps.castToRuntime(t);
        }
    }

    @Override
    public String getSourceAccessor(OgnlContext context,Object target,Object index){
        try{

            String indexStr = index.toString();
            String methodName = (indexStr.indexOf('"') >= 0 ? indexStr.replaceAll("\"", "") : indexStr);
            Method m = OgnlRuntime.getReadMethod(target.getClass(), methodName);

            // try last ditch effort of checking if they were trying to do reflection via a return method value

            if (m == null && context.getCurrentObject() != null){
                String currentObjectStr = context.getCurrentObject().toString();
                m = OgnlRuntime.getReadMethod(
                                target.getClass(),
                                (currentObjectStr.indexOf('"') >= 0 ? currentObjectStr.replaceAll("\"", "") : currentObjectStr));
            }

            //System.out.println("tried to get read method from target: " + target.getClass() + " with methodName:" + methodName + " result: " + m);
            // try to get field if no method could be found

            if (m == null){
                try{
                    if (String.class.isAssignableFrom(index.getClass()) && !target.getClass().isArray()){
                        Field f = target.getClass().getField(methodName);

                        if (f != null){
                            context.setCurrentType(f.getType());
                            context.setCurrentAccessor(f.getDeclaringClass());

                            return "." + f.getName();
                        }
                    }
                }catch (NoSuchFieldException e){
                    // ignore
                }

                return "";
            }

            context.setCurrentType(m.getReturnType());
            context.setCurrentAccessor(OgnlRuntime.getCompiler().getSuperOrInterfaceClass(m, m.getDeclaringClass()));

            return "." + m.getName() + "()";

        }catch (Throwable t){
            throw OgnlOps.castToRuntime(t);
        }
    }

    @Override
    public String getSourceSetter(OgnlContext context,Object target,Object index){
        try{

            String indexStr = index.toString();
            String methodName = (indexStr.indexOf('"') >= 0 ? indexStr.replaceAll("\"", "") : indexStr);
            Method m = OgnlRuntime.getWriteMethod(target.getClass(), methodName);

            if (m == null && context.getCurrentObject() != null && context.getCurrentObject().toString() != null){
                String currentObjectStr = context.getCurrentObject().toString();
                m = OgnlRuntime.getWriteMethod(
                                target.getClass(),
                                (currentObjectStr.indexOf('"') >= 0 ? currentObjectStr.replaceAll("\"", "") : currentObjectStr));
            }

            if (m == null || m.getParameterTypes() == null || m.getParameterTypes().length <= 0){
                throw new UnsupportedCompilationException(
                                "Unable to determine setting expression on " + context.getCurrentObject() + " with index of " + index);
            }

            Class parm = m.getParameterTypes()[0];
            String conversion;

            if (m.getParameterTypes().length > 1){
                throw new UnsupportedCompilationException("Object property accessors can only support single parameter setters.");
            }

            if (parm.isPrimitive()){
                Class wrapClass = OgnlRuntime.getPrimitiveWrapperClass(parm);
                conversion = OgnlRuntime.getCompiler().createLocalReference(
                                context,
                                "((" + wrapClass.getName() + ")ognl.OgnlOps#convertValue($3," + wrapClass.getName() + ".class, true))."
                                                + OgnlRuntime.getNumericValueGetter(wrapClass),
                                parm);

            }else if (parm.isArray()){
                conversion = OgnlRuntime.getCompiler().createLocalReference(
                                context,
                                "(" + ExpressionCompiler.getCastString(parm) + ")ognl.OgnlOps#toArray($3,"
                                                + parm.getComponentType().getName() + ".class)",
                                parm);

            }else{
                conversion = OgnlRuntime.getCompiler().createLocalReference(
                                context,
                                "(" + parm.getName() + ")ognl.OgnlOps#convertValue($3," + parm.getName() + ".class)",
                                parm);
            }

            context.setCurrentType(m.getReturnType());
            context.setCurrentAccessor(OgnlRuntime.getCompiler().getSuperOrInterfaceClass(m, m.getDeclaringClass()));

            return "." + m.getName() + "(" + conversion + ")";

        }catch (Throwable t){
            throw OgnlOps.castToRuntime(t);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy