+1 There's no reason, to my mind, that reflection-based behavior should be different than direct all behavior.
Donnie > -----Original Message----- > From: robert burrell donkin [mailto:[EMAIL PROTECTED]] > Sent: Saturday, December 08, 2001 8:33 AM > To: Jakarta Commons Developers List > Subject: Re: Digester yielding IllegalAccessException in CallMethodRule, > SetNextRule > > > i've played around the example code and craig's diagnosis seems to be > correct (as usual :) > > the Method.getMethod used by digester returns the inner implementation > which is only accessible within the package rather than the public > interface implementation. > > this problem can be fixed - in my test harness - by using the > PropertyUtils.getAccessibleMethod to find an accessible version of the > method. unfortunately, this method is currently private in PropertyUtils. > this is a method which is needed by PropertyUtils but doesn't really > belong in there (it's a general method finder method rather than a > property finder method). > > maybe the right thing to do would be to add a new class (in beanutils) - > MethodUtils? - which would contain the general method-related > methods from > PropertyUtils and which exposed them as public methods. other utility > method-related reflection methods could be added later. the public > interface for PropertyUtils could be maintained but the private > implementations would be moved into this new class. digester could them > use the improved reflection methods in this new class. > > i'm willing to create patches if this plan is acceptable. > > - robert > > > On Thursday, December 6, 2001, at 02:04 AM, Donnie Hale wrote: > > > See below... > > > > Donnie > > > > > >> -----Original Message----- > >> From: craigmcc@localhost [mailto:craigmcc@localhost]On Behalf Of Craig > >> R. McClanahan > >> Sent: Wednesday, December 05, 2001 1:41 AM > >> To: Jakarta Commons Developers List > >> Subject: RE: Digester yielding IllegalAccessException in > CallMethodRule, > >> SetNextRule > >> > >> > >> > >> > >> On Tue, 4 Dec 2001, Donnie Hale wrote: > >> > >>> Date: Tue, 4 Dec 2001 22:44:09 -0500 > >>> From: Donnie Hale <[EMAIL PROTECTED]> > >>> Reply-To: Jakarta Commons Developers List > >> <[EMAIL PROTECTED]> > >>> To: Jakarta Commons Developers List <[EMAIL PROTECTED]> > >>> Subject: RE: Digester yielding IllegalAccessException in > CallMethodRule, > >>> SetNextRule > >>> > >>> Craig, > >>> > >>> Thanks for the prompt response. If I understand your second > >> case, I tried > >>> it, and it worked as I wanted: > >>> > >>> // Callback.java > >>> public class Callback implements Reader.WebXmlFileDigestion > >>> { > >>> public Callback(Driver d) > >>> { > >>> driver_ = d; > >>> } > >>> > >>> public void parseError(Throwable t) throws Exception > >>> { > >>> t.printStackTrace(); > >>> } > >>> > >>> public void setServletMapping( > >>> String servletName, String urlPattern) > >>> { > >>> driver_.addServletMapping(servletName, urlPattern); > >>> } > >>> > >>> Driver driver_; > >>> } > >>> > >>> Then, in Driver.java, I used > >>> > >>> reader.digestWebXmlFile(new Callback(this)); > >>> > >>> instead of passing the anonymous implementing class. > >>> > >> > >> OK, so we know it definitely has something to do with visibility of the > >> called class. > >> > >>> I'll have to see if I have Sun's 1.3 JDK around to try. If not, > >> it could be > >>> a while, as I only have IDSL access. :) > >>> > >>> One more, related, thing, since you're in the know. > >> > >> I better be, since I wrote Digester :-). > >> > >>> Is it possible to > >>> implement an interface with methods which have package scope > though the > >>> interface methods are public? I don't care that some unknown > >> future entity > >>> implements the interface; but I don't want the methods in the > >> implementation > >>> of it that I care about to be publicly accessible. My copy of > >> the language > >>> spec is at work... > >>> > >> > >> I'm sure it's feasible to implement access via reflection > (which is what > >> Digester uses) to methods defined public through an interface - we ran > >> into a similar case in BeanUtils and solved it be looking up an > >> appropriate java.lang.reflect.Method object correctly. I'm > not sure what > >> happens when you shadow a package-private method with a public one -- > >> will > >> have to check on that. However, AFAIK, the class itself has > to be public > >> for any of this to work. > > > > Is the requirement of the class being public an artifact of doing this > > through reflection. If not, I don't understand. As an example, I've got > > this > > code in an app: > > > > File dir = new File(dirName); > > String[] fileList = dir.list( > > new FilenameFilter() > > { > > public boolean accept(java.io.File file, > java.lang.String > > name) > > { > > return name.toLowerCase().endsWith(fileSuffix); > > } > > }); > > > > Clearly, the File.list method needs an impl of FilenameFilter > on which to > > make callbacks. I'm providing it one, anonymously. I'm sure, > though, that > > the callback is direct - not via reflection. This works find for me. > > > > I guess that's my main source of confusion about the whole thing. > > > > > > > >> > >>> Thanks much, > >>> > >>> Donnie > >>> > >> > >> Craig > >> > >> > >>> > >>> -----Original Message----- > >>> From: craigmcc@localhost [mailto:craigmcc@localhost]On Behalf Of Craig > >>> R. McClanahan > >>> Sent: Tuesday, December 04, 2001 10:08 PM > >>> To: Jakarta Commons Developers List > >>> Subject: Re: Digester yielding IllegalAccessException in > CallMethodRule, > >>> SetNextRule > >>> > >>> > >>> Hi Donnie, > >>> > >>> IIRC, Digester only knows how to call public methods of public > >> classes -- > >>> and an anonymous inner class isn't public. > >>> > >>> Could you try two things for me? > >>> * Try this under the Sun JDK just to see if the behavior is different > >>> * Try this where the driver class is a regular public class, > >>> rather than an inner class > >>> > >>> That will help us narrow down where the difficulty is. > >>> > >>> Craig > >>> > >>> > >>> On Tue, 4 Dec 2001, Donnie Hale wrote: > >>> > >>>> Date: Tue, 4 Dec 2001 22:15:20 -0500 > >>>> From: Donnie Hale <[EMAIL PROTECTED]> > >>>> Reply-To: Jakarta Commons Developers List > >> <[EMAIL PROTECTED]> > >>>> To: [EMAIL PROTECTED] > >>>> Subject: Digester yielding IllegalAccessException in CallMethodRule, > >>>> SetNextRule > >>>> > >>>> I searched the list archives and didn't see anything directly > >> on-topic. > >>>> Sorry if I missed it. Also, this is likely a normal Java > >> issue, but I'm > >>> not > >>>> getting it. :( > >>>> > >>>> Here's a very pared down example which reproduces my problem exactly: > >>>> > >>>> // Driver.java > >>>> public class Driver > >>>> { > >>>> public static void main(String[] args) > >>>> { > >>>> try > >>>> { > >>>> Driver driver = new Driver(); > >>>> driver.parseWebApp(new Reader()); > >>>> } > >>>> catch (Exception e) > >>>> { > >>>> e.printStackTrace(); > >>>> } > >>>> } > >>>> > >>>> public void Driver() > >>>> { > >>>> } > >>>> > >>>> public void parseWebApp(Reader reader) throws Exception > >>>> { > >>>> reader.digestWebXmlFile( > >>>> new Reader.WebXmlFileDigestion() > >>>> { > >>>> public void parseError(Throwable t) throws Exception > >>>> { > >>>> t.printStackTrace(); > >>>> } > >>>> > >>>> public void setServletMapping( > >>>> String servletName, String urlPattern) > >>>> { > >>>> addServletMapping(servletName, urlPattern); > >>>> } > >>>> } > >>>> ); > >>>> } > >>>> > >>>> public void addServletMapping(String servletName, String > >> urlPattern) > >>>> { > >>>> System.out.println("Mapping read: " + servletName + " => " + > >>>> urlPattern); > >>>> } > >>>> } > >>>> > >>>> // Reader.java > >>>> import java.io.InputStream; > >>>> import java.io.IOException; > >>>> import java.net.URL; > >>>> import org.xml.sax.Attributes; > >>>> import org.xml.sax.SAXException; > >>>> import org.apache.commons.digester.Digester; > >>>> import org.apache.commons.digester.Rule; > >>>> > >>>> public class Reader > >>>> { > >>>> public static interface WebXmlFileDigestion > >>>> { > >>>> public void parseError(Throwable t) throws Exception; > >>>> > >>>> public void setServletMapping(String servletName, String > >>>> urlPattern); > >>>> } > >>>> > >>>> public void Reader() > >>>> { > >>>> } > >>>> > >>>> public void digestWebXmlFile(WebXmlFileDigestion callback) > >>>> throws Exception > >>>> { > >>>> // Prepare a Digester to scan the web application deployment > >>>> descriptor > >>>> Digester digester = new Digester(); > >>>> digester.push(callback); > >>>> digester.setDebug(1); > >>>> digester.setNamespaceAware(true); > >>>> digester.setValidating(false); > >>>> > >>>> // Register our local copy of the DTDs that we can find > >>>> for (int i = 0; i < registrations_.length; i += 2) > >>>> { > >>>> URL url = > >> this.getClass().getResource(registrations_[i+1]); > >>>> if (url != null) > >>>> { > >>>> digester.register(registrations_[i], url.toString()); > >>>> } > >>>> } > >>>> > >>>> // Configure the processing rules that we need > >>>> digester.addCallMethod("web-app/servlet-mapping", > >>>> "setServletMapping", 2); > >>>> > >> digester.addCallParam("web-app/servlet-mapping/servlet-name", 0); > >>>> > >> digester.addCallParam("web-app/servlet-mapping/url-pattern", 1); > >>>> > >>>> InputStream input= null; > >>>> try > >>>> { > >>>> input = this.getClass().getResourceAsStream("web.xml"); > >>>> digester.parse(input); > >>>> } > >>>> catch (Throwable e) > >>>> { > >>>> callback.parseError(e); > >>>> } > >>>> finally > >>>> { > >>>> if (input != null) > >>>> { > >>>> input.close(); > >>>> } > >>>> } > >>>> } > >>>> > >>>> protected static final String registrations_[] = > >>>> { > >>>> "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN", > >>>> "/org/apache/struts/resources/web-app_2_2.dtd", > >>>> "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN", > >>>> "/org/apache/struts/resources/web-app_2_3.dtd" > >>>> }; > >>>> } > >>>> > >>>> The object on which the method call is to be invoked is an > >> instance of an > >>>> anonymous inner class which implements a public (nested) > >> interface. All > >>> the > >>>> methods on the interface and its anonymous implementation are > >> public. All > >>>> the methods on Driver and Reader are public. Yet when I run > >> this, I get: > >>>> > >>>> java.lang.IllegalAccessException: Driver$1 > >>>> at java.lang.reflect.Method.invoke(Native Method) > >>>> at > >>>> > >> org.apache.commons.digester.CallMethodRule.end(CallMethodRule.java:308) > >>>> at > >>>> org.apache.commons.digester.Digester.endElement(Digester.java:757) > >>>> at > >>>> org.apache.xerces.parsers.SAXParser.endElement(SAXParser.java:1403) > >>>> at > >>>> > >>> > >> org.apache.xerces.validators.common.XMLValidator.callEndElement(XM > >> LValidator > >>>> .java:1480) > >>>> at > >>>> > >>> > >> org.apache.xerces.framework.XMLDocumentScanner$ContentDispatcher.d > >> ispatch(XM > >>>> LDocumentScanner.java:1149) > >>>> at > >>>> > >>> > >> org.apache.xerces.framework.XMLDocumentScanner.parseSome(XMLDocume > >> ntScanner. > >>>> java:381) > >>>> at > >>> org.apache.xerces.framework.XMLParser.parse(XMLParser.java:1081) > >>>> at > >> org.apache.commons.digester.Digester.parse(Digester.java:1206) > >>>> at Reader.digestWebXmlFile(Reader.java:53) > >>>> at Driver.parseWebApp(Driver.java:23) > >>>> at Driver.main(Driver.java:9) > >>>> > >>>> I'm guessing this has something to do with the "Driver$1" being the > >>>> classname. But it sure seems like I've done stuff like this > >> before, just > >>>> possibly not through reflection. Do I have to go to the > >> extreme of making > >>>> the interface implementation non-anonymous to have any hope > of getting > >>> this > >>>> to work? > >>>> > >>>> BTW, I'm using IBM's JDK 1.3 on Win2K. > >>>> > >>>> Thanks much, > >>>> > >>>> Donnie > >>>> > >>>> > >>>> -- > >>>> To unsubscribe, e-mail: > >>> <mailto:[EMAIL PROTECTED]> > >>>> For additional commands, e-mail: > >>> <mailto:[EMAIL PROTECTED]> > >>>> > >>>> > >>> > >>> > >>> -- > >>> To unsubscribe, e-mail: > >>> <mailto:[EMAIL PROTECTED]> > >>> For additional commands, e-mail: > >>> <mailto:[EMAIL PROTECTED]> > >>> > >>> > >>> > >>> -- > >>> To unsubscribe, e-mail: > >> <mailto:[EMAIL PROTECTED]> > >>> For additional commands, e-mail: > >> <mailto:[EMAIL PROTECTED]> > >>> > >>> > >> > >> > >> -- > >> To unsubscribe, e-mail: > >> <mailto:[EMAIL PROTECTED]> > >> For additional commands, e-mail: > >> <mailto:[EMAIL PROTECTED]> > >> > >> > > > > > > -- > > To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]. > org> > For additional commands, e-mail: <mailto:[EMAIL PROTECTED]. > org> > -- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]> -- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
