You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by re...@apache.org on 2008/06/13 16:23:14 UTC

svn commit: r667553 - in /cocoon/whiteboard/corona/trunk: corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/ corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/component/ corona-pipeline/src/main/java/org/apache/cocoon/corona...

Author: reinhard
Date: Fri Jun 13 07:23:14 2008
New Revision: 667553

URL: http://svn.apache.org/viewvc?rev=667553&view=rev
Log:
. add a simple implementation of an include transformer (no caching, no parallel processing etc)
. reuse IncludeXMLConsumer from trunk

Added:
    cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/ProcessingException.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/component/IncludeTransformer.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/util/IncludeXMLConsumer.java   (with props)
Modified:
    cocoon/whiteboard/corona/trunk/corona-sitemap/src/main/java/org/apache/cocoon/corona/sitemap/node/GenerateNode.java
    cocoon/whiteboard/corona/trunk/corona-sitemap/src/main/java/org/apache/cocoon/corona/sitemap/node/TransformNode.java
    cocoon/whiteboard/corona/trunk/corona-sitemap/src/main/resources/META-INF/cocoon/spring/corona-pipeline-component.xml

Added: cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/ProcessingException.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/ProcessingException.java?rev=667553&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/ProcessingException.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/ProcessingException.java Fri Jun 13 07:23:14 2008
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.corona.pipeline;
+
+/**
+ * Exception that indicates that there was a problem while processing a pipeline.
+ */
+public class ProcessingException extends RuntimeException {
+
+    public ProcessingException() {
+        super();
+    }
+
+    public ProcessingException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public ProcessingException(String message) {
+        super(message);
+    }
+
+    public ProcessingException(Throwable cause) {
+        super(cause);
+    }
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/ProcessingException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/ProcessingException.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/ProcessingException.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/component/IncludeTransformer.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/component/IncludeTransformer.java?rev=667553&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/component/IncludeTransformer.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/component/IncludeTransformer.java Fri Jun 13 07:23:14 2008
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.corona.pipeline.component;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Map;
+
+import org.apache.cocoon.corona.pipeline.ProcessingException;
+import org.apache.cocoon.corona.pipeline.util.IncludeXMLConsumer;
+import org.apache.cocoon.corona.pipeline.util.StringRepresentation;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+public class IncludeTransformer extends AbstractTransformer {
+
+    private final Log logger = LogFactory.getLog(this.getClass());
+
+    private static final String INCLUDE_NS = "http://apache.org/cocoon/corona/include/1.0";
+
+    private static final String INCLUDE_EL = "include";
+
+    private static final String SRC_ATTR = "src";
+
+    private URL baseUrl;
+
+    @Override
+    public void startElement(String uri, String localName, String name, Attributes atts) throws SAXException {
+        if (INCLUDE_NS.equals(uri) && INCLUDE_EL.equals(localName)) {
+            String sourceAtt = atts.getValue(SRC_ATTR);
+
+            if (null != sourceAtt && !"".equals(sourceAtt)) {
+                try {
+                    URL source = this.createSource(sourceAtt);
+
+                    XMLReader xmlReader = XMLReaderFactory.createXMLReader();
+                    xmlReader.setContentHandler(this.getXMLConsumer());
+                    IncludeXMLConsumer includeXMLConsumer = new IncludeXMLConsumer(this.getXMLConsumer());
+                    xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler", includeXMLConsumer);
+
+                    BufferedInputStream inputStream = new BufferedInputStream(source.openStream());
+                    xmlReader.parse(new InputSource(inputStream));
+
+                    return;
+                } catch (IOException e) {
+                    String message = "Can't read from URL " + sourceAtt;
+                    this.logger.error(message, e);
+                    throw new ProcessingException(message, e);
+                }
+            } else {
+                String message = "The <include> element must contain a 'src' attribute that contains a URL.";
+                this.logger.error(message);
+                throw new ProcessingException(message);
+            }
+        } else {
+            super.startElement(uri, localName, name, atts);
+        }
+    }
+
+    private URL createSource(String sourceAtt) {
+        try {
+            URL source = null;
+            if (sourceAtt.contains(":")) {
+                source = new URL(sourceAtt);
+            } else {
+                source = new URL(this.baseUrl, sourceAtt);
+            }
+            if (this.logger.isDebugEnabled()) {
+                this.logger.debug("Including source: " + source);
+            }
+
+            return source;
+        } catch (MalformedURLException e) {
+            String message = "Can't parse URL " + sourceAtt;
+            this.logger.error(message, e);
+            throw new ProcessingException(message, e);
+        }
+    }
+
+    @Override
+    public void endElement(String uri, String localName, String name) throws SAXException {
+        if (INCLUDE_NS.equals(uri) && INCLUDE_EL.equals(localName)) {
+            return;
+        }
+        super.endElement(uri, localName, name);
+    }
+
+    @Override
+    public void setConfiguration(Map<String, ? extends Object> parameters) {
+        this.setBaseUrl((URL) parameters.get("baseUrl"));
+    }
+
+    public void setBaseUrl(URL baseUrl) {
+        this.baseUrl = baseUrl;
+    }
+
+    @Override
+    public String toString() {
+        return StringRepresentation.buildString(this, "baseUrl=" + this.baseUrl);
+    }
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/component/IncludeTransformer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/component/IncludeTransformer.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/component/IncludeTransformer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/util/IncludeXMLConsumer.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/util/IncludeXMLConsumer.java?rev=667553&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/util/IncludeXMLConsumer.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/util/IncludeXMLConsumer.java Fri Jun 13 07:23:14 2008
@@ -0,0 +1,198 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.corona.pipeline.util;
+
+import org.apache.cocoon.corona.pipeline.component.XMLConsumer;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.ext.LexicalHandler;
+
+/**
+ * A special purpose <code>XMLConsumer</code> which can:
+ * <ul>
+ * <li>Trim empty characters if {@link #setIgnoreEmptyCharacters(boolean) ignoreEmptyCharacters} is set.
+ * <li>Ignore root element if {@link #setIgnoreRootElement(boolean) ignoreRootElement} is set.
+ * <li>Ignore startDocument, endDocument events.
+ * <li>Ignore startDTD, endDTD, and all comments within DTD.
+ * </ul>
+ * 
+ * <p>
+ * It is more complicated version of {@link EmbeddedXMLPipe} which, except being used to include other files into the
+ * SAX events stream, can perform optional operations described above.
+ * </p>
+ * 
+ * @see EmbeddedXMLPipe
+ * @version $Id$
+ */
+public class IncludeXMLConsumer implements XMLConsumer {
+
+    private final ContentHandler contentHandler;
+    private final LexicalHandler lexicalHandler;
+
+    private boolean ignoreEmptyCharacters;
+    private boolean ignoreRootElement;
+    private int ignoreRootElementCount;
+    private boolean inDTD;
+
+    /**
+     * Constructor
+     */
+    public IncludeXMLConsumer(XMLConsumer consumer) {
+        this(consumer, consumer);
+    }
+
+    /**
+     * Constructor
+     */
+    public IncludeXMLConsumer(ContentHandler contentHandler) {
+        this(contentHandler, contentHandler instanceof LexicalHandler ? (LexicalHandler) contentHandler : null);
+    }
+
+    /**
+     * Constructor
+     */
+    public IncludeXMLConsumer(ContentHandler contentHandler, LexicalHandler lexicalHandler) {
+        this.contentHandler = contentHandler;
+        this.lexicalHandler = lexicalHandler;
+    }
+
+    /**
+     * Control SAX event handling. If set to <code>true</code> all empty characters events are ignored. The default is
+     * <code>false</code>.
+     */
+    public void setIgnoreEmptyCharacters(boolean value) {
+        this.ignoreEmptyCharacters = value;
+    }
+
+    /**
+     * Control SAX event handling. If set to <code>true</code> the root element is ignored. The default is
+     * <code>false</code>.
+     */
+    public void setIgnoreRootElement(boolean value) {
+        this.ignoreRootElement = value;
+        this.ignoreRootElementCount = 0;
+    }
+
+    //
+    // ContentHandler interface
+    //
+
+    public void setDocumentLocator(Locator loc) {
+        this.contentHandler.setDocumentLocator(loc);
+    }
+
+    public void startDocument() throws SAXException {
+        // Ignored
+    }
+
+    public void endDocument() throws SAXException {
+        // Ignored
+    }
+
+    public void startPrefixMapping(String prefix, String uri) throws SAXException {
+        this.contentHandler.startPrefixMapping(prefix, uri);
+    }
+
+    public void endPrefixMapping(String prefix) throws SAXException {
+        this.contentHandler.endPrefixMapping(prefix);
+    }
+
+    public void startElement(String uri, String local, String qName, Attributes attr) throws SAXException {
+        if (this.ignoreRootElement == false || this.ignoreRootElementCount > 0) {
+            this.contentHandler.startElement(uri, local, qName, attr);
+        }
+        this.ignoreRootElementCount++;
+    }
+
+    public void endElement(String uri, String local, String qName) throws SAXException {
+        this.ignoreRootElementCount--;
+        if (!this.ignoreRootElement || this.ignoreRootElementCount > 0) {
+            this.contentHandler.endElement(uri, local, qName);
+        }
+    }
+
+    public void characters(char[] ch, int start, int end) throws SAXException {
+        if (this.ignoreEmptyCharacters) {
+            String text = new String(ch, start, end).trim();
+            if (text.length() > 0) {
+                this.contentHandler.characters(text.toCharArray(), 0, text.length());
+            }
+        } else {
+            this.contentHandler.characters(ch, start, end);
+        }
+    }
+
+    public void ignorableWhitespace(char[] ch, int start, int end) throws SAXException {
+        if (!this.ignoreEmptyCharacters) {
+            this.contentHandler.ignorableWhitespace(ch, start, end);
+        }
+    }
+
+    public void processingInstruction(String name, String value) throws SAXException {
+        this.contentHandler.processingInstruction(name, value);
+    }
+
+    public void skippedEntity(String ent) throws SAXException {
+        this.contentHandler.skippedEntity(ent);
+    }
+
+    //
+    // LexicalHandler interface
+    //
+
+    public void startDTD(String name, String public_id, String system_id) throws SAXException {
+        // Ignored
+        this.inDTD = true;
+    }
+
+    public void endDTD() throws SAXException {
+        // Ignored
+        this.inDTD = false;
+    }
+
+    public void startEntity(String name) throws SAXException {
+        if (this.lexicalHandler != null) {
+            this.lexicalHandler.startEntity(name);
+        }
+    }
+
+    public void endEntity(String name) throws SAXException {
+        if (this.lexicalHandler != null) {
+            this.lexicalHandler.endEntity(name);
+        }
+    }
+
+    public void startCDATA() throws SAXException {
+        if (this.lexicalHandler != null) {
+            this.lexicalHandler.startCDATA();
+        }
+    }
+
+    public void endCDATA() throws SAXException {
+        if (this.lexicalHandler != null) {
+            this.lexicalHandler.endCDATA();
+        }
+    }
+
+    public void comment(char ary[], int start, int length) throws SAXException {
+        if (!this.inDTD && this.lexicalHandler != null) {
+            this.lexicalHandler.comment(ary, start, length);
+        }
+    }
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/util/IncludeXMLConsumer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/util/IncludeXMLConsumer.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-pipeline/src/main/java/org/apache/cocoon/corona/pipeline/util/IncludeXMLConsumer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cocoon/whiteboard/corona/trunk/corona-sitemap/src/main/java/org/apache/cocoon/corona/sitemap/node/GenerateNode.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-sitemap/src/main/java/org/apache/cocoon/corona/sitemap/node/GenerateNode.java?rev=667553&r1=667552&r2=667553&view=diff
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-sitemap/src/main/java/org/apache/cocoon/corona/sitemap/node/GenerateNode.java (original)
+++ cocoon/whiteboard/corona/trunk/corona-sitemap/src/main/java/org/apache/cocoon/corona/sitemap/node/GenerateNode.java Fri Jun 13 07:23:14 2008
@@ -30,14 +30,14 @@
     private static final String GENERATOR_CATEGORY = "generator:";
 
     @Parameter
-    private String type = "file"; // "file" is the default type
+    private final String type = "file"; // "file" is the default type
 
     @Parameter
     private String src;
 
     /**
      * {@inheritDoc}
-     *
+     * 
      * @see org.apache.cocoon.corona.sitemap.node.AbstractSitemapNode#invoke(org.apache.cocoon.corona.sitemap.Invocation)
      */
     @Override
@@ -48,6 +48,9 @@
             parameters.put("source", invocation.resolve(resolvedSource));
         }
 
+        // set the baseUrl
+        parameters.put("baseUrl", invocation.resolve(""));
+
         // install the component
         invocation.installComponent(GENERATOR_CATEGORY + this.type, parameters);
 
@@ -57,7 +60,7 @@
 
     /**
      * {@inheritDoc}
-     *
+     * 
      * @see org.apache.cocoon.corona.sitemap.node.AbstractSitemapNode#toString()
      */
     @Override

Modified: cocoon/whiteboard/corona/trunk/corona-sitemap/src/main/java/org/apache/cocoon/corona/sitemap/node/TransformNode.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-sitemap/src/main/java/org/apache/cocoon/corona/sitemap/node/TransformNode.java?rev=667553&r1=667552&r2=667553&view=diff
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-sitemap/src/main/java/org/apache/cocoon/corona/sitemap/node/TransformNode.java (original)
+++ cocoon/whiteboard/corona/trunk/corona-sitemap/src/main/java/org/apache/cocoon/corona/sitemap/node/TransformNode.java Fri Jun 13 07:23:14 2008
@@ -42,10 +42,14 @@
      */
     @Override
     public InvocationResult invoke(final Invocation invocation) {
-        Map<String, Object> parameters = new HashMap<String, Object>(this.getParameters());
+        final Map<String, Object> parameters = new HashMap<String, Object>(this.getParameters());
         if (this.src != null) {
             parameters.put("source", invocation.resolve(this.src));
         }
+
+        // set the baseUrl
+        parameters.put("baseUrl", invocation.resolve(""));
+
         // install the component
         invocation.installComponent(TRANSFORMER_CATEGORY + this.type, parameters);
 

Modified: cocoon/whiteboard/corona/trunk/corona-sitemap/src/main/resources/META-INF/cocoon/spring/corona-pipeline-component.xml
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-sitemap/src/main/resources/META-INF/cocoon/spring/corona-pipeline-component.xml?rev=667553&r1=667552&r2=667553&view=diff
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-sitemap/src/main/resources/META-INF/cocoon/spring/corona-pipeline-component.xml (original)
+++ cocoon/whiteboard/corona/trunk/corona-sitemap/src/main/resources/META-INF/cocoon/spring/corona-pipeline-component.xml Fri Jun 13 07:23:14 2008
@@ -55,6 +55,8 @@
 
   <bean name="transformer:xslt" class="org.apache.cocoon.corona.pipeline.component.XSLTTransformer" scope="prototype" />
   
+  <bean name="transformer:include" class="org.apache.cocoon.corona.pipeline.component.IncludeTransformer" scope="prototype" />
+  
   <bean name="transformer:cleaning" class="org.apache.cocoon.corona.pipeline.component.CleaningTransformer" scope="prototype" />
 
 </beans>