mirror of https://github.com/apache/openjpa.git
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:
parent
6bad8ff715
commit
0e7feca04a
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue