Hi all,

I've fixed the bugs reported by Joe in SVN. He also suggested a couple of
enhancements that we'll discuss here or via the bug tracker.

Best regards,
Jerome  

> -----Message d'origine-----
> De : [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] De la part 
> de Jerome Louvel
> Envoyé : jeudi 25 octobre 2007 09:47
> À : [email protected]
> Objet : Re: TransformRepresentation URIResolver Out of order bug
> 
> Hi Joe,
> 
> Thanks for detailling the issues in this class. This URI resolver
> lacks tests indeed.
> 
> Could you provide a SVN patch that would fix those issues? I would
> like that to be fixed before releasing the 1.0.6 version next week.
> 
> Also, if you have time to provide a test case, we could add it to the
> build process :)
> 
> Best regards,
> Jerome
> 
> 
> 2007/10/24, Joe Nellis <[EMAIL PROTECTED]>:
> > Greetings again,
> >
> > There is a bug in the 
> TransformRepresentation.getTransformer() method
> > involving the wrong setURIResolver method being called.  
> The method in
> > question:
> >
> >     public Transformer getTransformer() throws IOException {
> >         if (this.transformer == null) {
> >             try {
> >                 // Prepare the XSLT transformer documents
> >                 StreamSource transformSheet = new StreamSource(
> >                         getTransformSheet().getStream());
> >
> >                 // Create a new transformer as they are not 
> thread safe
> >                 this.transformer = TransformerFactory.newInstance()
> >                         .newTransformer(transformSheet);
> >
> >                 // Set the URI resolver
> >                 transformer.setURIResolver(getURIResolver());
> >             } catch (TransformerConfigurationException tce) {
> >                 throw new IOException("Transformer 
> configuration exception.
> > "
> >                         + tce.getMessage());
> >             } catch (TransformerFactoryConfigurationError tfce) {
> >                 throw new IOException(
> >                         "Transformer factory configuration 
> exception. "
> >                                 + tfce.getMessage());
> >             }
> >         }
> >
> >         return this.transformer;
> >     }
> >
> > The this.transformer assignment calls for an instance of the
> > TransformerFactory, then calls for a new Transformer handing it the
> > transformsheet in the process.  At this point in execution, 
> compiling of the
> > transform sheet is done and any <xsl:include>,<xsl:import> 
> or document()
> > functions will use the default URIResolver.  But in this case, the
> > URIResolver that is intended to be used is set AFTER the 
> stylesheet is
> > compiled, which is after include/import tags need to be resolved.
> >
> > So what is being used as a URIResolver?  Null is the value, 
> and the XSLT
> > spec says that
> > if it's null then the base that the XSLT implementers 
> should use is the
> > address of the current stylesheet as the base reference.  
> In some contexts
> > of the Transformer, the stylesheet is passed as a file object so the
> > transformer implementation has a chance to resolve 
> include/imports when the
> > URIResolver is null.  In the TransformRepresentation case, 
> it only sees a
> > stream so there is a different default base address, which 
> is usually the
> > working address of the program that is creating Transformer 
> objects.  In the
> > case of using the ServerServlet, for the most part this 
> base address is
> > going to be the application container address.. In the 
> netbeans bundled
> > tomcat it resolves to the tomcat bin folder.  With Resin it resolves
> > somewhat more correctly to the webapps/application root directory.
> >
> > The next problem is that Transformer.setURIResolver is for 
> setting the
> > resolver for ONLY document() function calls in a 
> stylesheet, which are
> > dynamic and resolved at runtime.  Include/import tags are static and
> > resolved at compile time.  The 
> TransformerFactory.setURIResolver is the
> > correct method, it sets the resolver for include/import and 
> document()
> > function.  So the modified code would look like this:
> >
> >   @Override
> >   public Transformer getTransformer() throws IOException {
> >     /* There is no way to set the transformer in this override
> >      * since their is no protected setTransformer method.
> >      * A new Transformer is created for each call.     */
> >     Transformer result = null;
> >     try {
> >       // Prepare the XSLT transformer documents
> >       StreamSource transformSheet = new StreamSource(
> >           getTransformSheet().getStream());
> >
> >       // Get a transformer factory.
> >       TransformerFactory tfactory = 
> TransformerFactory.newInstance();
> >       // Set the URI resolver before compiling the stylesheet
> >       // since all it ever sees is a stream, not a file/path object.
> >       tfactory.setURIResolver(getURIResolver());
> >       // Create a new transformer as they are not thread safe
> >       result = tfactory.newTransformer(transformSheet);
> >
> >     } catch (TransformerConfigurationException tce) {
> >       throw new IOException("Transformer configuration exception. "
> >           + tce.getMessage());
> >     } catch (TransformerFactoryConfigurationError tfce) {
> >       throw new IOException(
> >           "Transformer factory configuration exception. "
> >           + tfce.getMessage());
> >     }
> >     return result;
> >   }
> >
> > Now the behavior actually invokes the default URIResolver for
> > TransformRepresentation, which is the embedded member class 
> ContextResolver.
> > Line 184-185 there seems like an error in forgetting to 
> resolve the base
> > address:
> >
> >                 Response response = 
> this.context.getDispatcher().get(
> >                         targetRef.toString());
> > should be:
> >                 Response response = 
> this.context.getDispatcher().get(
> >                         targetRef.getTargetRef().toString());
> >
> > Otherwise the base address is never resolved.  This base 
> address String
> > value that is passed into the URIResolver is, I think, 
> exclusively the
> > explicitly called base value that is encountered in xslt 
> tags that contain
> > xml:base="path to base" attributes. I'm not positive on 
> that. This is about
> > where I am right now. I think more test cases are needed for the
> > ContextResolver class maybe.  Some transformer 
> implementations may pass the
> > base parameter to the resolver as null or as an empty 
> string. Right now
> > there is no check for this but I would think they both mean 
> the same thing.
> > I'm currently unable to get line 184-185 to return a response with a
> > non-null entity even with a valid reference anyway, so I'm 
> still digging
> > around.
> >
> > Right now I suggest using a custom URIResolver when  you need
> > includes/imports in your xslt files or  you are running under the
> > ServerServlet in a app container.  Unfortunately, there is no
> > TransformRepresentation.setURIResolver as it is locked into 
> it's custom
> > ContextResolver during construction.  So until this is 
> remedied as well, you
> > need to subclass TransformRepresentation anyway and 
> override the entire
> > getTransformer() method to accept your custom resolver.
> >
> > Joe.
> >
> >

Reply via email to