cocoon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jheym...@apache.org
Subject svn commit: r330548 [45/132] - in /cocoon/whiteboard/maven2/cocoon-flat-layout: ./ cocoon-ajax-block/ cocoon-ajax-block/api/ cocoon-ajax-block/api/src/ cocoon-ajax-block/api/src/main/ cocoon-ajax-block/api/src/main/java/ cocoon-ajax-block/api/src/main/...
Date Thu, 03 Nov 2005 14:00:48 GMT
Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/CSVGenerator.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/CSVGenerator.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/CSVGenerator.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/CSVGenerator.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,429 @@
+/* =============================================================================== *
+ * Copyright (C) 1999-2004, The Apache Software Foundation.   All rights reserved. *
+ *                                                                                 *
+ * Licensed 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.excalibur.source.Source;
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * <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>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>
+ * &lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;
+ * &lt;csv:document xmlns:csv="http://apache.org/cocoon/csv/1.0"&gt;
+ *   &lt;csv:header&gt;
+ *     &lt;csv:column number="1"&gt;Column A&lt;/csv:column&gt;
+ *     &lt;csv:column number="2"&gt;Column B&lt;/csv:column&gt;
+ *     &lt;csv:column number="3"&gt;Column C&lt;/csv:column&gt;
+ *   &lt;/csv:header&gt;
+ *   &lt;csv:record number="1"&gt;
+ *     &lt;csv:field number="1" column="Column A"&gt;Field A1&lt;/csv:field&gt;
+ *     &lt;csv:field number="2" column="Column B"&gt;Field B1&lt;/csv:field&gt;
+ *     &lt;csv:field number="3" column="Column C"&gt;Field C1&lt;/csv:field&gt;
+ *   &lt;/csv:record&gt;
+ *   &lt;csv:record number="2"&gt;
+ *     &lt;csv:field number="1" column="Column A"&gt;Field A2&lt;/csv:field&gt;
+ *     &lt;csv:field number="2" column="Column B"&gt;Field B2&lt;/csv:field&gt;
+ *     &lt;csv:field number="3" column="Column C"&gt;Field C2&lt;/csv:field&gt;
+ *   &lt;/csv:record&gt;
+ * &lt;/csv:document&gt;
+ * </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>
+ *
+ * @author <a href="mailto:pier@apache.org">Pier Fumagalli</a>
+ * @author Copyright &copy; 2000-2004 <a href="http://www.apache.org/">The Apache
+ *         Software Foundation</a>. All rights reserved.
+ */
+public class CSVGenerator extends FileGenerator {
+
+    /** <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;
+    /** <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>A flag indicating whether the &lt;record&gt; 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 CSVGenerator} instance.</p>
+     */
+    public CSVGenerator() {
+        super();
+    }
+
+    /**
+     * <p>Recycle this component.</p>.
+     */
+    public void recycle() {
+        super.recycle();
+        
+        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 CSVGenerator} 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-header", 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.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() {
+        String key = this.inputSource.getURI();
+        if (this.columns != null) return (key + "+headers");
+        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.contentHandler.setDocumentLocator(csv);
+            this.contentHandler.startDocument();
+            this.contentHandler.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) {
+
+                /* 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.contentHandler.endPrefixMapping(NAMESPACE_PREFIX);
+            this.contentHandler.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.addAttribute("", "number", "number", "CDATA", 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.addAttribute("", "number", "number", "CDATA", 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.addAttribute("", "column", "column", "CDATA", header);
+            }
+        }
+
+        this.startElement(element, attributes);
+        this.contentHandler.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.contentHandler.characters(INDENT_STRING, 0, level + 1);
+    }
+
+    private void startElement(String name)
+    throws SAXException {
+        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.contentHandler.startElement(NAMESPACE_URI, name, qual, atts);
+    }
+
+    private void endElement(String name)
+    throws SAXException {
+        String qual = NAMESPACE_PREFIX + ':' + name;
+        this.contentHandler.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;
+
+        private 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;
+                    if (b != null) b[o + i] = (char)c;
+                }
+            } catch (IOException ee) {
+                return i;
+            }
+            return i;
+        }
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/CSVGenerator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/CalendarGenerator.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/CalendarGenerator.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/CalendarGenerator.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/CalendarGenerator.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,364 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.io.Serializable;
+import java.text.DateFormat;
+import java.text.DecimalFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.caching.CacheableProcessingComponent;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.excalibur.source.SourceValidity;
+import org.apache.excalibur.source.impl.validity.NOPValidity;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * @cocoon.sitemap.component.documentation
+ * Generates an XML document representing a calendar for a given month and year.
+ * 
+ * @cocoon.sitemap.component.documentation.caching TBD
+ * @cocoon.sitemap.component.name   calendar
+ * @cocoon.sitemap.component.label  content
+ * @cocoon.sitemap.component.logger sitemap.generator.calendar
+ *
+ *
+ * <p>
+ * Here is a sample output:
+ * </p>
+ * <pre>
+ * &lt;calendar:calendar xmlns:calendar="http://apache.org/cocoon/calendar/1.0"
+ *     year="2004" month="January" prevMonth="12" prevYear="2003"
+ *     nextMonth="02" nextYear="2004"&gt;
+ *   &lt;calendar:week number="1"&gt;
+ *     &lt;calendar:day number="1" weekday="THURSDAY" date="January 1, 2004"/&gt;
+ *     &lt;calendar:day number="2" weekday="FRIDAY" date="January 2, 2004"/&gt;
+ *     &lt;calendar:day number="3" weekday="SATURDAY" date="January 3, 2004"/&gt;
+ *     &lt;calendar:day number="4" weekday="SUNDAY" date="January 4, 2004"/&gt;
+ *   &lt;/calendar:week&gt;
+ *   ...
+ * &lt;/calendar:calendar&gt;
+ * </pre>
+ * <p>
+ * The <i>src</i> parameter is ignored.
+ * </p>
+ * <p>
+ *  <b>Configuration options:</b>
+ *  <dl>
+ *   <dt> <i>month</i> (optional)</dt>
+ *   <dd> Sets the month for the calendar (January is 1). Default is the current month.</dd>
+ *   <dt> <i>year</i> (optional)</dt>
+ *   <dd> Sets the year for the calendar. Default is the current year.</dd>
+ *   <dt> <i>dateFormat</i> (optional)</dt>
+ *   <dd> Sets the format for the date attribute of each node, as
+ *        described in java.text.SimpleDateFormat. If unset, the default
+ *        format for the current locale will be used.</dd>
+ *   <dt> <i>lang</i> (optional)</dt>
+ *   <dd> Sets the ISO language code for determining the locale.</dd>
+ *   <dt> <i>country</i> (optional)</dt>
+ *   <dd> Sets the ISO country code for determining the locale.</dd>
+ *   <dt> <i>padWeeks</i> (optional)</dt>
+ *   <dd> If set to true, full weeks will be generated by adding
+ *        days from the end of the previous month and the beginning
+ *        of the following month.</dd>
+ *  </dl>
+ * </p>
+ *               
+ * @version CVS $Id: CalendarGenerator.java 314929 2005-10-12 14:28:01Z hepabolu $
+ */
+public class CalendarGenerator extends ServiceableGenerator implements CacheableProcessingComponent {
+    
+    /** The URI of the namespace of this generator. */
+    protected static final String URI = "http://apache.org/cocoon/calendar/1.0";
+    
+    /** The namespace prefix for this namespace. */
+    protected static final String PREFIX = "calendar";
+    
+    /** Node and attribute names */
+    protected static final String CALENDAR_NODE_NAME   = "calendar";
+    protected static final String WEEK_NODE_NAME       = "week";
+    protected static final String DAY_NODE_NAME        = "day";
+    protected static final String MONTH_ATTR_NAME      = "month";
+    protected static final String YEAR_ATTR_NAME       = "year";
+    protected static final String DATE_ATTR_NAME       = "date";
+    protected static final String NUMBER_ATTR_NAME     = "number";
+    protected static final String WEEKDAY_ATTR_NAME    = "weekday";
+    protected static final String PREV_MONTH_ATTR_NAME = "prevMonth";
+    protected static final String PREV_YEAR_ATTR_NAME  = "prevYear";
+    protected static final String NEXT_MONTH_ATTR_NAME = "nextMonth";
+    protected static final String NEXT_YEAR_ATTR_NAME  = "nextYear";
+    
+    /** Formatter for month number */
+    protected static final DecimalFormat monthNumberFormatter = new DecimalFormat("00");
+    
+    /** Convenience object, so we don't need to create an AttributesImpl for every element. */
+    protected AttributesImpl attributes;
+    
+    /**
+     * The cache key needs to be generated for the configuration of this
+     * generator, so storing the parameters for generateKey().
+     */
+    protected List cacheKeyParList;
+    
+    /** The year to generate the calendar for */
+    protected int year;
+    
+    /** The month to generate the calendar for */
+    protected int month;
+    
+    /** The format for dates */
+    protected DateFormat dateFormatter;
+    
+    /** The format for month names */
+    protected DateFormat monthFormatter;
+    
+    /** The current locale */
+    protected Locale locale;
+    
+    /** Do we need to pad out the first and last weeks? */
+    protected boolean padWeeks;
+
+    /* Add the day of the week 
+     * 
+     * since SUNDAY=1, we start with a dummy
+     * entry. 
+     */
+    protected String weekdays[] = { "",
+        "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", 
+        "FRIDAY", "SATURDAY"
+    };
+	
+    /**
+     * Set the request parameters. Must be called before the generate method.
+     *
+     * @param resolver     the SourceResolver object
+     * @param objectModel  a <code>Map</code> containing model object
+     * @param src          the source URI (ignored)
+     * @param par          configuration parameters
+     */
+    public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par)
+    throws ProcessingException, SAXException, IOException {
+        super.setup(resolver, objectModel, src, par);
+        
+        this.cacheKeyParList = new ArrayList();
+        this.cacheKeyParList.add(src);
+        
+        // Determine the locale
+        String langString = par.getParameter("lang", null);
+        locale = Locale.getDefault();
+        if (langString != null) {
+            this.cacheKeyParList.add(langString);
+            String countryString = par.getParameter("country", "");
+            if (! "".equals(countryString)) {
+                this.cacheKeyParList.add(countryString);
+            }
+            locale = new Locale(langString, countryString);
+        }
+        
+        // Determine year and month. Default is current year and month.
+        Calendar now = Calendar.getInstance(locale);
+        this.year = par.getParameterAsInteger("year", now.get(Calendar.YEAR));
+        this.cacheKeyParList.add(String.valueOf(this.year));
+        this.month = par.getParameterAsInteger("month", now.get(Calendar.MONTH) + 1) - 1;
+        this.cacheKeyParList.add(String.valueOf(this.month));
+        
+        String dateFormatString = par.getParameter("dateFormat", null);
+        this.cacheKeyParList.add(dateFormatString);
+        if (dateFormatString != null) {
+            this.dateFormatter = new SimpleDateFormat(dateFormatString, locale);
+        } else {
+            this.dateFormatter = DateFormat.getDateInstance(DateFormat.LONG, locale);
+        }
+        this.padWeeks = par.getParameterAsBoolean("padWeeks", false);
+        this.cacheKeyParList.add(new Boolean(this.padWeeks));
+        this.monthFormatter = new SimpleDateFormat("MMMM", locale);
+        this.attributes = new AttributesImpl();
+    }
+    
+    /**
+     * Generate XML data.
+     *
+     * @throws  SAXException if an error occurs while outputting the document
+     */
+    public void generate() throws SAXException, ProcessingException {
+        Calendar start = Calendar.getInstance(TimeZone.getTimeZone("UTC"), locale);
+        start.clear();
+        start.set(Calendar.YEAR, this.year);
+        start.set(Calendar.MONTH, this.month);
+        start.set(Calendar.DAY_OF_MONTH, 1);
+        Calendar end = (Calendar) start.clone();
+        end.add(Calendar.MONTH, 1);
+        
+        // Determine previous and next months
+        Calendar prevMonth = (Calendar) start.clone();
+        prevMonth.add(Calendar.MONTH, -1);
+        
+        this.contentHandler.startDocument();
+        this.contentHandler.startPrefixMapping(PREFIX, URI);
+        attributes.clear();
+        attributes.addAttribute("", YEAR_ATTR_NAME, YEAR_ATTR_NAME, "CDATA", String.valueOf(year));
+        attributes.addAttribute("", MONTH_ATTR_NAME, MONTH_ATTR_NAME, "CDATA", 
+                monthFormatter.format(start.getTime()));
+        
+        // Add previous and next month
+        attributes.addAttribute("", PREV_YEAR_ATTR_NAME, PREV_YEAR_ATTR_NAME, "CDATA", 
+                String.valueOf(prevMonth.get(Calendar.YEAR)));
+        attributes.addAttribute("", PREV_MONTH_ATTR_NAME, PREV_MONTH_ATTR_NAME, "CDATA", 
+                monthNumberFormatter.format(prevMonth.get(Calendar.MONTH) + 1));
+        attributes.addAttribute("", NEXT_YEAR_ATTR_NAME, NEXT_YEAR_ATTR_NAME, "CDATA", 
+                String.valueOf(end.get(Calendar.YEAR)));
+        attributes.addAttribute("", NEXT_MONTH_ATTR_NAME, NEXT_MONTH_ATTR_NAME, "CDATA", 
+                monthNumberFormatter.format(end.get(Calendar.MONTH) + 1));
+        
+        this.contentHandler.startElement(URI, CALENDAR_NODE_NAME,
+                PREFIX + ':' + CALENDAR_NODE_NAME, attributes);
+        int weekNo = start.get(Calendar.WEEK_OF_MONTH);
+        int firstDay = start.getFirstDayOfWeek();
+        if (start.get(Calendar.DAY_OF_WEEK) != firstDay) {
+            attributes.clear();
+            attributes.addAttribute("", NUMBER_ATTR_NAME, NUMBER_ATTR_NAME, "CDATA", String.valueOf(weekNo));
+            this.contentHandler.startElement(URI, WEEK_NODE_NAME,
+                    PREFIX + ':' + WEEK_NODE_NAME, attributes);
+            if (padWeeks) {
+                Calendar previous = (Calendar) start.clone();
+                while (previous.get(Calendar.DAY_OF_WEEK) != firstDay) {
+                    previous.add(Calendar.DAY_OF_MONTH, -1);		
+                }
+                while (previous.before(start)) {
+                    attributes.clear();
+                    attributes.addAttribute("", NUMBER_ATTR_NAME, NUMBER_ATTR_NAME, "CDATA",
+                            String.valueOf(previous.get(Calendar.DAY_OF_MONTH)));
+                    attributes.addAttribute("", WEEKDAY_ATTR_NAME, WEEKDAY_ATTR_NAME, "CDATA",
+                            weekdays[previous.get(Calendar.DAY_OF_WEEK)]);
+                    attributes.addAttribute("", DATE_ATTR_NAME, DATE_ATTR_NAME, "CDATA",
+                            dateFormatter.format(previous.getTime()));
+                    this.contentHandler.startElement(URI, DAY_NODE_NAME,
+                            PREFIX + ':' + DAY_NODE_NAME, attributes);
+                    addContent(previous, locale);
+                    this.contentHandler.endElement(URI, DAY_NODE_NAME,
+                            PREFIX + ':' + DAY_NODE_NAME);
+                    previous.add(Calendar.DAY_OF_MONTH, 1); 
+                } 
+            }
+        }
+        while (start.before(end)) {
+            if (start.get(Calendar.DAY_OF_WEEK) == firstDay) {
+                weekNo = start.get(Calendar.WEEK_OF_MONTH);
+                attributes.clear();
+                attributes.addAttribute("", NUMBER_ATTR_NAME, NUMBER_ATTR_NAME, "CDATA", String.valueOf(weekNo));
+                this.contentHandler.startElement(URI, WEEK_NODE_NAME,
+                        PREFIX + ':' + WEEK_NODE_NAME, attributes);
+            }
+            attributes.clear();
+            attributes.addAttribute("", NUMBER_ATTR_NAME, NUMBER_ATTR_NAME, "CDATA",
+                    String.valueOf(start.get(Calendar.DAY_OF_MONTH)));
+            attributes.addAttribute("", WEEKDAY_ATTR_NAME, WEEKDAY_ATTR_NAME, "CDATA",
+                    weekdays[start.get(Calendar.DAY_OF_WEEK)]);
+            attributes.addAttribute("", DATE_ATTR_NAME, DATE_ATTR_NAME, "CDATA",
+                    dateFormatter.format(start.getTime()));
+            this.contentHandler.startElement(URI, DAY_NODE_NAME,
+                    PREFIX + ':' + DAY_NODE_NAME, attributes);
+            addContent(start, locale);
+            this.contentHandler.endElement(URI, DAY_NODE_NAME,
+                    PREFIX + ':' + DAY_NODE_NAME);
+            start.add(Calendar.DAY_OF_MONTH, 1);
+            if (start.get(Calendar.DAY_OF_WEEK) == firstDay
+                    || (!padWeeks && ! start.before(end))) {
+                this.contentHandler.endElement(URI, WEEK_NODE_NAME,
+                        PREFIX + ':' + WEEK_NODE_NAME);
+            }
+        }
+        
+        if (padWeeks) {
+            while (firstDay != end.get(Calendar.DAY_OF_WEEK)) {
+                attributes.clear();
+                attributes.addAttribute("", NUMBER_ATTR_NAME, NUMBER_ATTR_NAME, "CDATA",
+                        String.valueOf(end.get(Calendar.DAY_OF_MONTH)));
+                attributes.addAttribute("", WEEKDAY_ATTR_NAME, WEEKDAY_ATTR_NAME, "CDATA",
+                        weekdays[end.get(Calendar.DAY_OF_WEEK)]);
+                attributes.addAttribute("", DATE_ATTR_NAME, DATE_ATTR_NAME, "CDATA",
+                        dateFormatter.format(end.getTime()));
+                this.contentHandler.startElement(URI, DAY_NODE_NAME,
+                        PREFIX + ':' + DAY_NODE_NAME, attributes);
+                addContent(end, locale);
+                this.contentHandler.endElement(URI, DAY_NODE_NAME,
+                        PREFIX + ':' + DAY_NODE_NAME);
+                end.add(Calendar.DAY_OF_MONTH, 1); 		
+                if (firstDay == end.get(Calendar.DAY_OF_WEEK)) { 
+                    this.contentHandler.endElement(URI, WEEK_NODE_NAME,
+                       PREFIX + ':' + WEEK_NODE_NAME);
+                }
+            }
+        }
+        this.contentHandler.endElement(URI, CALENDAR_NODE_NAME,
+                PREFIX + ':' + CALENDAR_NODE_NAME);
+        this.contentHandler.endPrefixMapping(PREFIX);
+        this.contentHandler.endDocument();
+    }
+    
+    /**
+     * Add content to a &lt;day&gt; element. This method is intended to be overridden
+     * by subclasses that want to add content to one or more days of the calendar.
+     * 
+     * @param date   The date corresponding to the current element.
+     * @param locale The current locale.
+     * @throws SAXException if an error occurs while outputting the document
+     */
+    protected void addContent(Calendar date, Locale locale) throws SAXException {}
+    
+    /* (non-Javadoc)
+     * @see org.apache.cocoon.caching.CacheableProcessingComponent#getKey()
+     */
+    public Serializable getKey() {
+        StringBuffer buffer = new StringBuffer();
+        int len = this.cacheKeyParList.size();
+        for (int i = 0; i < len; i++) {
+            buffer.append(this.cacheKeyParList.get(i) + ":");
+        }
+        return buffer.toString();
+    }
+    
+    /* (non-Javadoc)
+     * @see org.apache.cocoon.caching.CacheableProcessingComponent#getValidity()
+     */
+    public SourceValidity getValidity() {
+        return NOPValidity.SHARED_INSTANCE;
+    }
+    
+    /**
+     * Recycle resources
+     * @see org.apache.avalon.excalibur.pool.Recyclable#recycle()
+     */
+    public void recycle() {
+        this.cacheKeyParList = null;
+        this.attributes = null;
+        this.dateFormatter = null;
+        this.monthFormatter = null;
+        this.locale = null;
+        super.recycle();
+    }
+    
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/CalendarGenerator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/DirectoryGenerator.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/DirectoryGenerator.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/DirectoryGenerator.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/DirectoryGenerator.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,552 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ * 
+ * Licensed 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.ResourceNotFoundException;
+import org.apache.cocoon.caching.CacheableProcessingComponent;
+import org.apache.cocoon.components.source.SourceUtil;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceException;
+import org.apache.excalibur.source.SourceValidity;
+import org.apache.regexp.RE;
+import org.apache.regexp.RESyntaxException;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Serializable;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+import java.util.Arrays;
+import java.util.Comparator;
+
+/**
+ * @cocoon.sitemap.component.documentation
+ * Generates an XML directory listing.
+ * A more general approach is implemented by the TraversableGenerator (src/blocks/repository/java/org/apache/cocoon/generation/TraversableGenerator.java)
+ * 
+ * @cocoon.sitemap.component.name   directory
+ * @cocoon.sitemap.component.label  content
+ * @cocoon.sitemap.component.logger sitemap.generator.directory
+ * @cocoon.sitemap.component.documentation.caching
+ *               Uses the last modification date of the directory and the contained files
+ * 
+ * @cocoon.sitemap.component.pooling.max  16
+ *  
+ * @author <a href="mailto:pier@apache.org">Pierpaolo Fumagalli</a>
+ *         (Apache Software Foundation)
+ * @author <a href="mailto:conny@smb-tec.com">Conny Krappatsch</a>
+ *         (SMB GmbH) for Virbus AG
+ * @version CVS $Id: DirectoryGenerator.java 225254 2005-07-26 08:02:05Z cziegeler $
+ */
+public class DirectoryGenerator 
+    extends ServiceableGenerator 
+    implements CacheableProcessingComponent {
+
+    /** Constant for the file protocol. */
+    private static final String FILE = "file:";
+
+    /** The URI of the namespace of this generator. */
+    protected static final String URI = "http://apache.org/cocoon/directory/2.0";
+
+    /** The namespace prefix for this namespace. */
+    protected static final String PREFIX = "dir";
+
+    /* Node and attribute names */
+    protected static final String DIR_NODE_NAME = "directory";
+    protected static final String FILE_NODE_NAME = "file";
+
+    protected static final String FILENAME_ATTR_NAME = "name";
+    protected static final String LASTMOD_ATTR_NAME = "lastModified";
+    protected static final String DATE_ATTR_NAME = "date";
+    protected static final String SIZE_ATTR_NAME = "size";
+
+    /** The validity that is being built */
+    protected DirValidity validity;
+    /** Convenience object, so we don't need to create an AttributesImpl for every element. */
+    protected AttributesImpl attributes;
+
+    /**
+     * The cache key needs to be generated for the configuration of this
+     * generator, so storing the parameters for generateKey().
+     * Using the member variables after setup() would not work I guess. I don't
+     * know a way from the regular expressions back to the pattern or at least
+     * a useful string.
+     */
+    protected List cacheKeyParList;
+
+    /** The depth parameter determines how deep the DirectoryGenerator should delve. */
+    protected int depth;
+    /**
+     * The dateFormatter determines into which date format the lastModified
+     * time should be converted.
+     * FIXME: SimpleDateFormat is not supported by all locales!
+     */
+    protected SimpleDateFormat dateFormatter;
+    /** The delay between checks on updates to the filesystem. */
+    protected long refreshDelay;
+    /**
+     * The sort parameter determines by which attribute the content of one
+     * directory should be sorted. Possible values are "name", "size", "lastmodified"
+     * and "directory", where "directory" is the same as "name", except that
+     * directory entries are listed first.
+     */
+    protected String sort;
+    /** The reverse parameter reverses the sort order. <code>false</code> is default. */
+    protected boolean reverse;
+    /** The regular expression for the root pattern. */
+    protected RE rootRE;
+    /** The regular expression for the include pattern. */
+    protected RE includeRE;
+    /** The regular expression for the exclude pattern. */
+    protected RE excludeRE;
+    /**
+     * This is only set to true for the requested directory specified by the
+     * <code>src</code> attribute on the generator's configuration.
+     */
+    protected boolean isRequestedDirectory;
+
+    /** The source object for the directory. */
+    protected Source directorySource;
+
+    /**
+     * Set the request parameters. Must be called before the generate method.
+     *
+     * @param resolver     the SourceResolver object
+     * @param objectModel  a <code>Map</code> containing model object
+     * @param src          the directory to be XMLized specified as src attribute on &lt;map:generate/>
+     * @param par          configuration parameters
+     */
+    public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par)
+            throws ProcessingException, SAXException, IOException {
+        if (src == null) {
+            throw new ProcessingException("No src attribute pointing to a directory to be XMLized specified.");
+        }
+        super.setup(resolver, objectModel, src, par);
+
+        try {
+            this.directorySource = this.resolver.resolveURI(src);
+        } catch (SourceException se) {
+            throw SourceUtil.handle(se);
+        }
+
+        this.cacheKeyParList = new ArrayList();
+        this.cacheKeyParList.add(this.directorySource.getURI());
+
+        this.depth = par.getParameterAsInteger("depth", 1);
+        this.cacheKeyParList.add(String.valueOf(this.depth));
+
+        String dateFormatString = par.getParameter("dateFormat", null);
+        this.cacheKeyParList.add(dateFormatString);
+        if (dateFormatString != null) {
+            this.dateFormatter = new SimpleDateFormat(dateFormatString);
+        } else {
+            this.dateFormatter = new SimpleDateFormat();
+        }
+
+        this.sort = par.getParameter("sort", "name");
+        this.cacheKeyParList.add(this.sort);
+
+        this.reverse = par.getParameterAsBoolean("reverse", false);
+        this.cacheKeyParList.add(String.valueOf(this.reverse));
+
+        this.refreshDelay = par.getParameterAsLong("refreshDelay", 1L) * 1000L;
+        this.cacheKeyParList.add(String.valueOf(this.refreshDelay));
+
+        if (this.getLogger().isDebugEnabled()) {
+            this.getLogger().debug("depth: " + this.depth);
+            this.getLogger().debug("dateFormat: " + this.dateFormatter.toPattern());
+            this.getLogger().debug("sort: " + this.sort);
+            this.getLogger().debug("reverse: " + this.reverse);
+            this.getLogger().debug("refreshDelay: " + this.refreshDelay);
+        }
+
+        String rePattern = null;
+        try {
+            rePattern = par.getParameter("root", null);
+            this.cacheKeyParList.add(rePattern);
+            this.rootRE = (rePattern == null) ? null : new RE(rePattern);
+            if (this.getLogger().isDebugEnabled()) {
+                this.getLogger().debug("root pattern: " + rePattern);
+            }
+
+            rePattern = par.getParameter("include", null);
+            this.cacheKeyParList.add(rePattern);
+            this.includeRE = (rePattern == null) ? null : new RE(rePattern);
+            if (this.getLogger().isDebugEnabled()) {
+                this.getLogger().debug("include pattern: " + rePattern);
+            }
+
+            rePattern = par.getParameter("exclude", null);
+            this.cacheKeyParList.add(rePattern);
+            this.excludeRE = (rePattern == null) ? null : new RE(rePattern);
+            if (this.getLogger().isDebugEnabled()) {
+                this.getLogger().debug("exclude pattern: " + rePattern);
+            }
+        } catch (RESyntaxException rese) {
+            throw new ProcessingException("Syntax error in regexp pattern '"
+                                          + rePattern + "'", rese);
+        }
+
+        this.isRequestedDirectory = false;
+        this.attributes = new AttributesImpl();
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.cocoon.caching.CacheableProcessingComponent#getKey()
+     */
+    public Serializable getKey() {
+        StringBuffer buffer = new StringBuffer();
+        int len = this.cacheKeyParList.size();
+        for (int i = 0; i < len; i++) {
+            buffer.append((String)this.cacheKeyParList.get(i) + ":");
+        }
+        return buffer.toString();
+    }
+
+    /**
+     * Gets the source validity, using a deferred validity object. The validity
+     * is initially empty since the files that define it are not known before
+     * generation has occured. So the returned object is kept by the generator
+     * and filled with each of the files that are traversed.
+     * 
+     * @see DirectoryGenerator.DirValidity
+     */
+    public SourceValidity getValidity() {
+        if (this.validity == null) {
+            this.validity = new DirValidity(this.refreshDelay);
+        }
+        return this.validity;
+    }
+
+    /**
+     * Generate XML data.
+     * 
+     * @throws SAXException  if an error occurs while outputting the document
+     * @throws ProcessingException  if the requsted URI isn't a directory on the local filesystem
+     */
+    public void generate() throws SAXException, ProcessingException {
+        try {
+            String systemId = this.directorySource.getURI();
+            if (!systemId.startsWith(FILE)) {
+                throw new ResourceNotFoundException(systemId + " does not denote a directory");
+            }
+            // This relies on systemId being of the form "file://..."
+            File directoryFile = new File(new URL(systemId).getFile());
+            if (!directoryFile.isDirectory()) {
+                throw new ResourceNotFoundException(super.source + " is not a directory.");
+            }
+
+            this.contentHandler.startDocument();
+            this.contentHandler.startPrefixMapping(PREFIX, URI);
+
+            Stack ancestors = getAncestors(directoryFile);
+            addAncestorPath(directoryFile, ancestors);
+
+            this.contentHandler.endPrefixMapping(PREFIX);
+            this.contentHandler.endDocument();
+        } catch (IOException ioe) {
+            throw new ResourceNotFoundException("Could not read directory " + super.source, ioe);
+        }
+    }
+
+    /**
+     * Creates a stack containing the ancestors of File up to specified directory.
+     * 
+     * @param path the File whose ancestors shall be retrieved
+     * @return a Stack containing the ancestors.
+     */
+    protected Stack getAncestors(File path) {
+        File parent = path;
+        Stack ancestors = new Stack();
+
+        while ((parent != null) && !isRoot(parent)) {
+            parent = parent.getParentFile();
+            if (parent != null) {
+                ancestors.push(parent);
+            } else {
+                // no ancestor matched the root pattern
+                ancestors.clear();
+            }
+        }
+
+        return ancestors;
+    }
+
+    /**
+     * Adds recursively the path from the directory matched by the root pattern
+     * down to the requested directory.
+     * 
+     * @param path       the requested directory.
+     * @param ancestors  the stack of the ancestors.
+     * @throws SAXException
+     */
+    protected void addAncestorPath(File path, Stack ancestors) throws SAXException {
+        if (ancestors.empty()) {
+            this.isRequestedDirectory = true;
+            addPath(path, depth);
+        } else {
+            startNode(DIR_NODE_NAME, (File)ancestors.pop());
+            addAncestorPath(path, ancestors);
+            endNode(DIR_NODE_NAME);
+        }
+    }
+
+    /**
+     * Adds a single node to the generated document. If the path is a
+     * directory, and depth is greater than zero, then recursive calls
+     * are made to add nodes for the directory's children.
+     * 
+     * @param path   the file/directory to process
+     * @param depth  how deep to scan the directory
+     * @throws SAXException  if an error occurs while constructing nodes
+     */
+    protected void addPath(File path, int depth) throws SAXException {
+        if (path.isDirectory()) {
+            startNode(DIR_NODE_NAME, path);
+            if (depth > 0) {
+                File contents[] = path.listFiles();
+
+                if (sort.equals("name")) {
+                    Arrays.sort(contents, new Comparator() {
+                        public int compare(Object o1, Object o2) {
+                            if (reverse) {
+                                return ((File)o2).getName().compareTo(((File)o1).getName());
+                            }
+                            return ((File)o1).getName().compareTo(((File)o2).getName());
+                        }
+                    });
+                } else if (sort.equals("size")) {
+                    Arrays.sort(contents, new Comparator() {
+                        public int compare(Object o1, Object o2) {
+                            if (reverse) {
+                                return new Long(((File)o2).length()).compareTo(
+                                    new Long(((File)o1).length()));
+                            }
+                            return new Long(((File)o1).length()).compareTo(
+                                new Long(((File)o2).length()));
+                        }
+                    });
+                } else if (sort.equals("lastmodified")) {
+                    Arrays.sort(contents, new Comparator() {
+                        public int compare(Object o1, Object o2) {
+                            if (reverse) {
+                                return new Long(((File)o2).lastModified()).compareTo(
+                                    new Long(((File)o1).lastModified()));
+                            }
+                            return new Long(((File)o1).lastModified()).compareTo(
+                                new Long(((File)o2).lastModified()));
+                        }
+                    });
+                } else if (sort.equals("directory")) {
+                    Arrays.sort(contents, new Comparator() {
+                        public int compare(Object o1, Object o2) {
+                            File f1 = (File)o1;
+                            File f2 = (File)o2;
+
+                            if (reverse) {
+                                if (f2.isDirectory() && f1.isFile())
+                                    return -1;
+                                if (f2.isFile() && f1.isDirectory())
+                                    return 1;
+                                return f2.getName().compareTo(f1.getName());
+                            }
+                            if (f2.isDirectory() && f1.isFile())
+                                return 1;
+                            if (f2.isFile() && f1.isDirectory())
+                                return -1;
+                            return f1.getName().compareTo(f2.getName());
+                        }
+                    });
+                }
+
+                for (int i = 0; i < contents.length; i++) {
+                    if (isIncluded(contents[i]) && !isExcluded(contents[i])) {
+                        addPath(contents[i], depth - 1);
+                    }
+                }
+            }
+            endNode(DIR_NODE_NAME);
+        } else {
+            if (isIncluded(path) && !isExcluded(path)) {
+                startNode(FILE_NODE_NAME, path);
+                endNode(FILE_NODE_NAME);
+            }
+        }
+    }
+
+    /**
+     * Begins a named node and calls setNodeAttributes to set its attributes.
+     * 
+     * @param nodeName  the name of the new node
+     * @param path      the file/directory to use when setting attributes
+     * @throws SAXException  if an error occurs while creating the node
+     */
+    protected void startNode(String nodeName, File path) throws SAXException {
+        if (this.validity != null) {
+            this.validity.addFile(path);
+        }
+        setNodeAttributes(path);
+        super.contentHandler.startElement(URI, nodeName, PREFIX + ':' + nodeName, attributes);
+    }
+
+    /**
+     * Sets the attributes for a given path. The default method sets attributes
+     * for the name of thefile/directory and for the last modification time
+     * of the path.
+     * 
+     * @param path  the file/directory to use when setting attributes
+     * @throws SAXException  if an error occurs while setting the attributes
+     */
+    protected void setNodeAttributes(File path) throws SAXException {
+        long lastModified = path.lastModified();
+        attributes.clear();
+        attributes.addAttribute("", FILENAME_ATTR_NAME, FILENAME_ATTR_NAME,
+                                "CDATA", path.getName());
+        attributes.addAttribute("", LASTMOD_ATTR_NAME, LASTMOD_ATTR_NAME,
+                                "CDATA", Long.toString(path.lastModified()));
+        attributes.addAttribute("", DATE_ATTR_NAME, DATE_ATTR_NAME,
+                                "CDATA", dateFormatter.format(new Date(lastModified)));
+        attributes.addAttribute("", SIZE_ATTR_NAME, SIZE_ATTR_NAME,
+                                "CDATA", Long.toString(path.length()));
+        if (this.isRequestedDirectory) {
+            attributes.addAttribute("", "sort", "sort", "CDATA", this.sort);
+            attributes.addAttribute("", "reverse", "reverse", "CDATA",
+                                    String.valueOf(this.reverse));
+            attributes.addAttribute("", "requested", "requested", "CDATA", "true");
+            this.isRequestedDirectory = false;
+        }
+    }
+
+    /**
+     * Ends the named node.
+     * 
+     * @param nodeName  the name of the new node
+     * @throws SAXException  if an error occurs while closing the node
+     */
+    protected void endNode(String nodeName) throws SAXException {
+        super.contentHandler.endElement(URI, nodeName, PREFIX + ':' + nodeName);
+    }
+
+    /**
+     * Determines if a given File is the defined root.
+     * 
+     * @param path  the File to check
+     * @return true if the File is the root or the root pattern is not set,
+     *         false otherwise.
+     */
+    protected boolean isRoot(File path) {
+        return (this.rootRE == null) ? true : this.rootRE.match(path.getName());
+    }
+
+    /**
+     * Determines if a given File shall be visible.
+     * 
+     * @param path  the File to check
+     * @return true if the File shall be visible or the include Pattern is <code>null</code>,
+     *         false otherwise.
+     */
+    protected boolean isIncluded(File path) {
+        return (this.includeRE == null) ? true : this.includeRE.match(path.getName());
+    }
+
+    /**
+     * Determines if a given File shall be excluded from viewing.
+     * 
+     * @param path  the File to check
+     * @return false if the given File shall not be excluded or the exclude Pattern is <code>null</code>,
+     *         true otherwise.
+     */
+    protected boolean isExcluded(File path) {
+        return (this.excludeRE == null) ? false : this.excludeRE.match(path.getName());
+    }
+
+    /**
+     * Recycle resources
+     */
+    public void recycle() {
+        if ( this.resolver != null ) {
+            this.resolver.release(this.directorySource);
+            this.directorySource = null;
+        }
+        this.cacheKeyParList = null;
+        this.attributes = null;
+        this.dateFormatter = null;
+        this.rootRE = null;
+        this.includeRE = null;
+        this.excludeRE = null;
+        this.validity = null;
+        super.recycle();
+    }
+
+    /** Specific validity class, that holds all files that have been generated */
+    public static class DirValidity implements SourceValidity {
+
+        private long expiry;
+        private long delay;
+        List files = new ArrayList();
+        List fileDates = new ArrayList();
+
+        public DirValidity(long delay) {
+            expiry = System.currentTimeMillis() + delay;
+            this.delay = delay;
+        }
+
+        public int isValid() {
+            if (System.currentTimeMillis() <= expiry) {
+                return 1;
+            }
+
+            expiry = System.currentTimeMillis() + delay;
+            int len = files.size();
+            for (int i = 0; i < len; i++) {
+                File f = (File)files.get(i);
+                if (!f.exists()) {
+                    return -1; // File was removed
+                }
+
+                long oldDate = ((Long)fileDates.get(i)).longValue();
+                long newDate = f.lastModified();
+
+                if (oldDate != newDate) {
+                    return -1;
+                }
+            }
+
+            // all content is up to date: update the expiry date
+            expiry = System.currentTimeMillis() + delay;
+            return 1;
+        }
+
+        public int isValid(SourceValidity newValidity) {
+            return isValid();
+        }
+
+        public void addFile(File f) {
+            files.add(f);
+            fileDates.add(new Long(f.lastModified()));
+        }
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/DirectoryGenerator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/ExceptionGenerator.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/ExceptionGenerator.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/ExceptionGenerator.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/ExceptionGenerator.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed 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.List;
+import java.util.Map;
+
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.cocoon.util.location.LocatableException;
+import org.apache.cocoon.util.location.Location;
+import org.apache.cocoon.util.location.LocationUtils;
+import org.apache.cocoon.util.location.MultiLocatable;
+import org.apache.cocoon.xml.AttributesImpl;
+import org.apache.commons.lang.SystemUtils;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * A generator that dumps an XML representation of the exception raised during a pipeline execution.
+ * <p>
+ * The Cocoon stack trace is produced, reflecting all locations the original exception went through,
+ * along with the root exception stacktrace and the full exception stacktrace.
+ * 
+ * @since 2.1.8
+ * @version $Id: ExceptionGenerator.java 280632 2005-09-13 19:35:46Z sylvain $
+ */
+public class ExceptionGenerator extends AbstractGenerator {
+    
+    private Throwable thr;
+    
+    public static String EXCEPTION_NS = "http://apache.org/cocoon/exception/1.0";
+
+    public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par) throws ProcessingException, SAXException, IOException {
+        super.setup(resolver, objectModel, src, par);
+        thr = (Throwable)objectModel.get(ObjectModelHelper.THROWABLE_OBJECT);
+        if (thr == null) {
+            throw new ProcessingException("ExceptionGenerator should be used in <map:handle-errors>");
+        }
+    }
+
+    public void generate() throws IOException, SAXException, ProcessingException {
+        this.contentHandler.startDocument();
+        toSAX(thr, this.contentHandler);
+        this.contentHandler.endDocument();
+    }
+    
+    public static void toSAX(Throwable thr, ContentHandler handler) throws SAXException {
+        Throwable root = ExceptionUtils.getRootCause(thr);
+        if (root == null) root = thr;
+
+        AttributesImpl attr = new AttributesImpl();
+        handler.startPrefixMapping("ex", EXCEPTION_NS);
+        attr.addCDATAAttribute("class", root.getClass().getName());
+        handler.startElement(EXCEPTION_NS, "exception-report", "ex:exception-report", attr);
+        
+        // Root exception location
+        Location loc = LocationUtils.getLocation(root);        
+        if (LocationUtils.isKnown(loc)) {
+            attr.clear();
+            dumpLocation(loc, attr, handler);
+        }
+
+        // Root exception message
+        attr.clear();
+        String message = root instanceof LocatableException ? ((LocatableException)root).getRawMessage() : root.getMessage();
+        simpleElement("message", attr, message, handler);
+        
+        // Cocoon stacktrace: dump all located exceptions in the exception stack
+        handler.startElement(EXCEPTION_NS, "cocoon-stacktrace", "ex:cocoon-stacktrace", attr);
+        Throwable current = thr;
+        while (current != null) {
+            loc = LocationUtils.getLocation(current);
+            if (LocationUtils.isKnown(loc)) {
+                // One or more locations: dump it
+                handler.startElement(EXCEPTION_NS, "exception", "ex:exception", attr);
+                
+                message = current instanceof LocatableException ? ((LocatableException)current).getRawMessage() : current.getMessage();
+                simpleElement("message", attr, message, handler);
+
+                attr.clear();
+                handler.startElement(EXCEPTION_NS, "locations", "ex:locations", attr);
+                dumpLocation(loc, attr, handler);
+                
+                if (current instanceof MultiLocatable) {
+                    List locations = ((MultiLocatable)current).getLocations();
+                    for (int i = 1; i < locations.size(); i++) { // start at 1 because we already dumped the first one
+                        attr.clear();
+                        dumpLocation((Location)locations.get(i), attr, handler);
+                    }
+                }
+                handler.endElement(EXCEPTION_NS, "locations", "ex:locations");
+                handler.endElement(EXCEPTION_NS, "exception", "ex:exception");
+            }
+            
+            
+            // Dump parent location
+            current = ExceptionUtils.getCause(current);
+        }
+        
+        handler.endElement(EXCEPTION_NS, "cocoon-stacktrace", "ex:cocoon-stacktrace");
+        
+        // Root exception stacktrace
+        attr.clear();
+        simpleElement("stacktrace", attr, ExceptionUtils.getStackTrace(root), handler);
+        
+        // Full stack trace (if exception is chained)
+        if (thr != root) {
+            String trace = SystemUtils.isJavaVersionAtLeast(140) ?
+                    ExceptionUtils.getStackTrace(thr) :
+                    ExceptionUtils.getFullStackTrace(thr);
+
+            simpleElement("full-stacktrace", attr, trace, handler);
+        }
+        
+        handler.endElement(EXCEPTION_NS, "exception-report", "ex:exception-report");
+        handler.endPrefixMapping("ex");
+    }
+    
+    private static void dumpLocation(Location loc, AttributesImpl attr, ContentHandler handler) throws SAXException {
+        attr.addCDATAAttribute("uri", loc.getURI());
+        attr.addCDATAAttribute("line", Integer.toString(loc.getLineNumber()));
+        attr.addCDATAAttribute("column", Integer.toString(loc.getColumnNumber()));        
+        simpleElement("location", attr, loc.getDescription(), handler);
+    }
+
+    private static void simpleElement(String name, Attributes attr, String value, ContentHandler handler) throws SAXException {
+        handler.startElement(EXCEPTION_NS, name, "ex:" + name, attr);
+        if (value != null && value.length() > 0) {
+            handler.characters(value.toCharArray(), 0, value.length());
+        }
+        handler.endElement(EXCEPTION_NS, name, "ex:" + name);
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/ExceptionGenerator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/FileGenerator.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/FileGenerator.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/FileGenerator.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/FileGenerator.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,123 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ *
+ * Licensed 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.SourceUtil;
+import org.apache.cocoon.environment.SourceResolver;
+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.
+ *
+ * <br>See {@link FileGeneratorFactory} for thread safe implementation of this
+ * component.
+ *
+ * @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
+ *
+ * @cocoon.sitemap.component.pooling.max  32
+ *
+ * @author <a href="mailto:pier@apache.org">Pierpaolo Fumagalli</a>
+ *         (Apache Software Foundation)
+ * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
+ * @version $Id: FileGenerator.java 158632 2005-03-22 18:00:41Z vgritsenko $
+ */
+public class FileGenerator extends ServiceableGenerator
+                           implements CacheableProcessingComponent {
+
+    /** The input source */
+    protected Source inputSource;
+
+    /**
+     * Recycle this component.
+     * All instance variables are set to <code>null</code>.
+     */
+    public void recycle() {
+        if (null != this.inputSource) {
+            super.resolver.release(this.inputSource);
+            this.inputSource = null;
+        }
+        super.recycle();
+    }
+
+    /**
+     * Setup the file generator.
+     * Try to get the last modification date of the source for caching.
+     */
+    public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par)
+    throws ProcessingException, SAXException, IOException {
+
+        super.setup(resolver, objectModel, src, par);
+        try {
+            this.inputSource = super.resolver.resolveURI(src);
+        } catch (SourceException se) {
+            throw SourceUtil.handle("Error during resolving of '" + src + "'.", se);
+        }
+    }
+
+    /**
+     * 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();
+    }
+
+    /**
+     * Generate XML data.
+     */
+    public void generate()
+    throws IOException, SAXException, ProcessingException {
+
+        try {
+            if (getLogger().isDebugEnabled()) {
+                getLogger().debug("Source " + super.source +
+                                  " resolved to " + this.inputSource.getURI());
+            }
+            SourceUtil.parse(this.manager, this.inputSource, super.xmlConsumer);
+        } catch (SAXException e) {
+            SourceUtil.handleSAXException(this.inputSource.getURI(), e);
+        }
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/FileGenerator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/FileGeneratorFactory.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/FileGeneratorFactory.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/FileGeneratorFactory.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/FileGeneratorFactory.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,149 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ *
+ * Licensed 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.avalon.framework.activity.Disposable;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.ServiceException;
+
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.xml.AbstractXMLProducer;
+import org.apache.cocoon.caching.CacheableProcessingComponent;
+import org.apache.cocoon.components.source.SourceUtil;
+import org.apache.cocoon.environment.SourceResolver;
+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>FileGeneratorFactory</code> is a class that reads XML from a source
+ * and generates SAX Events. The <code>FileGeneratorFactory</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
+ *
+ * @author <a href="mailto:pier@apache.org">Pierpaolo Fumagalli</a>
+ *         (Apache Software Foundation)
+ * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
+ * @author <a href="mailto:vgritsenko@apache.org">Vadim Gritsenko</a>
+ * @version $Id: FileGeneratorFactory.java 164222 2005-04-22 11:41:51Z cziegeler $
+ */
+public class FileGeneratorFactory extends AbstractLogEnabled
+                                  implements GeneratorFactory, Serviceable {
+
+    /** The service manager */
+    protected ServiceManager manager;
+
+    public void service(ServiceManager manager) throws ServiceException {
+        this.manager = manager;
+    }
+
+    /**
+     * Single threaded instance implementing generator functionality.
+     */
+    private class Instance extends AbstractXMLProducer
+                           implements GeneratorFactory.Instance,
+                                      CacheableProcessingComponent, Disposable {
+
+        /** The source resolver */
+        private SourceResolver resolver;
+
+        /** The input source */
+        private Source source;
+
+        /** Return GeneratorFactory */
+        public GeneratorFactory getFactory() {
+            return FileGeneratorFactory.this;
+        }
+
+        public Instance(Logger logger) {
+            enableLogging(logger);
+        }
+
+        /** Setup: resolve the source */
+        public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par)
+        throws ProcessingException, SAXException, IOException {
+            this.resolver = resolver;
+            try {
+                this.source = this.resolver.resolveURI(src);
+                if (getLogger().isDebugEnabled()) {
+                    getLogger().debug("Source '" + src +
+                                      "' resolved to <" + this.source.getURI() + ">");
+                }
+            } catch (SourceException se) {
+                throw SourceUtil.handle("Error during resolving of '" + src + "'.", se);
+            }
+        }
+
+        /** Dispose: release the source */
+        public void dispose() {
+            if (this.source != null) {
+                this.resolver.release(this.source);
+                this.source = null;
+            }
+        }
+
+        /**
+         * 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.source.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.source.getValidity();
+        }
+
+        /**
+         * Generate XML data.
+         */
+        public void generate()
+        throws IOException, SAXException, ProcessingException {
+            try {
+                SourceUtil.parse(manager, this.source, super.xmlConsumer);
+            } catch (SAXException e) {
+                SourceUtil.handleSAXException(this.source.getURI(), e);
+            }
+        }
+    }
+
+    public GeneratorFactory.Instance getInstance() {
+        return new Instance(getLogger());
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/FileGeneratorFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/FragmentExtractorGenerator.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/FragmentExtractorGenerator.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/FragmentExtractorGenerator.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/FragmentExtractorGenerator.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,100 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.Serializable;
+
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.cocoon.ResourceNotFoundException;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.caching.CacheableProcessingComponent;
+import org.apache.cocoon.components.sax.XMLDeserializer;
+
+import org.apache.excalibur.source.SourceValidity;
+import org.apache.excalibur.source.impl.validity.NOPValidity;
+import org.apache.excalibur.store.Store;
+
+import org.xml.sax.SAXException;
+
+/**
+ * The generation half of FragmentExtractor.
+ *
+ * FragmentExtractor is a transformer-generator pair which is designed to allow
+ * sitemap managers to extract certain nodes from a SAX stream and move them
+ * into a separate pipeline. The main use for this is to extract inline SVG
+ * images and serve them up through a separate pipeline, usually serializing
+ * them to PNG or JPEG format first.
+ *
+ * This is by no means complete yet, but it should prove useful, particularly
+ * for offline generation.
+ *
+ * @author <a href="mailto:paul@luminas.co.uk">Paul Russell</a>
+ * @version CVS $Id: FragmentExtractorGenerator.java 224617 2005-07-24 13:36:54Z joerg $
+ */
+public class FragmentExtractorGenerator extends ServiceableGenerator
+                                        implements CacheableProcessingComponent {
+
+    /**
+     * 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.source;
+    }
+
+    /**
+     * Generate the validity object.
+     *
+     * @return The generated validity object or <code>null</code> if the
+     *         component is currently not cacheable.
+     */
+    public SourceValidity getValidity() {
+        return NOPValidity.SHARED_INSTANCE;
+    }
+
+    public void generate() throws SAXException, ProcessingException {
+        // Obtain the fragmentID  (which is simply the filename portion of the source)
+        if (getLogger().isDebugEnabled()) {
+            getLogger().debug("Retrieving fragment " + source + ".");
+        }
+
+        Store store = null;
+        XMLDeserializer deserializer = null;
+        Object fragment = null;
+        try {
+            store = (Store) this.manager.lookup(Store.TRANSIENT_STORE);
+            fragment = store.get(source);
+            if (fragment == null) {
+                throw new ResourceNotFoundException("Could not find fragment " + source + " in store");
+            }
+
+            deserializer = (XMLDeserializer) this.manager.lookup(XMLDeserializer.ROLE);
+            deserializer.setConsumer(this.xmlConsumer);
+            deserializer.deserialize(fragment);
+
+        } catch (ServiceException ce) {
+            if (getLogger().isDebugEnabled()) {
+                getLogger().debug("Could not lookup for component.", ce);
+            }
+            throw new SAXException("Could not lookup for component.", ce);
+        } finally {
+            this.manager.release(store);
+            this.manager.release(deserializer);
+        }
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/FragmentExtractorGenerator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/Generator.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/Generator.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/Generator.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/Generator.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,42 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.cocoon.ProcessingException;
+import org.apache.cocoon.sitemap.SitemapModelComponent;
+import org.apache.cocoon.xml.XMLProducer;
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+
+/**
+ * A generator is the starting point of a pipeline. It "generates" XML
+ * and starts streaming them into the pipeline.
+ * 
+ * @author <a href="mailto:pier@apache.org">Pierpaolo Fumagalli</a>
+ *         (Apache Software Foundation)
+ * @version CVS $Id: Generator.java 30941 2004-07-29 19:56:58Z vgritsenko $
+ */
+public interface Generator extends XMLProducer, SitemapModelComponent {
+
+    String ROLE = Generator.class.getName();
+
+    /**
+     * Generate the XML and stream it into the pipeline
+     */
+    void generate()
+    throws IOException, SAXException, ProcessingException;
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/Generator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/GeneratorFactory.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/GeneratorFactory.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/GeneratorFactory.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/GeneratorFactory.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,58 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed 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;
+
+/**
+ * A generator factory is the factory of {@link Generator}s.
+ *
+ * <p>Regular GeneratorFactory implementation should be
+ * {@link org.apache.avalon.framework.thread.ThreadSafe} component
+ * serving as a factory of lightweight {@link Generator} objects.</p>
+ *
+ * <p>GeneratorFactory can implement any number of Avalon lifecycle interfaces
+ * and perform any initializations necessary. Ligtweight Generator instances
+ * created by {@link #getInstance()} method will only need to parse
+ * additional parameters passed on sitemap component invocation via
+ * {@link org.apache.cocoon.sitemap.SitemapModelComponent#setup(org.apache.cocoon.environment.SourceResolver, java.util.Map, String, org.apache.avalon.framework.parameters.Parameters)}
+ * method and can access global configuration of GeneratorFactory.</p>
+ *
+ * <p><strong>NOTE:</strong> Only Disposable interface is applicable to
+ * the Generator instance returned by the {@link #getInstance()}.</p>
+ *
+ * @since 2.2
+ * @author <a href="mailto:vgritsenko@apache.org">Vadim Gritsenko</a>
+ * @version CVS $Id: GeneratorFactory.java 55383 2004-10-23 15:10:46Z cziegeler $
+ */
+public interface GeneratorFactory {
+
+    String ROLE = Generator.ROLE;
+
+    /**
+     * Instance of the Generator created by the GeneratorFactory
+     */
+    interface Instance extends Generator {
+
+        /**
+         * @return GeneratorFactory which created this Generator instance
+         */
+        GeneratorFactory getFactory();
+    }
+
+    /**
+     * Create an instance of the Generator
+     */
+    Instance getInstance();
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/generation/GeneratorFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message