You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by cr...@apache.org on 2001/02/03 03:12:25 UTC
cvs commit: jakarta-struts/src/share/org/apache/struts/util PropertyUtils.java
craigmcc 01/02/02 18:12:25
Modified: src/share/org/apache/struts/util PropertyUtils.java
Log:
Make property introspection smarter, so that you can invoke a method
that is public in an implemented interface, even if the implementing class
is not itself public. Among other things, this makes iteration over the
Map.Entry values returned for a Map work correctly. Hats off to Martin
for figuring out how to do this!!!
Submitted by: Martin Cooper <ma...@tumbleweed.com>
Revision Changes Path
1.12 +89 -8 jakarta-struts/src/share/org/apache/struts/util/PropertyUtils.java
Index: PropertyUtils.java
===================================================================
RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/util/PropertyUtils.java,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- PropertyUtils.java 2001/01/10 01:54:21 1.11
+++ PropertyUtils.java 2001/02/03 02:12:25 1.12
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/util/PropertyUtils.java,v 1.11 2001/01/10 01:54:21 craigmcc Exp $
- * $Revision: 1.11 $
- * $Date: 2001/01/10 01:54:21 $
+ * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/util/PropertyUtils.java,v 1.12 2001/02/03 02:12:25 craigmcc Exp $
+ * $Revision: 1.12 $
+ * $Date: 2001/02/03 02:12:25 $
*
* ====================================================================
*
@@ -71,6 +71,7 @@
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
/**
@@ -116,7 +117,7 @@
* @author Craig R. McClanahan
* @author Ralph Schaer
* @author Chris Audley
- * @version $Revision: 1.11 $ $Date: 2001/01/10 01:54:21 $
+ * @version $Revision: 1.12 $ $Date: 2001/02/03 02:12:25 $
*/
public final class PropertyUtils {
@@ -298,7 +299,7 @@
}
// Otherwise, the underlying property must be an array
- Method readMethod = descriptor.getReadMethod();
+ Method readMethod = getReadMethod(descriptor);
if (readMethod == null)
throw new NoSuchMethodException("Property '" + name +
"' has no getter method");
@@ -581,7 +582,7 @@
if (descriptor == null)
throw new NoSuchMethodException("Unknown property '" +
name + "'");
- Method readMethod = descriptor.getReadMethod();
+ Method readMethod = getReadMethod(descriptor);
if (readMethod == null)
throw new NoSuchMethodException("Property '" + name +
"' has no getter method");
@@ -690,7 +691,7 @@
}
// Otherwise, the underlying property must be an array
- Method readMethod = descriptor.getReadMethod();
+ Method readMethod = descriptor.getReadMethod();
if (readMethod == null)
throw new NoSuchMethodException("Property '" + name +
"' has no getter method");
@@ -813,7 +814,7 @@
if (descriptor == null)
throw new NoSuchMethodException("Unknown property '" +
name + "'");
- Method writeMethod = descriptor.getWriteMethod();
+ Method writeMethod = getWriteMethod(descriptor);
if (writeMethod == null)
throw new NoSuchMethodException("Property '" + name +
"' has no setter method");
@@ -822,6 +823,86 @@
Object values[] = new Object[1];
values[0] = value;
writeMethod.invoke(bean, values);
+
+ }
+
+
+ // -------------------------------------------------------- Private Methods
+
+
+ /**
+ * Return an accessible method (that is, one that can be invoked via
+ * reflection) that implements the specified Method. If no such method
+ * can be found, return <code>null</code>.
+ *
+ * @param method The method that we wish to call
+ */
+ private static Method getAccessibleMethod(Method method) {
+
+ // Make sure we have a method to check
+ if (method == null) {
+ return (null);
+ }
+
+ // If the requested method is not public we cannot call it
+ if (!Modifier.isPublic(method.getModifiers())) {
+ return (null);
+ }
+
+ // If the declaring class is public, we are done
+ Class clazz = method.getDeclaringClass();
+ if (Modifier.isPublic(clazz.getModifiers())) {
+ return (method);
+ }
+
+ // Check the implemented interfaces
+ String methodName = method.getName();
+ Class[] parameterTypes = method.getParameterTypes();
+ Class[] interfaces = clazz.getInterfaces();
+ for (int i = 0; i < interfaces.length; i++) {
+ // Is this interface public?
+ if (!Modifier.isPublic(interfaces[i].getModifiers())) {
+ continue;
+ }
+ // Does the method exist on this interface?
+ try {
+ method = interfaces[i].getDeclaredMethod(methodName,
+ parameterTypes);
+ } catch (NoSuchMethodException e) {
+ continue;
+ }
+ // We have found what we are looking for
+ return (method);
+ }
+
+ // We are out of luck
+ return (null);
+
+ }
+
+
+ /**
+ * Return an accessible property getter method for this property,
+ * if there is one; otherwise return <code>null</code>.
+ *
+ * @param descriptor Property descriptor to return a getter for
+ */
+ private static Method getReadMethod(PropertyDescriptor descriptor) {
+
+ return (getAccessibleMethod(descriptor.getReadMethod()));
+
+ }
+
+
+ /**
+ * Return an accessible property setter method for this property,
+ * if there is one; otherwise return <code>null</code>.
+ *
+ * @param descriptor Property descriptor to return a setter for
+ */
+ private static Method getWriteMethod(PropertyDescriptor descriptor) {
+
+ return (getAccessibleMethod(descriptor.getWriteMethod()));
}