You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by cz...@apache.org on 2007/01/01 17:40:07 UTC
svn commit: r491595 - in /cocoon/trunk/core:
cocoon-core/src/main/resources/META-INF/cocoon/avalon/
cocoon-core/src/test/java/org/apache/cocoon/generation/
cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/
Author: cziegeler
Date: Mon Jan 1 08:40:06 2007
New Revision: 491595
URL: http://svn.apache.org/viewvc?view=rev&rev=491595
Log:
Restore avalon based components
Added:
cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/generation/FileGeneratorBeanTestCase.java (with props)
cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/generation/PauseGeneratorBean.java (with props)
cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/CSVGeneratorBean.java (with props)
cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/FileGeneratorBean.java (with props)
Modified:
cocoon/trunk/core/cocoon-core/src/main/resources/META-INF/cocoon/avalon/cocoon-core-sitemapcomponents.xconf
cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/generation/FileGeneratorTestCase.java
cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/CSVGenerator.java
cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/FileGenerator.java
Modified: cocoon/trunk/core/cocoon-core/src/main/resources/META-INF/cocoon/avalon/cocoon-core-sitemapcomponents.xconf
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/main/resources/META-INF/cocoon/avalon/cocoon-core-sitemapcomponents.xconf?view=diff&rev=491595&r1=491594&r2=491595
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/main/resources/META-INF/cocoon/avalon/cocoon-core-sitemapcomponents.xconf (original)
+++ cocoon/trunk/core/cocoon-core/src/main/resources/META-INF/cocoon/avalon/cocoon-core-sitemapcomponents.xconf Mon Jan 1 08:40:06 2007
@@ -53,6 +53,7 @@
| All components follow this scheme.
+-->
<map:generators default="file">
+ <map:generator label="content" logger="sitemap.generator.file" name="file" pool-max="32" src="org.apache.cocoon.generation.FileGenerator"/>
<map:generator label="content" logger="sitemap.generator.directory" name="directory" pool-max="16" src="org.apache.cocoon.generation.DirectoryGenerator"/>
<map:generator label="content" logger="sitemap.generator.xpathdirectory" name="xpathdirectory" src="org.apache.cocoon.generation.XPathDirectoryGenerator"/>
<map:generator label="content" logger="sitemap.generator.traversable" name="traversable" pool-max="16" src="org.apache.cocoon.generation.TraversableGenerator"/>
Added: cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/generation/FileGeneratorBeanTestCase.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/generation/FileGeneratorBeanTestCase.java?view=auto&rev=491595
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/generation/FileGeneratorBeanTestCase.java (added)
+++ cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/generation/FileGeneratorBeanTestCase.java Mon Jan 1 08:40:06 2007
@@ -0,0 +1,181 @@
+/*
+ * 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.generation;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.components.source.SourceUtil;
+import org.apache.cocoon.core.xml.impl.JaxpSAXParser;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.cocoon.xml.WhitespaceFilter;
+import org.apache.cocoon.xml.dom.DOMBuilder;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.impl.ResourceSource;
+import org.apache.excalibur.xml.sax.SAXParser;
+import org.custommonkey.xmlunit.Diff;
+import org.jmock.Mock;
+import org.jmock.MockObjectTestCase;
+import org.w3c.dom.Document;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+/**
+ *
+ * @version $Id$
+ */
+public class FileGeneratorBeanTestCase extends MockObjectTestCase {
+ private Map objectModel = new HashMap();
+ private SAXParser parser;
+ private Mock manager = new Mock(ServiceManager.class);
+
+ public void setUp() throws SAXException {
+ final XMLReader xmlReader = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
+ parser = new SAXParser() {
+
+ public void parse(InputSource src,
+ ContentHandler contentHandler) throws SAXException, IOException {
+ xmlReader.setContentHandler(contentHandler);
+ xmlReader.parse(src);
+ }
+
+ public void parse(InputSource src,
+ ContentHandler contentHandler,
+ LexicalHandler lexicalHandler) throws SAXException, IOException {
+ parse(src, contentHandler);
+ }
+
+ };
+ }
+
+ public void testFileGenerator() throws Exception {
+ String src = "resource://org/apache/cocoon/generation/FileGeneratorTestCase.source.xml";
+ Parameters parameters = new Parameters();
+ String result = "resource://org/apache/cocoon/generation/FileGeneratorTestCase.source.xml";
+ FileGeneratorBean generator = new FileGeneratorBean();
+ manager.expects(atLeastOnce()).method("lookup").with(same(SAXParser.ROLE)).
+ will(returnValue(parser));
+ manager.expects(once()).method("release").with(same(parser));
+ Mock resolver = new Mock(SourceResolver.class);
+ Source source = new ResourceSource(src);
+ resolver.expects(once()).method("resolveURI").with(same(src)).
+ will(returnValue(source));
+ resolver.expects(once()).method("release").with(same(source));
+ generator.setParser(new JaxpSAXParser());
+ generator.setup((SourceResolver) resolver.proxy(), objectModel, src, parameters);
+ DOMBuilder builder = new DOMBuilder();
+ generator.setConsumer(new WhitespaceFilter(builder));
+ generator.generate();
+ assertEqual(load(result), builder.getDocument());
+ }
+
+ protected Document load(String src) throws ProcessingException, SAXException, IOException {
+ Source source = new ResourceSource(src);
+ manager.expects(atLeastOnce()).method("lookup").with(same(SAXParser.ROLE)).
+ will(returnValue(parser));
+ manager.expects(once()).method("release").with(same(parser));
+ DOMBuilder builder = new DOMBuilder();
+ SourceUtil.parse((ServiceManager) manager.proxy(), source, new WhitespaceFilter(builder));
+ return builder.getDocument();
+ }
+
+ /**
+ * Compare two XML documents provided as strings
+ * @param control Control document
+ * @param test Document to test
+ * @return Diff object describing differences in documents
+ */
+ public final Diff compareXML(Document control, Document test) {
+ return new Diff(control, test);
+ }
+
+ /**
+ * Assert that the result of an XML comparison is similar.
+ *
+ * @param msg The assertion message
+ * @param expected The expected XML document
+ * @param actual The actual XML Document
+ */
+ public final void assertEqual(String msg, Document expected, Document actual) {
+
+ expected.getDocumentElement().normalize();
+ actual.getDocumentElement().normalize();
+
+ Diff diff = compareXML(expected, actual);
+
+ assertEquals(msg + ", " + diff.toString(), true, diff.similar());
+ }
+
+ /**
+ * Assert that the result of an XML comparison is similar.
+ *
+ * @param expected The expected XML document
+ * @param actual The actual XML Document
+ */
+ public final void assertEqual(Document expected, Document actual) {
+
+ expected.getDocumentElement().normalize();
+ actual.getDocumentElement().normalize();
+
+ Diff diff = compareXML(expected, actual);
+
+ assertEquals("Test if the assertion document is equal, " + diff.toString(), true, diff.similar());
+ }
+
+ /**
+ * Assert that the result of an XML comparison is identical.
+ *
+ * @param msg The assertion message
+ * @param expected The expected XML document
+ * @param actual The actual XML Document
+ */
+ public final void assertIdentical(String msg, Document expected, Document actual) {
+
+ expected.getDocumentElement().normalize();
+ actual.getDocumentElement().normalize();
+
+ Diff diff = compareXML(expected, actual);
+
+ assertEquals(msg + ", " + diff.toString(), true, diff.identical());
+ }
+
+ /**
+ * Assert that the result of an XML comparison is identical.
+ *
+ * @param expected The expected XML document
+ * @param actual The actual XML Document
+ */
+ public final void assertIdentical(Document expected, Document actual) {
+
+ expected.getDocumentElement().normalize();
+ actual.getDocumentElement().normalize();
+
+ Diff diff = compareXML(expected, actual);
+
+ assertEquals("Test if the assertion document is equal, " + diff.toString(), true, diff.identical());
+ }
+
+}
Propchange: cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/generation/FileGeneratorBeanTestCase.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/generation/FileGeneratorBeanTestCase.java
------------------------------------------------------------------------------
svn:keywords = Id
Modified: cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/generation/FileGeneratorTestCase.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/generation/FileGeneratorTestCase.java?view=diff&rev=491595&r1=491594&r2=491595
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/generation/FileGeneratorTestCase.java (original)
+++ cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/generation/FileGeneratorTestCase.java Mon Jan 1 08:40:06 2007
@@ -23,9 +23,9 @@
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.cocoon.MockLogger;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.components.source.SourceUtil;
-import org.apache.cocoon.core.xml.impl.JaxpSAXParser;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.xml.WhitespaceFilter;
import org.apache.cocoon.xml.dom.DOMBuilder;
@@ -76,6 +76,7 @@
Parameters parameters = new Parameters();
String result = "resource://org/apache/cocoon/generation/FileGeneratorTestCase.source.xml";
FileGenerator generator = new FileGenerator();
+ generator.enableLogging(new MockLogger(generator.getClass()));
manager.expects(atLeastOnce()).method("lookup").with(same(SAXParser.ROLE)).
will(returnValue(parser));
manager.expects(once()).method("release").with(same(parser));
@@ -84,7 +85,7 @@
resolver.expects(once()).method("resolveURI").with(same(src)).
will(returnValue(source));
resolver.expects(once()).method("release").with(same(source));
- generator.setParser(new JaxpSAXParser());
+ generator.service((ServiceManager) manager.proxy());
generator.setup((SourceResolver) resolver.proxy(), objectModel, src, parameters);
DOMBuilder builder = new DOMBuilder();
generator.setConsumer(new WhitespaceFilter(builder));
Added: cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/generation/PauseGeneratorBean.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/generation/PauseGeneratorBean.java?view=auto&rev=491595
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/generation/PauseGeneratorBean.java (added)
+++ cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/generation/PauseGeneratorBean.java Mon Jan 1 08:40:06 2007
@@ -0,0 +1,69 @@
+/*
+ * 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.generation;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.environment.SourceResolver;
+import org.xml.sax.SAXException;
+
+/**
+ * This generator extends the usual FileGenerator with a pause parameter.
+ * During generation of the content, this generator pauses for the given
+ * amount of time.
+ * This is very usefull for caching tests.
+ *
+ * @version $Id$
+ * @since 2.2
+ */
+public class PauseGeneratorBean
+ extends FileGeneratorBean {
+
+ protected long secs;
+
+ /**
+ * @see org.apache.cocoon.generation.FileGenerator#setup(org.apache.cocoon.environment.SourceResolver, java.util.Map, java.lang.String, org.apache.avalon.framework.parameters.Parameters)
+ */
+ public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par) throws ProcessingException, SAXException, IOException {
+ super.setup(resolver, objectModel, src, par);
+ this.secs = par.getParameterAsLong("pause", 60);
+ }
+
+ /**
+ * @see org.apache.cocoon.generation.FileGenerator#generate()
+ */
+ public void generate()
+ throws IOException, SAXException, ProcessingException {
+ if ( this.getLogger().isDebugEnabled() ) {
+ this.getLogger().debug("Waiting for " + secs + " secs.");
+ }
+ try {
+ Thread.sleep(secs * 1000);
+ } catch (InterruptedException ie) {
+ // ignore
+ }
+ if ( this.getLogger().isDebugEnabled() ) {
+ this.getLogger().debug("Finished waiting.");
+ }
+ super.generate();
+ }
+
+
+}
Propchange: cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/generation/PauseGeneratorBean.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/generation/PauseGeneratorBean.java
------------------------------------------------------------------------------
svn:keywords = Id
Modified: cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/CSVGenerator.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/CSVGenerator.java?view=diff&rev=491595&r1=491594&r2=491595
==============================================================================
--- cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/CSVGenerator.java (original)
+++ cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/CSVGenerator.java Mon Jan 1 08:40:06 2007
@@ -31,7 +31,6 @@
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.xml.AttributesImpl;
-import org.apache.cocoon.xml.XMLUtils;
import org.apache.excalibur.source.Source;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
@@ -148,11 +147,11 @@
}
/**
- * @see org.apache.cocoon.generation.FileGenerator#dispose()
+ * <p>Recycle this component.</p>.
*/
- public void dispose() {
- super.dispose();
-
+ public void recycle() {
+ super.recycle();
+
this.encoding = DEFAULT_ENCODING;
this.separator = DEFAULT_SEPARATOR.charAt(0);
this.escape = DEFAULT_ESCAPE.charAt(0);
@@ -209,9 +208,9 @@
try {
/* Start the document */
- this.consumer.setDocumentLocator(csv);
- this.consumer.startDocument();
- this.consumer.startPrefixMapping(NAMESPACE_PREFIX, NAMESPACE_URI);
+ this.contentHandler.setDocumentLocator(csv);
+ this.contentHandler.startDocument();
+ this.contentHandler.startPrefixMapping(NAMESPACE_PREFIX, NAMESPACE_URI);
this.indent(0);
this.startElement("document");
@@ -267,8 +266,8 @@
/* Terminate the document */
this.indent(0);
this.endElement("document");
- this.consumer.endPrefixMapping(NAMESPACE_PREFIX);
- this.consumer.endDocument();
+ this.contentHandler.endPrefixMapping(NAMESPACE_PREFIX);
+ this.contentHandler.endDocument();
} finally {
csv.close();
@@ -317,7 +316,7 @@
}
this.startElement(element, attributes);
- this.consumer.characters(array, 0, array.length);
+ this.contentHandler.characters(array, 0, array.length);
this.endElement(element);
this.buffer.reset();
@@ -340,25 +339,26 @@
private void indent(int level)
throws SAXException {
- this.consumer.characters(INDENT_STRING, 0, level + 1);
+ this.contentHandler.characters(INDENT_STRING, 0, level + 1);
}
private void startElement(String name)
throws SAXException {
- this.startElement(name, XMLUtils.EMPTY_ATTRIBUTES);
+ this.startElement(name, new AttributesImpl());
}
private void startElement(String name, Attributes atts)
throws SAXException {
if (name == null) throw new NullPointerException("Null name");
+ if (atts == null) atts = new AttributesImpl();
String qual = NAMESPACE_PREFIX + ':' + name;
- this.consumer.startElement(NAMESPACE_URI, name, qual, (atts == null ? XMLUtils.EMPTY_ATTRIBUTES : atts));
+ this.contentHandler.startElement(NAMESPACE_URI, name, qual, atts);
}
private void endElement(String name)
throws SAXException {
String qual = NAMESPACE_PREFIX + ':' + name;
- this.consumer.endElement(NAMESPACE_URI, name, qual);
+ this.contentHandler.endElement(NAMESPACE_URI, name, qual);
}
private static final class CSVReader extends Reader implements Locator {
Added: cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/CSVGeneratorBean.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/CSVGeneratorBean.java?view=auto&rev=491595
==============================================================================
--- cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/CSVGeneratorBean.java (added)
+++ cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/CSVGeneratorBean.java Mon Jan 1 08:40:06 2007
@@ -0,0 +1,440 @@
+/*
+* 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.generation;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.CharArrayWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.cocoon.xml.AttributesImpl;
+import org.apache.cocoon.xml.XMLUtils;
+import org.apache.excalibur.source.Source;
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+
+/**
+ * <p>A simple parser converting a Comma Separated Values (CSV) file into XML.</p>
+ *
+ * <p>This parser is controlled by the following sitemap parameters:</p>
+ *
+ * <ul>
+ * <li>
+ * <b>process-headers</b>: whether the first line in the CSV is considered
+ * to be the header defining column names (the resulting output will be
+ * different if this is <i>true</i> or <i>false</i> (default: <i>false</i>).
+ * </li>
+ * <li>
+ * <b>max-records</b>: the maximum number of records to read
+ * (default: <i>-1</i> read all records).
+ * </li>
+ * <li>
+ * <b>encoding</b>: the character encoding (UTF-8, ISO8859-1, ...) used to
+ * interpret the input CSV source file (default: <i>system default</i>).
+ * </li>
+ * <li>
+ * <b>separator</b>: the field-separator character in the CSV file (comma,
+ * tab, ...) (default: <i>,</i> <small>comma</small>).
+ * </li>
+ * <li>
+ * <b>escape</b>: the character used to escape fields, or part of them, in
+ * the CSV file (default: <i>"</i> <small>quote</small>).
+ * </li>
+ * <li>
+ * <b>buffer-size</b>: the size of the buffer used for reading the source
+ * CSV file (default: <i>4096 bytes</i>).
+ * </li>
+ * </ul>
+ *
+ * <p>The generated output will look something like the following:</p>
+ *
+ * <pre>
+ * <?xml version="1.0" encoding="ISO-8859-1"?>
+ * <csv:document xmlns:csv="http://apache.org/cocoon/csv/1.0">
+ * <csv:header>
+ * <csv:column number="1">Column A</csv:column>
+ * <csv:column number="2">Column B</csv:column>
+ * <csv:column number="3">Column C</csv:column>
+ * </csv:header>
+ * <csv:record number="1">
+ * <csv:field number="1" column="Column A">Field A1</csv:field>
+ * <csv:field number="2" column="Column B">Field B1</csv:field>
+ * <csv:field number="3" column="Column C">Field C1</csv:field>
+ * </csv:record>
+ * <csv:record number="2">
+ * <csv:field number="1" column="Column A">Field A2</csv:field>
+ * <csv:field number="2" column="Column B">Field B2</csv:field>
+ * <csv:field number="3" column="Column C">Field C2</csv:field>
+ * </csv:record>
+ * </csv:document>
+ * </pre>
+ *
+ * <p>Note that this generator has been thoroughly tested with CSV files generated
+ * by <a href="http://office.microsoft.com/" target="_new">Microsoft Excel</a>.
+ * Unfortunately no official CSV specification has ever been published by
+ * any standard body, so the interpretation of the format might be slightly
+ * different in cases.</p>
+ */
+public class CSVGeneratorBean extends FileGeneratorBean {
+
+ /** <p>The namespace URI of XML generated by this instance.</p> */
+ public static final String NAMESPACE_URI = "http://apache.org/cocoon/csv/1.0";
+ /** <p>The namespace prefix of XML generated by this instance.</p> */
+ public static final String NAMESPACE_PREFIX = "csv";
+
+ /** <p>The default encoding configured in the Java VM.</p> */
+ private static final String DEFAULT_ENCODING =
+ new InputStreamReader(new ByteArrayInputStream(new byte[0])).getEncoding();
+ /** <p>The default field separator character.</p> */
+ private static final String DEFAULT_SEPARATOR = ",";
+ /** <p>The default field separator character.</p> */
+ private static final String DEFAULT_ESCAPE = "\"";
+ /** <p>The default field separator character.</p> */
+ private static final int DEFAULT_BUFFER_SIZE = 4096;
+ private static final int UNLIMITED_MAXRECORDS = -1;
+ /** <p>A string used for indenting.</p> */
+ private static final char INDENT_STRING[] = "\n ".toCharArray();
+
+ /** <p>The encoding used to read the CSV resource from a stream.</p> */
+ private String encoding = DEFAULT_ENCODING;
+ /** <p>The character used to separate fields.</p> */
+ private char separator = DEFAULT_SEPARATOR.charAt(0);
+ /** <p>The character used to initiate and terminate esacaped sequences.</p> */
+ private char escape = DEFAULT_ESCAPE.charAt(0);
+ /** <p>The size of the buffer used to read the input.</p> */
+ private int buffersize = DEFAULT_BUFFER_SIZE;
+ /** <p>The current field (column) number in the current record.</p> */
+ private int fieldnumber = 1;
+ /** <p>The current record (line) number in the current CSV.</p> */
+ private int recordnumber = 1;
+ /** <p>The maximum number of records to read (-1 = read all records)</p> */
+ private int maxrecords;
+ /** <p>A flag indicating whether the <record> tag was opened.</p> */
+ private boolean openrecord = false;
+ /** <p>The character buffer for the current field.</p> */
+ private CharArrayWriter buffer = null;
+ /** <p>A map of all known columns or null if no headers are processed.</p> */
+ private Map columns = null;
+
+ /**
+ * <p>Create a new {@link CSVGeneratorBean} instance.</p>
+ */
+ public CSVGeneratorBean() {
+ super();
+ }
+
+ /**
+ * @see org.apache.cocoon.generation.FileGenerator#dispose()
+ */
+ public void dispose() {
+ super.dispose();
+
+ this.encoding = DEFAULT_ENCODING;
+ this.separator = DEFAULT_SEPARATOR.charAt(0);
+ this.escape = DEFAULT_ESCAPE.charAt(0);
+ this.buffersize = DEFAULT_BUFFER_SIZE;
+ this.buffer = null;
+ this.columns = null;
+ this.recordnumber = 1;
+ this.fieldnumber = 1;
+ this.openrecord = false;
+ }
+
+ /**
+ * <p>Setup this {@link CSVGeneratorBean} instance.</p>
+ */
+ public void setup(SourceResolver resolver, Map object_model, String source,
+ Parameters parameters)
+ throws ProcessingException, SAXException, IOException {
+ super.setup(resolver, object_model, source, parameters);
+
+ boolean header = parameters.getParameterAsBoolean("process-headers", false);
+
+ this.encoding = parameters.getParameter("encoding", DEFAULT_ENCODING);
+ this.separator = parameters.getParameter("separator", DEFAULT_SEPARATOR).charAt(0);
+ this.escape = parameters.getParameter("escape", DEFAULT_ESCAPE).charAt(0);
+ this.buffersize = parameters.getParameterAsInteger("buffer-size", DEFAULT_BUFFER_SIZE);
+ this.maxrecords = parameters.getParameterAsInteger("max-records", UNLIMITED_MAXRECORDS);
+ this.buffer = new CharArrayWriter();
+ this.columns = (header ? new HashMap() : null);
+ this.recordnumber = (header ? 0 : 1);
+ this.fieldnumber = 1;
+ this.openrecord = false;
+ }
+
+ /**
+ * <p>Generate the unique key.</p>
+ */
+ public Serializable getKey() {
+ StringBuffer key = new StringBuffer(this.inputSource.getURI());
+ if (this.columns != null) key.append("headers");
+ key.append(separator);
+ key.append(maxrecords);
+ key.append(escape);
+ return key;
+ }
+
+ /**
+ * <p>Generate XML data from a Comma Separated Value resource.</p>.
+ */
+ public void generate()
+ throws IOException, SAXException, ProcessingException {
+
+ /* Create a new Reader correctly decoding the source stream */
+ CSVReader csv = new CSVReader(this.inputSource, this.encoding, this.buffersize);
+
+ try {
+ /* Start the document */
+ this.consumer.setDocumentLocator(csv);
+ this.consumer.startDocument();
+ this.consumer.startPrefixMapping(NAMESPACE_PREFIX, NAMESPACE_URI);
+ this.indent(0);
+ this.startElement("document");
+
+ /* Allocate buffer and status for parsing */
+ boolean unescaped = true;
+ int prev = -1;
+ int curr = -1;
+
+ /* Parse the file reading characters one-by-one */
+ while ((curr = csv.read()) >= 0 && (this.maxrecords == UNLIMITED_MAXRECORDS || recordnumber <= this.maxrecords)) {
+
+ /* Process any occurrence of the escape character */
+ if (curr == this.escape) {
+ if ((unescaped) && (prev == this.escape)) {
+ this.buffer.write(this.escape);
+ }
+ unescaped = ! unescaped;
+ prev = curr;
+ continue;
+ }
+
+ /* Process any occurrence of the field separator */
+ if ((unescaped) && (curr == this.separator)) {
+ this.dumpField();
+ prev = curr;
+ continue;
+ }
+
+ /* Process newline characters */
+ if ((unescaped) && ((curr == '\r') || (curr == '\n'))) {
+ this.dumpField();
+ this.dumpRecord();
+
+ /* Record numbering */
+ if (((curr == '\n') && (prev != '\r')) || (curr == '\r')) {
+ this.recordnumber ++;
+ }
+
+ /* Nothing else to do */
+ prev = curr;
+ continue;
+ }
+
+ /* Any other character simply gets added to the buffer */
+ this.buffer.write(curr);
+ prev = curr;
+ }
+
+ /* Terminate any hanging open record element (just in case) */
+ this.dumpField();
+ this.dumpRecord();
+
+ /* Terminate the document */
+ this.indent(0);
+ this.endElement("document");
+ this.consumer.endPrefixMapping(NAMESPACE_PREFIX);
+ this.consumer.endDocument();
+
+ } finally {
+ csv.close();
+ }
+ }
+
+
+ private void dumpField()
+ throws SAXException {
+ if (this.buffer.size() < 1) {
+ this.fieldnumber ++;
+ return;
+ }
+
+ if (! this.openrecord) {
+ this.indent(4);
+
+ if (this.recordnumber > 0) {
+ AttributesImpl attributes = new AttributesImpl();
+ String value = Integer.toString(this.recordnumber);
+ attributes.addCDATAAttribute("number", value);
+ this.startElement("record", attributes);
+ } else {
+ this.startElement("header");
+ }
+ this.openrecord = true;
+ }
+
+ /* Enclode the field in the proper element */
+ String element = "field";
+ char array[] = this.buffer.toCharArray();
+ this.indent(8);
+
+ AttributesImpl attributes = new AttributesImpl();
+ String value = Integer.toString(this.fieldnumber);
+ attributes.addCDATAAttribute("number", value);
+
+ if (this.recordnumber < 1) {
+ this.columns.put(new Integer(this.fieldnumber), new String(array));
+ element = "column";
+ } else if (this.columns != null) {
+ String header = (String) this.columns.get(new Integer(this.fieldnumber));
+ if (header != null) {
+ attributes.addCDATAAttribute("column", header);
+ }
+ }
+
+ this.startElement(element, attributes);
+ this.consumer.characters(array, 0, array.length);
+ this.endElement(element);
+ this.buffer.reset();
+
+ this.fieldnumber ++;
+ }
+
+ private void dumpRecord()
+ throws SAXException {
+ if (this.openrecord) {
+ this.indent(4);
+ if (this.recordnumber > 0) {
+ this.endElement("record");
+ } else {
+ this.endElement("header");
+ }
+ this.openrecord = false;
+ }
+ this.fieldnumber = 1;
+ }
+
+ private void indent(int level)
+ throws SAXException {
+ this.consumer.characters(INDENT_STRING, 0, level + 1);
+ }
+
+ private void startElement(String name)
+ throws SAXException {
+ this.startElement(name, XMLUtils.EMPTY_ATTRIBUTES);
+ }
+
+ private void startElement(String name, Attributes atts)
+ throws SAXException {
+ if (name == null) throw new NullPointerException("Null name");
+ String qual = NAMESPACE_PREFIX + ':' + name;
+ this.consumer.startElement(NAMESPACE_URI, name, qual, (atts == null ? XMLUtils.EMPTY_ATTRIBUTES : atts));
+ }
+
+ private void endElement(String name)
+ throws SAXException {
+ String qual = NAMESPACE_PREFIX + ':' + name;
+ this.consumer.endElement(NAMESPACE_URI, name, qual);
+ }
+
+ private static final class CSVReader extends Reader implements Locator {
+
+ private String uri = null;
+ private Reader input = null;
+ private int column = 1;
+ private int line = 1;
+ private int last = -1;
+
+ protected CSVReader(Source source, String encoding, int buffer)
+ throws IOException {
+ InputStream stream = source.getInputStream();
+ Reader reader = new InputStreamReader(stream, encoding);
+ this.input = new BufferedReader(reader, buffer);
+ this.uri = source.getURI();
+ }
+
+ public String getPublicId() {
+ return null;
+ }
+
+ public String getSystemId() {
+ return this.uri;
+ }
+
+ public int getLineNumber() {
+ return this.line;
+ }
+
+ public int getColumnNumber() {
+ return this.column;
+ }
+
+ public void close()
+ throws IOException {
+ this.input.close();
+ }
+
+ public int read()
+ throws IOException {
+ int c = this.input.read();
+ if (c < 0) return c;
+
+ if (((c == '\n') && (this.last != '\r')) || (c == '\r')) {
+ this.column = 1;
+ this.line ++;
+ }
+
+ this.last = c;
+ return c;
+ }
+
+ public int read(char b[], int o, int l)
+ throws IOException {
+ if (b == null) throw new NullPointerException();
+ if ((o<0)||(o>b.length)||(l<0)||((o+l)>b.length)||((o+l)<0)) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (l == 0) return 0;
+
+ int c = read();
+ if (c == -1) return -1;
+ b[o] = (char)c;
+
+ int i = 1;
+ try {
+ for (i = 1; i < l ; i++) {
+ c = read();
+ if (c == -1) break;
+ b[o + i] = (char)c;
+ }
+ } catch (IOException ee) {
+ return i;
+ }
+ return i;
+ }
+ }
+}
Propchange: cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/CSVGeneratorBean.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/CSVGeneratorBean.java
------------------------------------------------------------------------------
svn:keywords = Id
Modified: cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/FileGenerator.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/FileGenerator.java?view=diff&rev=491595&r1=491594&r2=491595
==============================================================================
--- cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/FileGenerator.java (original)
+++ cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/FileGenerator.java Mon Jan 1 08:40:06 2007
@@ -20,11 +20,7 @@
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.caching.CacheableProcessingComponent;
import org.apache.cocoon.components.source.util.SourceUtil;
-import org.apache.cocoon.core.xml.SAXParser;
import org.apache.cocoon.environment.SourceResolver;
-import org.apache.cocoon.sitemap.DisposableSitemapComponent;
-import org.apache.cocoon.util.AbstractLogEnabled;
-import org.apache.cocoon.xml.XMLConsumer;
import org.apache.excalibur.source.Source;
import org.apache.excalibur.source.SourceException;
import org.apache.excalibur.source.SourceValidity;
@@ -48,54 +44,38 @@
*
* @version $Id$
*/
-public class FileGenerator
- extends AbstractLogEnabled
- implements Generator, CacheableProcessingComponent, DisposableSitemapComponent {
+public class FileGenerator extends ServiceableGenerator
+ implements CacheableProcessingComponent {
/** The input source */
protected Source inputSource;
- /** The source resolver. */
- protected SourceResolver resolver;
-
- /** The consumer. */
- protected XMLConsumer consumer;
-
- /** The SAX Parser. */
- protected SAXParser parser;
-
- public void setParser(SAXParser parser) {
- this.parser = parser;
- }
-
/**
- * @see org.apache.cocoon.sitemap.DisposableSitemapComponent#dispose()
+ * Recycle this component.
+ * All instance variables are set to <code>null</code>.
*/
- public void dispose() {
- if ( this.inputSource != null ) {
- this.resolver.release(this.inputSource);
+ public void recycle() {
+ if (null != this.inputSource) {
+ super.resolver.release(this.inputSource);
this.inputSource = null;
}
- this.resolver = null;
- this.consumer = null;
+ super.recycle();
}
/**
* Setup the file generator.
* Try to get the last modification date of the source for caching.
- *
- * @see org.apache.cocoon.sitemap.SitemapModelComponent#setup(org.apache.cocoon.environment.SourceResolver, java.util.Map, java.lang.String, org.apache.avalon.framework.parameters.Parameters)
*/
public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par)
throws ProcessingException, SAXException, IOException {
- this.resolver = resolver;
+ super.setup(resolver, objectModel, src, par);
try {
- this.inputSource = this.resolver.resolveURI(src);
+ this.inputSource = super.resolver.resolveURI(src);
} catch (SourceException se) {
throw SourceUtil.handle("Error during resolving of '" + src + "'.", se);
}
if (getLogger().isDebugEnabled()) {
- getLogger().debug("Source " + src +
+ getLogger().debug("Source " + super.source +
" resolved to " + this.inputSource.getURI());
}
}
@@ -121,19 +101,12 @@
}
/**
- * @see org.apache.cocoon.xml.XMLProducer#setConsumer(org.apache.cocoon.xml.XMLConsumer)
- */
- public void setConsumer(XMLConsumer consumer) {
- this.consumer = consumer;
- }
-
- /**
* Generate XML data.
*/
public void generate()
throws IOException, SAXException, ProcessingException {
try {
- this.parser.parse(SourceUtil.getInputSource(this.inputSource), this.consumer);
+ SourceUtil.parse(this.manager, this.inputSource, super.xmlConsumer);
} catch (SAXException e) {
SourceUtil.handleSAXException(this.inputSource.getURI(), e);
}
Added: cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/FileGeneratorBean.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/FileGeneratorBean.java?view=auto&rev=491595
==============================================================================
--- cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/FileGeneratorBean.java (added)
+++ cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/FileGeneratorBean.java Mon Jan 1 08:40:06 2007
@@ -0,0 +1,141 @@
+/*
+ * 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.generation;
+
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.caching.CacheableProcessingComponent;
+import org.apache.cocoon.components.source.util.SourceUtil;
+import org.apache.cocoon.core.xml.SAXParser;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.cocoon.sitemap.DisposableSitemapComponent;
+import org.apache.cocoon.util.AbstractLogEnabled;
+import org.apache.cocoon.xml.XMLConsumer;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceException;
+import org.apache.excalibur.source.SourceValidity;
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * @cocoon.sitemap.component.documentation
+ * The <code>FileGenerator</code> is a class that reads XML from a source
+ * and generates SAX Events. The <code>FileGenerator</code> implements the
+ * <code>CacheableProcessingComponent</code> interface.
+ *
+ * @cocoon.sitemap.component.name file
+ * @cocoon.sitemap.component.label content
+ * @cocoon.sitemap.component.logger sitemap.generator.file
+ * @cocoon.sitemap.component.documentation.caching
+ * Uses the last modification date of the xml document for validation
+ *
+ * @version $Id$
+ */
+public class FileGeneratorBean
+ extends AbstractLogEnabled
+ implements Generator, CacheableProcessingComponent, DisposableSitemapComponent {
+
+ /** The input source */
+ protected Source inputSource;
+
+ /** The source resolver. */
+ protected SourceResolver resolver;
+
+ /** The consumer. */
+ protected XMLConsumer consumer;
+
+ /** The SAX Parser. */
+ protected SAXParser parser;
+
+ public void setParser(SAXParser parser) {
+ this.parser = parser;
+ }
+
+ /**
+ * @see org.apache.cocoon.sitemap.DisposableSitemapComponent#dispose()
+ */
+ public void dispose() {
+ if ( this.inputSource != null ) {
+ this.resolver.release(this.inputSource);
+ this.inputSource = null;
+ }
+ this.resolver = null;
+ this.consumer = null;
+ }
+
+ /**
+ * Setup the file generator.
+ * Try to get the last modification date of the source for caching.
+ *
+ * @see org.apache.cocoon.sitemap.SitemapModelComponent#setup(org.apache.cocoon.environment.SourceResolver, java.util.Map, java.lang.String, org.apache.avalon.framework.parameters.Parameters)
+ */
+ public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par)
+ throws ProcessingException, SAXException, IOException {
+ this.resolver = resolver;
+ try {
+ this.inputSource = this.resolver.resolveURI(src);
+ } catch (SourceException se) {
+ throw SourceUtil.handle("Error during resolving of '" + src + "'.", se);
+ }
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("Source " + src +
+ " resolved to " + this.inputSource.getURI());
+ }
+ }
+
+ /**
+ * Generate the unique key.
+ * This key must be unique inside the space of this component.
+ *
+ * @return The generated key hashes the src
+ */
+ public Serializable getKey() {
+ return this.inputSource.getURI();
+ }
+
+ /**
+ * Generate the validity object.
+ *
+ * @return The generated validity object or <code>null</code> if the
+ * component is currently not cacheable.
+ */
+ public SourceValidity getValidity() {
+ return this.inputSource.getValidity();
+ }
+
+ /**
+ * @see org.apache.cocoon.xml.XMLProducer#setConsumer(org.apache.cocoon.xml.XMLConsumer)
+ */
+ public void setConsumer(XMLConsumer consumer) {
+ this.consumer = consumer;
+ }
+
+ /**
+ * Generate XML data.
+ */
+ public void generate()
+ throws IOException, SAXException, ProcessingException {
+ try {
+ this.parser.parse(SourceUtil.getInputSource(this.inputSource), this.consumer);
+ } catch (SAXException e) {
+ SourceUtil.handleSAXException(this.inputSource.getURI(), e);
+ }
+ }
+}
Propchange: cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/FileGeneratorBean.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cocoon/trunk/core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/generation/FileGeneratorBean.java
------------------------------------------------------------------------------
svn:keywords = Id