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) {
|
Class owner) {
|
||||||
// find the actual ancestor class that declares the field, then
|
// find the actual ancestor class that declares the field, then
|
||||||
// check if the class is persistent, and if the field is managed
|
// check if the class is persistent, and if the field is managed
|
||||||
for (; !owner.getName().equals(Object.class.getName());
|
Field f = Reflection.findField(owner, fieldName, false);
|
||||||
owner = owner.getSuperclass()) {
|
if (f == null)
|
||||||
try {
|
|
||||||
owner.getDeclaredField(fieldName);
|
|
||||||
break;
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (owner.getName().equals(Object.class.getName()))
|
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// managed interface
|
// managed interface
|
||||||
|
|
|
@ -47,20 +47,20 @@ public class Reflection {
|
||||||
public static Method findGetter(Class cls, String prop, boolean mustExist) {
|
public static Method findGetter(Class cls, String prop, boolean mustExist) {
|
||||||
prop = StringUtils.capitalize(prop);
|
prop = StringUtils.capitalize(prop);
|
||||||
String name = "get" + prop;
|
String name = "get" + prop;
|
||||||
|
Method m;
|
||||||
try {
|
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;
|
for (Class c = cls; c != null && c != Object.class;
|
||||||
c = c.getSuperclass()) {
|
c = c.getSuperclass()) {
|
||||||
try {
|
m = getDeclaredMethod(c, name, null);
|
||||||
return c.getDeclaredMethod(name, (Class[]) null);
|
if (m != null) {
|
||||||
} catch (NoSuchMethodException nsme) {
|
return m;
|
||||||
try {
|
} else {
|
||||||
Method m = c.getDeclaredMethod("is" + prop,
|
m = getDeclaredMethod(c, "is" + prop, null);
|
||||||
(Class[]) null);
|
|
||||||
if (m != null && (m.getReturnType() == boolean.class
|
if (m != null && (m.getReturnType() == boolean.class
|
||||||
|| m.getReturnType() == Boolean.class))
|
|| m.getReturnType() == Boolean.class))
|
||||||
return m;
|
return m;
|
||||||
} catch (NoSuchMethodException nsme2) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -89,14 +89,13 @@ public class Reflection {
|
||||||
public static Method findSetter(Class cls, String prop, Class param,
|
public static Method findSetter(Class cls, String prop, Class param,
|
||||||
boolean mustExist) {
|
boolean mustExist) {
|
||||||
String name = "set" + StringUtils.capitalize(prop);
|
String name = "set" + StringUtils.capitalize(prop);
|
||||||
Class[] params = new Class[] { param };
|
Method m;
|
||||||
try {
|
try {
|
||||||
for (Class c = cls; c != null && c != Object.class;
|
for (Class c = cls; c != null && c != Object.class;
|
||||||
c = c.getSuperclass()) {
|
c = c.getSuperclass()) {
|
||||||
try {
|
m = getDeclaredMethod(c, name, param);
|
||||||
return c.getDeclaredMethod(name, params);
|
if (m != null)
|
||||||
} catch (NoSuchMethodException nsme) {
|
return m;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new GeneralException(e);
|
throw new GeneralException(e);
|
||||||
|
@ -107,18 +106,42 @@ public class Reflection {
|
||||||
return null;
|
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
|
* Return the field with the given name, optionally throwing an exception
|
||||||
* if none.
|
* if none.
|
||||||
*/
|
*/
|
||||||
public static Field findField(Class cls, String name, boolean mustExist) {
|
public static Field findField(Class cls, String name, boolean mustExist) {
|
||||||
try {
|
try {
|
||||||
|
Field f;
|
||||||
for (Class c = cls; c != null && c != Object.class;
|
for (Class c = cls; c != null && c != Object.class;
|
||||||
c = c.getSuperclass()) {
|
c = c.getSuperclass()) {
|
||||||
try {
|
f = getDeclaredField(c, name);
|
||||||
return c.getDeclaredField(name);
|
if (f != null)
|
||||||
} catch (NoSuchFieldException nsfe) {
|
return f;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new GeneralException(e);
|
throw new GeneralException(e);
|
||||||
|
@ -129,6 +152,22 @@ public class Reflection {
|
||||||
return null;
|
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.
|
* 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.LongId;
|
||||||
import org.apache.openjpa.util.MetaDataException;
|
import org.apache.openjpa.util.MetaDataException;
|
||||||
import org.apache.openjpa.util.ObjectId;
|
import org.apache.openjpa.util.ObjectId;
|
||||||
import org.apache.openjpa.util.OpenJPAException;
|
|
||||||
import org.apache.openjpa.util.OpenJPAId;
|
import org.apache.openjpa.util.OpenJPAId;
|
||||||
import org.apache.openjpa.util.ShortId;
|
import org.apache.openjpa.util.ShortId;
|
||||||
import org.apache.openjpa.util.StringId;
|
import org.apache.openjpa.util.StringId;
|
||||||
|
@ -117,6 +116,10 @@ public class ClassMetaData
|
||||||
private static final Localizer _loc = Localizer.forPackage
|
private static final Localizer _loc = Localizer.forPackage
|
||||||
(ClassMetaData.class);
|
(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 MetaDataRepository _repos;
|
||||||
private transient ClassLoader _loader = null;
|
private transient ClassLoader _loader = null;
|
||||||
|
|
||||||
|
@ -784,8 +787,9 @@ public class ClassMetaData
|
||||||
synchronized (_ifaceMap) {
|
synchronized (_ifaceMap) {
|
||||||
Map fields = (Map) _ifaceMap.get(iface);
|
Map fields = (Map) _ifaceMap.get(iface);
|
||||||
if (fields == null)
|
if (fields == null)
|
||||||
return new String[0];
|
return EMPTY_STRING_ARRAY;
|
||||||
return (String[]) fields.keySet().toArray(new String[0]);
|
return (String[]) fields.keySet().toArray(
|
||||||
|
new String[fields.size()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1397,15 +1401,12 @@ public class ClassMetaData
|
||||||
if (fieldName == null || SYNTHETIC.equals(fieldName))
|
if (fieldName == null || SYNTHETIC.equals(fieldName))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
for (Class type = _type; type != null && type != Object.class;
|
Field f = Reflection.findField(_type, fieldName, false);
|
||||||
type = type.getSuperclass()) {
|
if (f != null)
|
||||||
try {
|
return f;
|
||||||
return type.getDeclaredField(fieldName);
|
else
|
||||||
} catch (Exception e) {
|
throw new MetaDataException(
|
||||||
}
|
_loc.get("no-detach-state", fieldName, _type));
|
||||||
}
|
|
||||||
throw new MetaDataException(_loc.get("no-detach-state", fieldName,
|
|
||||||
_type));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1823,7 +1824,7 @@ public class ClassMetaData
|
||||||
ClassMetaData embed = pks[0].getEmbeddedMetaData();
|
ClassMetaData embed = pks[0].getEmbeddedMetaData();
|
||||||
validateAppIdClassMethods(embed.getDescribedType());
|
validateAppIdClassMethods(embed.getDescribedType());
|
||||||
validateAppIdClassPKs(embed, embed.getFields(),
|
validateAppIdClassPKs(embed, embed.getFields(),
|
||||||
embed.getDescribedType(), runtime);
|
embed.getDescribedType());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1850,7 +1851,7 @@ public class ClassMetaData
|
||||||
validateAppIdClassMethods(_objectId);
|
validateAppIdClassMethods(_objectId);
|
||||||
|
|
||||||
// make sure the app id class has all pk fields
|
// 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.
|
* Validate that the primary key class has all pk fields.
|
||||||
*/
|
*/
|
||||||
private void validateAppIdClassPKs(ClassMetaData meta,
|
private void validateAppIdClassPKs(ClassMetaData meta,
|
||||||
FieldMetaData[] fmds, Class oid, boolean runtime) {
|
FieldMetaData[] fmds, Class oid) {
|
||||||
if (fmds.length == 0 && !Modifier.isAbstract(meta.getDescribedType().
|
if (fmds.length == 0 && !Modifier.isAbstract(meta.getDescribedType().
|
||||||
getModifiers()))
|
getModifiers()))
|
||||||
throw new MetaDataException(_loc.get("no-pk", _type));
|
throw new MetaDataException(_loc.get("no-pk", _type));
|
||||||
|
@ -2012,7 +2013,7 @@ public class ClassMetaData
|
||||||
*/
|
*/
|
||||||
public FetchGroup[] getDeclaredFetchGroups() {
|
public FetchGroup[] getDeclaredFetchGroups() {
|
||||||
if (_fgs == null)
|
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()]);
|
_fgMap.values().toArray(new FetchGroup[_fgMap.size()]);
|
||||||
return _fgs;
|
return _fgs;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue