Looks OK to me.
Tim Fennell wrote:
> Hey All,
>
> I've been working on a bug fix for STS-330, which describes a bug
> whereby the property binding code doesn't like working with
> Map.Entry's (and more generally, public properties specified in
> public interfaces, and implemented in private classes).
>
> I've tracked down what I believe is the cause of the problem, and
> have a nice little test case and solution - but since this looks to
> me like a bug in Sun's Java implementation, I'd really like to get
> some other opinions on it before I a) work around it and b) post it
> to the bug parade.
>
> Essentially what's happening is as follows. When introspecting a
> class which is private, but is an implementation of a public
> interface, the Introspector returns PropertyDescriptors which contain
> references to the methods in the private class instead of those in
> the public interface. The JLS (section 6.6.1) defines an object as
> accessible (assuming it's in a different package) only if the object
> is public and the type containing it is public - which in this case
> it's not. So when you invoke the read or write methods, you get
> access exceptions :( This seems to be a bug in the Introspector if
> you ask me.
>
> The second bizarro thing I discovered is that calling isAccessible()
> on public methods of public interfaces seems to return false! So
> you'll see in the example code below that I actually check the
> interface and member for the public modifier, because isAccessible()
> returns false. I can't find anything either way on this in the JLS,
> but given the prior statement (if the member is public and the type
> is public) and no contrary statements about requiring concrete types,
> this seems like a bug also!
>
> Anyway, if someone could take a few minutes to read through the test
> case below, and see if you can find some holes in my logic, I'd
> appreciate it.
>
> -t
>
> -------------------------------------------------------
>
> package net.sourceforge.stripes.test;
>
> import java.beans.BeanInfo;
> import java.beans.Introspector;
> import java.beans.PropertyDescriptor;
> import java.lang.reflect.Method;
> import static java.lang.reflect.Modifier.isPublic;
> import java.util.HashMap;
> import java.util.Map;
>
> public class PrivateInnerTest {
> public static void main(String[] args) throws Exception {
> Map<String,String> map = new HashMap<String,String>();
> map.put("foo", "bar");
> Map.Entry<String,String> entry = map.entrySet().iterator
> ().next();
>
> BeanInfo info = Introspector.getBeanInfo(entry.getClass());
> for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
> Method m1 = pd.getReadMethod();
> Method m2 = resolveAccessibleMethod(m1);
>
> //Works
> System.out.println(pd.getName() + ": " + m2.invoke(entry));
>
> // Explodes sometimes
> System.out.println(pd.getName() + ": " + m1.invoke(entry));
> }
> }
>
> public static final Method resolveAccessibleMethod(Method m)
> throws Exception {
> // If the passed in method is accessible, then just give it
> back.
> if (m.isAccessible()) return m;
>
> final Class<?> clazz = m.getDeclaringClass();
> final String name = m.getName();
> final Class<?>[] ptypes = m.getParameterTypes();
>
> // Else, loop through the interfaces for the declaring
> class, looking for a
> // public version of the method that we can call
> for (Class<?> iface : clazz.getInterfaces()) {
> try {
> Method m2 = iface.getMethod(name, ptypes);
> if (m2.isAccessible()) return m2;
> if (isPublic(iface.getModifiers()) && isPublic
> (m2.getModifiers())) return m2;
> }
> catch (NoSuchMethodException nsme) { /* Not Unexpected.
> */ }
> }
>
> // Else loop through the superclasses looking for a public
> method
> Class<?> c = clazz.getSuperclass();
> while (c != null) {
> try {
> Method m2 = c.getMethod(name, ptypes);
> if (m2.isAccessible()) return m2;
> if (isPublic(c.getModifiers()) && isPublic
> (m2.getModifiers())) return m2;
> }
> catch (NoSuchMethodException nsme) { /* Not Unexpected.
> */ }
>
> c = c.getSuperclass();
> }
>
> // If we haven't found anything at this point, just give up!
> return m;
> }
> }
>
>
>
> -------------------------------------------------------------------------
> Take Surveys. Earn Cash. Influence the Future of IT
> Join SourceForge.net's Techsay panel and you'll get the chance to share your
> opinions on IT & business topics through brief surveys-and earn cash
> http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
> _______________________________________________
> Stripes-development mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/stripes-development
>
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development