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 [EMAIL PROTECTED]
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: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]