cocoon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jheym...@apache.org
Subject svn commit: r330548 [68/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/xml/LoggingEntityResolver.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/LoggingEntityResolver.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/LoggingEntityResolver.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/LoggingEntityResolver.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,55 @@
+/*
+ * 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.xml;
+
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Logging entity resolver to assist in caching.
+ *
+ * @author <a href="mailto:balld@webslingerZ.com">Donald Ball</a>
+ * @version CVS $Id: LoggingEntityResolver.java 30941 2004-07-29 19:56:58Z vgritsenko $
+ */
+public class LoggingEntityResolver extends AbstractLogEnabled implements EntityResolver {
+
+  protected EntityResolver resolver;
+  protected Set dependencies;
+
+  public LoggingEntityResolver(EntityResolver resolver) {
+    this.resolver = resolver;
+    dependencies = new HashSet();
+  }
+
+  public InputSource resolveEntity(String public_id, String system_id) throws SAXException,IOException {
+    InputSource input_source = resolver.resolveEntity(public_id,system_id);
+    dependencies.add(input_source);
+    getLogger().debug("Dependency: "+input_source.getSystemId());
+    return input_source;
+  }
+
+  public Set getDependencies() {
+    return Collections.unmodifiableSet(dependencies);
+  }
+
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/NamespacesTable.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/NamespacesTable.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/NamespacesTable.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/NamespacesTable.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,534 @@
+/*
+ * 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.xml;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * Keeps track of namespaces declarations and resolve namespaces names.
+ * <p>
+ * This class also provides a very convenient and safe way of handling
+ * namespace declarations in SAX pipes. It also allows to filter duplicate namespace
+ * declarations that too often clutter up XML documents that went through
+ * several transformations, and avoid useless namespace declarations that aren't followed
+ * by element events.
+ * <p>
+ * Usage example in a SAX pipe:
+ * <pre>
+ *   NamespacesTable namespaces = new NamespacesTable();
+ *   ContentHandler nextHandler;
+ *
+ *   public void startPrefixMapping(String prefix, String uri) throws SAXException {
+ *       namespaces.addDeclaration(prefix, uri);
+ *   }
+ *
+ *   public void startElement(...) throws SAXException {
+ *       // automatically start mappings for this scope
+ *       namespaces.enterScope(nextHandler);
+ *       nextHandler.startElement(...);
+ *   }
+ *
+ *   public void endElement(...) throws SAXException {
+ *       nextHandler.endElement(...);
+ *       // automatically end mappings for this scope
+ *       namespaces.leaveScope(nextHandler);
+ *   }
+ *
+ *   public void endPrefixMapping(String prefix) throws SAXException {
+ *       // Ignore, it is handled by leaveScope()
+ *   }
+ * </pre>
+ *
+ * @version $Id: NamespacesTable.java 233343 2005-08-18 18:06:44Z sylvain $
+ */
+public class NamespacesTable {
+    /** The last namespace declaration. */
+    private Entry lastEntry;
+    
+    /** The entry that start the prefix mappings for the scope that's about to be entered
+     * or was just left.
+     */
+    private Entry lastDeclaredEntry;
+
+    private boolean usesScopes = false;
+
+    /**
+     * Construct a new <code>NamespacesTable</code> instance.
+     */
+    public NamespacesTable() {
+        clear();
+    }
+
+    /**
+     * Clear and reinitialize this namespace table before reuse.
+     *
+     * @since 2.1.8
+     */
+    public void clear() {
+        this.lastEntry = Entry.create("","");
+        this.addDeclaration("xml", "http://www.w3.org/XML/1998/namespace");
+        // Lock this scope
+        this.lastEntry.closedScopes = 1;
+    }
+
+    /**
+     * Declare a new namespace prefix-uri mapping.
+     *
+     * @return The newly added <code>Declaration</code>.
+     */
+    public Declaration addDeclaration(String prefix, String uri) {
+        // Find a previous declaration of the same prefix
+        Entry dup = this.lastEntry;
+        while (dup != null && !dup.prefix.equals(prefix)) {
+            dup = dup.previous;
+        }
+
+        if (dup != null) {
+            if (usesScopes && dup.uri.equals(uri)) {
+                return dup;
+            }
+            dup.overriden = true;
+        }
+
+        Entry e = Entry.create(prefix, uri);
+        e.previous = this.lastEntry;
+        e.overrides = dup;
+        this.lastEntry = e;
+        // this always starts the declared prefix chain
+        this.lastDeclaredEntry = e;
+        return e;
+    }
+
+    /**
+     * Undeclare a namespace prefix-uri mapping. If the prefix was previously declared
+     * mapping another URI, its value is restored.
+     * <p>
+     * When using {@link #enterScope()}/{@link #leaveScope()}, this method does nothing and always
+     * returns <code>null</code>, as declaration removal is handled in {@link #leaveScope()}.
+     *
+     * @return the removed <code>Declaration</code> or <b>null</b>.
+     */
+    public Declaration removeDeclaration(String prefix) {
+        if (usesScopes) {
+            // Automatically handled in leaveScope
+            return null; // or throw and IllegalStateException if enterScope(handler) was used?
+        }
+
+        Entry current = this.lastEntry;
+        Entry afterCurrent = null;
+        while(current != null) {
+            if (current.closedScopes > 0) {
+                // Don't undeclare mappings not declared in this scope
+                return null;
+            }
+
+            if (current.prefix.equals(prefix)) {
+                // Got it
+                // Remove it from the chain
+                if (afterCurrent != null) {
+                    afterCurrent.previous = current.previous;
+                }
+                // And report closed scopes on the previous entry
+                current.previous.closedScopes += current.closedScopes;
+                Entry overrides = current.overrides;
+                if (overrides != null) {
+                    // No more overriden
+                    overrides.overriden = false;
+                }
+
+                if (this.lastDeclaredEntry == current) {
+                    if (current.previous.closedScopes == 0) {
+                        this.lastDeclaredEntry = current.previous;
+                    } else {
+                        this.lastDeclaredEntry = null;
+                    }
+                }
+
+                if (this.lastEntry == current) {
+                    this.lastEntry = current.previous;
+                }
+
+                return current;
+            }
+
+            afterCurrent = current;
+            current = current.previous;
+        }
+
+        // Not found
+        return null;
+    }
+
+    /**
+     * Enter a new scope. This starts a new, empty list of declarations for the new scope.
+     * <p>
+     * Typically called in a SAX handler <em>before</em> sending a <code>startElement()</code>
+     * event.
+     *
+     * @since 2.1.8
+     */
+    public void enterScope() {
+        this.usesScopes = true;
+        this.lastEntry.closedScopes++;
+        this.lastDeclaredEntry = null;
+    }
+
+    /**
+     * Start all declared mappings of the current scope and enter a new scope.  This starts a new,
+     * empty list of declarations for the new scope.
+     * <p>
+     * Typically called in a SAX handler <em>before</em> sending a <code>startElement()</code>
+     * event.
+     *
+     * @param handler the handler that will receive startPrefixMapping events.
+     * @throws SAXException
+     * @since 2.1.8
+     */
+    public void enterScope(ContentHandler handler) throws SAXException {
+        this.usesScopes = true;
+        Entry current = this.lastEntry;
+        while (current != null && current.closedScopes == 0) {
+            handler.startPrefixMapping(current.prefix, current.uri);
+            current = current.previous;
+        }
+        this.lastEntry.closedScopes++;
+        this.lastDeclaredEntry = null;
+    }
+
+    /**
+     * Leave a scope. The namespace declarations that occured before the corresponding
+     * <code>enterScope()</code> are no more visible using the resolution methods, but
+     * still available using {@link #getCurrentScopeDeclarations()} until the next call
+     * to {@link #addDeclaration(String, String)} or {@link #enterScope()}.
+     * <p>
+     * Typically called in a SAX handler <em>after</em> sending a <code>endElement()</code>
+     * event.
+     *
+     * @since 2.1.8
+     */
+    public void leaveScope() {
+        Entry current = this.lastEntry;
+
+        // Purge declarations that were added but not included in a scope
+        while (current.closedScopes == 0) {
+            current = current.previous;
+        }
+
+        current.closedScopes--;
+
+        if (current.closedScopes == 0) {
+            this.lastDeclaredEntry = current;
+        } else {
+            // More than one scope closed here: no local declarations
+            this.lastDeclaredEntry = null;
+        }
+
+        while (current != null && current.closedScopes == 0) {
+            Entry overrides = current.overrides;
+            if (overrides != null) {
+                // No more overriden
+                overrides.overriden = false;
+            }
+            current = current.previous;
+        }
+        this.lastEntry = current;
+    }
+
+    /**
+     * Leave a scope. The namespace declarations that occured before the corresponding
+     * <code>enterScope()</code> are no more visible using the resolution methods, but
+     * still available using {@link #getCurrentScopeDeclarations()} until the next call
+     * to {@link #addDeclaration(String, String)} or {@link #enterScope()}.
+     * <p>
+     * Typically called in a SAX handler <em>after</em> sending a <code>endElement()</code>
+     * event.
+     *
+     * @param handler the handler that will receive endPrefixMapping events.
+     * @throws SAXException
+     * @since 2.1.8
+     */
+    public void leaveScope(ContentHandler handler) throws SAXException {
+        Entry current = this.lastEntry;
+        
+        // Purge declarations that were added but not included in a scope
+        while (current.closedScopes == 0) {
+            current = current.previous;
+        }
+
+        current.closedScopes--;
+
+        if (current.closedScopes == 0) {
+            this.lastDeclaredEntry = current;
+        } else {
+            // More than one scope closed here: no local declarations
+            this.lastDeclaredEntry = null;
+        }
+
+        while (current != null && current.closedScopes == 0) {
+            handler.endPrefixMapping(current.prefix);
+            Entry overrides = current.overrides;
+            if (overrides != null) {
+                // No more overriden
+                overrides.overriden = false;
+            }
+            current = current.previous;
+        }
+
+        this.lastEntry = current;
+    }
+
+    private static final Declaration[] NO_DECLS = new Declaration[0];
+
+    /**
+     * Get the declarations that were declared within the current scope.
+     *
+     * @return the declarations (possibly empty, but never null)
+     * @since 2.1.8
+     */
+    public Declaration[] getCurrentScopeDeclarations() {
+        int count = 0;
+        Entry current = this.lastDeclaredEntry;
+        while (current != null && current.closedScopes == 0) {
+            count++;
+            current = current.previous;
+        }
+
+        if (count == 0) return NO_DECLS;
+
+        Declaration[] decls = new Declaration[count];
+        count = 0;
+        current = this.lastDeclaredEntry;
+        while (current != null && current.closedScopes == 0) {
+            decls[count++] = current;
+            current = current.previous;
+        }
+        return decls;
+    }
+
+    /**
+     * Return the URI associated with the given prefix or <b>null</b> if the
+     * prefix was not mapped.
+     */
+    public String getUri(String prefix) {
+        Entry current = this.lastEntry;
+        while (current != null) {
+            if (current.prefix.equals(prefix)) {
+                return current.uri;
+            }
+            current = current.previous;
+        }
+
+        // Not found
+        return null;
+    }
+
+    /**
+     * Return an array with all prefixes currently mapped to the specified URI.
+     * <br>
+     * The array length might be <b>zero</b> if no prefixes are associated with
+     * the specified uri.
+     *
+     * @return A <b>non-null</b> <code>String</code> array.
+     */
+    public String[] getPrefixes(String uri) {
+
+        Entry current=this.lastEntry;
+        int count=0;
+        while (current!=null) {
+            if(!current.overriden && current.uri.equals(uri))
+                count++;
+            current=current.previous;
+        }
+        if (count==0) return(new String[0]);
+
+        String prefixes[]=new String[count];
+        count=0;
+        current = this.lastEntry;
+        while (current!=null) {
+            if(!current.overriden && current.uri.equals(uri))
+                prefixes[count++] = current.prefix;
+            current = current.previous;
+        }
+        return prefixes;
+    }
+
+
+    /**
+     * Return one of the prefixes currently mapped to the specified URI or
+     * <b>null</b>.
+     */
+    public String getPrefix(String uri) {
+        Entry current = this.lastEntry;
+        while (current != null) {
+            if(!current.overriden && current.uri.equals(uri))
+                return current.prefix;
+            current = current.previous;
+        }
+        return null;
+    }
+
+    /**
+     * Resolve a namespace-aware name against the current namespaces
+     * declarations.
+     *
+     * @param uri The namespace URI or <b>null</b> if not known.
+     * @param raw The raw (complete) name or <b>null</b> if not known.
+     * @param prefix The namespace prefix or <b>null</b> if not known.
+     * @param local The local name or <b>null</b> if not known.
+     * @return A <b>non-null</b> <code>Name</code>.
+     * @exception SAXException If the name cannot be resolved.
+     */
+    public Name resolve(String uri, String raw, String prefix, String local)
+    throws SAXException {
+        if (uri==null) uri="";
+        if (raw==null) raw="";
+        if (prefix==null) prefix="";
+        if (local==null) local="";
+        // Start examining the URI
+        if (raw.length()>0) {
+            // The raw name was specified
+            int pos=raw.indexOf(':');
+            if (pos>0) {
+                // We have a namespace prefix:local separator
+                String pre=raw.substring(0,pos);
+                String loc=raw.substring(pos+1);
+                if (prefix.length()==0) prefix=pre;
+                else if (!prefix.equals(pre))
+                    throw new SAXException("Raw/Prefix mismatch");
+                if (local.length()==0) local=loc;
+                else if (!local.equals(loc))
+                    throw new SAXException("Raw/Local Name mismatch");
+            } else {
+                // We don't have a prefix:local separator
+                if (prefix.length()>0)
+                    throw new SAXException("Raw Name/Prefix mismatch");
+                if (local.length()==0) local=raw;
+                else if (!local.equals(raw))
+                    throw new SAXException("Raw Name/Local Name mismatch");
+            }
+        } else {
+            // The raw name was not specified
+            if (local.length()==0) throw new SAXException("No Raw/Local Name");
+            if (prefix.length()==0) raw=local;
+            else raw=prefix+':'+local;
+        }
+        // We have resolved and checked data between the raw, local, and
+        // prefix... We have to doublecheck the namespaces.
+        if (uri.length()>0) {
+            // We have a URI and a prefix, check them
+            if ((prefix.length()>0) &&  (!uri.equals(this.getUri(prefix)))) {
+                throw new SAXException("URI/Prefix mismatch [" + prefix + "," + uri + "]");
+            } else {
+                String temp=this.getPrefix(uri);
+                if (temp==null) throw new SAXException("URI not declared");
+                else if (temp.length()>0) {
+                    prefix=temp;
+                    raw=prefix+':'+local;
+                }
+            }
+        } else {
+            // We don't have a URI, check if we can find one from the prefix.
+            String temp=this.getUri(prefix);
+            if (temp==null) throw new SAXException("Prefix not declared");
+            else uri=temp;
+        }
+        NameImpl name=new NameImpl();
+        if (uri.length() > 0) name.uri=uri;
+        else name.uri=null;
+        name.raw=raw;
+        name.prefix=prefix;
+        name.local=local;
+        return(name);
+    }
+
+    /** The internal entry structure for this table. */
+    private static class Entry implements Declaration {
+        /** The URI string. */
+        protected String uri="";
+        /** The prefix string. */
+        protected String prefix="";
+        /** The previous declaration. */
+        protected Entry previous;
+        protected Entry overrides;
+        protected int closedScopes = 0;
+        protected boolean overriden = false;
+
+        /** Create a new namespace declaration. */
+        protected static Entry create(String prefix, String uri) {
+            // Create a new entry
+            Entry e = new Entry();
+            // Set the prefix string.
+            if (prefix != null) e.prefix=prefix;
+            // Set the uri string.
+            if (uri != null) e.uri=uri;
+            // Return the entry
+            return e;
+        }
+
+        /** Return the namespace URI. */
+        public String getUri() { return this.uri; }
+        /** Return the namespace prefix. */
+        public String getPrefix() { return this.prefix; }
+    }
+
+    /** The default namespace-aware name declaration implementation */
+    private static class NameImpl implements Name {
+        /** The namespace URI. */
+        protected String uri;
+        /** The namespace prefix. */
+        protected String prefix;
+        /** The namespace local name. */
+        protected String local;
+        /** The namespace raw name. */
+        protected String raw;
+
+        /** Return the namespace URI. */
+        public String getUri() { return this.uri; }
+        /** Return the namespace prefix. */
+        public String getPrefix() { return this.prefix; }
+        /** Return the namespace local name. */
+        public String getLocalName() { return this.local; }
+        /** Return the namespace raw name. */
+        public String getQName() { return this.raw; }
+    }
+
+    /**
+     * A namespace-aware name. (This interface is used in conjunction
+     * with <code>NamespacesTable</code>).
+     */
+    public interface Name {
+        /** Return the namespace URI. */
+        String getUri();
+        /** Return the namespace prefix. */
+        String getPrefix();
+        /** Return the namespace local name. */
+        String getLocalName();
+        /** Return the namespace raw name. */
+        String getQName();
+    }
+
+    /**
+     * A namespace declaration. (This interface is used in conjunction
+     * with <code>NamespacesTable</code>).
+     */
+    public interface Declaration {
+        /** Return the namespace URI. */
+        String getUri();
+        /** Return the namespace prefix. */
+        String getPrefix();
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/ParamSaxBuffer.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/ParamSaxBuffer.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/ParamSaxBuffer.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/ParamSaxBuffer.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,206 @@
+/*
+ * 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.xml;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.io.Writer;
+import java.io.IOException;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.Attributes;
+
+/**
+ * Modification of the SAX buffer with parameterization capabilities.
+ *
+ * Any <code>{name}</code> expression inside of the character events can be
+ * replaced by the content of another SaxBuffer if it is present in the map
+ * passed to the {@link #toSAX(ContentHandler, Map)} method.
+ *
+ * @author <a href="mailto:vgritsenko@apache.org">Vadim Gritsenko</a>
+ * @version CVS $Id: ParamSaxBuffer.java 106182 2004-11-22 14:16:31Z bruno $
+ */
+public class ParamSaxBuffer extends SaxBuffer {
+
+   /**
+    * If ch (in characters()) contains an unmatched '{' then
+    * we save the chars from '{' onward in previous_ch.
+    * Next call to characters() prepends the saved chars to ch before processing
+    * (and sets previous_ch to null).
+    */
+    private char[] previous_ch = null;
+
+    /**
+     * Creates empty SaxBuffer
+     */
+    public ParamSaxBuffer() {
+    }
+
+    /**
+     * Creates copy of another SaxBuffer
+     */
+    public ParamSaxBuffer(SaxBuffer saxBuffer) {
+        super(saxBuffer);
+    }
+
+    /**
+     * Parses text and extracts <code>{name}</code> parameters for later
+     * substitution.
+     */
+    public void characters(char ch[], int start, int length) throws SAXException {
+
+        if (previous_ch != null) {
+            // prepend char's from previous_ch to ch
+            char[] buf = new char[length + previous_ch.length];
+            System.arraycopy(previous_ch, 0, buf, 0, previous_ch.length);
+            System.arraycopy(ch, start, buf, previous_ch.length, length);
+            ch = buf;
+            start = 0;
+            length += previous_ch.length;
+            previous_ch = null;
+        }
+
+        final int end = start + length;
+        for (int i = start; i < end; i++) {
+            if (ch[i] == '{') {
+                // Send any collected characters so far
+                if (i > start) {
+                    addBit(new Characters(ch, start, i - start));
+                }
+
+                // Find closing brace, and construct parameter name
+                StringBuffer name = new StringBuffer();
+                int j = i + 1;
+                for (; j < end; j++) {
+                    if (ch[j] == '}') {
+                        break;
+                    }
+                    name.append(ch[j]);
+                }
+                if (j == end) {
+                    // '{' without a closing '}'
+                    // save char's from '{' in previous_ch in case the following call to characters()
+                    // provides the '}'
+                    previous_ch = new char[end - i];
+                    System.arraycopy(ch, i, previous_ch, 0, end - i);
+                    break;
+                }
+                addBit(new Parameter(name.toString()));
+
+                // Continue processing
+                i = j;
+                start = j + 1;
+                continue;
+            }
+        }
+
+        // Send any tailing characters
+        if (start < end) {
+            addBit(new Characters(ch, start, end - start));
+        }
+    }
+
+    public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
+        flushChars();
+        super.endElement(namespaceURI, localName, qName);
+    }
+
+    public void ignorableWhitespace(char ch[], int start, int length) throws SAXException {
+        flushChars();
+        super.ignorableWhitespace(ch, start, length);
+    }
+
+    public void processingInstruction(String target, String data) throws SAXException {
+        flushChars();
+        super.processingInstruction(target, data);
+    }
+
+    public void startDocument() throws SAXException {
+        flushChars();
+        super.startDocument();
+    }
+
+    public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
+        flushChars();
+        super.startElement(namespaceURI, localName, qName, atts);
+    }
+
+    public void endDocument() throws SAXException {
+        flushChars();
+        super.endDocument();
+    }
+
+    public void comment(char ch[], int start, int length) throws SAXException {
+        flushChars();
+        super.comment(ch, start, length);
+    }
+
+    public void endDTD() throws SAXException {
+        flushChars();
+        super.endDTD();
+    }
+
+    public void startDTD(String name, String publicId, String systemId) throws SAXException {
+        flushChars();
+        super.startDTD(name, publicId, systemId);
+    }
+
+    private void flushChars() {
+        // Handle saved chars (in case we had a '{' with no matching '}').
+        if (previous_ch != null) {
+            addBit(new Characters(previous_ch, 0, previous_ch.length));
+            previous_ch = null;
+        }
+    }
+
+    /**
+     * @param parameters map containing SaxBuffers
+     */
+    public void toSAX(ContentHandler contentHandler, Map parameters) throws SAXException {
+        for (Iterator i = bits(); i.hasNext();) {
+            SaxBit saxbit = (SaxBit)i.next();
+            if (saxbit instanceof Parameter) {
+                ((Parameter)saxbit).send(contentHandler, parameters);
+            } else {
+                saxbit.send(contentHandler);
+            }
+        }
+    }
+
+
+    final static class Parameter implements SaxBit {
+        private final String name;
+
+        public Parameter(String name) {
+            this.name = name;
+        }
+
+        public void send(ContentHandler contentHandler) {
+        }
+
+        public void send(ContentHandler contentHandler, Map parameters) throws SAXException {
+            SaxBuffer value = (SaxBuffer)parameters.get(name);
+            if (value != null) {
+                value.toSAX(contentHandler);
+            }
+        }
+
+        public void dump(Writer writer) throws IOException {
+            writer.write("[Parameter] name=" + name);
+        }
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/RedundantNamespacesFilter.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/RedundantNamespacesFilter.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/RedundantNamespacesFilter.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/RedundantNamespacesFilter.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,78 @@
+/*
+ * 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.xml;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+/**
+ * A SAX filter that strips out redundant namespace declarations.
+ *
+ * <p>
+ * It handles both duplicate declarations (i.e. a namespace already declared by a
+ * parent element) and empty namespaces scopes (i.e. start/stopPrefixMapping with
+ * no element inbetween) that can be produced by some components (e.g. JXTG or
+ * BrowserUpdateTransformer). Such empty scopes confuse the Xalan serializer which
+ * then produces weird namespace declarations (<code>xmlns:%@$#^@#="%@$#^@#"</code>).
+ *
+ * <p>
+ * This is a the most simple use of {@link NamespacesTable}.
+ *
+ * @version CVS $Id: RedundantNamespacesFilter.java 231484 2005-08-11 17:18:02Z sylvain $
+ */
+public class RedundantNamespacesFilter extends AbstractXMLPipe {
+
+    /** Layered storage for all namespace declarations */
+    private NamespacesTable ns = new NamespacesTable();
+
+    /**
+     * No-arg constructor. Requires an explicit call to
+     * <code>setConsumer()</code>.
+     */
+    public RedundantNamespacesFilter() {
+        // Nothing
+    }
+
+    /**
+     * Creates a filter directly linked to its consumer
+     *
+     * @param consumer
+     *            the SAX stream consumer
+     */
+    public RedundantNamespacesFilter(XMLConsumer consumer) {
+        setConsumer(consumer);
+    }
+
+    public void startPrefixMapping(String prefix, String uri) throws SAXException {
+        // Just declare it: duplicate declarations are ignorede by NamespacesTable
+        ns.addDeclaration(prefix, uri);
+    }
+
+    public void startElement(String uri, String loc, String raw, Attributes a) throws SAXException {
+        // Declare namespaces for this scope, if any
+        ns.enterScope(this.contentHandler);
+        super.startElement(uri, loc, raw, a);
+    }
+
+    public void endElement(String uri, String loc, String raw) throws SAXException {
+        super.endElement(uri, loc, raw);
+        ns.leaveScope(this.contentHandler);
+    }
+
+    public void endPrefixMapping(String prefix) throws SAXException {
+        ns.removeDeclaration(prefix);
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/SaxBuffer.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/SaxBuffer.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/SaxBuffer.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/SaxBuffer.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,569 @@
+/*
+ * 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.xml;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.Locator;
+import org.xml.sax.Attributes;
+import org.xml.sax.ext.LexicalHandler;
+import org.apache.excalibur.xml.sax.XMLizable;
+import org.apache.avalon.excalibur.pool.Recyclable;
+
+import java.io.Serializable;
+import java.io.Writer;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Collections;
+
+/**
+ * A class that can record SAX events and replay them later.
+ *
+ * <p>Compared to {@link org.apache.cocoon.components.sax.XMLByteStreamCompiler},
+ * this class is many times faster at sending out the recorded SAX events since
+ * it doesn't need to convert between byte and char representations etc.
+ * On the other hand, its data structure is more complex then a simple byte array,
+ * making XMLByteStreamCompiler better in case the recorded SAX should be stored long-term.
+ *
+ * <p>Use this class if you need to frequently generate smaller amounts of SAX events,
+ * or replay a set of recorded start events immediately.</p>
+ *
+ * <p>Both {@link ContentHandler} and {@link LexicalHandler} are supported, the only
+ * exception is that the setDocumentLocator event is not recorded.</p>
+ *
+ * @version CVS $Id: SaxBuffer.java 54075 2004-10-08 13:02:12Z vgritsenko $
+ */
+public class SaxBuffer extends AbstractSAXFragment
+                       implements XMLConsumer, Recyclable, Serializable {
+
+    /**
+     * Stores list of {@link SaxBit} objects.
+     */
+    protected List saxbits;
+
+    /**
+     * Creates empty SaxBuffer
+     */
+    public SaxBuffer() {
+        this.saxbits = new ArrayList();
+    }
+
+    /**
+     * Creates SaxBuffer based on the provided bits list.
+     */
+    public SaxBuffer(List bits) {
+        this.saxbits = bits;
+    }
+
+    /**
+     * Creates copy of another SaxBuffer
+     */
+    public SaxBuffer(SaxBuffer saxBuffer) {
+        this.saxbits = new ArrayList(saxBuffer.saxbits);
+    }
+
+    //
+    // ContentHandler Interface
+    //
+
+    public void skippedEntity(String name) throws SAXException {
+        saxbits.add(new SkippedEntity(name));
+    }
+
+    public void setDocumentLocator(Locator locator) {
+        // Don't record this event
+    }
+
+    public void ignorableWhitespace(char ch[], int start, int length) throws SAXException {
+        saxbits.add(new IgnorableWhitespace(ch, start, length));
+    }
+
+    public void processingInstruction(String target, String data) throws SAXException {
+        saxbits.add(new PI(target, data));
+    }
+
+    public void startDocument() throws SAXException {
+        saxbits.add(StartDocument.SINGLETON);
+    }
+
+    public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
+        saxbits.add(new StartElement(namespaceURI, localName, qName, atts));
+    }
+
+    public void endPrefixMapping(String prefix) throws SAXException {
+        saxbits.add(new EndPrefixMapping(prefix));
+    }
+
+    public void characters(char ch[], int start, int length) throws SAXException {
+        saxbits.add(new Characters(ch, start, length));
+    }
+
+    public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
+        saxbits.add(new EndElement(namespaceURI, localName, qName));
+    }
+
+    public void endDocument() throws SAXException {
+        saxbits.add(EndDocument.SINGLETON);
+    }
+
+    public void startPrefixMapping(String prefix, String uri) throws SAXException {
+        saxbits.add(new StartPrefixMapping(prefix, uri));
+    }
+
+    //
+    // LexicalHandler Interface
+    //
+
+    public void endCDATA() throws SAXException {
+        saxbits.add(EndCDATA.SINGLETON);
+    }
+
+    public void comment(char ch[], int start, int length) throws SAXException {
+        saxbits.add(new Comment(ch, start, length));
+    }
+
+    public void startEntity(String name) throws SAXException {
+        saxbits.add(new StartEntity(name));
+    }
+
+    public void endDTD() throws SAXException {
+        saxbits.add(EndDTD.SINGLETON);
+    }
+
+    public void startDTD(String name, String publicId, String systemId) throws SAXException {
+        saxbits.add(new StartDTD(name, publicId, systemId));
+    }
+
+    public void startCDATA() throws SAXException {
+        saxbits.add(StartCDATA.SINGLETON);
+    }
+
+    public void endEntity(String name) throws SAXException {
+        saxbits.add(new EndEntity(name));
+    }
+
+    //
+    // Public Methods
+    //
+
+    /**
+     * Add a bit containing XMLizable object
+     */
+    public void xmlizable(XMLizable xml) {
+        saxbits.add(new XMLizableBit(xml));
+    }
+
+    /**
+     * @return true if buffer is empty
+     */
+    public boolean isEmpty() {
+        return saxbits.isEmpty();
+    }
+
+    /**
+     * @return unmodifiable list of SAX bits
+     */
+    public List getBits() {
+        return Collections.unmodifiableList(saxbits);
+    }
+
+    /**
+     * Stream this buffer into the provided content handler.
+     * If contentHandler object implements LexicalHandler, it will get lexical
+     * events as well.
+     */
+    public void toSAX(ContentHandler contentHandler) throws SAXException {
+        for (Iterator i = saxbits.iterator(); i.hasNext();) {
+            SaxBit saxbit = (SaxBit)i.next();
+            saxbit.send(contentHandler);
+        }
+    }
+
+    /**
+     * @return String value of the buffer
+     */
+    public String toString() {
+        // NOTE: This method is used in i18n XML bundle implementation
+        final StringBuffer value = new StringBuffer();
+        for (Iterator i = saxbits.iterator(); i.hasNext();) {
+            final SaxBit saxbit = (SaxBit) i.next();
+            if (saxbit instanceof Characters) {
+                ((Characters) saxbit).toString(value);
+            }
+        }
+
+        return value.toString();
+    }
+
+    /**
+     * Clear this buffer
+     */
+    public void recycle() {
+        saxbits.clear();
+    }
+
+    /**
+     * Dump buffer contents into the provided writer.
+     */
+    public void dump(Writer writer) throws IOException {
+        Iterator i = saxbits.iterator();
+        while (i.hasNext()) {
+            final SaxBit saxbit = (SaxBit) i.next();
+            saxbit.dump(writer);
+        }
+        writer.flush();
+    }
+
+    //
+    // Implementation Methods
+    //
+
+    /**
+     * Adds a SaxBit to the bits list
+     */
+    protected final void addBit(SaxBit bit) {
+        saxbits.add(bit);
+    }
+
+    /**
+     * Iterates through the bits list
+     */
+    protected final Iterator bits() {
+        return saxbits.iterator();
+    }
+
+    /**
+     * SaxBit is a representation of the SAX event. Every SaxBit is immutable object.
+     */
+    interface SaxBit {
+        public void send(ContentHandler contentHandler) throws SAXException;
+        public void dump(Writer writer) throws IOException;
+    }
+
+    public final static class StartDocument implements SaxBit, Serializable {
+        public static final StartDocument SINGLETON = new StartDocument();
+
+        public void send(ContentHandler contentHandler) throws SAXException {
+            contentHandler.startDocument();
+        }
+
+        public void dump(Writer writer) throws IOException {
+            writer.write("[StartDocument]\n");
+        }
+    }
+
+    public final static class EndDocument implements SaxBit, Serializable {
+        public static final EndDocument SINGLETON = new EndDocument();
+
+        public void send(ContentHandler contentHandler) throws SAXException {
+            contentHandler.endDocument();
+        }
+
+        public void dump(Writer writer) throws IOException {
+            writer.write("[EndDocument]\n");
+        }
+    }
+
+    public final static class PI implements SaxBit, Serializable {
+        public final String target;
+        public final String data;
+
+        public PI(String target, String data) {
+            this.target = target;
+            this.data = data;
+        }
+
+        public void send(ContentHandler contentHandler) throws SAXException {
+            contentHandler.processingInstruction(target, data);
+        }
+
+        public void dump(Writer writer) throws IOException {
+            writer.write("[ProcessingInstruction] target=" + target + ",data=" + data + "\n");
+        }
+    }
+
+    public final static class StartDTD implements SaxBit, Serializable {
+        public final String name;
+        public final String publicId;
+        public final String systemId;
+
+        public StartDTD(String name, String publicId, String systemId) {
+            this.name = name;
+            this.publicId = publicId;
+            this.systemId = systemId;
+        }
+
+        public void send(ContentHandler contentHandler) throws SAXException {
+            if (contentHandler instanceof LexicalHandler)
+                ((LexicalHandler)contentHandler).startDTD(name, publicId, systemId);
+        }
+
+        public void dump(Writer writer) throws IOException {
+            writer.write("[StartDTD] name=" + name + ",publicId=" + publicId + ",systemId=" + systemId + "\n");
+        }
+    }
+
+    public final static class EndDTD implements SaxBit, Serializable {
+        public static final EndDTD SINGLETON = new EndDTD();
+
+        public void send(ContentHandler contentHandler) throws SAXException {
+            if (contentHandler instanceof LexicalHandler)
+                ((LexicalHandler)contentHandler).endDTD();
+        }
+
+        public void dump(Writer writer) throws IOException {
+            writer.write("[EndDTD]\n");
+        }
+    }
+
+    public final static class StartEntity implements SaxBit, Serializable {
+        public final String name;
+
+        public StartEntity(String name) {
+            this.name = name;
+        }
+
+        public void send(ContentHandler contentHandler) throws SAXException {
+            if (contentHandler instanceof LexicalHandler)
+                ((LexicalHandler)contentHandler).startEntity(name);
+        }
+
+        public void dump(Writer writer) throws IOException {
+            writer.write("[StartEntity] name=" + name + "\n");
+        }
+    }
+
+    public final static class EndEntity implements SaxBit, Serializable {
+        public final String name;
+
+        public EndEntity(String name) {
+            this.name = name;
+        }
+
+        public void send(ContentHandler contentHandler) throws SAXException {
+            if (contentHandler instanceof LexicalHandler)
+                ((LexicalHandler)contentHandler).endEntity(name);
+        }
+
+        public void dump(Writer writer) throws IOException {
+            writer.write("[EndEntity] name=" + name + "\n");
+        }
+    }
+
+    public final static class SkippedEntity implements SaxBit, Serializable {
+        public final String name;
+
+        public SkippedEntity(String name) {
+            this.name = name;
+        }
+
+        public void send(ContentHandler contentHandler) throws SAXException {
+            contentHandler.skippedEntity(name);
+        }
+
+        public void dump(Writer writer) throws IOException {
+            writer.write("[SkippedEntity] name=" + name + "\n");
+        }
+    }
+
+    public final static class StartPrefixMapping implements SaxBit, Serializable {
+        public final String prefix;
+        public final String uri;
+
+        public StartPrefixMapping(String prefix, String uri) {
+            this.prefix = prefix;
+            this.uri = uri;
+        }
+
+        public void send(ContentHandler contentHandler) throws SAXException {
+            contentHandler.startPrefixMapping(prefix, uri);
+        }
+
+        public void dump(Writer writer) throws IOException {
+            writer.write("[StartPrefixMapping] prefix=" + prefix + ",uri=" + uri + "\n");
+        }
+    }
+
+    public final static class EndPrefixMapping implements SaxBit, Serializable {
+        public final String prefix;
+
+        public EndPrefixMapping(String prefix) {
+            this.prefix = prefix;
+        }
+
+        public void send(ContentHandler contentHandler) throws SAXException {
+            contentHandler.endPrefixMapping(prefix);
+        }
+
+        public void dump(Writer writer) throws IOException {
+            writer.write("[EndPrefixMapping] prefix=" + prefix + "\n");
+        }
+    }
+
+    public final static class StartElement implements SaxBit, Serializable {
+        public final String namespaceURI;
+        public final String localName;
+        public final String qName;
+        public final Attributes attrs;
+
+        public StartElement(String namespaceURI, String localName, String qName, Attributes attrs) {
+            this.namespaceURI = namespaceURI;
+            this.localName = localName;
+            this.qName = qName;
+            this.attrs = new org.xml.sax.helpers.AttributesImpl(attrs);
+        }
+
+        public void send(ContentHandler contentHandler) throws SAXException {
+            contentHandler.startElement(namespaceURI, localName, qName, attrs);
+        }
+
+        public void dump(Writer writer) throws IOException {
+            writer.write("[StartElement] namespaceURI=" + namespaceURI + ",localName=" + localName + ",qName=" + qName + "\n");
+            for (int i = 0; i < attrs.getLength(); i++) {
+                writer.write("      [Attribute] namespaceURI=" + attrs.getURI(i) + ",localName=" + attrs.getLocalName(i) + ",qName=" + attrs.getQName(i) + ",type=" + attrs.getType(i) + ",value=" + attrs.getValue(i) + "\n");
+            }
+        }
+    }
+
+    public final static class EndElement implements SaxBit, Serializable {
+        public final String namespaceURI;
+        public final String localName;
+        public final String qName;
+
+        public EndElement(String namespaceURI, String localName, String qName) {
+            this.namespaceURI = namespaceURI;
+            this.localName = localName;
+            this.qName = qName;
+        }
+
+        public void send(ContentHandler contentHandler) throws SAXException {
+            contentHandler.endElement(namespaceURI, localName, qName);
+        }
+
+        public void dump(Writer writer) throws IOException {
+            writer.write("[EndElement] namespaceURI=" + namespaceURI + ",localName=" + localName + ",qName=" + qName + "\n");
+        }
+    }
+
+    public final static class Characters implements SaxBit, Serializable {
+        public final char[] ch;
+
+        public Characters(char[] ch, int start, int length) {
+            // make a copy so that we don't hold references to a potentially large array we don't control
+            this.ch = new char[length];
+            System.arraycopy(ch, start, this.ch, 0, length);
+        }
+
+        public void send(ContentHandler contentHandler) throws SAXException {
+            contentHandler.characters(ch, 0, ch.length);
+        }
+
+        public void toString(StringBuffer value) {
+            value.append(ch);
+        }
+
+        public void dump(Writer writer) throws IOException {
+            writer.write("[Characters] ch=" + new String(ch) + "\n");
+        }
+    }
+
+    public final static class Comment implements SaxBit, Serializable {
+        public final char[] ch;
+
+        public Comment(char[] ch, int start, int length) {
+            // make a copy so that we don't hold references to a potentially large array we don't control
+            this.ch = new char[length];
+            System.arraycopy(ch, start, this.ch, 0, length);
+        }
+
+        public void send(ContentHandler contentHandler) throws SAXException {
+            if (contentHandler instanceof LexicalHandler)
+                ((LexicalHandler)contentHandler).comment(ch, 0, ch.length);
+        }
+
+        public void dump(Writer writer) throws IOException {
+            writer.write("[Comment] ch=" + new String(ch) + "\n");
+        }
+    }
+
+    public final static class StartCDATA implements SaxBit, Serializable {
+        public static final StartCDATA SINGLETON = new StartCDATA();
+
+        public void send(ContentHandler contentHandler) throws SAXException {
+            if (contentHandler instanceof LexicalHandler)
+                ((LexicalHandler)contentHandler).startCDATA();
+        }
+
+        public void dump(Writer writer) throws IOException {
+            writer.write("[StartCDATA]\n");
+        }
+    }
+
+    public final static class EndCDATA implements SaxBit, Serializable {
+        public static final EndCDATA SINGLETON = new EndCDATA();
+
+        public void send(ContentHandler contentHandler) throws SAXException {
+            if (contentHandler instanceof LexicalHandler)
+                ((LexicalHandler)contentHandler).endCDATA();
+        }
+
+        public void dump(Writer writer) throws IOException {
+            writer.write("[EndCDATA]\n");
+        }
+    }
+
+    public final static class IgnorableWhitespace implements SaxBit, Serializable {
+        public final char[] ch;
+
+        public IgnorableWhitespace(char[] ch, int start, int length) {
+            // make a copy so that we don't hold references to a potentially large array we don't control
+            this.ch = new char[length];
+            System.arraycopy(ch, start, this.ch, 0, length);
+        }
+
+        public void send(ContentHandler contentHandler) throws SAXException {
+            contentHandler.ignorableWhitespace(ch, 0, ch.length);
+        }
+
+        public void dump(Writer writer) throws IOException {
+            writer.write("[IgnorableWhitespace] ch=" + new String(ch) + "\n");
+        }
+    }
+
+    public final static class XMLizableBit implements SaxBit, Serializable {
+        public final XMLizable xml;
+
+        public XMLizableBit(XMLizable xml) {
+            this.xml = xml;
+        }
+
+        public void send(ContentHandler contentHandler) throws SAXException {
+            this.xml.toSAX(new EmbeddedXMLPipe(contentHandler));
+        }
+
+        public void dump(Writer writer) throws IOException {
+            if (xml instanceof SaxBuffer) {
+                writer.write("[XMLizable] Begin nested SaxBuffer\n");
+                ((SaxBuffer)xml).dump(writer);
+                writer.write("[XMLizable] End nested SaxBuffer\n");
+            } else {
+                writer.write("[XMLizable] xml=" + xml + "\n");
+            }
+        }
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/StringXMLizable.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/StringXMLizable.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/StringXMLizable.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/StringXMLizable.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,59 @@
+/*
+ * Copyright 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.xml;
+
+import org.apache.excalibur.xml.sax.XMLizable;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.InputSource;
+
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.IOException;
+import java.io.StringReader;
+
+/**
+ * XMLizable a String
+ * 
+ * @since 2.1.7
+ * @author Bruno Dumon
+ */
+public class StringXMLizable implements XMLizable {
+    private String data;
+
+    public StringXMLizable(String data) {
+        this.data = data;
+    }
+
+    public void toSAX(ContentHandler contentHandler) throws SAXException {
+        SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+        parserFactory.setNamespaceAware(true);
+        SAXParser parser = null;
+        try {
+            parser = parserFactory.newSAXParser();
+        } catch (ParserConfigurationException e) {
+            throw new SAXException("Error creating SAX parser.", e);
+        }
+        parser.getXMLReader().setContentHandler(contentHandler);
+        InputSource is = new InputSource(new StringReader(data));
+        try {
+            parser.getXMLReader().parse(is);
+        } catch (IOException e) {
+            throw new SAXException(e);
+        }
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLBaseSupport.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLBaseSupport.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLBaseSupport.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLBaseSupport.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,152 @@
+/*
+ * 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.xml;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.apache.excalibur.source.SourceResolver;
+import org.apache.excalibur.source.Source;
+import org.apache.avalon.framework.logger.Logger;
+
+import java.util.Stack;
+import java.util.Collections;
+import java.io.IOException;
+
+/**
+ * Helper class for handling xml:base attributes.
+ *
+ * <p>Usage:
+ * <ul>
+ *  <li>set location of the containing document by calling {@link #setDocumentLocation(String)}.
+ *      This is usually done when getting setDocumentLocator SAX event.
+ *  <li>forward each startElement and endElement event to this object.
+ *  <li>to resolve a relative URL against the current base, call {@link #makeAbsolute(String)}.
+ * </ul>
+ *
+ * <p>External entities are not yet taken into account when determing the current base.
+ */
+public class XMLBaseSupport {
+    public static final String XMLBASE_NAMESPACE_URI = "http://www.w3.org/XML/1998/namespace";
+    public static final String XMLBASE_ATTRIBUTE = "base";
+
+    /** Increased on each startElement, decreased on each endElement. */
+    private int level = 0;
+    /**
+     * The stack contains an instance of {@link BaseInfo} for each XML element
+     * that contained an xml:base attribute (not for the other elements).
+     */
+    private Stack bases = new Stack();
+    private SourceResolver resolver;
+    private Logger logger;
+
+    public XMLBaseSupport(SourceResolver resolver, Logger logger) {
+        this.resolver = resolver;
+        this.logger = logger;
+    }
+
+    public void setDocumentLocation(String loc) throws SAXException {
+        // -2 is used as level to avoid this BaseInfo to be ever popped of the stack
+        bases.push(new BaseInfo(loc, -2));
+    }
+
+    public void startElement(String namespaceURI, String localName, String qName, Attributes attrs) throws SAXException {
+        level++;
+        String base = attrs.getValue(XMLBASE_NAMESPACE_URI, XMLBASE_ATTRIBUTE);
+        if (base != null) {
+            Source baseSource = null;
+            String baseUrl;
+            try {
+                baseSource = resolve(getCurrentBase(), base);
+                baseUrl = baseSource.getURI();
+            } finally {
+                if (baseSource != null) {
+                    resolver.release(baseSource);
+                }
+            }
+            bases.push(new BaseInfo(baseUrl, level));
+        }
+    }
+
+    public void endElement(String namespaceURI, String localName, String qName) {
+        if (getCurrentBaseLevel() == level)
+            bases.pop();
+        level--;
+    }
+
+    /**
+     * Warning: do not forget to release the source returned by this method.
+     */
+    private Source resolve(String baseURI, String location) throws SAXException {
+        try {
+            Source source;
+            if (baseURI != null) {
+                source = resolver.resolveURI(location, baseURI, Collections.EMPTY_MAP);
+            } else {
+                source = resolver.resolveURI(location);
+            }
+            if (logger.isDebugEnabled()) {
+                logger.debug("XMLBaseSupport: resolved location " + location +
+                             " against base URI " + baseURI + " to " + source.getURI());
+            }
+            return source;
+        } catch (IOException e) {
+            throw new SAXException("XMLBaseSupport: problem resolving uri.", e);
+        }
+    }
+
+    /**
+     * Makes the given path absolute based on the current base URL. Do not forget to release
+     * the returned source object!
+     * @param spec any URL (relative or absolute, containing a scheme or not)
+     */
+    public Source makeAbsolute(String spec) throws SAXException {
+        return resolve(getCurrentBase(), spec);
+    }
+
+    private String getCurrentBase() {
+        if (bases.size() > 0) {
+            BaseInfo baseInfo = (BaseInfo)bases.peek();
+            return baseInfo.getUrl();
+        }
+        return null;
+    }
+
+    private int getCurrentBaseLevel() {
+        if (bases.size() > 0) {
+            BaseInfo baseInfo = (BaseInfo)bases.peek();
+            return baseInfo.getLevel();
+        }
+        return -1;
+    }
+
+    private static final class BaseInfo {
+        private String url;
+        private int level;
+
+        public BaseInfo(String url, int level) {
+            this.url = url;
+            this.level = level;
+        }
+
+        public String getUrl() {
+            return url;
+        }
+
+        public int getLevel() {
+            return level;
+        }
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLConsumer.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLConsumer.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLConsumer.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLConsumer.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,46 @@
+/*
+ * 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.xml;
+
+/**
+ * This interfaces identifies classes that consume XML data, receiving
+ * notification of SAX events.
+ * <p>
+ * An XMLConsumer is also a SAX ContentHandler and a SAX LexicalHandler.  That
+ * means the XMLConsumer has to respect all the contracts with the SAX
+ * interfaces.  SAX stands for Serialized API for XML.  A document start, and
+ * each element start must be matched by the corresponding element end or
+ * document end.  So why does Cocoon use SAX instead of manipulating a DOM?
+ * For two main reasons: performance and scalability.  A DOM tree is much more
+ * heavy on system memory than successive calls to an API.  SAX events can be
+ * sent as soon as they are read from the originating XML, the parsing and
+ * processing can happen essentially at the same time.
+ * </p>
+ * <p>
+ * Most people's needs will be handled just fine with the ContentHandler
+ * interface, as that declares your namespaces.  However if you need lexical
+ * support to resolve entity names and such, you need the LexicalHandler
+ * interface.  The AbstractXMLConsumer base class can make implementing this
+ * interface easier so that you only need to override the events you intend to
+ * do anything with.
+ * </p>
+ *
+ * @author <a href="mailto:pier@apache.org">Pierpaolo Fumagalli</a>
+ *         (Apache Software Foundation)
+ * @version CVS $Id: XMLConsumer.java 279586 2005-09-08 17:12:20Z bloritsch $
+ */
+public interface XMLConsumer extends org.apache.excalibur.xml.sax.XMLConsumer {
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLFragment.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLFragment.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLFragment.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLFragment.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,40 @@
+/*
+ * 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.xml;
+
+import org.w3c.dom.Node;
+
+/**
+ * This interface must be implemented by classes willing
+ * to provide an XML representation of their current state.
+ *
+ * <p>This interface exists in both Cocoon 1 and Cocoon 2 and to ensure
+ * a minimal compatibility between the two versions.</p>
+ *
+ * <p>Cocoon 2 only objects can implement the SAX-only <code>XMLizable</code>
+ * interface.</p>
+ *
+ * @author <a href="mailto:sylvain.wallez@anyware-tech.com">Sylvain Wallez</a>
+ * @author <a href="mailto:ricardo@apache.org">Ricardo Rocha</a> for the original XObject class
+ * @version CVS $Id: XMLFragment.java 53979 2004-10-07 14:26:29Z vgritsenko $
+ */
+public interface XMLFragment extends org.apache.excalibur.xml.sax.XMLizable {
+
+    /**
+     * Appends children representing the object's state to the given node.
+     */
+    void toDOM(Node node) throws Exception;
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLMulticaster.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLMulticaster.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLMulticaster.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLMulticaster.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,163 @@
+/*
+ * 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.xml;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.ext.LexicalHandler;
+
+/**
+ * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
+ * @version CVS $Id: XMLMulticaster.java 30941 2004-07-29 19:56:58Z vgritsenko $
+ */
+
+public final class XMLMulticaster implements XMLConsumer {
+
+    /**
+     * The XMLMulticaster forwards incomming sax events to a list of
+     * receiving objects.
+     */
+    private ContentHandler[] contentHandlerList;
+    private LexicalHandler[] lexicalHandlerList;
+
+    /**
+     * Create a new XMLMulticaster with two consumers
+     */
+    public XMLMulticaster(XMLConsumer firstConsumer, XMLConsumer secondConsumer) {
+        this.contentHandlerList = new ContentHandler[] {firstConsumer, secondConsumer};
+        this.lexicalHandlerList = new LexicalHandler[] {firstConsumer, secondConsumer};
+    }
+
+    /**
+     * Create a new XMLMulticaster from two contentHandler/lexicalHandler pairs
+     */
+    public XMLMulticaster(ContentHandler firstContentHandler,
+                          LexicalHandler firstLexicalHandler,
+                          ContentHandler secondContentHandler,
+                          LexicalHandler secondLexicalHandler) {
+        this.contentHandlerList = new ContentHandler[] {firstContentHandler, secondContentHandler};
+        this.lexicalHandlerList = new LexicalHandler[] {firstLexicalHandler, secondLexicalHandler};
+    }
+
+    public XMLMulticaster(ContentHandler[] chList,
+                          LexicalHandler[] lhList) {
+        this.contentHandlerList = chList;
+        this.lexicalHandlerList = lhList;
+    }
+
+    public void startDocument() throws SAXException {
+        for(int i=0; i<this.contentHandlerList.length; i++) {
+            this.contentHandlerList[i].startDocument();
+        }
+    }
+
+    public void endDocument() throws SAXException {
+        for(int i=0; i<this.contentHandlerList.length; i++) {
+                this.contentHandlerList[i].endDocument();
+        }
+    }
+
+    public void startPrefixMapping(java.lang.String prefix, java.lang.String uri) throws SAXException {
+        for(int i=0; i<this.contentHandlerList.length; i++)
+                this.contentHandlerList[i].startPrefixMapping(prefix, uri);
+    }
+
+    public void endPrefixMapping(java.lang.String prefix) throws SAXException {
+        for(int i=0; i<this.contentHandlerList.length; i++)
+                this.contentHandlerList[i].endPrefixMapping(prefix);
+    }
+
+    public void startElement(java.lang.String namespaceURI, java.lang.String localName, java.lang.String qName, Attributes atts) throws SAXException {
+        for(int i=0; i<this.contentHandlerList.length; i++)
+                this.contentHandlerList[i].startElement(namespaceURI, localName, qName, atts);
+    }
+
+    public void endElement(java.lang.String namespaceURI, java.lang.String localName, java.lang.String qName) throws SAXException {
+        for(int i=0; i<this.contentHandlerList.length; i++)
+                this.contentHandlerList[i].endElement(namespaceURI, localName, qName);
+    }
+
+    public void characters(char[] ch, int start, int length) throws SAXException {
+        for(int i=0; i<this.contentHandlerList.length; i++)
+                this.contentHandlerList[i].characters(ch, start, length);
+    }
+
+    public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
+        for(int i=0; i<this.contentHandlerList.length; i++)
+                this.contentHandlerList[i].ignorableWhitespace(ch, start, length);
+    }
+
+    public void processingInstruction(java.lang.String target, java.lang.String data) throws SAXException {
+        for(int i=0; i<this.contentHandlerList.length; i++)
+                this.contentHandlerList[i].processingInstruction(target, data);
+    }
+
+    public void setDocumentLocator(Locator locator) {
+        for(int i=0; i<this.contentHandlerList.length; i++)
+                this.contentHandlerList[i].setDocumentLocator(locator);
+    }
+
+    public void skippedEntity(java.lang.String name) throws SAXException {
+        for(int i=0; i<this.contentHandlerList.length; i++)
+                this.contentHandlerList[i].skippedEntity(name);
+    }
+
+    public void startDTD(String name, String public_id, String system_id)
+                        throws SAXException {
+        for(int i=0; i<this.lexicalHandlerList.length; i++)
+            if (this.lexicalHandlerList[i] != null)
+                this.lexicalHandlerList[i].startDTD(name, public_id, system_id);
+    }
+
+    public void endDTD() throws SAXException {
+        for(int i=0; i<this.lexicalHandlerList.length; i++)
+            if (this.lexicalHandlerList[i] != null)
+                this.lexicalHandlerList[i].endDTD();
+    }
+
+    public void startEntity(String name) throws SAXException {
+        for(int i=0; i<this.lexicalHandlerList.length; i++)
+            if (this.lexicalHandlerList[i] != null)
+                 this.lexicalHandlerList[i].startEntity(name);
+    }
+
+    public void endEntity(String name) throws SAXException {
+        for(int i=0; i<this.lexicalHandlerList.length; i++)
+            if (this.lexicalHandlerList[i] != null)
+                this.lexicalHandlerList[i].endEntity(name);
+    }
+
+    public void startCDATA() throws SAXException {
+        for(int i=0; i<this.lexicalHandlerList.length; i++)
+            if (this.lexicalHandlerList[i] != null)
+                this.lexicalHandlerList[i].startCDATA();
+    }
+
+    public void endCDATA() throws SAXException {
+        for(int i=0; i<this.lexicalHandlerList.length; i++)
+            if (this.lexicalHandlerList[i] != null)
+                this.lexicalHandlerList[i].endCDATA();
+    }
+
+    public void comment(char ary[], int start, int length)
+                        throws SAXException {
+        for(int i=0; i<this.lexicalHandlerList.length; i++)
+            if (this.lexicalHandlerList[i] != null)
+                this.lexicalHandlerList[i].comment(ary, start, length);
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLPipe.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLPipe.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLPipe.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLPipe.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,55 @@
+/*
+ * 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.xml;
+
+/**
+ * The XMLPipe is both an XMLProducer and an XMLConsumer.  All the Transformers
+ * implement this interface for example.  By having an XMLPipe interface, we
+ * can chain more than one pipeline component together.  What this means is
+ * that Cocoon will honor all the XMLProducer contracts in a pipeline first.
+ * The SAX pipeline will be completely assembled before any SAX calls are
+ * issued.  Cocoon does not want any stray calls to get lost.  There can be
+ * zero or more XMLPipes in a pipeline, but there must always be at least one
+ * XMLProducer and XMLConsumer pair.
+ * <p>
+ * Because an XMLPipe is both a source and a sink for SAX events, the basic
+ * contract that you need to worry about is that you must forward any SAX
+ * events on that you are not intercepting and transforming.  As you receive
+ * your startDocument event, pass it on to the XMLConsumer you received as part
+ * of the XMLProducer side of the contract.  An example ASCII art will help
+ * make it a bit more clear:
+ * </p>
+ * <pre>
+ * XMLProducer -&gt; (XMLConsumer)XMLPipe(XMLProducer) -&gt; XMLConsumer
+ * </pre>
+ * <p>
+ * A typical example would be using the FileGenerator (an XMLProducer), sending
+ * events to an XSLTTransformer (an XMLPipe), which then sends events to an
+ * HTMLSerializer (an XMLConsumer).  The XSLTTransformer acts as an XMLConsumer
+ * to the FileGenerator, and also acts as an XMLProducer to the HTMLSerializer.
+ * It is still the responsibility of the XMLPipe component to ensure that the
+ * XML passed on to the next component is valid--provided the XML received from
+ * the previous component is valid.  In layman's terms it means if you don't
+ * intend to alter the input, just pass it on.  In most cases we just want to
+ * transform a small snippet of XML.  For example, inserting a snippet of XML
+ * based on an embedded element in a certain namespace.  Anything that doesn't
+ * belong to the namespace you are worried about should be passed on as is.
+ * </p>
+ *
+ * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
+ * @version CVS $Id: XMLPipe.java 279586 2005-09-08 17:12:20Z bloritsch $
+ */
+public interface XMLPipe extends XMLConsumer, XMLProducer {}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLProducer.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLProducer.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLProducer.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLProducer.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,53 @@
+/*
+ * 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.xml;
+
+/**
+ * This interfaces identifies classes that produce XML data, sending SAX
+ * events to the configured <code>XMLConsumer</code>.
+ * <p>
+ * The XMLProducer is comprised of only one method to give the component the
+ * next element of the pipeline.  Cocoon calls the <code>setConsumer()</code>
+ * method with the reference to the next XMLConsumer in the pipeline.  The
+ * approach allows the XMLProducer to call the different SAX related methods on
+ * the XMLConsumer without knowing ahead of time what that consumer will be.
+ * The design is very simple and very powerful in that it allows Cocoon to
+ * daisy chain several components in any order and then execute the pipeline.
+ * </p>
+ * <p>
+ * Any producer can be paired with any consumer and we have a pipeline.  The
+ * core design is very powerful and allows the end user to mix and match
+ * sitemap components as they see fit.  Cocoon will always call
+ * <code>setConsumer()</code> on every XMLProducer in a pipeline or it will
+ * throw an exception saying that the pipeline is invalid (i.e. there is no
+ * serializer for the pipeline).  The only contract that the XMLProducer has to
+ * worry about is that it must always make calls to the XMLConsumer passed in
+ * through the <code>setConsumer()</code> method.
+ * </p>
+ *
+ * @author <a href="mailto:pier@apache.org">Pierpaolo Fumagalli</a>
+ *         (Apache Software Foundation)
+ * @version CVS $Id: XMLProducer.java 279586 2005-09-08 17:12:20Z bloritsch $
+ */
+public interface XMLProducer {
+
+    /**
+     * Set the <code>XMLConsumer</code> that will receive XML data.
+     *
+     * @param consumer  The XMLConsumer target for SAX events.
+     */
+    void setConsumer(XMLConsumer consumer);
+}

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



Mime
View raw message