You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2009/10/14 08:54:43 UTC

svn commit: r825031 - in /sling/trunk/contrib/extensions/rewriter: ./ src/main/java/org/apache/ src/main/java/org/apache/sling/rewriter/impl/ src/main/java/org/apache/sling/rewriter/impl/components/

Author: cziegeler
Date: Wed Oct 14 06:54:42 2009
New Revision: 825031

URL: http://svn.apache.org/viewvc?rev=825031&view=rev
Log:
First implementation of trax based serializers

Added:
    sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/
    sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/AbstractTraxSerializerFactory.java   (with props)
    sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/HtmlGeneratorFactory.java   (contents, props changed)
      - copied, changed from r825016, sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/HtmlGeneratorFactory.java
    sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/HtmlSerializerFactory.java   (with props)
    sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/TraxErrorHandler.java   (with props)
    sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/TraxSerializer.java   (with props)
    sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/XHtmlSerializerFactory.java   (with props)
Removed:
    sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/HTMLSerializer.java
    sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/HtmlGeneratorFactory.java
    sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/HtmlSerializerFactory.java
    sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/XHTMLSerializer.java
    sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/XHtmlSerializerFactory.java
Modified:
    sling/trunk/contrib/extensions/rewriter/pom.xml
    sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/   (props changed)

Modified: sling/trunk/contrib/extensions/rewriter/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/rewriter/pom.xml?rev=825031&r1=825030&r2=825031&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/rewriter/pom.xml (original)
+++ sling/trunk/contrib/extensions/rewriter/pom.xml Wed Oct 14 06:54:42 2009
@@ -23,11 +23,11 @@
     <parent>
         <groupId>org.apache.sling</groupId>
         <artifactId>sling</artifactId>
-        <version>6</version>
+        <version>7</version>
     </parent>
 
     <artifactId>org.apache.sling.rewriter</artifactId>
-    <version>0.7.0-SNAPSHOT</version>
+    <version>0.8.0-SNAPSHOT</version>
     <packaging>bundle</packaging>
 
     <name>Apache Sling Rewriter</name>
@@ -110,11 +110,11 @@
             <artifactId>servlet-api</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.apache.felix</groupId>
+            <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.apache.felix</groupId>
+            <groupId>org.osgi</groupId>
             <artifactId>org.osgi.compendium</artifactId>
         </dependency>
         <dependency>

Propchange: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/
            ('svn:externals' removed)

Added: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/AbstractTraxSerializerFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/AbstractTraxSerializerFactory.java?rev=825031&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/AbstractTraxSerializerFactory.java (added)
+++ sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/AbstractTraxSerializerFactory.java Wed Oct 14 06:54:42 2009
@@ -0,0 +1,465 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.rewriter.impl.components;
+
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.sling.rewriter.Serializer;
+import org.apache.sling.rewriter.SerializerFactory;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+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;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * Base class for trax based serializers.
+ */
+public abstract class AbstractTraxSerializerFactory implements SerializerFactory {
+
+    private final Logger logger = LoggerFactory.getLogger(this.getClass().getName());
+
+    /**
+     * The trax <code>TransformerFactory</code> used by this serializer.
+     */
+    private SAXTransformerFactory tfactory;
+
+    private boolean needsNamespacesAsAttributes;
+
+    protected abstract String getOutputFormat();
+    /**
+     * @see org.apache.sling.rewriter.SerializerFactory#createSerializer()
+     */
+    public Serializer createSerializer() {
+        TransformerHandler tHandler = null;
+        try {
+            tHandler = this.tfactory.newTransformerHandler();
+        } catch (TransformerConfigurationException e) {
+            logger.error("Unable to create new transformer handler.", e);
+        }
+        final ContentHandler ch;
+        if ( this.needsNamespacesAsAttributes ) {
+            final NamespaceAsAttributes nsPipeline = new NamespaceAsAttributes(tHandler, this.logger);
+            ch = nsPipeline;
+        } else {
+            ch = tHandler;
+        }
+        return new TraxSerializer(tHandler, ch, getOutputFormat());
+    }
+
+    protected void activate(final ComponentContext ctx) {
+        this.tfactory = (SAXTransformerFactory) TransformerFactory.newInstance();
+        tfactory.setErrorListener(new TraxErrorHandler(this.logger));
+        // Check if we need namespace as attributes.
+        try {
+            this.needsNamespacesAsAttributes = this.needsNamespacesAsAttributes();
+        } catch (Exception e) {
+            this.logger.warn("Cannot know if transformer needs namespaces attributes - assuming NO.", e);
+            this.needsNamespacesAsAttributes = false;
+        }
+    }
+
+    protected void deactivat(final ComponentContext ctx) {
+        this.tfactory = null;
+    }
+
+    /**
+     * Checks if the used Trax implementation correctly handles namespaces set using
+     * <code>startPrefixMapping()</code>, but wants them also as 'xmlns:' attributes.
+     * <p>
+     * The check consists in sending SAX events representing a minimal namespaced document
+     * with namespaces defined only with calls to <code>startPrefixMapping</code> (no
+     * xmlns:xxx attributes) and check if they are present in the resulting text.
+     */
+    protected boolean needsNamespacesAsAttributes() throws Exception {
+        // Serialize a minimal document to check how namespaces are handled.
+        final StringWriter writer = new StringWriter();
+
+        final String uri = "namespaceuri";
+        final String prefix = "nsp";
+        final String check = "xmlns:" + prefix + "='" + uri + "'";
+
+        final TransformerHandler handler = this.tfactory.newTransformerHandler();
+        handler.setResult(new StreamResult(writer));
+
+        // Output a single element
+        handler.startDocument();
+        handler.startPrefixMapping(prefix, uri);
+        handler.startElement(uri, "element", "element", new AttributesImpl());
+        handler.endElement(uri, "element", "element");
+        handler.endPrefixMapping(prefix);
+        handler.endDocument();
+
+        final String text = writer.toString();
+
+        // Check if the namespace is there (replace " by ' to be sure of what we search in)
+        return (text.replace('"', '\'').indexOf(check) == -1);
+    }
+
+    //--------------------------------------------------------------------------------------------
+
+    /**
+     * A pipe that ensures that all namespace prefixes are also present as
+     * 'xmlns:' attributes. This used to circumvent Xalan's serialization behaviour
+     * which is to ignore namespaces if they're not present as 'xmlns:xxx' attributes.
+     */
+    public static class NamespaceAsAttributes implements ContentHandler, LexicalHandler {
+
+        /** The URI for xml namespaces */
+        private static final String XML_NAMESPACE_URI = "http://www.w3.org/XML/1998/namespace";
+
+        /**
+         * The prefixes of startPrefixMapping() declarations for the coming element.
+         */
+        private List<String> prefixList = new ArrayList<String>();
+
+        /**
+         * The URIs of startPrefixMapping() declarations for the coming element.
+         */
+        private List<String> uriList = new ArrayList<String>();
+
+        /**
+         * Maps of URI<->prefix mappings. Used to work around a bug in the Xalan
+         * serializer.
+         */
+        private Map<String, String> uriToPrefixMap = new HashMap<String, String>();
+        private Map<String, String> prefixToUriMap = new HashMap<String, String>();
+
+        /**
+         * True if there has been some startPrefixMapping() for the coming element.
+         */
+        private boolean hasMappings = false;
+
+        protected final ContentHandler contentHandler;
+        protected final LexicalHandler lexicalHandler;
+        protected final Logger logger;
+
+        public NamespaceAsAttributes(final ContentHandler handler, final Logger logger) {
+            this.contentHandler = handler;
+            this.lexicalHandler = (LexicalHandler)handler;
+            this.logger = logger;
+        }
+
+        /**
+         * @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator)
+         */
+        public void setDocumentLocator(Locator locator) {
+            contentHandler.setDocumentLocator(locator);
+        }
+
+        /**
+         * Receive notification of character data.
+         *
+         * @param c The characters from the XML document.
+         * @param start The start position in the array.
+         * @param len The number of characters to read from the array.
+         */
+        public void characters(char c[], int start, int len)
+        throws SAXException {
+            contentHandler.characters(c, start, len);
+        }
+
+        /**
+         * Receive notification of ignorable whitespace in element content.
+         *
+         * @param c The characters from the XML document.
+         * @param start The start position in the array.
+         * @param len The number of characters to read from the array.
+         */
+        public void ignorableWhitespace(char c[], int start, int len)
+        throws SAXException {
+            contentHandler.ignorableWhitespace(c, start, len);
+        }
+
+        /**
+         * Receive notification of a processing instruction.
+         *
+         * @param target The processing instruction target.
+         * @param data The processing instruction data, or null if none was
+         *             supplied.
+         */
+        public void processingInstruction(String target, String data)
+        throws SAXException {
+            contentHandler.processingInstruction(target, data);
+        }
+
+        /**
+         * Receive notification of a skipped entity.
+         *
+         * @param name The name of the skipped entity.  If it is a  parameter
+         *             entity, the name will begin with '%'.
+         */
+        public void skippedEntity(String name)
+        throws SAXException {
+            contentHandler.skippedEntity(name);
+        }
+
+        /**
+         * Report the start of DTD declarations, if any.
+         *
+         * @param name The document type name.
+         * @param publicId The declared public identifier for the external DTD
+         *                 subset, or null if none was declared.
+         * @param systemId The declared system identifier for the external DTD
+         *                 subset, or null if none was declared.
+         */
+        public void startDTD(String name, String publicId, String systemId)
+        throws SAXException {
+            lexicalHandler.startDTD(name, publicId, systemId);
+        }
+
+        /**
+         * Report the end of DTD declarations.
+         */
+        public void endDTD()
+        throws SAXException {
+            lexicalHandler.endDTD();
+        }
+
+        /**
+         * Report the beginning of an entity.
+         *
+         * @param name The name of the entity. If it is a parameter entity, the
+         *             name will begin with '%'.
+         */
+        public void startEntity(String name)
+        throws SAXException {
+            lexicalHandler.startEntity(name);
+        }
+
+        /**
+         * Report the end of an entity.
+         *
+         * @param name The name of the entity that is ending.
+         */
+        public void endEntity(String name)
+        throws SAXException {
+            lexicalHandler.endEntity(name);
+        }
+
+        /**
+         * Report the start of a CDATA section.
+         */
+        public void startCDATA()
+        throws SAXException {
+            lexicalHandler.startCDATA();
+        }
+
+        /**
+         * Report the end of a CDATA section.
+         */
+        public void endCDATA()
+        throws SAXException {
+            lexicalHandler.endCDATA();
+        }
+
+        /**
+         * Report an XML comment anywhere in the document.
+         *
+         * @param ch An array holding the characters in the comment.
+         * @param start The starting position in the array.
+         * @param len The number of characters to use from the array.
+         */
+        public void comment(char ch[], int start, int len)
+        throws SAXException {
+            lexicalHandler.comment(ch, start, len);
+        }
+
+        public void startDocument() throws SAXException {
+            // Cleanup
+            this.uriToPrefixMap.clear();
+            this.prefixToUriMap.clear();
+            clearMappings();
+            this.contentHandler.startDocument();
+        }
+
+        /**
+         * Track mappings to be able to add <code>xmlns:</code> attributes
+         * in <code>startElement()</code>.
+         */
+        public void startPrefixMapping(String prefix, String uri) throws SAXException {
+            // Store the mappings to reconstitute xmlns:attributes
+            // except prefixes starting with "xml": these are reserved
+            // VG: (uri != null) fixes NPE in startElement
+            if (uri != null && !prefix.startsWith("xml")) {
+                this.hasMappings = true;
+                this.prefixList.add(prefix);
+                this.uriList.add(uri);
+
+                // append the prefix colon now, in order to save concatenations later, but
+                // only for non-empty prefixes.
+                if (prefix.length() > 0) {
+                    this.uriToPrefixMap.put(uri, prefix + ":");
+                } else {
+                    this.uriToPrefixMap.put(uri, prefix);
+                }
+
+                this.prefixToUriMap.put(prefix, uri);
+            }
+            this.contentHandler.startPrefixMapping(prefix, uri);
+        }
+
+        /**
+         * Ensure all namespace declarations are present as <code>xmlns:</code> attributes
+         * and add those needed before calling superclass. This is a workaround for a Xalan bug
+         * (at least in version 2.0.1) : <code>org.apache.xalan.serialize.SerializerToXML</code>
+         * ignores <code>start/endPrefixMapping()</code>.
+         */
+        public void startElement(String eltUri, String eltLocalName, String eltQName, Attributes attrs)
+                throws SAXException {
+
+            // try to restore the qName. The map already contains the colon
+            if (null != eltUri && eltUri.length() != 0 && this.uriToPrefixMap.containsKey(eltUri)) {
+                eltQName = this.uriToPrefixMap.get(eltUri) + eltLocalName;
+            }
+            if (this.hasMappings) {
+                // Add xmlns* attributes where needed
+
+                // New Attributes if we have to add some.
+                AttributesImpl newAttrs = null;
+
+                int mappingCount = this.prefixList.size();
+                int attrCount = attrs.getLength();
+
+                for (int mapping = 0; mapping < mappingCount; mapping++) {
+
+                    // Build infos for this namespace
+                    String uri = this.uriList.get(mapping);
+                    String prefix = this.prefixList.get(mapping);
+                    String qName = prefix.equals("") ? "xmlns" : ("xmlns:" + prefix);
+
+                    // Search for the corresponding xmlns* attribute
+                    boolean found = false;
+                    for (int attr = 0; attr < attrCount; attr++) {
+                        if (qName.equals(attrs.getQName(attr))) {
+                            // Check if mapping and attribute URI match
+                            if (!uri.equals(attrs.getValue(attr))) {
+                                logger.error("URI in prefix mapping and attribute do not match : '"
+                                                  + uri + "' - '" + attrs.getURI(attr) + "'");
+                                throw new SAXException("URI in prefix mapping and attribute do not match");
+                            }
+                            found = true;
+                            break;
+                        }
+                    }
+
+                    if (!found) {
+                        // Need to add this namespace
+                        if (newAttrs == null) {
+                            // Need to test if attrs is empty or we go into an infinite loop...
+                            // Well know SAX bug which I spent 3 hours to remind of :-(
+                            if (attrCount == 0) {
+                                newAttrs = new AttributesImpl();
+                            } else {
+                                newAttrs = new AttributesImpl(attrs);
+                            }
+                        }
+
+                        if (prefix.equals("")) {
+                            newAttrs.addAttribute(XML_NAMESPACE_URI, "xmlns", "xmlns", "CDATA", uri);
+                        } else {
+                            newAttrs.addAttribute(XML_NAMESPACE_URI, prefix, qName, "CDATA", uri);
+                        }
+                    }
+                } // end for mapping
+
+                // Cleanup for the next element
+                clearMappings();
+
+                // Start element with new attributes, if any
+                this.contentHandler.startElement(eltUri, eltLocalName, eltQName, newAttrs == null ? attrs : newAttrs);
+            } else {
+                // Normal job
+                this.contentHandler.startElement(eltUri, eltLocalName, eltQName, attrs);
+            }
+        }
+
+
+        /**
+         * Receive notification of the end of an element.
+         * Try to restore the element qName.
+         */
+        public void endElement(String eltUri, String eltLocalName, String eltQName) throws SAXException {
+            // try to restore the qName. The map already contains the colon
+            if (null != eltUri && eltUri.length() != 0 && this.uriToPrefixMap.containsKey(eltUri)) {
+                eltQName = this.uriToPrefixMap.get(eltUri) + eltLocalName;
+            }
+            this.contentHandler.endElement(eltUri, eltLocalName, eltQName);
+        }
+
+        /**
+         * End the scope of a prefix-URI mapping:
+         * remove entry from mapping tables.
+         */
+        public void endPrefixMapping(String prefix) throws SAXException {
+            // remove mappings for xalan-bug-workaround.
+            // Unfortunately, we're not passed the uri, but the prefix here,
+            // so we need to maintain maps in both directions.
+            if (this.prefixToUriMap.containsKey(prefix)) {
+                this.uriToPrefixMap.remove(this.prefixToUriMap.get(prefix));
+                this.prefixToUriMap.remove(prefix);
+            }
+
+            if (hasMappings) {
+                // most of the time, start/endPrefixMapping calls have an element event between them,
+                // which will clear the hasMapping flag and so this code will only be executed in the
+                // rather rare occasion when there are start/endPrefixMapping calls with no element
+                // event in between. If we wouldn't remove the items from the prefixList and uriList here,
+                // the namespace would be incorrectly declared on the next element following the
+                // endPrefixMapping call.
+                int pos = prefixList.lastIndexOf(prefix);
+                if (pos != -1) {
+                    prefixList.remove(pos);
+                    uriList.remove(pos);
+                }
+            }
+
+            this.contentHandler.endPrefixMapping(prefix);
+        }
+
+        /**
+         *
+         */
+        public void endDocument() throws SAXException {
+            // Cleanup
+            this.uriToPrefixMap.clear();
+            this.prefixToUriMap.clear();
+            clearMappings();
+            this.contentHandler.endDocument();
+        }
+
+        private void clearMappings() {
+            this.hasMappings = false;
+            this.prefixList.clear();
+            this.uriList.clear();
+        }
+    }
+}

Propchange: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/AbstractTraxSerializerFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/AbstractTraxSerializerFactory.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/AbstractTraxSerializerFactory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Copied: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/HtmlGeneratorFactory.java (from r825016, sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/HtmlGeneratorFactory.java)
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/HtmlGeneratorFactory.java?p2=sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/HtmlGeneratorFactory.java&p1=sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/HtmlGeneratorFactory.java&r1=825016&r2=825031&rev=825031&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/HtmlGeneratorFactory.java (original)
+++ sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/HtmlGeneratorFactory.java Wed Oct 14 06:54:42 2009
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.rewriter.impl;
+package org.apache.sling.rewriter.impl.components;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;

Propchange: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/HtmlGeneratorFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/HtmlGeneratorFactory.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/HtmlGeneratorFactory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/HtmlSerializerFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/HtmlSerializerFactory.java?rev=825031&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/HtmlSerializerFactory.java (added)
+++ sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/HtmlSerializerFactory.java Wed Oct 14 06:54:42 2009
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.rewriter.impl.components;
+
+
+/**
+ * This sax serializer serializes html-
+ * @scr.component metatype="no"
+ * @scr.service
+ * @scr.property name="pipeline.type" value="html-serializer"
+ */
+public class HtmlSerializerFactory extends AbstractTraxSerializerFactory {
+
+    @Override
+    protected String getOutputFormat() {
+        return "html";
+    }
+
+}

Propchange: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/HtmlSerializerFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/HtmlSerializerFactory.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/HtmlSerializerFactory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/TraxErrorHandler.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/TraxErrorHandler.java?rev=825031&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/TraxErrorHandler.java (added)
+++ sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/TraxErrorHandler.java Wed Oct 14 06:54:42 2009
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.rewriter.impl.components;
+
+import javax.xml.transform.ErrorListener;
+import javax.xml.transform.SourceLocator;
+import javax.xml.transform.TransformerException;
+
+import org.slf4j.Logger;
+
+
+/**
+ * This error handler simply logs all exception and, in case of a fatal error,
+ * the exception is rethrown. Warnings and errors are not re-thrown.
+ */
+public class TraxErrorHandler implements ErrorListener {
+
+    private final Logger logger;
+
+    private StringBuilder warnings = new StringBuilder("Errors in serialization:\n");
+
+
+    public TraxErrorHandler(Logger logger) {
+        this.logger = logger;
+    }
+
+    public void warning(TransformerException exception)
+    throws TransformerException {
+        final String message = getMessage(exception);
+        if (this.logger != null) {
+            this.logger.warn(message);
+        } else {
+            System.out.println("WARNING: " + message);
+        }
+        warnings.append("Warning: ");
+        warnings.append(message);
+        warnings.append("\n");
+    }
+
+    public void error(TransformerException exception)
+    throws TransformerException {
+        final String message = getMessage(exception);
+        if (this.logger != null) {
+            this.logger.error(message, exception);
+        } else {
+            System.out.println("ERROR: " + message);
+        }
+        warnings.append("Error: ");
+        warnings.append(message);
+        warnings.append("\n");
+    }
+
+    public void fatalError(TransformerException exception)
+    throws TransformerException {
+        final String message = getMessage(exception);
+        if (this.logger != null) {
+            this.logger.error(message, exception);
+        } else {
+            System.out.println("FATAL-ERROR: " + message);
+        }
+        warnings.append("Fatal: ");
+        warnings.append(message);
+        warnings.append("\n");
+
+        try {
+            throw new TransformerException(warnings.toString());
+        } finally {
+            warnings = new StringBuilder();
+        }
+    }
+
+    private String getMessage(TransformerException exception) {
+        SourceLocator locator = exception.getLocator();
+        if (locator != null) {
+            String id = (!locator.getPublicId().equals(locator.getPublicId()))
+                    ? locator.getPublicId()
+                    : (null != locator.getSystemId())
+                    ? locator.getSystemId() : "SystemId Unknown";
+            return "File " + id
+                   + "; Line " + locator.getLineNumber()
+                   + "; Column " + locator.getColumnNumber()
+                   + "; " + exception.getMessage();
+        }
+        return exception.getMessage();
+    }
+}

Propchange: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/TraxErrorHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/TraxErrorHandler.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/TraxErrorHandler.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/TraxSerializer.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/TraxSerializer.java?rev=825031&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/TraxSerializer.java (added)
+++ sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/TraxSerializer.java Wed Oct 14 06:54:42 2009
@@ -0,0 +1,280 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.rewriter.impl.components;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Properties;
+
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.sling.rewriter.ProcessingComponentConfiguration;
+import org.apache.sling.rewriter.ProcessingContext;
+import org.apache.sling.rewriter.Serializer;
+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;
+
+/**
+ * The <code>TraxSerializer</code> is a serializer based on
+ * the jaxp serializers.
+ */
+public class TraxSerializer implements Serializer, LexicalHandler {
+
+    /** The default encoding. */
+    private static final String DEFAULT_ENCODING = "UTF-8";
+
+    /** The <code>Properties</code> used by this serializer. */
+    private final Properties format = new Properties();
+
+    private final TransformerHandler transformerHandler;
+
+    private final ContentHandler contentHandler;
+    private final LexicalHandler lexicalHandler;
+
+    public TraxSerializer(final TransformerHandler transformerHandler,
+                                  final ContentHandler handler,
+                                  final String outputFormat) {
+        this.contentHandler = handler;
+        this.lexicalHandler = (LexicalHandler)handler;
+        this.transformerHandler = transformerHandler;
+        this.format.put(OutputKeys.METHOD, outputFormat);
+    }
+
+    /**
+     * @see org.apache.sling.rewriter.Serializer#init(org.apache.sling.rewriter.ProcessingContext, org.apache.sling.rewriter.ProcessingComponentConfiguration)
+     */
+    public void init(ProcessingContext context,
+                     ProcessingComponentConfiguration config)
+    throws IOException {
+        if ( this.transformerHandler == null ) {
+            throw new IOException("Transformer handler could not be instantiated.");
+        }
+
+        if (!this.format.containsKey(OutputKeys.ENCODING)) {
+            this.format.put(OutputKeys.ENCODING, DEFAULT_ENCODING);
+        }
+
+        String cdataSectionElements = config.getConfiguration().get("cdata-section-elements", String.class);
+        String dtPublic = config.getConfiguration().get("doctype-public", String.class);
+        String dtSystem = config.getConfiguration().get("doctype-system", String.class);
+        String encoding = config.getConfiguration().get("encoding", String.class);
+        String indent = config.getConfiguration().get("indent", String.class);
+        String mediaType = config.getConfiguration().get("media-type", String.class);
+        String method = config.getConfiguration().get("method", String.class);
+        String omitXMLDeclaration = config.getConfiguration().get("omit-xml-declaration", String.class);
+        String standAlone = config.getConfiguration().get("standalone", String.class);
+        String version = config.getConfiguration().get("version", String.class);
+
+        if (cdataSectionElements != null) {
+            format.put(OutputKeys.CDATA_SECTION_ELEMENTS, cdataSectionElements);
+        }
+        if (dtPublic != null) {
+            format.put(OutputKeys.DOCTYPE_PUBLIC, dtPublic);
+        }
+        if (dtSystem != null) {
+            format.put(OutputKeys.DOCTYPE_SYSTEM, dtSystem);
+        }
+        if (encoding != null) {
+            format.put(OutputKeys.ENCODING, encoding);
+        }
+        if (indent != null) {
+            format.put(OutputKeys.INDENT, indent);
+        }
+        if (mediaType != null) {
+            format.put(OutputKeys.MEDIA_TYPE, mediaType);
+        }
+        if (method != null) {
+            format.put(OutputKeys.METHOD, method);
+        }
+        if (omitXMLDeclaration != null) {
+            format.put(OutputKeys.OMIT_XML_DECLARATION, omitXMLDeclaration);
+        }
+        if (standAlone != null) {
+            format.put(OutputKeys.STANDALONE, standAlone);
+        }
+        if (version != null) {
+            format.put(OutputKeys.VERSION, version);
+        }
+        this.setOutputStream(context.getOutputStream());
+    }
+
+    /**
+     * Set the {@link OutputStream} where the requested resource should
+     * be serialized.
+     */
+    private void setOutputStream(OutputStream out) throws IOException {
+        try {
+            this.transformerHandler.getTransformer().setOutputProperties(this.format);
+            this.transformerHandler.setResult(new StreamResult(out));
+        } catch (Exception e) {
+            final String message = "Cannot set XMLSerializer outputstream";
+            throw ((IOException)new IOException(message).initCause(e));
+        }
+    }
+
+    /**
+     * @see org.apache.sling.rewriter.Serializer#dispose()
+     */
+    public void dispose() {
+        // nothing to do
+    }
+
+    /**
+     * @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator)
+     */
+    public void setDocumentLocator(Locator locator) {
+        contentHandler.setDocumentLocator(locator);
+    }
+
+    /**
+     * @see org.xml.sax.ContentHandler#startDocument()
+     */
+    public void startDocument()
+    throws SAXException {
+        contentHandler.startDocument();
+    }
+
+    /**
+     * @see org.xml.sax.ContentHandler#endDocument()
+     */
+    public void endDocument()
+    throws SAXException {
+        contentHandler.endDocument();
+    }
+
+    /**
+     * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String)
+     */
+    public void startPrefixMapping(String prefix, String uri)
+    throws SAXException {
+        contentHandler.startPrefixMapping(prefix, uri);
+    }
+
+    /**
+     * @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String)
+     */
+    public void endPrefixMapping(String prefix)
+    throws SAXException {
+        contentHandler.endPrefixMapping(prefix);
+    }
+
+    public void startElement(String uri, String loc, String raw, Attributes a)
+    throws SAXException {
+        contentHandler.startElement(uri, loc, raw, a);
+    }
+
+    /**
+     * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
+     */
+    public void endElement(String uri, String loc, String raw)
+    throws SAXException {
+        contentHandler.endElement(uri, loc, raw);
+    }
+
+    /**
+     * @see org.xml.sax.ContentHandler#characters(char[], int, int)
+     */
+    public void characters(char c[], int start, int len)
+    throws SAXException {
+        contentHandler.characters(c, start, len);
+    }
+
+    /**
+     * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)
+     */
+    public void ignorableWhitespace(char c[], int start, int len)
+    throws SAXException {
+        contentHandler.ignorableWhitespace(c, start, len);
+    }
+
+    /**
+     * @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String)
+     */
+    public void processingInstruction(String target, String data)
+    throws SAXException {
+        contentHandler.processingInstruction(target, data);
+    }
+
+    /**
+     * @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String)
+     */
+    public void skippedEntity(String name)
+    throws SAXException {
+        contentHandler.skippedEntity(name);
+    }
+
+    /**
+     * @see org.xml.sax.ext.LexicalHandler#startDTD(java.lang.String, java.lang.String, java.lang.String)
+     */
+    public void startDTD(String name, String publicId, String systemId)
+    throws SAXException {
+        lexicalHandler.startDTD(name, publicId, systemId);
+    }
+
+    /**
+     * @see org.xml.sax.ext.LexicalHandler#endDTD()
+     */
+    public void endDTD()
+    throws SAXException {
+        lexicalHandler.endDTD();
+    }
+
+    /**
+     * @see org.xml.sax.ext.LexicalHandler#startEntity(java.lang.String)
+     */
+    public void startEntity(String name)
+    throws SAXException {
+        lexicalHandler.startEntity(name);
+    }
+
+    /**
+     * @see org.xml.sax.ext.LexicalHandler#endEntity(java.lang.String)
+     */
+    public void endEntity(String name)
+    throws SAXException {
+        lexicalHandler.endEntity(name);
+    }
+
+    /**
+     * @see org.xml.sax.ext.LexicalHandler#startCDATA()
+     */
+    public void startCDATA()
+    throws SAXException {
+        lexicalHandler.startCDATA();
+    }
+
+    /**
+     * @see org.xml.sax.ext.LexicalHandler#endCDATA()
+     */
+    public void endCDATA()
+    throws SAXException {
+        lexicalHandler.endCDATA();
+    }
+
+    /**
+     * @see org.xml.sax.ext.LexicalHandler#comment(char[], int, int)
+     */
+    public void comment(char ch[], int start, int len)
+    throws SAXException {
+        lexicalHandler.comment(ch, start, len);
+    }
+}

Propchange: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/TraxSerializer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/TraxSerializer.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/TraxSerializer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/XHtmlSerializerFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/XHtmlSerializerFactory.java?rev=825031&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/XHtmlSerializerFactory.java (added)
+++ sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/XHtmlSerializerFactory.java Wed Oct 14 06:54:42 2009
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.rewriter.impl.components;
+
+
+/**
+ * This sax serializer serializes xhtml-
+ * @scr.component metatype="no"
+ * @scr.service
+ * @scr.property name="pipeline.type" value="xhtml-serializer"
+ */
+public class XHtmlSerializerFactory extends AbstractTraxSerializerFactory {
+
+    @Override
+    protected String getOutputFormat() {
+        return "xhtml";
+    }
+}

Propchange: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/XHtmlSerializerFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/XHtmlSerializerFactory.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/contrib/extensions/rewriter/src/main/java/org/apache/sling/rewriter/impl/components/XHtmlSerializerFactory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain