Hi Tim Looks fine to me too...
/Jeppe > -----Original Message----- > From: [EMAIL PROTECTED] [mailto:stripes- > [EMAIL PROTECTED] On Behalf Of Tim Fennell > Sent: 2. april 2007 16:14 > To: Stripes Development List > Subject: [Stripes-dev] Introspector/PropertyDescriptor issues > > 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 > > > __________ NOD32 2164 (20070402) Information __________ > > This message was checked by NOD32 antivirus system. > http://www.eset.com ------------------------------------------------------------------------- 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
