Return-Path: Delivered-To: apmail-db-ojb-dev-archive@www.apache.org Received: (qmail 76650 invoked from network); 8 Jan 2006 00:37:26 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 8 Jan 2006 00:37:26 -0000 Received: (qmail 41570 invoked by uid 500); 8 Jan 2006 00:37:25 -0000 Delivered-To: apmail-db-ojb-dev-archive@db.apache.org Received: (qmail 41543 invoked by uid 500); 8 Jan 2006 00:37:25 -0000 Mailing-List: contact ojb-dev-help@db.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Help: List-Post: List-Id: "OJB Developers List" Reply-To: "OJB Developers List" Delivered-To: mailing list ojb-dev@db.apache.org Received: (qmail 41532 invoked by uid 500); 8 Jan 2006 00:37:25 -0000 Received: (qmail 41529 invoked by uid 99); 8 Jan 2006 00:37:25 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 07 Jan 2006 16:37:25 -0800 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.29) with SMTP; Sat, 07 Jan 2006 16:37:24 -0800 Received: (qmail 76605 invoked by uid 65534); 8 Jan 2006 00:37:03 -0000 Message-ID: <20060108003703.76604.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit 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 -0000 To: ojb-commits@db.apache.org From: arminw@apache.org X-Mailer: svnmailer-1.0.5 X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N 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