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 Thu, 06 Dec 2001 02:04:00 GMT
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>


Mime
View raw message