You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pc...@apache.org on 2007/04/25 01:34:46 UTC

svn commit: r532137 - in /incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa: enhance/PCEnhancer.java enhance/Reflection.java meta/ClassMetaData.java

Author: pcl
Date: Tue Apr 24 16:34:46 2007
New Revision: 532137

URL: http://svn.apache.org/viewvc?view=rev&rev=532137
Log:
OPENJPA-219. Avoid Class.getDeclaredField() / Class.getDeclaredMethod() in Reflection, since they throw exceptions as a side-effect. Also contains assorted clean-up in ClassMetaData.

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/Reflection.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.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=532137&r1=532136&r2=532137
==============================================================================
--- 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 Tue Apr 24 16:34:46 2007
@@ -687,15 +687,8 @@
         Class owner) {
         // find the actual ancestor class that declares the field, then
         // check if the class is persistent, and if the field is managed
-        for (; !owner.getName().equals(Object.class.getName());
-            owner = owner.getSuperclass()) {
-            try {
-                owner.getDeclaredField(fieldName);
-                break;
-            } catch (Exception e) {
-            }
-        }
-        if (owner.getName().equals(Object.class.getName()))
+        Field f = Reflection.findField(owner, fieldName, false);
+        if (f == null)
             return null;
 
         // managed interface

Modified: 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=diff&rev=532137&r1=532136&r2=532137
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/Reflection.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/Reflection.java Tue Apr 24 16:34:46 2007
@@ -47,20 +47,20 @@
     public static Method findGetter(Class cls, String prop, boolean mustExist) {
         prop = StringUtils.capitalize(prop);
         String name = "get" + prop;
+        Method m;
         try {
-            for (Class c = cls; c != null && c != Object.class; 
+            // this algorithm searches for a get<prop> or is<prop> method in
+            // a breadth-first manner.
+            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) {
-                    }
+                m = getDeclaredMethod(c, name, null);
+                if (m != null) {
+                    return m;
+                } else {
+                    m = getDeclaredMethod(c, "is" + prop, null);
+                    if (m != null && (m.getReturnType() == boolean.class
+                        || m.getReturnType() == Boolean.class))
+                        return m;
                 }
             }
         } catch (Exception e) {
@@ -89,14 +89,13 @@
     public static Method findSetter(Class cls, String prop, Class param,
         boolean mustExist) {
         String name = "set" + StringUtils.capitalize(prop);
-        Class[] params = new Class[] { param };
+        Method m;
         try {
-            for (Class c = cls; c != null && c != Object.class; 
+            for (Class c = cls; c != null && c != Object.class;
                 c = c.getSuperclass()) {
-                try {
-                    return c.getDeclaredMethod(name, params);
-                } catch (NoSuchMethodException nsme) {
-                }
+                m = getDeclaredMethod(c, name, param);
+                if (m != null)
+                    return m;
             }
         } catch (Exception e) {
             throw new GeneralException(e);
@@ -108,17 +107,41 @@
     }
 
     /**
-     * Return the field with the given name, optionally throwing an exception 
+     * Invokes <code>cls.getDeclaredMethods()</code>, and returns the method
+     * that matches the <code>name</code> and <code>param</code> arguments.
+     * Avoids the exception thrown by <code>Class.getDeclaredMethod()</code>
+     * for performance reasons. <code>param</code> may be null.
+     *
+     * @since 0.9.8
+     */
+    private static Method getDeclaredMethod(Class cls, String name,
+        Class param) {
+        Method[] methods = cls.getDeclaredMethods();
+        for (int i = 0 ; i < methods.length; i++) {
+    	    if (name.equals(methods[i].getName())) {
+                Class[] methodParams = methods[i].getParameterTypes();
+                if (param == null && methodParams.length == 0)
+                    return methods[i];
+                if (param != null && methodParams.length == 1
+                    && param.equals(methodParams[0]))
+                    return methods[i];
+            }
+        }
+        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; 
+            Field f;
+            for (Class c = cls; c != null && c != Object.class;
                 c = c.getSuperclass()) {
-                try {
-                    return c.getDeclaredField(name);
-                } catch (NoSuchFieldException nsfe) {
-                }
+                f = getDeclaredField(c, name);
+                if (f != null)
+                    return f;
             }
         } catch (Exception e) {
             throw new GeneralException(e);
@@ -126,6 +149,22 @@
 
         if (mustExist)
             throw new UserException(_loc.get("bad-field", cls, name));
+        return null;
+    }
+
+    /**
+     * Invokes <code>cls.getDeclaredFields()</code>, and returns the field
+     * that matches the <code>name</code> argument.  Avoids the exception
+     * thrown by <code>Class.getDeclaredField()</code> for performance reasons.
+     *
+     * @since 0.9.8
+     */
+    private static Field getDeclaredField(Class cls, String name) {
+        Field[] fields = cls.getDeclaredFields();
+        for (int i = 0 ; i < fields.length; i++) {
+    	    if (name.equals(fields[i].getName()))
+		        return fields[i];
+        }
         return null;
     }
 

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=532137&r1=532136&r2=532137
==============================================================================
--- 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 Tue Apr 24 16:34:46 2007
@@ -55,7 +55,6 @@
 import org.apache.openjpa.util.LongId;
 import org.apache.openjpa.util.MetaDataException;
 import org.apache.openjpa.util.ObjectId;
-import org.apache.openjpa.util.OpenJPAException;
 import org.apache.openjpa.util.OpenJPAId;
 import org.apache.openjpa.util.ShortId;
 import org.apache.openjpa.util.StringId;
@@ -117,6 +116,10 @@
     private static final Localizer _loc = Localizer.forPackage
         (ClassMetaData.class);
 
+    private static final FetchGroup[] EMPTY_FETCH_GROUP_ARRAY
+        = new FetchGroup[0];
+    private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
     private MetaDataRepository _repos;
     private transient ClassLoader _loader = null;
 
@@ -784,8 +787,9 @@
         synchronized (_ifaceMap) {
             Map fields = (Map) _ifaceMap.get(iface);
             if (fields == null)
-                return new String[0];
-            return (String[]) fields.keySet().toArray(new String[0]);
+                return EMPTY_STRING_ARRAY;
+            return (String[]) fields.keySet().toArray(
+                new String[fields.size()]);
         }
     }
     
@@ -1397,15 +1401,12 @@
         if (fieldName == null || SYNTHETIC.equals(fieldName))
             return null;
 
-        for (Class type = _type; type != null && type != Object.class;
-            type = type.getSuperclass()) {
-            try {
-                return type.getDeclaredField(fieldName);
-            } catch (Exception e) {
-            }
-        }
-        throw new MetaDataException(_loc.get("no-detach-state", fieldName,
-            _type));
+        Field f = Reflection.findField(_type, fieldName, false);
+        if (f != null)
+            return f;
+        else
+            throw new MetaDataException(
+                _loc.get("no-detach-state", fieldName, _type));
     }
 
     /**
@@ -1823,7 +1824,7 @@
                 ClassMetaData embed = pks[0].getEmbeddedMetaData();
                 validateAppIdClassMethods(embed.getDescribedType());
                 validateAppIdClassPKs(embed, embed.getFields(),
-                    embed.getDescribedType(), runtime);
+                    embed.getDescribedType());
             }
             return;
         }
@@ -1850,7 +1851,7 @@
                 validateAppIdClassMethods(_objectId);
 
             // make sure the app id class has all pk fields
-            validateAppIdClassPKs(this, pks, _objectId, runtime);
+            validateAppIdClassPKs(this, pks, _objectId);
         }
     }
 
@@ -1904,7 +1905,7 @@
      * Validate that the primary key class has all pk fields.
      */
     private void validateAppIdClassPKs(ClassMetaData meta,
-        FieldMetaData[] fmds, Class oid, boolean runtime) {
+        FieldMetaData[] fmds, Class oid) {
         if (fmds.length == 0 && !Modifier.isAbstract(meta.getDescribedType().
             getModifiers()))
             throw new MetaDataException(_loc.get("no-pk", _type));
@@ -2012,7 +2013,7 @@
      */
     public FetchGroup[] getDeclaredFetchGroups() {
         if (_fgs == null)
-            _fgs = (_fgMap == null) ? new FetchGroup[0] : (FetchGroup[])
+            _fgs = (_fgMap == null) ? EMPTY_FETCH_GROUP_ARRAY : (FetchGroup[])
                 _fgMap.values().toArray(new FetchGroup[_fgMap.size()]); 
         return _fgs;
     }