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. > > > >

