Return-Path: Delivered-To: apmail-cocoon-cvs-archive@www.apache.org Received: (qmail 21581 invoked from network); 13 Jun 2008 14:23:47 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 13 Jun 2008 14:23:47 -0000 Received: (qmail 3815 invoked by uid 500); 13 Jun 2008 14:23:49 -0000 Delivered-To: apmail-cocoon-cvs-archive@cocoon.apache.org Received: (qmail 3771 invoked by uid 500); 13 Jun 2008 14:23:49 -0000 Mailing-List: contact cvs-help@cocoon.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@cocoon.apache.org list-help: list-unsubscribe: List-Post: List-Id: Delivered-To: mailing list cvs@cocoon.apache.org Received: (qmail 3762 invoked by uid 99); 13 Jun 2008 14:23:49 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 13 Jun 2008 07:23:49 -0700 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 13 Jun 2008 14:22:57 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 3EE5423889F1; Fri, 13 Jun 2008 07:23:15 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: 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... Date: Fri, 13 Jun 2008 14:23:14 -0000 To: cvs@cocoon.apache.org From: reinhard@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20080613142315.3EE5423889F1@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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 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 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 XMLConsumer which can: + *
    + *
  • Trim empty characters if {@link #setIgnoreEmptyCharacters(boolean) ignoreEmptyCharacters} is set. + *
  • Ignore root element if {@link #setIgnoreRootElement(boolean) ignoreRootElement} is set. + *
  • Ignore startDocument, endDocument events. + *
  • Ignore startDTD, endDTD, and all comments within DTD. + *
+ * + *

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

+ * + * @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 true all empty characters events are ignored. The default is + * false. + */ + public void setIgnoreEmptyCharacters(boolean value) { + this.ignoreEmptyCharacters = value; + } + + /** + * Control SAX event handling. If set to true the root element is ignored. The default is + * false. + */ + 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 parameters = new HashMap(this.getParameters()); + final Map parameters = new HashMap(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 @@ + +