You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by aw...@apache.org on 2006/12/21 18:08:39 UTC

svn commit: r489408 - in /incubator/openjpa/trunk: openjpa-kernel/src/main/java/org/apache/openjpa/enhance/ openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ openjpa-kernel/src/main/java/org/apache/openjpa/meta/ openjpa-kernel/src/main/java/org/a...

Author: awhite
Date: Thu Dec 21 09:08:38 2006
New Revision: 489408

URL: http://svn.apache.org/viewvc?view=rev&rev=489408
Log:
Stop enhancing entity identity classes to make non-public properties public for
access by the various identity object manipulation methods of the enhanced 
entity class.  This caused problems with runtime enhancement if the identity 
class was loaded before the entity class.  Instead, rely on reflection to 
access non-public identity class members.


Added:
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/Reflection.java   (with props)
Modified:
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCRegistry.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ObjectIdStateManager.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ResultPacker.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/enhance/localizer.properties
    incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties
    incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties
    incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/util/localizer.properties
    incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java
    incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java?view=diff&rev=489408&r1=489407&r2=489408
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java Thu Dec 21 09:08:38 2006
@@ -101,7 +101,6 @@
     public static final int ENHANCE_AWARE = 2 << 0;
     public static final int ENHANCE_INTERFACE = 2 << 1;
     public static final int ENHANCE_PC = 2 << 2;
-    public static final int ENHANCE_OID = 2 << 3;
 
     private static final String PRE = "pc";
     private static final Class PCTYPE = PersistenceCapable.class;
@@ -206,14 +205,6 @@
     }
 
     /**
-     * Return the bytecode representations of any oid classes that must be
-     * manipulated.
-     */
-    public Collection getObjectIdBytecode() {
-        return (_oids == null) ? Collections.EMPTY_LIST : _oids;
-    }
-
-    /**
      * Return the metadata for the class being manipulated, or null if not
      * a persistent type.
      */
@@ -311,8 +302,6 @@
                 if (interfaces[i].getName().equals(PCTYPE.getName())) {
                     if (_log.isTraceEnabled())
                         _log.trace(_loc.get("pc-type", _pc.getType()));
-                    if (_meta != null && enhanceObjectId())
-                        return ENHANCE_OID;
                     return ENHANCE_NONE;
                 }
             }
@@ -335,8 +324,6 @@
                 addAttachDetachCode();
                 addSerializationCode();
                 addCloningCode();
-                if (enhanceObjectId())
-                    ret |= ENHANCE_OID;
                 runAuxiliaryEnhancers();
                 return ret;
             }
@@ -1535,14 +1522,43 @@
         FieldMetaData[] fmds = _meta.getDeclaredFields();
         Class type;
         String name;
+        Field field;
+        Method setter;
+        boolean reflect;
         for (int i = 0; i < fmds.length; i++) {
             if (!fmds[i].isPrimaryKey())
                 continue;
+            code.aload().setLocal(id);
 
             name = fmds[i].getName();
             type = fmds[i].getObjectIdFieldType();
+            if (_meta.getAccessType() == ClassMetaData.ACCESS_FIELD) {
+                setter = null;
+                field = Reflection.findField(oidType, name, true);
+                reflect = !Modifier.isPublic(field.getModifiers());
+                if (reflect) {
+                    code.constant().setValue(oidType);
+                    code.constant().setValue(name);
+                    code.constant().setValue(true);
+                    code.invokestatic().setMethod(Reflection.class, 
+                        "findField", Field.class, new Class[] { Class.class,
+                        String.class, boolean.class });
+                }
+            } else {
+                field = null;
+                setter = Reflection.findSetter(oidType, name, type, true);
+                reflect = !Modifier.isPublic(setter.getModifiers());
+                if (reflect) {
+                    code.constant().setValue(oidType);
+                    code.constant().setValue(name);
+                    setClassConstant(code, type);
+                    code.constant().setValue(true);
+                    code.invokestatic().setMethod(Reflection.class, 
+                        "findSetter", Method.class, new Class[] { Class.class,
+                        String.class, Class.class, boolean.class });
+                }
+            }
 
-            code.aload().setLocal(id);
             if (fieldManager) {
                 code.aload().setParam(0);
                 code.constant().setValue(i);
@@ -1554,7 +1570,7 @@
                 // if the type of this field meta data is
                 // non-primitive and non-string, be sure to cast
                 // to the appropriate type.
-                if (!type.isPrimitive()
+                if (!reflect && !type.isPrimitive()
                     && !type.getName().equals(String.class.getName()))
                     code.checkcast().setType(type);
             } else {
@@ -1566,12 +1582,18 @@
                     addExtractObjectIdFieldValueCode(code, fmds[i]);
             }
 
-            if (_meta.getAccessType() == ClassMetaData.ACCESS_FIELD)
-                code.putfield().setField(findDeclaredField(oidType, name));
+            if (reflect && field != null) {
+                code.invokestatic().setMethod(Reflection.class, "set", 
+                    void.class, new Class[] { Object.class, Field.class,
+                    (type.isPrimitive()) ? type : Object.class });
+            } else if (reflect) { 
+                code.invokestatic().setMethod(Reflection.class, "set", 
+                    void.class, new Class[] { Object.class, Method.class,
+                    (type.isPrimitive()) ? type : Object.class });
+            } else if (field != null)
+                code.putfield().setField(field);
             else
-                code.invokevirtual().setMethod(findDeclaredMethod
-                    (oidType, "set" + StringUtils.capitalize(name),
-                        new Class[]{ type }));
+                code.invokevirtual().setMethod(setter);
         }
         code.vreturn();
 
@@ -1580,6 +1602,30 @@
     }
 
     /**
+     * Works around a bug in serp when primitive type constants. 
+     */
+    private static void setClassConstant(Code code, Class type) {
+        if (type == boolean.class) 
+            code.getstatic().setField(Boolean.class, "TYPE", Class.class);
+        else if (type == byte.class) 
+            code.getstatic().setField(Byte.class, "TYPE", Class.class);
+        else if (type == char.class) 
+            code.getstatic().setField(Character.class, "TYPE", Class.class);
+        else if (type == double.class) 
+            code.getstatic().setField(Double.class, "TYPE", Class.class);
+        else if (type == float.class) 
+            code.getstatic().setField(Float.class, "TYPE", Class.class);
+        else if (type == int.class) 
+            code.getstatic().setField(Integer.class, "TYPE", Class.class);
+        else if (type == long.class) 
+            code.getstatic().setField(Long.class, "TYPE", Class.class);
+        else if (type == short.class) 
+            code.getstatic().setField(Short.class, "TYPE", Class.class);
+        else
+            code.constant().setValue(type);
+    }
+
+    /**
      * Add code to extract the id of the given primary key relation field for
      * setting into an objectid instance.
      */
@@ -1788,9 +1834,11 @@
         // this.<field> = id.<field>
         // or for single field identity: id.getId ()
         FieldMetaData[] fmds = _meta.getDeclaredFields();
+        String name;
         Class type;
         Class unwrapped;
-        String name;
+        Field field;
+        Method getter;
         for (int i = 0; i < fmds.length; i++) {
             if (!fmds[i].isPrimaryKey())
                 continue;
@@ -1840,11 +1888,41 @@
                             code.invokespecial().setMethod(type, "<init>",
                                 void.class, new Class[]{ unwrapped });
                     }
-                } else if (_meta.getAccessType() == ClassMetaData.ACCESS_FIELD)
-                    code.getfield().setField(findDeclaredField(oidType, name));
-                else // property
-                    code.invokevirtual().setMethod(findDeclaredGetterMethod
-                        (oidType, StringUtils.capitalize(name)));
+                } else if (_meta.getAccessType() == ClassMetaData.ACCESS_FIELD){
+                    field = Reflection.findField(oidType, name, true);
+                    if (Modifier.isPublic(field.getModifiers()))
+                        code.getfield().setField(field);
+                    else {
+                        // Reflection.getXXX(oid, Reflection.findField(...));
+                        code.constant().setValue(oidType);
+                        code.constant().setValue(name);
+                        code.constant().setValue(true);
+                        code.invokestatic().setMethod(Reflection.class,
+                            "findField", Field.class, new Class[] { 
+                            Class.class, String.class, boolean.class });
+                        code.invokestatic().setMethod
+                            (getReflectionGetterMethod(type, Field.class));
+                        if (!type.isPrimitive() && type != Object.class)
+                            code.checkcast().setType(type);
+                    }
+                } else {
+                    getter = Reflection.findGetter(oidType, name, true);
+                    if (Modifier.isPublic(getter.getModifiers()))
+                        code.invokevirtual().setMethod(getter);
+                    else {
+                        // Reflection.getXXX(oid, Reflection.findGetter(...));
+                        code.constant().setValue(oidType);
+                        code.constant().setValue(name);
+                        code.constant().setValue(true);
+                        code.invokestatic().setMethod(Reflection.class,
+                            "findGetter", Method.class, new Class[] { 
+                            Class.class, String.class, boolean.class });
+                        code.invokestatic().setMethod
+                            (getReflectionGetterMethod(type, Method.class));
+                        if (!type.isPrimitive() && type != Object.class)
+                            code.checkcast().setType(type);
+                    }
+                }
             }
 
             if (fieldManager)
@@ -1911,6 +1989,19 @@
     }
 
     /**
+     * Return the proper getter method of the {@link Reflection} helper for
+     * a field or getter method of the given type.
+     */
+    private Method getReflectionGetterMethod(Class type, Class argType)
+        throws NoSuchMethodException {
+        String name = "get";
+        if (type.isPrimitive())
+            name += StringUtils.capitalize(type.getName());
+        return Reflection.class.getMethod(name, new Class[] { Object.class, 
+            argType }); 
+    }
+
+    /**
      * Return the proper fetch method of the ObjectIdFieldSupplier for
      * a field of the given type.
      */
@@ -2728,123 +2819,6 @@
     }
 
     /**
-     * Enhance the PC's object id class.
-     */
-    private boolean enhanceObjectId()
-        throws IOException {
-        Class cls = _meta.getObjectIdType();
-        if (cls == null)
-            return false;
-
-        FieldMetaData[] pks = _meta.getPrimaryKeyFields();
-        int access = _meta.getAccessType();
-        if (_meta.isOpenJPAIdentity()) {
-            if (pks[0].getDeclaredTypeCode() != JavaTypes.OID)
-                return false;
-            cls = pks[0].getDeclaredType();
-            access = pks[0].getEmbeddedMetaData().getAccessType();
-            pks = pks[0].getEmbeddedMetaData().getFields();
-        }
-
-        String cap;
-        for (int i = 0; i < pks.length; i++) {
-            if (access == ClassMetaData.ACCESS_FIELD)
-                makeObjectIdFieldPublic(findDeclaredField(cls,
-                    pks[i].getName()));
-            else // property
-            {
-                cap = StringUtils.capitalize(pks[i].getName());
-                makeObjectIdMethodPublic(findDeclaredGetterMethod(cls, cap));
-                makeObjectIdMethodPublic(findDeclaredMethod(cls, "set" + cap,
-                    new Class[]{ pks[i].getDeclaredType() }));
-            }
-        }
-        return _oids != null;
-    }
-
-    /**
-     * Find the given (possibly private) field.
-     */
-    private Field findDeclaredField(Class cls, String name) {
-        if (cls == null || cls == Object.class)
-            return null;
-
-        try {
-            return cls.getDeclaredField(name);
-        } catch (NoSuchFieldException nsfe) {
-            return findDeclaredField(cls.getSuperclass(), name);
-        } catch (Exception e) {
-            throw new GeneralException(e);
-        }
-    }
-
-    /**
-     * Return the getter method for the given capitalized property name.
-     */
-    private Method findDeclaredGetterMethod(Class cls, String baseName) {
-        Method meth = findDeclaredMethod(cls, "get" + baseName, null);
-        if (meth != null)
-            return meth;
-        return findDeclaredMethod(_meta.getObjectIdType(), "is" + baseName,
-            null);
-    }
-
-    /**
-     * Find the given (possibly private) method.
-     */
-    private Method findDeclaredMethod(Class cls, String name, Class[] params) {
-        if (cls == null || cls == Object.class)
-            return null;
-
-        try {
-            return cls.getDeclaredMethod(name, params);
-        } catch (NoSuchMethodException nsme) {
-            return findDeclaredMethod(cls.getSuperclass(), name, params);
-        } catch (Exception e) {
-            throw new GeneralException(e);
-        }
-    }
-
-    /**
-     * Ensure that the given oid field is public.
-     */
-    private void makeObjectIdFieldPublic(Field field) {
-        if (Modifier.isPublic(field.getModifiers()))
-            return;
-
-        BCClass bc = getObjectIdBytecode(field.getDeclaringClass());
-        bc.getDeclaredField(field.getName()).makePublic();
-    }
-
-    /**
-     * Ensure that the given oid method is public.
-     */
-    private void makeObjectIdMethodPublic(Method meth) {
-        if (Modifier.isPublic(meth.getModifiers()))
-            return;
-
-        BCClass bc = getObjectIdBytecode(meth.getDeclaringClass());
-        bc.getDeclaredMethod(meth.getName(), meth.getParameterTypes()).
-            makePublic();
-    }
-
-    /**
-     * Return the bytecode for the given oid class, creating and caching it
-     * if necessary.
-     */
-    private BCClass getObjectIdBytecode(Class cls) {
-        BCClass bc = _pc.getProject().loadClass(cls);
-        if (_oids == null)
-            _oids = new ArrayList(3);
-        if (!_oids.contains(bc)) {
-            if (_log.isTraceEnabled())
-                _log.trace(_loc.get("enhance-oid", bc.getName()));
-            _oids.add(bc);
-        }
-        return bc;
-    }
-
-    /**
      * Gets the auxiliary enhancers registered as {@link Services services}.
      */
     public AuxiliaryEnhancer[] getAuxiliaryEnhancers() {
@@ -3716,22 +3690,8 @@
             else if (status == ENHANCE_AWARE) {
                 log.info(_loc.get("enhance-aware"));
                 enhancer.record();
-            } else {
+            } else
                 enhancer.record();
-                if ((status & ENHANCE_OID) != 0) {
-                    if (log.isInfoEnabled()) {
-                        Collection oids = enhancer.getObjectIdBytecode();
-                        StringBuffer buf = new StringBuffer();
-                        for (Iterator oiditr = oids.iterator();
-                            oiditr.hasNext();) {
-                            buf.append(((BCClass) oiditr.next()).getName());
-                            if (oiditr.hasNext())
-                                buf.append(", ");
-                        }
-                        log.info(_loc.get("enhance-running-oids", buf));
-                    }
-                }
-            }
             project.clear();
         }
         return true;

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCRegistry.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCRegistry.java?view=diff&rev=489408&r1=489407&r2=489408
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCRegistry.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCRegistry.java Thu Dec 21 09:08:38 2006
@@ -21,8 +21,10 @@
 import java.util.LinkedList;
 import java.util.Map;
 
+import org.apache.openjpa.lib.util.Localizer;
 import org.apache.openjpa.lib.util.ReferenceMap;
 import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap;
+import org.apache.openjpa.util.UserException;
 
 /**
  * Tracks registered persistence-capable classes.
@@ -33,14 +35,13 @@
 public class PCRegistry {
     // DO NOT ADD ADDITIONAL DEPENDENCIES TO THIS CLASS
 
-    // intentionally left unlocalized to minimize dependencies
-    private static final String COPY_NO_ID = "Cannot copy identity for "
-        + "abstract class ";
-    private static final String NO_META = "No metadata found for class ";
+    private static final Localizer _loc = Localizer.forPackage
+        (PCRegistry.class);
 
     // map of pc classes to meta structs; weak so the VM can GC classes
     private static final Map _metas = new ConcurrentReferenceHashMap
         (ReferenceMap.WEAK, ReferenceMap.HARD);
+
     // register class listeners
     private static final Collection _listeners = new LinkedList();
 
@@ -151,7 +152,7 @@
         Object oid) {
         Meta meta = getMeta(pcClass);
         if (meta.pc == null)
-            throw new IllegalStateException(COPY_NO_ID + pcClass.getName());
+            throw new UserException(_loc.get("copy-no-id", pcClass));
 
         meta.pc.pcCopyKeyFieldsToObjectId(fm, oid);
     }
@@ -164,7 +165,7 @@
         FieldConsumer fm, Object oid) {
         Meta meta = getMeta(pcClass);
         if (meta.pc == null)
-            throw new IllegalStateException(COPY_NO_ID + pcClass.getName());
+            throw new UserException(_loc.get("copy-no-id", pcClass));
 
         meta.pc.pcCopyKeyFieldsFromObjectId(fm, oid);
     }
@@ -219,7 +220,8 @@
     private static Meta getMeta(Class pcClass) {
         Meta ret = (Meta) _metas.get(pcClass);
         if (ret == null)
-            throw new IllegalStateException(NO_META + pcClass.getName());
+            throw new IllegalStateException(_loc.get("no-meta", pcClass).
+                getMessage());
         return ret;
     }
 

Added: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/Reflection.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/Reflection.java?view=auto&rev=489408
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/Reflection.java (added)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/Reflection.java Thu Dec 21 09:08:38 2006
@@ -0,0 +1,537 @@
+package org.apache.openjpa.enhance;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.util.GeneralException; 
+import org.apache.openjpa.util.UserException; 
+
+/**
+ * Reflection utilities used to support and augment enhancement.  Used both
+ * at enhancement time and at runtime.
+ *
+ * @author Abe White
+ */
+public class Reflection {
+
+    private static final Localizer _loc = Localizer.forPackage
+        (Reflection.class);
+
+    /**
+     * Return the getter method matching the given property name, optionally
+     * throwing an exception if none.
+     */
+    public static Method findGetter(Class cls, String prop, boolean mustExist) {
+        prop = StringUtils.capitalize(prop);
+        String name = "get" + prop;
+        try {
+            for (Class c = cls; c != null && c != Object.class; 
+                c = c.getSuperclass()) {
+                try {
+                    return c.getDeclaredMethod(name, (Class[]) null);
+                } catch (NoSuchMethodException nsme) {
+                    try {
+                        Method m = c.getDeclaredMethod("is" + prop, 
+                            (Class[]) null);
+                        if (m != null && (m.getReturnType() == boolean.class
+                            || m.getReturnType() == Boolean.class))
+                            return m;
+                    } catch (NoSuchMethodException nsme2) {
+                    }
+                }
+            }
+        } catch (Exception e) {
+            throw new GeneralException(e);
+        }
+
+        if (mustExist)
+            throw new UserException(_loc.get("bad-getter", cls, prop));
+        return null;
+    }
+
+    /**
+     * Return the setter method matching the given property name, optionally
+     * throwing an exception if none.  The property must also have a getter.
+     */
+    public static Method findSetter(Class cls, String prop, boolean mustExist) {
+        Method getter = findGetter(cls, prop, mustExist);
+        return (getter == null) ? null 
+            : findSetter(cls, prop, getter.getReturnType(), mustExist);
+    }
+
+    /**
+     * Return the setter method matching the given property name, optionally
+     * throwing an exception if none.
+     */
+    public static Method findSetter(Class cls, String prop, Class param,
+        boolean mustExist) {
+        String name = "set" + StringUtils.capitalize(prop);
+        Class[] params = new Class[] { param };
+        try {
+            for (Class c = cls; c != null && c != Object.class; 
+                c = c.getSuperclass()) {
+                try {
+                    return c.getDeclaredMethod(name, params);
+                } catch (NoSuchMethodException nsme) {
+                }
+            }
+        } catch (Exception e) {
+            throw new GeneralException(e);
+        }
+
+        if (mustExist)
+            throw new UserException(_loc.get("bad-setter", cls, prop));
+        return null;
+    }
+
+    /**
+     * Return the field with the given name, optionally throwing an exception 
+     * if none.
+     */
+    public static Field findField(Class cls, String name, boolean mustExist) {
+        try {
+            for (Class c = cls; c != null && c != Object.class; 
+                c = c.getSuperclass()) {
+                try {
+                    return c.getDeclaredField(name);
+                } catch (NoSuchFieldException nsfe) {
+                }
+            }
+        } catch (Exception e) {
+            throw new GeneralException(e);
+        }
+
+        if (mustExist)
+            throw new UserException(_loc.get("bad-field", cls, name));
+        return null;
+    }
+
+    /**
+     * Return the value of the given field in the given object.
+     */
+    public static Object get(Object target, Field field) {
+        if (target == null || field == null)
+            return null;
+        makeAccessible(field, field.getModifiers());
+        try {
+            return field.get(target);
+        } catch (Throwable t) {
+            throw wrapReflectionException(t);
+        }
+    }
+
+    /**
+     * Make the given member accessible if it isn't already.
+     */
+    private static void makeAccessible(AccessibleObject ao, int mods) {
+        try {
+            if (!Modifier.isPublic(mods) && !ao.isAccessible())
+                ao.setAccessible(true);
+        } catch (SecurityException se) {
+            throw new UserException(_loc.get("reflect-security", ao)).
+                setFatal(true);
+        }
+    }
+
+    /**
+     * Wrap the given reflection exception as a runtime exception.
+     */
+    private static RuntimeException wrapReflectionException(Throwable t) {
+        if (t instanceof InvocationTargetException)
+            t = ((InvocationTargetException) t).getTargetException();    
+        if (t instanceof RuntimeException)
+            return (RuntimeException) t;
+        return new GeneralException(t);
+    }
+
+    /**
+     * Return the value of the given field in the given object.
+     */
+    public static boolean getBoolean(Object target, Field field) {
+        if (target == null || field == null)
+            return false;
+        makeAccessible(field, field.getModifiers());
+        try {
+            return field.getBoolean(target);
+        } catch (Throwable t) {
+            throw wrapReflectionException(t);
+        }
+    }
+
+    /**
+     * Return the value of the given field in the given object.
+     */
+    public static byte getByte(Object target, Field field) {
+        if (target == null || field == null)
+            return (byte) 0;
+        makeAccessible(field, field.getModifiers());
+        try {
+            return field.getByte(target);
+        } catch (Throwable t) {
+            throw wrapReflectionException(t);
+        }
+    }
+
+    /**
+     * Return the value of the given field in the given object.
+     */
+    public static char getChar(Object target, Field field) {
+        if (target == null || field == null)
+            return (char) 0;
+        makeAccessible(field, field.getModifiers());
+        try {
+            return field.getChar(target);
+        } catch (Throwable t) {
+            throw wrapReflectionException(t);
+        }
+    }
+
+    /**
+     * Return the value of the given field in the given object.
+     */
+    public static double getDouble(Object target, Field field) {
+        if (target == null || field == null)
+            return 0D;
+        makeAccessible(field, field.getModifiers());
+        try {
+            return field.getDouble(target);
+        } catch (Throwable t) {
+            throw wrapReflectionException(t);
+        }
+    }
+
+    /**
+     * Return the value of the given field in the given object.
+     */
+    public static float getFloat(Object target, Field field) {
+        if (target == null || field == null)
+            return 0F;
+        makeAccessible(field, field.getModifiers());
+        try {
+            return field.getFloat(target);
+        } catch (Throwable t) {
+            throw wrapReflectionException(t);
+        }
+    }
+
+    /**
+     * Return the value of the given field in the given object.
+     */
+    public static int getInt(Object target, Field field) {
+        if (target == null || field == null)
+            return 0;
+        makeAccessible(field, field.getModifiers());
+        try {
+            return field.getInt(target);
+        } catch (Throwable t) {
+            throw wrapReflectionException(t);
+        }
+    }
+
+    /**
+     * Return the value of the given field in the given object.
+     */
+    public static long getLong(Object target, Field field) {
+        if (target == null || field == null)
+            return 0L;
+        makeAccessible(field, field.getModifiers());
+        try {
+            return field.getLong(target);
+        } catch (Throwable t) {
+            throw wrapReflectionException(t);
+        }
+    }
+
+    /**
+     * Return the value of the given field in the given object.
+     */
+    public static short getShort(Object target, Field field) {
+        if (target == null || field == null)
+            return (short) 0;
+        makeAccessible(field, field.getModifiers());
+        try {
+            return field.getShort(target);
+        } catch (Throwable t) {
+            throw wrapReflectionException(t);
+        }
+    }
+
+    /**
+     * Return the return value of the given getter in the given object.
+     */
+    public static Object get(Object target, Method getter) {
+        if (target == null || getter == null)
+            return null;
+        makeAccessible(getter, getter.getModifiers());
+        try {
+            return getter.invoke(target, (Object[]) null);
+        } catch (Throwable t) {
+            throw wrapReflectionException(t);
+        }
+    }
+
+    /**
+     * Return the return value of the given getter in the given object.
+     */
+    public static boolean getBoolean(Object target, Method getter) {
+        Object o = get(target, getter);
+        return (o == null) ? false : ((Boolean) o).booleanValue();
+    }
+
+    /**
+     * Return the return value of the given getter in the given object.
+     */
+    public static byte getByte(Object target, Method getter) {
+        Object o = get(target, getter);
+        return (o == null) ? (byte) 0 : ((Number) o).byteValue();
+    }
+
+    /**
+     * Return the return value of the given getter in the given object.
+     */
+    public static char getChar(Object target, Method getter) {
+        Object o = get(target, getter);
+        return (o == null) ? (char) 0 : ((Character) o).charValue();
+    }
+
+    /**
+     * Return the return value of the given getter in the given object.
+     */
+    public static double getDouble(Object target, Method getter) {
+        Object o = get(target, getter);
+        return (o == null) ? 0D : ((Number) o).doubleValue();
+    }
+
+    /**
+     * Return the return value of the given getter in the given object.
+     */
+    public static float getFloat(Object target, Method getter) {
+        Object o = get(target, getter);
+        return (o == null) ? 0F : ((Number) o).floatValue();
+    }
+
+    /**
+     * Return the return value of the given getter in the given object.
+     */
+    public static int getInt(Object target, Method getter) {
+        Object o = get(target, getter);
+        return (o == null) ? 0 : ((Number) o).intValue();
+    }
+
+    /**
+     * Return the return value of the given getter in the given object.
+     */
+    public static long getLong(Object target, Method getter) {
+        Object o = get(target, getter);
+        return (o == null) ? 0L : ((Number) o).longValue();
+    }
+
+    /**
+     * Return the return value of the given getter in the given object.
+     */
+    public static short getShort(Object target, Method getter) {
+        Object o = get(target, getter);
+        return (o == null) ? (short) 0 : ((Number) o).shortValue();
+    }
+
+    /**
+     * Set the value of the given field in the given object.
+     */
+    public static void set(Object target, Field field, Object value) {
+        if (target == null || field == null)
+            return;
+        makeAccessible(field, field.getModifiers());
+        try {
+            field.set(target, value);
+        } catch (Throwable t) {
+            throw wrapReflectionException(t);
+        }
+    }
+
+    /**
+     * Set the value of the given field in the given object.
+     */
+    public static void set(Object target, Field field, boolean value) {
+        if (target == null || field == null)
+            return;
+        makeAccessible(field, field.getModifiers());
+        try {
+            field.setBoolean(target, value);
+        } catch (Throwable t) {
+            throw wrapReflectionException(t);
+        }
+    }
+
+    /**
+     * Set the value of the given field in the given object.
+     */
+    public static void set(Object target, Field field, byte value) {
+        if (target == null || field == null)
+            return;
+        makeAccessible(field, field.getModifiers());
+        try {
+            field.setByte(target, value);
+        } catch (Throwable t) {
+            throw wrapReflectionException(t);
+        }
+    }
+
+    /**
+     * Set the value of the given field in the given object.
+     */
+    public static void set(Object target, Field field, char value) {
+        if (target == null || field == null)
+            return;
+        makeAccessible(field, field.getModifiers());
+        try {
+            field.setChar(target, value);
+        } catch (Throwable t) {
+            throw wrapReflectionException(t);
+        }
+    }
+
+    /**
+     * Set the value of the given field in the given object.
+     */
+    public static void set(Object target, Field field, double value) {
+        if (target == null || field == null)
+            return;
+        makeAccessible(field, field.getModifiers());
+        try {
+            field.setDouble(target, value);
+        } catch (Throwable t) {
+            throw wrapReflectionException(t);
+        }
+    }
+
+    /**
+     * Set the value of the given field in the given object.
+     */
+    public static void set(Object target, Field field, float value) {
+        if (target == null || field == null)
+            return;
+        makeAccessible(field, field.getModifiers());
+        try {
+            field.setFloat(target, value);
+        } catch (Throwable t) {
+            throw wrapReflectionException(t);
+        }
+    }
+
+    /**
+     * Set the value of the given field in the given object.
+     */
+    public static void set(Object target, Field field, int value) {
+        if (target == null || field == null)
+            return;
+        makeAccessible(field, field.getModifiers());
+        try {
+            field.setInt(target, value);
+        } catch (Throwable t) {
+            throw wrapReflectionException(t);
+        }
+    }
+
+    /**
+     * Set the value of the given field in the given object.
+     */
+    public static void set(Object target, Field field, long value) {
+        if (target == null || field == null)
+            return;
+        makeAccessible(field, field.getModifiers());
+        try {
+            field.setLong(target, value);
+        } catch (Throwable t) {
+            throw wrapReflectionException(t);
+        }
+    }
+
+    /**
+     * Set the value of the given field in the given object.
+     */
+    public static void set(Object target, Field field, short value) {
+        if (target == null || field == null)
+            return;
+        makeAccessible(field, field.getModifiers());
+        try {
+            field.setShort(target, value);
+        } catch (Throwable t) {
+            throw wrapReflectionException(t);
+        }
+    }
+
+    /**
+     * Invoke the given setter on the given object.
+     */
+    public static void set(Object target, Method setter, Object value) {
+        if (target == null || setter == null)
+            return;
+        makeAccessible(setter, setter.getModifiers());
+        try {
+            setter.invoke(target, new Object[] { value });
+        } catch (Throwable t) {
+            throw wrapReflectionException(t);
+        }
+    }
+
+    /**
+     * Invoke the given setter on the given object.
+     */
+    public static void set(Object target, Method setter, boolean value) {
+        set(target, setter, (value) ? Boolean.TRUE : Boolean.FALSE);
+    }
+
+    /**
+     * Invoke the given setter on the given object.
+     */
+    public static void set(Object target, Method setter, byte value) {
+        set(target, setter, new Byte(value));
+    }
+
+    /**
+     * Invoke the given setter on the given object.
+     */
+    public static void set(Object target, Method setter, char value) {
+        set(target, setter, new Character(value));
+    }
+
+    /**
+     * Invoke the given setter on the given object.
+     */
+    public static void set(Object target, Method setter, double value) {
+        set(target, setter, new Double(value));
+    }
+
+    /**
+     * Invoke the given setter on the given object.
+     */
+    public static void set(Object target, Method setter, float value) {
+        set(target, setter, new Float(value));
+    }
+
+    /**
+     * Invoke the given setter on the given object.
+     */
+    public static void set(Object target, Method setter, int value) {
+        set(target, setter, new Integer(value));
+    }
+
+    /**
+     * Invoke the given setter on the given object.
+     */
+    public static void set(Object target, Method setter, long value) {
+        set(target, setter, new Long(value));
+    }
+
+    /**
+     * Invoke the given setter on the given object.
+     */
+    public static void set(Object target, Method setter, short value) {
+        set(target, setter, new Short(value));
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/Reflection.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java?view=diff&rev=489408&r1=489407&r2=489408
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java Thu Dec 21 09:08:38 2006
@@ -25,6 +25,7 @@
 import java.util.Date;
 import java.util.List;
 
+import org.apache.openjpa.enhance.Reflection;
 import org.apache.openjpa.kernel.exps.AggregateListener;
 import org.apache.openjpa.kernel.exps.FilterListener;
 import org.apache.openjpa.lib.util.Localizer;
@@ -854,16 +855,8 @@
         if (target == null || hintKey == null)
             return null;
 
-        Method getter = ImplHelper.getGetter(target.getClass(), hintKey);
-        try {
-            return getter.invoke(target, (Object[]) null);
-        } catch (Exception e) {
-            Throwable t = e;
-            if (e instanceof InvocationTargetException)
-                t = ((InvocationTargetException) e).getTargetException();
-            throw new UserException(_loc.get("bad-getter-hint",
-                target.getClass(), hintKey)).setCause(t);
-        }
+        Method getter = Reflection.findGetter(target.getClass(), hintKey, true);
+        return Reflection.get(target, getter);
     }
 
     /**
@@ -874,22 +867,21 @@
         if (target == null || hintKey == null)
             return;
 
-        Method setter = ImplHelper.getSetter(target.getClass(), hintKey);
-        try {
-            if (value instanceof String) {
-                if ("null".equals(value))
-                    value = null;
-                else
+        Method setter = Reflection.findSetter(target.getClass(), hintKey, true);
+        if (value instanceof String) {
+            if ("null".equals(value))
+                value = null;
+            else {
+                try {
                     value = Strings.parse((String) value,
                         setter.getParameterTypes()[0]);
+                } catch (Exception e) {
+                    throw new UserException(_loc.get("bad-setter-hint-arg",
+                        hintKey, value, setter.getParameterTypes()[0])).
+                        setCause(e);
+                }
             }
-            setter.invoke(target, new Object[]{ value });
-        } catch (Exception e) {
-            Throwable t = e;
-            if (e instanceof InvocationTargetException)
-                t = ((InvocationTargetException) e).getTargetException();
-            throw new UserException(_loc.get("bad-setter-hint",
-				target.getClass (), hintKey, value)).setCause (t);
-		}
+        }
+        Reflection.set(target, setter, value);
 	}
 }

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ObjectIdStateManager.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ObjectIdStateManager.java?view=diff&rev=489408&r1=489407&r2=489408
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ObjectIdStateManager.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ObjectIdStateManager.java Thu Dec 21 09:08:38 2006
@@ -24,6 +24,7 @@
 import org.apache.commons.lang.StringUtils;
 import org.apache.openjpa.enhance.PersistenceCapable;
 import org.apache.openjpa.enhance.StateManager;
+import org.apache.openjpa.enhance.Reflection;
 import org.apache.openjpa.meta.ClassMetaData;
 import org.apache.openjpa.meta.FieldMetaData;
 import org.apache.openjpa.meta.JavaTypes;
@@ -689,30 +690,17 @@
             return null;
 
         FieldMetaData fmd = getMetaData().getField(field);
-        try {
-            if (fmd.getBackingMember() instanceof Field)
-                return ((Field) fmd.getBackingMember()).get(_oid);
-            if (fmd.getBackingMember() instanceof Method)
-                return ((Method) fmd.getBackingMember()).
-                    invoke(_oid, (Object[]) null);
-
-            if (fmd.getDefiningMetaData().getAccessType()
-                == ClassMetaData.ACCESS_FIELD)
-                return _oid.getClass().getField(fmd.getName()).get(_oid);
-
-            // property
-            Method meth;
-            try {
-                meth = _oid.getClass().getMethod("get"
-                    + StringUtils.capitalize(fmd.getName()), (Class[]) null);
-            } catch (NoSuchMethodException nsme) {
-                meth = _oid.getClass().getMethod("is"
-                    + StringUtils.capitalize(fmd.getName()), (Class[]) null);
-            }
-            return meth.invoke(_oid, (Object[]) null);
-        } catch (Exception e) {
-            throw new GeneralException(e);
-        }
+        if (fmd.getBackingMember() instanceof Field)
+            return Reflection.get(_oid, (Field) fmd.getBackingMember());
+        if (fmd.getBackingMember() instanceof Method)
+            return Reflection.get(_oid, (Method) fmd.getBackingMember());
+
+        if (fmd.getDefiningMetaData().getAccessType()
+            == ClassMetaData.ACCESS_FIELD)
+            return Reflection.get(_oid, Reflection.findField(_oid.getClass(), 
+                fmd.getName(), true));
+        return Reflection.get(_oid, Reflection.findGetter(_oid.getClass(),
+            fmd.getName(), true));
     }
 
     /**
@@ -731,18 +719,14 @@
             return;
 
         FieldMetaData fmd = getMetaData().getField(field);
-        try {
-            if (fmd.getBackingMember() instanceof Field)
-                ((Field) fmd.getBackingMember()).set(_oid, val);
-            else if (fmd.getDefiningMetaData().getAccessType()
-                == ClassMetaData.ACCESS_FIELD)
-                _oid.getClass().getField(fmd.getName()).set(_oid, val);
-            else // property
-                _oid.getClass().getMethod("set" + StringUtils.capitalize
-                    (fmd.getName()), new Class[]{ fmd.getDeclaredType() }).
-                    invoke(_oid, new Object[]{ val });
-        } catch (Exception e) {
-            throw new GeneralException(e);
-        }
+        if (fmd.getBackingMember() instanceof Field)
+            Reflection.set(_oid, (Field) fmd.getBackingMember(), val);
+        else if (fmd.getDefiningMetaData().getAccessType()
+            == ClassMetaData.ACCESS_FIELD) {
+            Reflection.set(_oid, Reflection.findField(_oid.getClass(), 
+                fmd.getName(), true), val);
+        } else
+            Reflection.set(_oid, Reflection.findSetter(_oid.getClass(),
+                fmd.getName(), fmd.getDeclaredType(), true), val);
 	}
 }

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ResultPacker.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ResultPacker.java?view=diff&rev=489408&r1=489407&r2=489408
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ResultPacker.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ResultPacker.java Thu Dec 21 09:08:38 2006
@@ -285,10 +285,7 @@
         }
 
         // check setter methods
-        String setName = "set" + Character.toUpperCase(alias.charAt(0));
-        if (alias.length() > 1)
-            setName = setName + alias.substring(1);
-
+        String setName = "set" + StringUtils.capitalize(alias);
         Method method = null;
         boolean eqName = false;
         Class[] params;

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java?view=diff&rev=489408&r1=489407&r2=489408
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java Thu Dec 21 09:08:38 2006
@@ -22,6 +22,7 @@
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.openjpa.enhance.PCRegistry;
+import org.apache.openjpa.enhance.Reflection;
 import org.apache.openjpa.lib.log.Log;
 import org.apache.openjpa.lib.util.Localizer;
 import org.apache.openjpa.util.InternalException;
@@ -183,8 +184,8 @@
                 if (meta.getAccessType() == ClassMetaData.ACCESS_FIELD)
                     member = cls.getDeclaredField(fieldNames[i]);
                 else
-                    member = getBackingMethod(meta.getDescribedType(),
-                        fieldNames[i], fieldTypes[i]);
+                    member = Reflection.findGetter(meta.getDescribedType(),
+                        fieldNames[i], true);
                 fmd = meta.addDeclaredField(fieldNames[i], fieldTypes[i]);
                 fmd.backingMember(member);
                 populate(fmd);
@@ -310,51 +311,13 @@
             if (fmd.getDefiningMetaData().getAccessType() ==
                 ClassMetaData.ACCESS_FIELD)
                 return fmd.getDeclaringType().getDeclaredField(fmd.getName());
-            return getBackingMethod(fmd.getDeclaringType(), fmd.getName(),
-                fmd.getDeclaredType());
+            return Reflection.findGetter(fmd.getDeclaringType(), fmd.getName(),
+                true);
         } catch (OpenJPAException ke) {
             throw ke;
         } catch (Exception e) {
             throw new InternalException(e);
         }
-    }
-
-    /**
-     * Return the method backing the given field metadata. Looks for
-     * "get" and "is" methods with no parameters by default. This looks
-     * for elements defined in <code>cls</code> and its superclasses.
-     */
-    private Method getBackingMethod(Class cls, String name,
-        Class methReturnType)
-        throws NoSuchMethodException {
-        String clsName = cls.getName();
-        String capName = StringUtils.capitalize(name);
-        boolean isBoolean = methReturnType == boolean.class
-            || methReturnType == Boolean.class;
-        do {
-            try {
-                return cls.getDeclaredMethod("get" + capName, (Class[]) null);
-            } catch (NoSuchMethodException e) {
-            }
-
-            if (isBoolean) {
-                try {
-                    return cls.getDeclaredMethod("is" + capName,
-                        (Class[]) null);
-                } catch (NoSuchMethodException e) {
-                }
-            }
-            // ### EJB3: recursion should be limited to manageable types,
-            // ### including embeddable and embeddable superclass
-            cls = cls.getSuperclass();
-        }
-        while (cls != null);
-
-        if (!isBoolean)
-            throw new UserException(_loc.get("pc-registry-no-method",
-                name, clsName, "get" + capName));
-        throw new UserException(_loc.get("pc-registry-no-boolean-method",
-            new String[]{ name, clsName, "get" + capName, "is" + capName }));
     }
 
     public Class getUnimplementedExceptionType() {

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java?view=diff&rev=489408&r1=489407&r2=489408
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java Thu Dec 21 09:08:38 2006
@@ -36,6 +36,7 @@
 import org.apache.openjpa.datacache.DataCache;
 import org.apache.openjpa.enhance.PCRegistry;
 import org.apache.openjpa.enhance.PersistenceCapable;
+import org.apache.openjpa.enhance.Reflection;
 import org.apache.openjpa.lib.log.Log;
 import org.apache.openjpa.lib.meta.SourceTracker;
 import org.apache.openjpa.lib.util.Localizer;
@@ -1894,95 +1895,45 @@
             throw new MetaDataException(_loc.get("no-pk", _type));
 
         // check that the oid type contains all pk fields
-        try {
-            Field f;
-            Method m;
-            String cap;
-            int type;
-            Class c;
-            int access = meta.getAccessType();
-            for (int i = 0; i < fmds.length; i++) {
-                switch (fmds[i].getDeclaredTypeCode()) {
-                    case JavaTypes.ARRAY:
-                        c = fmds[i].getDeclaredType().getComponentType();
-                        if (c == byte.class || c == Byte.class
-                            || c == char.class || c == Character.class) {
-                            c = fmds[i].getDeclaredType();
-                            break;
-                        }
-                        // else no break
-                    case JavaTypes.PC_UNTYPED:
-                    case JavaTypes.COLLECTION:
-                    case JavaTypes.MAP:
-                    case JavaTypes.OID: // we're validating embedded fields
-                        throw new MetaDataException(_loc.get("bad-pk-type",
-                            fmds[i]));
-                    default:
-                        c = fmds[i].getObjectIdFieldType();
-                }
-
-                if (access == ACCESS_FIELD) {
-                    f = findField(oid, fmds[i].getName(), runtime);
-                    if (f == null || !f.getType().isAssignableFrom(c))
-                        throw new MetaDataException(_loc.get("invalid-id",
-                            _type)).setFailedObject(fmds[i].getName());
-                } else if (access == ACCESS_PROPERTY) {
-                    cap = StringUtils.capitalize(fmds[i].getName());
-                    type = fmds[i].getDeclaredTypeCode();
-
-                    m = findMethod(oid, "get" + cap, null, runtime);
-                    if (m == null && (type == JavaTypes.BOOLEAN
-                        || type == JavaTypes.BOOLEAN_OBJ))
-                        m = findMethod(oid, "is" + cap, null, runtime);
-                    if (m == null || !m.getReturnType().isAssignableFrom(c))
-                        throw new MetaDataException(_loc.get("invalid-id",
-                            _type)).setFailedObject("get" + cap);
-
-                    m = findMethod(oid, "set" + cap,
-                        new Class[]{ fmds[i].getDeclaredType() }, runtime);
-                    if (m == null || m.getReturnType() != void.class)
-                        throw new MetaDataException(_loc.get("invalid-id",
-                            _type)).setFailedObject("set" + cap);
-                }
+        Field f;
+        Method m;
+        Class c;
+        for (int i = 0; i < fmds.length; i++) {
+            switch (fmds[i].getDeclaredTypeCode()) {
+                case JavaTypes.ARRAY:
+                    c = fmds[i].getDeclaredType().getComponentType();
+                    if (c == byte.class || c == Byte.class
+                        || c == char.class || c == Character.class) {
+                        c = fmds[i].getDeclaredType();
+                        break;
+                    }
+                    // else no break
+                case JavaTypes.PC_UNTYPED:
+                case JavaTypes.COLLECTION:
+                case JavaTypes.MAP:
+                case JavaTypes.OID: // we're validating embedded fields
+                    throw new MetaDataException(_loc.get("bad-pk-type",
+                        fmds[i]));
+                default:
+                    c = fmds[i].getObjectIdFieldType();
+            }
+
+            if (meta.getAccessType() == ACCESS_FIELD) {
+                f = Reflection.findField(oid, fmds[i].getName(), false);
+                if (f == null || !f.getType().isAssignableFrom(c))
+                    throw new MetaDataException(_loc.get("invalid-id",
+                        _type, fmds[i].getName()));
+            } else if (meta.getAccessType() == ACCESS_PROPERTY) {
+                m = Reflection.findGetter(oid, fmds[i].getName(), false);
+                if (m == null || !m.getReturnType().isAssignableFrom(c))
+                    throw new MetaDataException(_loc.get("invalid-id",
+                        _type, fmds[i].getName()));
+                m = Reflection.findSetter(oid, fmds[i].getName(),
+                    fmds[i].getDeclaredType(), false);
+                if (m == null || m.getReturnType() != void.class)
+                    throw new MetaDataException(_loc.get("invalid-id",
+                        _type, fmds[i].getName()));
             }
-        } catch (OpenJPAException ke) {
-            throw ke;
-        } catch (Throwable t) {
-            throw new MetaDataException(_loc.get("invalid-id", _type)).
-                setCause(t);
-        }
-    }
-
-    /**
-     * Find the named field, recursing to superclasses if necessary.
-     */
-    private static Field findField(Class c, String name, boolean pub)
-        throws Exception {
-        if (c == null || c == Object.class)
-            return null;
-
-        try {
-            return (pub) ? c.getField(name) : c.getDeclaredField(name);
-        } catch (NoSuchFieldException nsfe) {
-            return (pub) ? null : findField(c.getSuperclass(), name, false);
-        }
-    }
-
-    /**
-     * Find the named method, recursing to superclasses if necessary.
-     */
-    private static Method findMethod(Class c, String name, Class[] params,
-        boolean pub)
-        throws Exception {
-        if (c == null || c == Object.class)
-            return null;
-
-        try {
-            return (pub) ? c.getMethod(name, params)
-                : c.getDeclaredMethod(name, params);
-        } catch (NoSuchMethodException nsfe) {
-            return (pub) ? null : findMethod(c.getSuperclass(), name, params,
-                false);
         }
     }
 

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java?view=diff&rev=489408&r1=489407&r2=489408
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java Thu Dec 21 09:08:38 2006
@@ -16,7 +16,6 @@
 package org.apache.openjpa.util;
 
 import java.lang.reflect.Field;
-import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.Date;
 
@@ -24,6 +23,7 @@
 import org.apache.openjpa.enhance.FieldManager;
 import org.apache.openjpa.enhance.PCRegistry;
 import org.apache.openjpa.enhance.PersistenceCapable;
+import org.apache.openjpa.enhance.Reflection;
 import org.apache.openjpa.kernel.ObjectIdStateManager;
 import org.apache.openjpa.kernel.OpenJPAStateManager;
 import org.apache.openjpa.kernel.StoreManager;
@@ -84,24 +84,15 @@
         if (meta.isObjectIdTypeShared())
             oid = ((ObjectId) oid).getId();
         Class oidType = oid.getClass();
-        try {
-            Field field;
-            Method meth;
-            for (int i = 0; i < fmds.length; i++) {
-                if (meta.getAccessType() == ClassMetaData.ACCESS_FIELD) {
-                    field = oidType.getField(fmds[i].getName());
-                    pks[i] = field.get(oid);
-                } else { // property
-                    meth = ImplHelper.getGetter(oidType, fmds[i].getName());
-                    pks[i] = meth.invoke(oid, (Object[]) null);
-                }
-            }
-            return pks;
-        } catch (OpenJPAException ke) {
-            throw ke;
-        } catch (Throwable t) {
-            throw new GeneralException(t);
+        for (int i = 0; i < fmds.length; i++) {
+            if (meta.getAccessType() == ClassMetaData.ACCESS_FIELD)
+                pks[i] = Reflection.get(oid, Reflection.findField(oidType, 
+                    fmds[i].getName(), true));
+            else
+                pks[i] = Reflection.get(oid, Reflection.findGetter(oidType,
+                    fmds[i].getName(), true));
         }
+        return pks;
     }
 
     /**
@@ -133,19 +124,19 @@
                 case JavaTypes.INT:
                 case JavaTypes.INT_OBJ:
                     if (!convert && !(val instanceof Integer))
-                        throw new ClassCastException("!(x instanceof Byte)");
+                        throw new ClassCastException("!(x instanceof Integer)");
                     return new IntId(meta.getDescribedType(),
                         ((Number) val).intValue());
                 case JavaTypes.LONG:
                 case JavaTypes.LONG_OBJ:
                     if (!convert && !(val instanceof Long))
-                        throw new ClassCastException("!(x instanceof Byte)");
+                        throw new ClassCastException("!(x instanceof Long)");
                     return new LongId(meta.getDescribedType(),
                         ((Number) val).longValue());
                 case JavaTypes.SHORT:
                 case JavaTypes.SHORT_OBJ:
                     if (!convert && !(val instanceof Short))
-                        throw new ClassCastException("!(x instanceof Byte)");
+                        throw new ClassCastException("!(x instanceof Short)");
                     return new ShortId(meta.getDescribedType(),
                         ((Number) val).shortValue());
                 case JavaTypes.STRING:
@@ -174,41 +165,29 @@
 
         // default to reflection
         Class oidType = meta.getObjectIdType();
+        Object copy = null;
         try {
-            // create a new id
-            Object copy = oidType.newInstance();
-
-            // set each field
-            FieldMetaData[] fmds = meta.getPrimaryKeyFields();
-            Field field;
-            Method meth;
-            Class[] paramTypes = null;
-            Object[] params = null;
-            for (int i = 0; i < fmds.length; i++) {
-                if (meta.getAccessType() == ClassMetaData.ACCESS_FIELD) {
-                    field = oidType.getField(fmds[i].getName());
-                    field.set(copy, (convert) ? JavaTypes.convert(pks[i],
-                        fmds[i].getObjectIdFieldTypeCode()) : pks[i]);
-                } else { // property
-                    if (paramTypes == null)
-                        paramTypes = new Class[1];
-                    paramTypes[0] = fmds[i].getDeclaredType();
-                    meth = oidType.getMethod("set" + StringUtils.capitalize
-                        (fmds[i].getName()), paramTypes);
-                    if (params == null)
-                        params = new Object[1];
-                    params[0] = (convert) ? JavaTypes.convert(pks[i],
-                        fmds[i].getObjectIdFieldTypeCode()) : pks[i];
-                    meth.invoke(copy, params);
-                }
-            }
-
-            if (meta.isObjectIdTypeShared())
-                copy = new ObjectId(meta.getDescribedType(), copy);
-            return copy;
+            copy = oidType.newInstance();
         } catch (Throwable t) {
             throw new GeneralException(t);
         }
+
+        FieldMetaData[] fmds = meta.getPrimaryKeyFields();
+        Object val;
+        for (int i = 0; i < fmds.length; i++) {
+            val = (convert) ? JavaTypes.convert(pks[i],
+                fmds[i].getObjectIdFieldTypeCode()) : pks[i];
+            if (meta.getAccessType() == ClassMetaData.ACCESS_FIELD)
+                Reflection.set(copy, Reflection.findField(oidType, 
+                    fmds[i].getName(), true), val); 
+            else
+                Reflection.set(copy, Reflection.findSetter(oidType, 
+                    fmds[i].getName(), fmds[i].getDeclaredType(), true), val);
+        }
+
+        if (meta.isObjectIdTypeShared())
+            copy = new ObjectId(meta.getDescribedType(), copy);
+        return copy;
     }
 
     /**
@@ -306,39 +285,31 @@
             return null;
 
         Class oidType = oid.getClass();
+        Object copy = null;
         try {
-            Object copy = oidType.newInstance();
-            Field field;
-            Method meth;
-            String cap;
-            Class[] paramTypes = null;
-            Object[] params = null;
-            for (int i = 0; i < fmds.length; i++) {
-                if (fmds[i].getManagement() != FieldMetaData.MANAGE_PERSISTENT)
-                    continue;
-
-                if (meta.getAccessType() == ClassMetaData.ACCESS_FIELD) {
-                    field = oidType.getField(fmds[i].getName());
-                    field.set(copy, field.get(oid));
+            copy = oidType.newInstance();
+        } catch (Throwable t) {
+            throw new GeneralException(t);
+        }
+
+        Field field;
+        Object val;
+        for (int i = 0; i < fmds.length; i++) {
+            if (fmds[i].getManagement() != FieldMetaData.MANAGE_PERSISTENT)
+                continue;
+
+            if (meta.getAccessType() == ClassMetaData.ACCESS_FIELD) {
+                    field = Reflection.findField(oidType, fmds[i].getName(),
+                        true);
+                    Reflection.set(copy, field, Reflection.get(oid, field));
                 } else { // property
-                    if (paramTypes == null)
-                        paramTypes = new Class[1];
-                    paramTypes[0] = fmds[i].getObjectIdFieldType();
-                    cap = StringUtils.capitalize(fmds[i].getName());
-                    meth = oidType.getMethod("set" + cap, paramTypes);
-                    if (params == null)
-                        params = new Object[1];
-                    params[0] = ImplHelper.getGetter(oidType, cap).
-                        invoke(oid, (Object[]) null);
-                    meth.invoke(copy, params);
+                    val = Reflection.get(oid, Reflection.findGetter(oidType,
+                        fmds[i].getName(), true));
+                    Reflection.set(copy, Reflection.findSetter(oidType, fmds[i].
+                        getName(), fmds[i].getObjectIdFieldType(), true), val);
                 }
             }
             return copy;
-        } catch (OpenJPAException ke) {
-            throw ke;
-        } catch (Throwable t) {
-            throw new GeneralException(t);
-        }
     }
 
     /**
@@ -352,19 +323,11 @@
 
         ClassMetaData meta = fmd.getDefiningMetaData();
         Class oidType = oid.getClass();
-        try {
-            if (meta.getAccessType() == ClassMetaData.ACCESS_FIELD)
-                return oidType.getField(fmd.getName()).get(oid);
-
-            // property
-            String cap = StringUtils.capitalize(fmd.getName());
-            return ImplHelper.getGetter(oidType, cap).
-                invoke(oid, (Object[]) null);
-        } catch (OpenJPAException ke) {
-            throw ke;
-        } catch (Throwable t) {
-            throw new GeneralException(t);
-        }
+        if (meta.getAccessType() == ClassMetaData.ACCESS_FIELD)
+            return Reflection.get(oid, Reflection.findField(oidType, 
+                fmd.getName(), true));
+        return Reflection.get(oid, Reflection.findGetter(oidType, fmd.getName(),
+            true));
     }
 
     /**

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java?view=diff&rev=489408&r1=489407&r2=489408
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java Thu Dec 21 09:08:38 2006
@@ -15,7 +15,6 @@
  */
 package org.apache.openjpa.util;
 
-import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.BitSet;
 import java.util.Collection;
@@ -50,38 +49,6 @@
 
     private static final Localizer _loc = Localizer.forPackage
         (ImplHelper.class);
-
-    /**
-     * Return the getter method matching the given property name.
-     */
-    public static Method getGetter(Class cls, String prop) {
-        prop = StringUtils.capitalize(prop);
-        try {
-            return cls.getMethod("get" + prop, (Class[]) null);
-        } catch (Exception e) {
-            try {
-                return cls.getMethod("is" + prop, (Class[]) null);
-            } catch (Exception e2) {
-                throw new UserException(_loc.get("bad-getter", cls,
-                    prop)).setCause(e);
-            }
-        }
-    }
-
-    /**
-     * Return the setter method matching the given property name.
-     */
-    public static Method getSetter(Class cls, String prop) {
-        Method getter = getGetter(cls, prop);
-        prop = StringUtils.capitalize(prop);
-        try {
-            return cls.getMethod("set" + prop,
-                new Class[]{ getter.getReturnType() });
-        } catch (Exception e) {
-            throw new UserException(_loc.get("bad-setter", cls, prop)).
-                setCause(e);
-        }
-    }
 
     /**
      * Helper for store manager implementations. This method simply delegates

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/enhance/localizer.properties
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/enhance/localizer.properties?view=diff&rev=489408&r1=489407&r2=489408
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/enhance/localizer.properties (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/enhance/localizer.properties Thu Dec 21 09:08:38 2006
@@ -12,6 +12,13 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+copy-no-oid: Cannot copy identity for abstract type "{0}".
+no-meta: No registered metadata for type "{0}".
+bad-getter: Missing getter for property "{1}" in type "{0}". 
+bad-setter: Missing setter for property "{1}" in type "{0}". 
+bad-field: Missing field for property "{1}" in type "{0}".
+reflect-security: Unable to access "{0}" via reflection.  Make sure OpenJPA \
+    has the "suppressAccessChecks" permission.
 needs-runtime-enhance: "{0}" requires runtime enhancement: {1}
 runtime-enhance-pcclasses: You have enabled runtime enhancement, but have not \
 	specified the set of persistent classes.  OpenJPA must look for metadata \
@@ -35,7 +42,6 @@
 	metadata files are not named properly. See the documentation on metadata \
 	placement for more information.
 enhance-running: Enhancer running on type "{0}".
-enhance-running-oids: Enhancer running on oid: {0}
 enhance-aware: The class does not have metadata - enhanced as persistence-aware.
 enhance-norun: The class is already persistence capable - no enhancement \
 	performed.
@@ -59,7 +65,6 @@
 	bug in JDK 1.4+ when using a custom ClassLoader to enhance a \
 	class that implements java.io.Serializable. If compatibility with \
 	non-enhanced versions of "{0}" is not needed, this warning can be ignored.
-enhance-oid: Enhancing object id type "{0}" to allow member access. 
 enhance-defcons-extern: Type "{0}" requires a public constructor to support \
     detach on serialize.  Making default constructor public.
 cons-access: An error occurred trying to instantiate a custom storage class.

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties?view=diff&rev=489408&r1=489407&r2=489408
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties Thu Dec 21 09:08:38 2006
@@ -341,10 +341,8 @@
 	an aggregate listener.
 bad-filter-listener-hint: Query hint value "{0}" ({1}) cannot be converted \
 	into a filter listener.
-bad-getter-hint: Invoking the getter for hint key "{0}" on "{1}" caused \
-	an error.
-bad-setter-hint: Invoking the setter for hint key "{0}" on "{1}" with \
-	value "{2}" caused an error.
+bad-setter-hint-arg: In query hint "{0}", cannot convert hint value "{1}" to \
+    type "{2}".
 detach-val-mismatch: The instance "{0}" is managed by another context and \
 	cannot be inspected for field values.
 detach-val-badsm: The instance "{0}" has an unknown state manager which \

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties?view=diff&rev=489408&r1=489407&r2=489408
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties Thu Dec 21 09:08:38 2006
@@ -165,9 +165,7 @@
 	primary key fields.
 invalid-id: The id class specified by type "{0}" does not match the \
 	primary key fields of the class.  Make sure your identity class has the \
-	same primary keys as your persistent type, that the access types are the \
-	same, and if you are getting this error at runtime, that you have \
-	your persistent class since last compiling your identity class.
+	same primary keys as your persistent type.  Mismatched property: "{1}"
 null-cons: The id class specified by type "{0}" does not have public a \
 	no-args constructor.
 hc-method: The identity class specified by type "{0}" is not valid, as the \
@@ -242,14 +240,6 @@
 # show up with the prefix will not be included in the list of
 # extensions that are validated by generic tools (such as the enhancer)
 extension-datastore-prefix: jdbc-
-pc-registry-no-method: No method was found for the persistent property "{0}" \
-	declared in "{1}" or one of its superclasses. Searched for a method called \
-	"{2}".
-pc-registry-no-boolean-method: No method was found for the persistent property \
-	"{0}" declared in "{1}" or one of its superclasses. Searched for methods \
-	called "{2}" and "{3}".
-pc-registry-no-field: No field was found for the persistent property "{0}" \
-	declared in "{1}" or one of its superclasses.
 nonpc-field-orderable: Cannot order "{0}" on "{1}", because {0} is not a \
 	relation to another persistent type.  For non-relation fields, you can \
 	only order on the field element values themselves, represented by \

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/util/localizer.properties
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/util/localizer.properties?view=diff&rev=489408&r1=489407&r2=489408
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/util/localizer.properties (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/util/localizer.properties Thu Dec 21 09:08:38 2006
@@ -67,5 +67,3 @@
 unique: A unique constraint violation has occurred. 
 ref-integrity: A referential integrity constraint has occurred.
 no-store-exts: No store-specific facade found matching "{0}".  Using default.
-bad-getter: Missing getter for property "{1}" in type "{0}". 
-bad-setter: Missing setter for property "{1}" in type "{0}". 

Modified: incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java?view=diff&rev=489408&r1=489407&r2=489408
==============================================================================
--- incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java (original)
+++ incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java Thu Dec 21 09:08:38 2006
@@ -28,6 +28,7 @@
 import javax.persistence.EntityManagerFactory;
 
 import org.apache.openjpa.conf.OpenJPAConfiguration;
+import org.apache.openjpa.enhance.Reflection;
 import org.apache.openjpa.kernel.AutoDetach;
 import org.apache.openjpa.kernel.Broker;
 import org.apache.openjpa.kernel.BrokerFactory;
@@ -38,7 +39,6 @@
 import org.apache.openjpa.lib.conf.ProductDerivations;
 import org.apache.openjpa.lib.conf.Value;
 import org.apache.openjpa.lib.util.Localizer;
-import org.apache.openjpa.util.ImplHelper;
 import org.apache.openjpa.util.OpenJPAException;
 import serp.util.Strings;
 
@@ -211,7 +211,7 @@
                 continue; 
             prop = prop.substring(prefix.length());
             try {
-                setter = ImplHelper.getSetter(em.getClass(), prop);
+                setter = Reflection.findSetter(em.getClass(), prop, true);
             } catch (OpenJPAException ke) {
                 if (errs == null)
                     errs = new LinkedList<RuntimeException>();
@@ -228,11 +228,13 @@
                         val = Strings.parse((String) val,
                             setter.getParameterTypes()[0]);
                 }
-                setter.invoke(em, new Object[]{ val });
-            } catch (Exception e) {
+                Reflection.set(em, setter, val);
+            } catch (Throwable t) {
+                while (t.getCause() != null)
+                    t = t.getCause();
                 ArgumentException err = new ArgumentException(_loc.get
                     ("bad-em-prop", prop, entry.getValue()),
-                    new Throwable[]{ e }, null, true);
+                    new Throwable[]{ t }, null, true);
                 if (errs == null)
                     errs = new LinkedList<RuntimeException>();
                 errs.add(err);

Modified: incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java?view=diff&rev=489408&r1=489407&r2=489408
==============================================================================
--- incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java (original)
+++ incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java Thu Dec 21 09:08:38 2006
@@ -43,6 +43,7 @@
 import javax.persistence.PreUpdate;
 import javax.persistence.Transient;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.openjpa.lib.util.Localizer;
 import org.apache.openjpa.meta.AbstractMetaDataDefaults;
 import org.apache.openjpa.meta.ClassMetaData;
@@ -282,8 +283,8 @@
             try {
                 // check for setters for methods
                 Method setter = meta.getDescribedType().getDeclaredMethod("set"
-                    + name.substring(0, 1).toUpperCase() + name.substring(1),
-                    new Class[] { ((Method) member).getReturnType() });
+                    + StringUtils.capitalize(name), new Class[] { 
+                    ((Method) member).getReturnType() });
                 if (setter == null)
                     return false;
             } catch (Exception e) {