db-ojb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From arm...@apache.org
Subject svn commit: r366961 - /db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentFieldCGLibImpl.java
Date Sun, 08 Jan 2006 00:37:03 GMT
Author: arminw
Date: Sat Jan  7 16:36:58 2006
New Revision: 366961

URL: http://svn.apache.org/viewcvs?rev=366961&view=rev
Log:
initial check in of a CGLib based PersistentField implementation which requires bean compatible
getter/setter for all fields

Added:
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentFieldCGLibImpl.java

Added: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentFieldCGLibImpl.java
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentFieldCGLibImpl.java?rev=366961&view=auto
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentFieldCGLibImpl.java
(added)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentFieldCGLibImpl.java
Sat Jan  7 16:36:58 2006
@@ -0,0 +1,259 @@
+package org.apache.ojb.broker.metadata.fieldaccess;
+
+/* Copyright 2003-2005 The Apache Software Foundation
+ *
+ * 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.
+ */
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sf.cglib.reflect.FastClass;
+import net.sf.cglib.reflect.FastMethod;
+import org.apache.commons.lang.StringUtils;
+import org.apache.ojb.broker.metadata.MetadataException;
+import org.apache.ojb.broker.util.ClassHelper;
+
+/**
+ * A {@link org.apache.ojb.broker.metadata.fieldaccess.PersistentField} implementation using
+ * JavaBeans compliant calls only to access persistent attributes.
+ * No Reflection is needed. But for each attribute xxx there must be
+ * public getXxx() and setXxx() methods. In metadata the field name must be
+ * the bean compliant 'xxx'.
+ *
+ * @version $Id: PersistentFieldIntrospectorImpl.java,v 1.11.2.2 2005/12/21 22:26:41 tomdz
Exp $
+ */
+public class PersistentFieldCGLibImpl extends PersistentFieldBase
+{
+    private Class type;
+    private transient FastMethod[] methodGraphGetter;
+    private transient FastMethod[] methodGraphSetter;
+    private transient FastMethod singleMethodGraphGetter;
+    private transient FastMethod singleMethodGraphSetter;
+    private transient boolean initialized;
+    private boolean nonNested = false;
+
+    public PersistentFieldCGLibImpl()
+    {
+        super();
+    }
+
+    public PersistentFieldCGLibImpl(Class aClass, String aPropertyName)
+    {
+        super(aClass, aPropertyName);
+    }
+
+    public Class getType()
+    {
+        if(type == null)
+        {
+            if(!initialized) init();
+            type = methodGraphGetter[methodGraphGetter.length - 1].getReturnType();
+        }
+        return type;
+    }
+
+    public void set(Object target, final Object value) throws MetadataException
+    {
+        if(target == null) return;
+        if(!initialized) init();
+
+        if(nonNested)
+        {
+            setValueFor(singleMethodGraphSetter, target, value);
+        }
+        else
+        {
+            int size = methodGraphSetter.length - 1;
+            for(int i = 0; i < size; i++)
+            {
+                Object attribute;
+                attribute = getValueFrom(methodGraphGetter[i], target);
+                if(attribute != null || value != null)
+                {
+                    if(attribute == null)
+                    {
+                        try
+                        {
+                            attribute = ClassHelper.newInstance(methodGraphGetter[i].getReturnType());
+                        }
+                        catch(Exception e)
+                        {
+                            throw new MetadataException("Can't instantiate nested object
of type '"
+                                    + methodGraphGetter[i].getReturnType() + "' for field
'"
+                                    + methodGraphGetter[i].getName() + "'", e);
+                        }
+                    }
+                    setValueFor(methodGraphSetter[i], target, attribute);
+                }
+                else
+                {
+                    return;
+                }
+                target = attribute;
+            }
+            setValueFor(methodGraphSetter[size], target, value);
+        }
+    }
+
+    public Object get(Object target) throws MetadataException
+    {
+        if(!initialized) init();
+        if(nonNested)
+        {
+            return getValueFrom(singleMethodGraphGetter, target);
+        }
+        else
+        {
+            for(int i = 0; i < methodGraphGetter.length; i++)
+            {
+                FastMethod fastMethod = methodGraphGetter[i];
+                target = getValueFrom(fastMethod, target);
+                if(target == null) break;
+            }
+            return target;
+        }
+    }
+
+    private Object getValueFrom(final FastMethod fastMethodGetter, final Object target)
+    {
+        try
+        {
+            return fastMethodGetter.invoke(target, null);
+        }
+        catch(Throwable e)
+        {
+            String msg = buildGetterErrorMsg(fastMethodGetter.getReturnType(), target, "Can't
read value from given object");
+            getLog().error(msg);
+            throw new MetadataException("Error invoking method:" + fastMethodGetter.getName()
+ " in object " + target.getClass().getName(), e);
+        }
+    }
+
+    private void setValueFor(final FastMethod fastMethodSetter, final Object target, Object
value)
+    {
+        try
+        {
+            /**
+             * it is safe to call getParameterTypes()[0] because this is
+             * the "set" method and it needs to take one parameter only.
+             * we need to be able to set values to null. We can only set something to null
if
+             * the type is not a primitive (assignable from Object).
+             */
+            if((value != null) || !fastMethodSetter.getParameterTypes()[0].isPrimitive())
+            {
+                fastMethodSetter.invoke(target, new Object[]{value});
+            }
+        }
+        catch(Throwable e)
+        {
+            Class[] argTypes = fastMethodSetter.getParameterTypes();
+            Class argType = argTypes != null ? argTypes[0] : null;
+            String msg = buildSetterErrorMsg(argType, target, value, "Can't set value on
given object.");
+            getLog().error(msg);
+            throw new MetadataException("Error invoking method:" + fastMethodSetter.getName()
+ " in object:" + target.getClass().getName(), e);
+        }
+    }
+
+    private void init()
+    {
+        methodGraphGetter = buildMethodGraphGetter();
+        methodGraphSetter = buildMethodGraphSetter();
+        if(methodGraphGetter.length == 1)
+        {
+            singleMethodGraphGetter = methodGraphGetter[0];
+            singleMethodGraphSetter = methodGraphSetter[0];
+            nonNested = true;
+        }
+        initialized = true;
+    }
+
+    private FastMethod[] buildMethodGraphGetter()
+    {
+        List result = new ArrayList();
+        String[] fields = StringUtils.split(getName(), PATH_TOKEN);
+        PropertyDescriptor pd = null;
+        for(int i = 0; i < fields.length; i++)
+        {
+            String fieldName = fields[i];
+            Class clazz;
+            if(pd == null)
+            {
+                clazz = getDeclaringClass();
+                pd = findPropertyDescriptor(clazz, fieldName);
+            }
+            else
+            {
+                clazz = pd.getPropertyType();
+                pd = findPropertyDescriptor(clazz, fieldName);
+            }
+            Method method = pd.getReadMethod();
+            if(method == null)
+            {
+                throw new MetadataException("Can't get readMethod for property '"
+                        + pd.getName() + "' in object '" + clazz.getName() + "'");
+            }
+            FastMethod m = FastClass.create(method.getDeclaringClass()).getMethod(method);
+            result.add(m);
+        }
+        return (FastMethod[]) result.toArray(new FastMethod[result.size()]);
+    }
+
+    private FastMethod[] buildMethodGraphSetter()
+    {
+        List result = new ArrayList();
+        String[] fields = StringUtils.split(getName(), PATH_TOKEN);
+        PropertyDescriptor pd = null;
+        for(int i = 0; i < fields.length; i++)
+        {
+            String fieldName = fields[i];
+            Class clazz;
+            if(pd == null)
+            {
+                clazz = getDeclaringClass();
+                pd = findPropertyDescriptor(clazz, fieldName);
+            }
+            else
+            {
+                clazz = pd.getPropertyType();
+                pd = findPropertyDescriptor(clazz, fieldName);
+            }
+            Method method = pd.getWriteMethod();
+            if(method == null)
+            {
+                throw new MetadataException("Can't get writeMethod for property '"
+                        + pd.getName() + "' in object '" + clazz.getName() + "'");
+            }
+            FastMethod m = FastClass.create(method.getDeclaringClass()).getMethod(method);
+            result.add(m);
+        }
+        return (FastMethod[]) result.toArray(new FastMethod[result.size()]);
+    }
+
+    /** This implementation returns always 'false'. */
+    public boolean makeAccessible()
+    {
+        return false;
+    }
+
+    /**
+     * Always returns 'false'.
+     *
+     * @see org.apache.ojb.broker.metadata.fieldaccess.PersistentField#usesAccessorsAndMutators
+     */
+    public boolean usesAccessorsAndMutators()
+    {
+        return true;
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org


Mime
View raw message