commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Donnie Hale" <don...@haleonline.net>
Subject RE: Digester yielding IllegalAccessException in CallMethodRule, SetNextRule
Date Sat, 08 Dec 2001 17:30:36 GMT
Oops - "direct *c*all behavior" :)

Donnie


> -----Original Message-----
> From: Donnie Hale [mailto:donnie@haleonline.net]
> Sent: Saturday, December 08, 2001 12:09 PM
> To: Jakarta Commons Developers List
> Subject: RE: Digester yielding IllegalAccessException in CallMethodRule,
> SetNextRule
>
>
> +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:robertdonkin@mac.com]
> > 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 <donnie@haleonline.net>
> > >>> Reply-To: Jakarta Commons Developers List
> > >> <commons-dev@jakarta.apache.org>
> > >>> To: Jakarta Commons Developers List <commons-dev@jakarta.apache.org>
> > >>> 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 <donnie@haleonline.net>
> > >>>> Reply-To: Jakarta Commons Developers List
> > >> <commons-dev@jakarta.apache.org>
> > >>>> To: commons-dev@jakarta.apache.org
> > >>>> 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:commons-dev-unsubscribe@jakarta.apache.org>
> > >>>> For additional commands, e-mail:
> > >>> <mailto:commons-dev-help@jakarta.apache.org>
> > >>>>
> > >>>>
> > >>>
> > >>>
> > >>> --
> > >>> To unsubscribe, e-mail:
> > >>> <mailto:commons-dev-unsubscribe@jakarta.apache.org>
> > >>> For additional commands, e-mail:
> > >>> <mailto:commons-dev-help@jakarta.apache.org>
> > >>>
> > >>>
> > >>>
> > >>> --
> > >>> To unsubscribe, e-mail:
> > >> <mailto:commons-dev-unsubscribe@jakarta.apache.org>
> > >>> For additional commands, e-mail:
> > >> <mailto:commons-dev-help@jakarta.apache.org>
> > >>>
> > >>>
> > >>
> > >>
> > >> --
> > >> To unsubscribe, e-mail:
> > >> <mailto:commons-dev-unsubscribe@jakarta.apache.org>
> > >> For additional commands, e-mail:
> > >> <mailto:commons-dev-help@jakarta.apache.org>
> > >>
> > >>
> > >
> > >
> > > --
> > > To unsubscribe, e-mail:
> <mailto:commons-dev-unsubscribe@jakarta.apache.
> > org>
> > For additional commands, e-mail:
<mailto:commons-dev-help@jakarta.apache.
> org>
>


--
To unsubscribe, e-mail:
<mailto:commons-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail:
<mailto:commons-dev-help@jakarta.apache.org>



--
To unsubscribe, e-mail:
<mailto:commons-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail:
<mailto:commons-dev-help@jakarta.apache.org>



--
To unsubscribe, e-mail:   <mailto:commons-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:commons-dev-help@jakarta.apache.org>


Mime
View raw message