diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java index 1a2b78536..2c4446b47 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java @@ -101,7 +101,6 @@ public class PCEnhancer { 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; @@ -205,14 +204,6 @@ public class PCEnhancer { return _pc; } - /** - * 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 @@ public class PCEnhancer { 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 @@ public class PCEnhancer { addAttachDetachCode(); addSerializationCode(); addCloningCode(); - if (enhanceObjectId()) - ret |= ENHANCE_OID; runAuxiliaryEnhancers(); return ret; } @@ -1535,14 +1522,43 @@ public class PCEnhancer { 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 @@ public class PCEnhancer { // 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 @@ public class PCEnhancer { 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(); @@ -1579,6 +1601,30 @@ public class PCEnhancer { code.calculateMaxLocals(); } + /** + * 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 @@ public class PCEnhancer { // this. = id. // 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 @@ public class PCEnhancer { code.invokespecial().setMethod(type, "", 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) @@ -1910,6 +1988,19 @@ public class PCEnhancer { } } + /** + * 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. @@ -2727,123 +2818,6 @@ public class PCEnhancer { } } - /** - * 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}. */ @@ -3716,22 +3690,8 @@ public class PCEnhancer { 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; diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCRegistry.java b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCRegistry.java index dd4bb0523..c62e402aa 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCRegistry.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCRegistry.java @@ -21,8 +21,10 @@ import java.util.Iterator; 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 @@ import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap; 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 @@ public class PCRegistry { 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 @@ public class PCRegistry { 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 @@ public class PCRegistry { 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; } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/Reflection.java b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/Reflection.java new file mode 100644 index 000000000..c038f74c9 --- /dev/null +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/Reflection.java @@ -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)); + } +} diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java index 6136dfe32..4afadcb7d 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java @@ -25,6 +25,7 @@ import java.util.Collection; 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 @@ public class Filters { 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 @@ public class Filters { 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); } } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ObjectIdStateManager.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ObjectIdStateManager.java index bd293f2ea..7231d262d 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ObjectIdStateManager.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ObjectIdStateManager.java @@ -24,6 +24,7 @@ import java.util.BitSet; 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 @@ public class ObjectIdStateManager 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.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 _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.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 @@ public class ObjectIdStateManager 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); } } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ResultPacker.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ResultPacker.java index ed9bcd22b..0323e25b5 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ResultPacker.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ResultPacker.java @@ -285,10 +285,7 @@ public class ResultPacker { } // 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; diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java index c562c7ae2..b2e6d2b6c 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java @@ -22,6 +22,7 @@ import java.lang.reflect.Modifier; 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 @@ public abstract class AbstractMetaDataDefaults 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,8 +311,8 @@ public abstract class AbstractMetaDataDefaults 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) { @@ -319,44 +320,6 @@ public abstract class AbstractMetaDataDefaults } } - /** - * 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 cls 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() { return UnsupportedOperationException.class; } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java index 405916b25..4796d2a3e 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java @@ -36,6 +36,7 @@ import org.apache.openjpa.conf.OpenJPAConfiguration; 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 @@ public class ClassMetaData 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(); } - } 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); + 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())); + } } } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java b/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java index becc59ea3..d2d4db43b 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java @@ -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.commons.lang.StringUtils; 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 @@ public class ApplicationIds { 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 @@ public class ApplicationIds { 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 @@ public class ApplicationIds { // 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 @@ public class ApplicationIds { 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)); - } 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); - } - } - return copy; - } catch (OpenJPAException ke) { - throw ke; + 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 + 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; } /** @@ -352,19 +323,11 @@ public class ApplicationIds { 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)); } /** diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java b/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java index 8830f8d83..575fa21ef 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java @@ -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; @@ -51,38 +50,6 @@ public class ImplHelper { 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 * to the proper singular method for each state manager. diff --git a/openjpa-kernel/src/main/resources/org/apache/openjpa/enhance/localizer.properties b/openjpa-kernel/src/main/resources/org/apache/openjpa/enhance/localizer.properties index 4a282c225..e0f32bf7e 100644 --- a/openjpa-kernel/src/main/resources/org/apache/openjpa/enhance/localizer.properties +++ b/openjpa-kernel/src/main/resources/org/apache/openjpa/enhance/localizer.properties @@ -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 @@ pers-aware: Type "{0}" has no metadata; enhancing as persistence aware. \ 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 @@ enhance-uid-access: An IllegalAccessException occured when trying to \ 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. diff --git a/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties b/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties index 29ab6af64..afd0726d2 100644 --- a/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties +++ b/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties @@ -341,10 +341,8 @@ bad-agg-listener-hint: Query hint value "{0}" ({1}) cannot be converted into \ 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 \ diff --git a/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties b/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties index 79535e16b..fd14c38ac 100644 --- a/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties +++ b/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties @@ -165,9 +165,7 @@ no-pk: Concrete type "{0}" with application identity does not declare any \ 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 @@ val-not-one-pk: The map value type of field "{0}" a derived key must be a \ # 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 \ diff --git a/openjpa-kernel/src/main/resources/org/apache/openjpa/util/localizer.properties b/openjpa-kernel/src/main/resources/org/apache/openjpa/util/localizer.properties index f3a4ab8b2..84adb8e60 100644 --- a/openjpa-kernel/src/main/resources/org/apache/openjpa/util/localizer.properties +++ b/openjpa-kernel/src/main/resources/org/apache/openjpa/util/localizer.properties @@ -67,5 +67,3 @@ dup-oid: A duplicate object id exception has occurred. Each object you \ 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}". diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java index 2f6cb5a36..e836dd17e 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java @@ -28,6 +28,7 @@ import java.util.Set; 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.Configurations; 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 @@ public class EntityManagerFactoryImpl 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(); @@ -228,11 +228,13 @@ public class EntityManagerFactoryImpl 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(); errs.add(err); diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java index 907f929a3..bdce0c80a 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java @@ -43,6 +43,7 @@ import javax.persistence.PreRemove; 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 @@ public class PersistenceMetaDataDefaults 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) {