Return-Path: Delivered-To: apmail-cocoon-dev-archive@www.apache.org Received: (qmail 13590 invoked from network); 2 Oct 2003 14:51:47 -0000 Received: from daedalus.apache.org (HELO mail.apache.org) (208.185.179.12) by minotaur-2.apache.org with SMTP; 2 Oct 2003 14:51:47 -0000 Received: (qmail 15582 invoked by uid 500); 2 Oct 2003 14:51:11 -0000 Delivered-To: apmail-cocoon-dev-archive@cocoon.apache.org Received: (qmail 15519 invoked by uid 500); 2 Oct 2003 14:51:10 -0000 Mailing-List: contact dev-help@cocoon.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: list-post: Reply-To: dev@cocoon.apache.org Delivered-To: mailing list dev@cocoon.apache.org Received: (qmail 15445 invoked from network); 2 Oct 2003 14:51:10 -0000 Received: from unknown (HELO thoth.sbs.de) (192.35.17.2) by daedalus.apache.org with SMTP; 2 Oct 2003 14:51:10 -0000 Received: from mail1.siemens.de (mail1.siemens.de [139.23.33.14]) by thoth.sbs.de (8.11.7/8.11.7) with ESMTP id h92EpBj07739 for ; Thu, 2 Oct 2003 16:51:11 +0200 (MEST) Received: from blues.mchh.siemens.de (blues.mchh.siemens.de [139.21.204.206]) by mail1.siemens.de (8.11.7/8.11.7) with ESMTP id h92EpAn13141 for ; Thu, 2 Oct 2003 16:51:10 +0200 (MEST) Received: from mchh274e.mchh.siemens.de (mchh274e.mchh.siemens.de [139.21.200.84]) by blues.mchh.siemens.de (8.9.3/8.9.1) with ESMTP id QAA29778 for ; Thu, 2 Oct 2003 16:49:38 +0200 (MET DST) Received: by mchh274e.mchh.siemens.de with Internet Mail Service (5.5.2656.59) id ; Thu, 2 Oct 2003 16:50:20 +0200 Message-ID: <33519B8EABFBD61199560002A58EDB3101D6D338@mchh2c3e.mchh.siemens.de> From: Weber Dietmar EXT To: "'dev@cocoon.apache.org'" Subject: XTTransformer Date: Thu, 2 Oct 2003 16:50:18 +0200 MIME-Version: 1.0 X-Mailer: Internet Mail Service (5.5.2656.59) Content-Type: text/plain X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N Hello, Cocoon 2.1 does not contain org.apache.cocoon.transformation.XTTransformer any more. Unfortunately because it is fast and resource sparing. So I added it to my local environment. It had to be modified because of the modified source resolving (excalibur). It works with j2sdk1.4.2_01,tomcat4.1.27,cocoon2.1.2 both on Win2000 and Solaris5.8(Spark). Greetings. ------------------------------------------------------------------------- /* ============================================================================ The Apache Software License, Version 1.1 ============================================================================ Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modifica- tion, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by the Apache Software Foundation (http://www.apache.org/)." Alternately, this acknowledgment may appear in the software itself, if and wherever such third-party acknowledgments normally appear. 4. The names "Apache Cocoon" and "Apache Software Foundation" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact apache@apache.org. 5. Products derived from this software may not be called "Apache", nor may "Apache" appear in their name, without prior written permission of the Apache Software Foundation. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This software consists of voluntary contributions made by many individuals on behalf of the Apache Software Foundation and was originally created by Stefano Mazzocchi . For more information on the Apache Software Foundation, please see . */ package org.apache.cocoon.transformation; import com.jclark.xsl.om.Name; import com.jclark.xsl.om.Node; import com.jclark.xsl.om.XSLException; import com.jclark.xsl.sax.*; import com.jclark.xsl.tr.Engine; import com.jclark.xsl.tr.EngineImpl; import com.jclark.xsl.tr.ParameterSet; import com.jclark.xsl.tr.Sheet; import org.apache.avalon.framework.activity.Disposable; import org.apache.avalon.framework.component.Component; import org.apache.avalon.framework.component.ComponentManager; import org.apache.avalon.framework.component.Composable; import org.apache.avalon.framework.logger.Loggable; import org.apache.avalon.framework.parameters.Parameters; import org.apache.cocoon.Modifiable; import org.apache.cocoon.ProcessingException; // dwe: now excalibur! import org.apache.cocoon.components.store.Store; import org.apache.excalibur.store.Store; import org.apache.excalibur.source.Source; //import org.apache.cocoon.environment.SourceResolver; import org.apache.excalibur.source.SourceResolver; import org.apache.excalibur.source.SourceUtil; import org.apache.cocoon.xml.DocumentHandlerAdapter; import org.apache.cocoon.xml.DocumentHandlerWrapper; import org.apache.cocoon.xml.XMLConsumer; import org.apache.log.Logger; import org.xml.sax.*; import org.xml.sax.ext.LexicalHandler; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import java.io.File; import java.io.InputStream; import java.io.IOException; import java.net.URL; import java.util.HashMap; import java.util.Map; /** * This Transformer use the XT processor. * * @author Sahuc Sebastien * @version CVS $Id: XTTransformer.java,v 1.9 2002/02/22 07:03:56 cziegeler Exp $ */ public class XTTransformer extends DocumentHandlerWrapper implements Transformer, Composable, Loggable, Disposable { private Logger log; /** The component manager */ private ComponentManager manager = null; /** The store service instance */ private Store store = null; /** The XT Processor */ private XTProcessor processor = null; /**The DocumentHandler */ private DocumentHandler docHandler = null; public void setLogger(Logger logger) { if (this.log == null) { this.log = logger; } } /** * Set the current ComponentManager instance used by this * Composable. */ public void compose(ComponentManager manager) { this.manager = manager; try { this.store = (Store) manager.lookup(Store.TRANSIENT_STORE); } catch (Exception e) { log.error("Could not find component for role " + Store.TRANSIENT_STORE, e); } } /** * Set the SourceResolver, the Dictionary with * the object model, the source and sitemap * Parameters used to process the request. */ public void setup(org.apache.cocoon.environment.SourceResolver resolver, Map objectModel, String src, Parameters par) throws SAXException, ProcessingException, IOException { // Check the stylesheet uri String xsluri = src; if (xsluri == null) { throw new ProcessingException("Stylesheet URI can't be null"); } // Get the stylesheet from the Store if available, // otherwise load it and put it into the store for further request XTProcessor loaderprocessor = null; if (store != null) { loaderprocessor = (XTProcessor) store.get(xsluri); if (loaderprocessor != null) { loaderprocessor.setLogger(this.log); loaderprocessor.compose(this.manager); } } // If not in the store or if style sheet has changed, loads and stores it if (loaderprocessor == null || loaderprocessor.hasChanged()) { loaderprocessor= new XTProcessor(); loaderprocessor.setLogger(this.log); loaderprocessor.compose(this.manager); SAXParser saxParser = null; try { saxParser = SAXParserFactory.newInstance().newSAXParser(); } catch (ParserConfigurationException e) { log.error("XTTransformer.setup", e); new ProcessingException(e.getMessage(),e); } loaderprocessor.setParser(saxParser.getParser()); Source source = resolver.resolveURI(xsluri);// dwe: resolve -> resolveURI; InputSource -> Source try { loaderprocessor.loadStylesheet(source);// dwe: InputSource -> Source if (store != null) store.store(xsluri, loaderprocessor); } finally { // dwe source.recycle();// this method was used by the previous xttransformer but is no longer exists! // source.dispose();// dwe: api-doc lists this method but new excalibur lib does not contain it! } } // Always clone the processor before using it, // Indeed 1 instance per thread is allowed this.processor = (XTProcessor) loaderprocessor.clone(); this.processor.setLogger(this.log); this.processor.compose(this.manager); // Create the processor and set it as this documenthandler // FIXME (SS): set the correct SystemId to the XML inputSource DocHandler temp = new DocHandler(processor.createBuilder("XTSystemID")); temp.setLogger(this.log); this.docHandler = temp; this.setDocumentHandler(this.docHandler); } /** * Set the XMLConsumer that will receive XML data. *
* This method will simply call setContentHandler(consumer) * and setLexicalHandler(consumer). */ public void setConsumer(XMLConsumer consumer) { this.setContentHandler(consumer); } /** * Set the ContentHandler that will receive XML data. *
* Subclasses may retrieve this ContentHandler instance * accessing the protected super.contentHandler field. */ public void setContentHandler(ContentHandler content) { this.processor.setDocumentHandler(new DocumentHandlerAdapter(content)); } /** * Set the LexicalHandler that will receive XML data. *
* Subclasses may retrieve this LexicalHandler instance * accessing the protected super.lexicalHandler field. * * @exception IllegalStateException If the LexicalHandler or * the XMLConsumer were * already set. */ public void setLexicalHandler(LexicalHandler lexical) { } /** * inner class DocumentHandler that delegates all SAX Events to the XT's builder. */ class DocHandler implements DocumentHandler, DTDHandler, Loggable { protected Logger log; /** * The XT's DocumentHandler instance to which SAX events are forwarded */ private XMLProcessorImpl.Builder builder = null; /** * The Document Handler delivered. */ public DocHandler(XMLProcessorImpl.Builder builder) { this.builder = builder; } public void setLogger(Logger logger) { if (this.log == null) { this.log = logger; } } public void setDocumentLocator (Locator locator) { builder.setDocumentLocator(locator); } public void ignorableWhitespace (char[] ch, int start, int length) throws SAXException { builder.ignorableWhitespace (ch, start, length); } public void processingInstruction (String target, String data) throws SAXException { builder.processingInstruction (target, data); } public void startDocument () throws SAXException { builder.startDocument(); } public void endDocument () throws SAXException { builder.endDocument(); try { // We've finished with the source document. // Start processing it by passing the builder processor.process(builder.getRootNode()); } catch (IOException ioe) { log.error("XTTransformer", ioe); throw new SAXException(ioe); } } public void startElement (String name, AttributeList atts) throws SAXException { builder.startElement (name, atts); } public void endElement (String name) throws SAXException { builder.endElement (name); } public void characters (char[] str, int index, int len) throws SAXException { builder.characters ( str, index, len); } public void notationDecl (String name, String publicId, String systemId) throws SAXException { builder.notationDecl (name, publicId, systemId); } public void unparsedEntityDecl (String name, String publicId, String systemId, String notationName) throws SAXException { builder.unparsedEntityDecl (name, publicId, systemId, notationName); } } /** * dispose */ public void dispose() { this.manager.release(this.store); } } /** * The XT processor. */ class XTProcessor implements Cloneable, ParameterSet, Modifiable, Loggable, Composable { protected Logger log; private XMLProcessorEx sheetLoader; private Parser sheetParser; private Sheet sheet; private Engine engine; private InputSource sheetSource; private ResultBase result; private DocumentHandler documentHandler; private ErrorHandler errorHandler; private HashMap params = new HashMap(); private File xslFile; private long lastModified; private ComponentManager manager; public void setLogger(Logger logger) { if (this.log == null) { this.log = logger; } } public void compose(ComponentManager manager) { this.manager = manager; } /** * set the Parser that will parse the XSL style sheet */ public void setParser(Parser sheetParser) { this.sheetParser = sheetParser; sheetLoader = new XMLProcessorImpl(sheetParser); } /** * set the DocumentHandler (Consumer) to which the XT Porcessor will * fire the result SAX events. */ public void setDocumentHandler(DocumentHandler handler) { documentHandler = handler; } /** * set the ErrorHandler */ public void setErrorHandler(ErrorHandler handler) { if (sheetParser != null) sheetParser.setErrorHandler(handler); if (sheetLoader != null) sheetLoader.setErrorHandler(handler); this.errorHandler = handler; } /** * Load the style sheet given its InputSource * Should be called after the setParser() and before the process() */ public void loadStylesheet(Source source)// dwe: InputSource -> Source throws SAXException, IOException { // Set the xslFile for the caching mechanism URL url = null; InputSource sheetSource = null;//dwe: the former parameter; There is a field with the same name ! SourceResolver resolver = null; try { resolver = (SourceResolver)this.manager.lookup(SourceResolver.ROLE); //dwe patch this.xslFile = SourceUtil.getFile(source);//dwe sheetSource = new InputSource(source.getInputStream()); sheetSource.setEncoding("iso-8859-1");// @TODO dwe: get from environment/configuration // url = SourceResolver.getURL(sheetSource.getSystemId()); //end dwe patch } catch (Exception e) { log.error("cannot obtain the SourceResolver", e); throw new SAXException ("cannot obtain the SourceResolver", e); } finally { if ( null != resolver ) { // resolver.release(configSource); manager.release(resolver); } } //dwe already set this.xslFile = new File(url.getFile()); lastModified = xslFile.lastModified(); // XT internal engine = new EngineImpl(sheetLoader, new ExtensionHandlerImpl()); try { Node node = sheetLoader.load(sheetSource, 0, engine.getSheetLoadContext(), engine.getNameTable()); sheet = engine.createSheet(node); } catch (XSLException e) { handleXSLException(e); } } /** * Create the XT's Builder which implements a DocumentHandler */ public XMLProcessorImpl.Builder createBuilder (String systemId) { XMLProcessorImpl.Builder builder = XMLProcessorImpl.createBuilder ( systemId, 0, sheet.getSourceLoadContext(),engine.getNameTable()); return builder; } /** * Applies the Style sheet to the source root node. * the rootNode are taken from the builder retrieved with createBuilder() method, * and by calling on the builder object the method getRootNode() after the SAX events * have fed the builder. */ public void process(Node root) throws SAXException, IOException { try { result = new MultiNamespaceResult(documentHandler, errorHandler); sheet.process(root, sheetLoader, this, result); } catch (XSLException e) { handleXSLException(e); } } void handleXSLException(XSLException e) throws SAXException, IOException { log.error("XTTransformer", e); String systemId = null; int lineNumber = -1; Node node = e.getNode(); if (node != null) { URL url = node.getURL(); if (url != null) systemId = url.toString(); lineNumber = node.getLineNumber(); } Exception wrapped = e.getException(); String message = e.getMessage(); if (systemId != null || lineNumber != -1) throw new SAXParseException(message, null, systemId, lineNumber, -1, wrapped); if (message == null) { if (wrapped instanceof SAXException) throw (SAXException)wrapped; if (wrapped instanceof IOException) throw (IOException)wrapped; } throw new SAXException(message, wrapped); } public Object clone() { try { XTProcessor cloned = (XTProcessor) super.clone(); cloned.setLogger(this.log); cloned.params = (HashMap) cloned.params.clone(); return cloned; } catch (CloneNotSupportedException e) { log.error("unexpected CloneNotSupportedException", e); throw new Error("unexpected CloneNotSupportedException"); } } public Object getParameter(Name name) { String nameString = name.getNamespace(); if (nameString == null) nameString = name.getLocalPart(); else nameString = (nameString + OutputMethodHandler.namespaceSeparator + name.getLocalPart()); return params.get(nameString); } /** * Set XSL parameters */ public void setParameter(String name, Object obj) { params.put(name, obj); } /** * implements interface Modifiable */ public boolean modifiedSince(long date) { return(date < this.xslFile.lastModified()); } /** * Checks if the style sheet file have changed since the construction * of this instance. */ public boolean hasChanged() { if (this.xslFile == null) { return false; } return modifiedSince(this.lastModified); } }