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

Reply via email to