OPENJPA-219. Avoid Class.getDeclaredField() / Class.getDeclaredMethod() in Reflection, since they throw exceptions as a side-effect. Also contains assorted clean-up in ClassMetaData.

git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@532137 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Patrick Linskey 2007-04-24 23:34:46 +00:00
parent 6bad8ff715
commit 0e7feca04a
3 changed files with 82 additions and 49 deletions

View File

@ -687,15 +687,8 @@ public class PCEnhancer {
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

View File

@ -47,20 +47,20 @@ public class Reflection {
public static Method findGetter(Class cls, String prop, boolean mustExist) {
prop = StringUtils.capitalize(prop);
String name = "get" + prop;
Method m;
try {
// 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);
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 (NoSuchMethodException nsme2) {
}
}
}
} catch (Exception e) {
@ -89,14 +89,13 @@ public class Reflection {
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;
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);
@ -107,18 +106,42 @@ public class Reflection {
return null;
}
/**
* 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 {
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);
@ -129,6 +152,22 @@ public class Reflection {
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;
}
/**
* Return the value of the given field in the given object.
*/

View File

@ -55,7 +55,6 @@ import org.apache.openjpa.util.InternalException;
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 @@ public class ClassMetaData
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 @@ public class ClassMetaData
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 @@ public class ClassMetaData
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 @@ public class ClassMetaData
ClassMetaData embed = pks[0].getEmbeddedMetaData();
validateAppIdClassMethods(embed.getDescribedType());
validateAppIdClassPKs(embed, embed.getFields(),
embed.getDescribedType(), runtime);
embed.getDescribedType());
}
return;
}
@ -1850,7 +1851,7 @@ public class ClassMetaData
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 @@ public class ClassMetaData
* 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 class ClassMetaData
*/
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;
}