Index: jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/xml/DocumentViewExporter.java
===================================================================
--- jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/xml/DocumentViewExporter.java	(revision 0)
+++ jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/xml/DocumentViewExporter.java	(revision 0)
@@ -0,0 +1,105 @@
+/*
+ * 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.jackrabbit.commons.xml;
+
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+
+import org.apache.jackrabbit.util.ISO9075;
+import org.apache.jackrabbit.value.ValueHelper;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * Document view exporter.
+ *
+ * @since Jackrabbit JCR Commons 1.5
+ */
+public class DocumentViewExporter extends Exporter {
+
+    /**
+     * Creates a document view exporter.
+     *
+     * @param session current session
+     * @param handler SAX event handler for the export
+     * @param recurse whether to recursively export the whole subtree
+     * @param binary whether to export binary values
+     */
+    public DocumentViewExporter(
+            Session session, ContentHandler handler,
+            boolean recurse, boolean binary) {
+        super(session, handler, recurse, binary);
+    }
+
+    /**
+     * Exports the given node either as XML characters (if it's an
+     * <code>xml:text</code> node) or as an XML element with properties
+     * mapped to XML attributes.
+     */
+    protected void exportNode(String uri, String local, Node node)
+            throws RepositoryException, SAXException {
+        if (JCR.equals(uri) && "xmltext".equals(local)) {
+            try {
+                // assume jcr:xmlcharacters is single-valued
+                Property property =
+                    node.getProperty(getJCRName(JCR, "xmlcharacters"));
+                char[] ch = property.getString().toCharArray();
+                characters(ch, 0, ch.length);
+            } catch (PathNotFoundException e) {
+                // jcr:xmlcharacters not found, ignore this node
+            }
+        } else {
+            // attributes (properties)
+            exportProperties(node);
+
+            // encode node name to make sure it's a valid xml name
+            String encoded = ISO9075.encode(local);
+            startElement(uri, encoded);
+            exportNodes(node);
+            endElement(uri, encoded);
+        }
+    }
+
+    /**
+     * Maps the given single-valued property to an XML attribute.
+     */
+    protected void exportProperty(String uri, String local, Value value)
+            throws RepositoryException {
+        // TODO: Serialized names and paths should use XML namespace mappings
+        String attribute = ValueHelper.serialize(value, false);
+        addAttribute(uri, ISO9075.encode(local), attribute);
+    }
+
+    /**
+     * Does nothing. Multi-valued properties are skipped for the time being
+     * until a way of properly handling/detecting multi-valued properties
+     * on re-import is found. Skipping multi-valued properties entirely is
+     * legal according to "6.4.2.5 Multi-value Properties" of the JSR 170
+     * specification.
+     *
+     * @see https://issues.apache.org/jira/browse/JCR-325
+     */
+    protected void exportProperty(
+            String uri, String local, int type, Value[] values) {
+        // TODO: proper multi-value serialization support
+    }
+
+}
Index: jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/xml/Exporter.java
===================================================================
--- jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/xml/Exporter.java	(revision 0)
+++ jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/xml/Exporter.java	(revision 0)
@@ -0,0 +1,581 @@
+/*
+ * 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.jackrabbit.commons.xml;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.helpers.NamespaceSupport;
+
+/**
+ * Abstract base class for document and system view exporters. This class
+ * takes care of all the details related to namespace mappings, shareable
+ * nodes, recursive exports, binary values, and so on while leaving the
+ * decisions about what kind of SAX events to generate to subclasses.
+ * <p>
+ * A subclass should only need to implement the abstract methods of this
+ * class to produce a fully functional exporter.
+ *
+ * @since Jackrabbit JCR Commons 1.5
+ */
+public abstract class Exporter {
+
+    /**
+     * The <code>jcr</code> namespace URI.
+     */
+    protected static final String JCR = "http://www.jcp.org/jcr/1.0";
+
+    /**
+     * The <code>nt</code> namespace URI.
+     */
+    private static final String NT = "http://www.jcp.org/jcr/nt/1.0";
+
+    /**
+     * The <code>mix</code> namespace URI.
+     */
+    private static final String MIX = "http://www.jcp.org/jcr/mix/1.0";
+
+    /**
+     * Attributes of the next element. This single instance is reused for
+     * all elements by simply clearing it after each element has been emitted.
+     */
+    private final AttributesImpl attributes = new AttributesImpl();
+
+    /**
+     * Stack of namespace mappings. 
+     */
+    private final LinkedList stack = new LinkedList();
+
+    /**
+     * The UUID strings of all shareable nodes already exported.
+     */
+    private final Set shareables = new HashSet();
+
+    /**
+     * Whether the current node is a shareable node that has already been
+     * exported.
+     */
+    private boolean share = false;
+
+    /**
+     * Current session.
+     */
+    private final Session session;
+
+    /**
+     * SAX event handler to which the export events are sent.
+     */
+    private final ContentHandler handler;
+
+    /**
+     * Whether to export the subtree or just the given node.
+     */
+    private final boolean recurse;
+
+    /**
+     * Whether to export binary values.
+     */
+    private final boolean binary;
+
+    /**
+     * Creates an exporter instance.
+     *
+     * @param session current session
+     * @param handler SAX event handler
+     * @param recurse whether the export should be recursive
+     * @param binary whether the export should include binary values
+     */
+    protected Exporter(
+            Session session, ContentHandler handler,
+            boolean recurse, boolean binary) {
+        this.session = session;
+        this.handler = handler;
+        this.recurse = recurse;
+        this.binary = binary;
+        stack.add(new HashMap());
+    }
+
+    /**
+     * Exports the given node by preparing the export and calling the
+     * abstract {@link #exportNode(String, String, Node)} method to give
+     * control of the export format to a subclass.
+     * <p>
+     * This method should be called only once for an exporter instance.
+     *
+     * @param node node to be exported
+     * @throws SAXException if a SAX error occurs
+     * @throws RepositoryException if a repository error occurs
+     */
+    public void export(Node node) throws RepositoryException, SAXException {
+        handler.startDocument();
+
+        String[] prefixes = session.getNamespacePrefixes();
+        for (int i = 0; i < prefixes.length; i++) {
+            if (prefixes[i].length() > 0 && !prefixes[i].equals("xml") ) {
+                addNamespace(prefixes[i], session.getNamespaceURI(prefixes[i]));
+            }
+        }
+
+        exportNode(node);
+
+        handler.endDocument();
+    }
+
+    /**
+     * Called to export the given node. The node name (or <code>jcr:root</code>
+     * if the node is the root node) is given as an explicit pair of the
+     * resolved namespace URI and local part of the name.
+     * <p>
+     * The implementation of this method should call the methods
+     * {@link #exportProperties(Node)} and {@link #exportProperties(Node)}
+     * to respectively export the properties and child nodes of the given node.
+     * Those methods will call back to the implementations of this method and
+     * the abstract property export methods so the subclass can decide what
+     * SAX events to emit for each exported item.
+     *
+     * @param uri node namespace, or <code>null</code>
+     * @param local node name
+     * @param node node
+     * @throws RepositoryException if a repository error occurs
+     * @throws SAXException if a SAX error occurs
+     */
+    protected abstract void exportNode(String uri, String local, Node node)
+            throws RepositoryException, SAXException;
+
+    /**
+     * Called by {@link #processProperties(Node)} to process a single-valued
+     * property.
+     *
+     * @param uri property namespace, or <code>null</code>
+     * @param local property name
+     * @param value property value
+     * @throws RepositoryException if a repository error occurs
+     * @throws SAXException if a SAX error occurs
+     */
+    protected abstract void exportProperty(
+            String uri, String local, Value value)
+            throws RepositoryException, SAXException;
+
+    /**
+     * Called by {@link #processProperties(Node)} to process a multivalued
+     * property.
+     *
+     * @param uri property namespace, or <code>null</code>
+     * @param local property name
+     * @param type property type
+     * @param value property values
+     * @throws RepositoryException if a repository error occurs
+     * @throws SAXException if a SAX error occurs
+     */
+    protected abstract void exportProperty(
+            String uri, String local, int type, Value[] values)
+            throws RepositoryException, SAXException;
+
+    /**
+     * Called by {@link #exportNode(String, String, Node)} to recursively
+     * call {@link #exportNode(String, String, Node)} for each child node.
+     * Does nothing if this exporter is not recursive. 
+     *
+     * @param node parent node
+     * @throws RepositoryException if a repository error occurs
+     * @throws SAXException if a SAX error occurs
+     */
+    protected void exportNodes(Node node)
+            throws RepositoryException, SAXException {
+        if (recurse && !share) {
+            NodeIterator iterator = node.getNodes();
+            while (iterator.hasNext()) {
+                Node child = iterator.nextNode();
+                exportNode(child);
+            }
+        }
+    }
+
+    /**
+     * Processes all properties of the given node by calling the abstract
+     * {@link #exportProperty(String, String, Value)} and
+     * {@link #exportProperty(String, String, int, Value[])} methods for
+     * each property depending on whether the property is single- or
+     * multivalued.
+     * <p>
+     * The first properties to be processed are <code>jcr:primaryType</code>,
+     * <code>jcr:mixinTypes</code>, and <code>jcr:uuid</code>, and then the
+     * remaining properties ordered by their names.
+     * <p>
+     * If the node is a shareable node that has already been encountered by
+     * this event generator, then only a <code>jcr:primaryType</code> property
+     * with the fixed value "nt:share" and the <code>jcr:uuid</code> property
+     * of the shareable node are exported.
+     *
+     * @see https://issues.apache.org/jira/browse/JCR-1084
+     * @param node node
+     * @return properties as sorted map
+     * @throws RepositoryException if a repository error occurs
+     * @throws SAXException if a SAX error occurs
+     */
+    protected void exportProperties(Node node)
+            throws RepositoryException, SAXException {
+        // if node is shareable and has already been serialized, change its
+        // type to nt:share and process only the properties jcr:primaryType
+        // and jcr:uuid (mix:shareable is referenceable, so jcr:uuid exists)
+        if (share) {
+            ValueFactory factory = session.getValueFactory();
+            Value share =
+                factory.createValue(getJCRName(NT, "share"), PropertyType.NAME);
+            exportProperty(JCR, "primaryType", share);
+            exportProperty(JCR, "uuid", factory.createValue(node.getUUID()));
+        } else {
+            // Standard behaviour: return all properties (sorted, see JCR-1084)
+            SortedMap properties = getProperties(node);
+
+            // serialize jcr:primaryType, jcr:mixinTypes & jcr:uuid first:
+            exportProperty(properties, JCR, "primaryType");
+            exportProperty(properties, JCR, "mixinTypes");
+            exportProperty(properties, JCR, "uuid");
+
+            // serialize remaining properties
+            Iterator iterator = properties.entrySet().iterator();
+            while (iterator.hasNext()) {
+                Map.Entry entry = (Map.Entry) iterator.next();
+                String uri = null;
+                String name = (String) entry.getKey();
+                int colon = name.indexOf(':');
+                if (colon != -1) {
+                    uri = session.getNamespaceURI(name.substring(0, colon));
+                    name = name.substring(colon + 1);
+                }
+                exportProperty(uri, name, (Property) entry.getValue());
+            }
+        }
+    }
+
+    /**
+     * Utility method for exporting the given node. Parses the node name
+     * (or <code>jcr:root</code> if given the root node) and calls
+     * {@link #exportNode(String, String, Node)} with the resolved namespace
+     * URI and the local part of the name.
+     *
+     * @param node node
+     * @throws RepositoryException if a repository error occurs
+     * @throws SAXException if a SAX error occurs
+     */
+    private void exportNode(Node node)
+            throws RepositoryException, SAXException {
+        share = node.isNodeType(getJCRName(MIX, "shareable"))
+            && !shareables.add(node.getUUID());
+
+        if (node.getDepth() == 0) {
+            exportNode(JCR, "root", node);
+        } else {
+            String name = node.getName();
+            int colon = name.indexOf(':');
+            if (colon == -1) {
+                exportNode(null, name, node);
+            } else {
+                String uri = session.getNamespaceURI(name.substring(0, colon));
+                exportNode(uri, name.substring(colon + 1), node);
+            }
+        }
+    }
+
+    /**
+     * Returns a sorted map of the properties of the given node.
+     *
+     * @param node JCR node
+     * @return sorted map (keyed by name) of properties
+     * @throws RepositoryException if a repository error occurs
+     */
+    private SortedMap getProperties(Node node) throws RepositoryException {
+        SortedMap properties = new TreeMap();
+        PropertyIterator iterator = node.getProperties();
+        while (iterator.hasNext()) {
+            Property property = iterator.nextProperty();
+            properties.put(property.getName(), property);
+        }
+        return properties;
+    }
+
+    /**
+     * Utility method for processing the named property from the given
+     * map of properties. If the property exists, it is removed from the
+     * given map and passed to {@link #exportProperty(Property)}.
+     * The property is ignored if it does not exist.
+     *
+     * @param properties map of properties
+     * @param uri property namespace
+     * @param local property name
+     * @throws RepositoryException if a repository error occurs
+     * @throws SAXException if a SAX error occurs
+     */
+    private void exportProperty(Map properties, String uri, String local)
+            throws RepositoryException, SAXException {
+        Property property = (Property) properties.remove(getJCRName(uri, local));
+        if (property != null) {
+            exportProperty(uri, local, property);
+        }
+    }
+
+    /**
+     * Utility method for processing the given property. Calls either
+     * {@link #exportProperty(Value)} or {@link #exportProperty(int, Value[])}
+     * depending on whether the the property is single- or multivalued.
+     *
+     * @param uri property namespace
+     * @param local property name
+     * @param property property
+     * @throws RepositoryException if a repository error occurs
+     * @throws SAXException if a SAX error occurs
+     */
+    private void exportProperty(String uri, String local, Property property)
+            throws RepositoryException, SAXException {
+        int type = property.getType();
+        if (type != PropertyType.BINARY || binary) {
+            if (property.getDefinition().isMultiple()) {
+                exportProperty(uri, local, type, property.getValues());
+            } else {
+                exportProperty(uri, local, property.getValue());
+            }
+        } else {
+            ValueFactory factory = session.getValueFactory();
+            Value value = factory.createValue("", PropertyType.BINARY);
+            if (property.getDefinition().isMultiple()) {
+                exportProperty(uri, local, type, new Value[] { value });
+            } else {
+                exportProperty(uri, local, value);
+            }
+        }
+    }
+
+    //---------------------------------------------< XML handling methods >--
+
+    /**
+     * Emits a characters event with the given character content.
+     *
+     * @param ch character array
+     * @param start start offset within the array
+     * @param length number of characters to emit
+     * @throws SAXException if a SAX error occurs
+     */
+    protected void characters(char[] ch, int start, int length)
+            throws SAXException {
+        handler.characters(ch, start, length);
+    }
+
+    /**
+     * Adds the given attribute to be included in the next element.
+     *
+     * @param uri namespace URI of the attribute
+     * @param local local name of the attribute
+     * @param value attribute value
+     * @throws RepositoryException if a repository error occurs
+     */
+    protected void addAttribute(String uri, String local, String value)
+            throws RepositoryException {
+        attributes.addAttribute(
+                uri, local, getXMLName(uri, local), "CDATA", value);
+    }
+
+    /**
+     * Emits the start element event for an element with the given name.
+     * All the attributes added using
+     * {@link #addAttribute(String, String, String)} are included in the
+     * element along with any new namespace mappings. The namespace stack
+     * is extended for potential child elements.
+     *
+     * @param uri namespace URI or the element
+     * @param local local name of the element
+     * @throws RepositoryException if a repository error occurs
+     * @throws SAXException if a SAX error occurs
+     */
+    protected void startElement(String uri, String local)
+            throws SAXException, RepositoryException {
+        // Prefixed name is generated before namespace handling so that a
+        // potential new prefix mapping gets included as a xmlns attribute
+        String name = getXMLName(uri, local);
+
+        // Add namespace mappings
+        Map namespaces = (Map) stack.getFirst();
+        Iterator iterator = namespaces.entrySet().iterator();
+        while (iterator.hasNext()) {
+            Map.Entry entry = (Map.Entry) iterator.next();
+            String namespace = (String) entry.getKey();
+            String prefix = (String) entry.getValue();
+            handler.startPrefixMapping(prefix, namespace);
+            attributes.addAttribute(
+                    NamespaceSupport.XMLNS, prefix, "xmlns:" + prefix,
+                    "CDATA", namespace);
+        }
+
+        // Emit the start element event, and clear things for the next element
+        handler.startElement(uri, local, name, attributes);
+        attributes.clear();
+        stack.addFirst(new HashMap());
+    }
+
+    /**
+     * Emits the end element event for an element with the given name.
+     * The namespace stack and mappings are automatically updated.
+     *
+     * @param uri namespace URI or the element
+     * @param local local name of the element
+     * @throws RepositoryException if a repository error occurs
+     * @throws SAXException if a SAX error occurs
+     */
+    protected void endElement(String uri, String local)
+            throws SAXException, RepositoryException {
+        stack.removeFirst();
+        handler.endElement(uri, local, getXMLName(uri, local));
+
+        Map namespaces = (Map) stack.getFirst();
+        Iterator iterator = namespaces.values().iterator();
+        while (iterator.hasNext()) {
+            handler.endPrefixMapping((String) iterator.next());
+        }
+        namespaces.clear();
+    }
+
+    /**
+     * Returns the prefixed JCR name for the given namespace URI and local
+     * name.
+     *
+     * @param uri namespace URI (must not be the empty namespace)
+     * @param name local name
+     * @return prefixed JCR name
+     * @throws RepositoryException if a JCR namespace mapping is not available
+     */
+    protected String getJCRName(String uri, String name)
+            throws RepositoryException {
+        return session.getNamespacePrefix(uri) + ":" + name;
+    }
+
+    /**
+     * Returns a prefixed XML name for the given namespace URI and local
+     * name. If a prefix mapping for the namespace URI is not yet available,
+     * it is created based on the namespace mappings of the current JCR
+     * session.
+     *
+     * @param uri namespace URI, or <code>null</code>
+     * @param local local name
+     * @return prefixed XML name
+     * @throws RepositoryException if a JCR namespace mapping is not available
+     */
+    protected String getXMLName(String uri, String local)
+            throws RepositoryException {
+        if (uri == null) {
+            return local;
+        } else {
+            String prefix = getPrefix(uri);
+            if (prefix == null) {
+                prefix = getUniquePrefix(session.getNamespacePrefix(uri));
+                ((Map) stack.getFirst()).put(uri, prefix);
+            }
+            return prefix + ":" + local;
+        }
+    }
+
+    /**
+     * Adds the given namespace to the export. A unique prefix based on
+     * the given prefix hint is mapped to the given namespace URI. If the
+     * namespace is already mapped, then the existing prefix is returned.
+     *
+     * @param hint prefix hint
+     * @param uri namespace URI
+     * @return registered prefix
+     */
+    protected String addNamespace(String hint, String uri) {
+        String prefix = getPrefix(uri);
+        if (prefix == null) {
+            prefix = getUniquePrefix(hint);
+            ((Map) stack.getFirst()).put(uri, prefix);
+        }
+        return prefix;
+    }
+
+    /**
+     * Returns the namespace prefix mapped to the given URI. Returns
+     * <code>null</code> if the namespace URI is not registered.
+     *
+     * @param uri namespace URI
+     * @return prefix mapped to the URI, or <code>null</code>
+     */
+    private String getPrefix(String uri) {
+        Iterator iterator = stack.iterator();
+        while (iterator.hasNext()) {
+            String prefix = (String) ((Map) iterator.next()).get(uri);
+            if (prefix != null) {
+                return prefix;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns a unique namespace prefix based on the given hint.
+     * We need prefixes to be unique within the current namespace
+     * stack as otherwise for example a previously added attribute
+     * to the current element might incorrectly be using a prefix
+     * that is being redefined in this element.
+     *
+     * @param hint prefix hint
+     * @return unique prefix
+     */
+    private String getUniquePrefix(String hint) {
+        String prefix = hint;
+        for (int i = 2; prefixExists(prefix); i++) {
+            prefix = hint + i;
+        }
+        return prefix;
+    }
+
+    /**
+     * Checks whether the given prefix is already mapped within the
+     * current namespace stack.
+     *
+     * @param prefix namespace prefix
+     * @return <code>true</code> if the prefix is mapped,
+     *         <code>false</code> otherwise
+     */
+    private boolean prefixExists(String prefix) {
+        Iterator iterator = stack.iterator();
+        while (iterator.hasNext()) {
+            if (((Map) iterator.next()).containsValue(prefix)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}
Index: jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/xml/SystemViewExporter.java
===================================================================
--- jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/xml/SystemViewExporter.java	(revision 0)
+++ jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/xml/SystemViewExporter.java	(revision 0)
@@ -0,0 +1,171 @@
+/*
+ * 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.jackrabbit.commons.xml;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import javax.jcr.Node;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+
+import org.apache.jackrabbit.value.ValueHelper;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * System view exporter.
+ *
+ * @since Jackrabbit JCR Commons 1.5
+ */
+public class SystemViewExporter extends Exporter {
+
+    /**
+     * The <code>sv</code> namespace URI.
+     */
+    private static final String SV = "http://www.jcp.org/jcr/sv/1.0";
+
+    /**
+     * The <code>xs</code> namespace URI.
+     */
+    private static final String XS = "http://www.w3.org/2001/XMLSchema";
+
+    /**
+     * The <code>xsi</code> namespace URI.
+     */
+    private static final String XSI =
+        "http://www.w3.org/2001/XMLSchema-instance";
+
+    /**
+     * Creates a system view exporter.
+     *
+     * @param session current session
+     * @param handler SAX event handler for the export
+     * @param recurse whether to recursively export the whole subtree
+     * @param binary whether to export binary values
+     */
+    public SystemViewExporter(
+            Session session, ContentHandler handler,
+            boolean recurse, boolean binary) {
+        super(session, handler, recurse, binary);
+    }
+
+    /**
+     * Exports the given node as an <code>sv:node</code> element.
+     */
+    protected void exportNode(String uri, String local, Node node)
+            throws RepositoryException, SAXException {
+        addAttribute(SV, "name", getXMLName(uri, local));
+        startElement(SV, "node");
+        exportProperties(node);
+        exportNodes(node);
+        endElement(SV, "node");
+    }
+
+    /**
+     * Calls {@link #exportProperty(String, String, int, Value[])}.
+     */
+    protected void exportProperty(String uri, String local, Value value)
+            throws RepositoryException, SAXException {
+        exportProperty(uri, local, value.getType(), new Value[] { value });
+    }
+
+    /**
+     * Exports the given property as an <code>sv:property</code> element.
+     */
+    protected void exportProperty(
+            String uri, String local, int type, Value[] values)
+            throws RepositoryException, SAXException {
+        // start property element
+        addAttribute(SV, "name", getXMLName(uri, local));
+        addAttribute(SV, "type", PropertyType.nameFromValue(type));
+        startElement(SV, "property");
+        // values
+        for (int i = 0; i < values.length; i++) {
+            exportValue(values[i]);
+        }
+        endElement(SV, "property");
+    }
+
+    /**
+     * Exports the given value as an <code>sv:value</code> element.
+     *
+     * @param value value to be exported
+     */
+    private void exportValue(Value value)
+            throws RepositoryException, SAXException {
+        try {
+            boolean binary = mustSendBinary(value);
+            if (binary) {
+                addNamespace("xs", XS);
+                addNamespace("xsi", XSI);
+                addAttribute(XSI, "type", getXMLName(XS, "base64Binary"));
+            }
+            startElement(SV, "value");
+            ValueHelper.serialize(value, false, binary, new Writer() {
+                public void write(char[] cbuf, int off, int len)
+                        throws IOException {
+                    try {
+                        SystemViewExporter.this.characters(cbuf, off, len);
+                    } catch (Exception e) {
+                        IOException exception = new IOException();
+                        exception.initCause(e);
+                        throw exception;
+                    }
+                }
+                public void close() {
+                }
+                public void flush() {
+                }
+            });
+            endElement(SV, "value");
+        } catch (IOException e) {
+            // check if the exception wraps a SAXException
+            // (see Writer.write(char[], int, int) above)
+            if (e.getCause() instanceof SAXException) {
+                throw (SAXException) e.getCause();
+            } else {
+                throw new RepositoryException(e);
+            }
+        }
+    }
+
+    /**
+     * Utility method for determining whether a non-binary value should
+     * still be exported in base64 encoding to avoid emitting invalid XML
+     * characters.
+     *
+     * @param value value to be exported
+     * @return whether the value should be treated as a binary
+     * @throws RepositoryException if a repository error occurs
+     */
+    private boolean mustSendBinary(Value value) throws RepositoryException {
+        if (value.getType() != PropertyType.BINARY) {
+            String string = value.getString();
+            for (int i = 0; i < string.length(); i++) {
+                char c = string.charAt(i);
+                if (c >= 0 && c < 32 && c != '\r' && c != '\n' && c != '\t') {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+}
Index: jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/AbstractSession.java
===================================================================
--- jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/AbstractSession.java	(revision 654751)
+++ jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/AbstractSession.java	(working copy)
@@ -37,7 +37,10 @@
 import javax.xml.transform.sax.TransformerHandler;
 import javax.xml.transform.stream.StreamResult;
 
+import org.apache.jackrabbit.commons.xml.DocumentViewExporter;
+import org.apache.jackrabbit.commons.xml.Exporter;
 import org.apache.jackrabbit.commons.xml.ParsingContentHandler;
+import org.apache.jackrabbit.commons.xml.SystemViewExporter;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
@@ -47,6 +50,46 @@
 public abstract class AbstractSession implements Session {
 
     /**
+     * Generates a document view export using a {@link DocumentViewExporter}
+     * instance.
+     *
+     * @param path of the node to be exported
+     * @param handler handler for the SAX events of the export
+     * @param skipBinary whether binary values should be skipped
+     * @param noRecurse whether to export just the identified node
+     * @throws PathNotFoundException if a node at the given path does not exist
+     * @throws SAXException if the SAX event handler failed
+     * @throws RepositoryException if another error occurs
+     */
+    public void exportDocumentView(
+            String path, ContentHandler handler,
+            boolean skipBinary, boolean noRecurse)
+            throws PathNotFoundException, SAXException, RepositoryException {
+        export(path, new DocumentViewExporter(
+                this, handler, !noRecurse, !skipBinary));
+    }
+
+    /**
+     * Generates a system view export using a {@link SystemViewExporter}
+     * instance.
+     *
+     * @param path of the node to be exported
+     * @param handler handler for the SAX events of the export
+     * @param skipBinary whether binary values should be skipped
+     * @param noRecurse whether to export just the identified node
+     * @throws PathNotFoundException if a node at the given path does not exist
+     * @throws SAXException if the SAX event handler failed
+     * @throws RepositoryException if another error occurs
+     */
+    public void exportSystemView(
+            String path, ContentHandler handler,
+            boolean skipBinary, boolean noRecurse)
+            throws PathNotFoundException, SAXException, RepositoryException {
+        export(path, new SystemViewExporter(
+                this, handler, !noRecurse, !skipBinary));
+    }
+
+    /**
      * Calls {@link Session#exportDocumentView(String, ContentHandler, boolean, boolean)}
      * with the given arguments and a {@link ContentHandler} that serializes
      * SAX events to the given output stream.
@@ -227,6 +270,25 @@
     //-------------------------------------------------------------< private >
 
     /**
+     * Exports content at the given path using the given exporter.
+     *
+     * @param path of the node to be exported
+     * @param exporter document or system view exporter
+     * @throws SAXException if the SAX event handler failed
+     * @throws RepositoryException if another error occurs
+     */
+    private void export(String path, Exporter exporter)
+            throws PathNotFoundException, SAXException, RepositoryException {
+        Item item = getItem(path);
+        if (item.isNode()) {
+            exporter.export((Node) item);
+        } else {
+            throw new PathNotFoundException(
+                    "Only nodes, not properties, can be exported: " + path);
+        }
+    }
+
+    /**
      * Creates a {@link ContentHandler} instance that serializes the
      * received SAX events to the given output stream.
      *
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java	(revision 654751)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java	(working copy)
@@ -45,10 +45,8 @@
 import org.apache.jackrabbit.core.util.Dumpable;
 import org.apache.jackrabbit.core.version.VersionManager;
 import org.apache.jackrabbit.core.version.VersionManagerImpl;
-import org.apache.jackrabbit.core.xml.DocViewSAXEventGenerator;
 import org.apache.jackrabbit.core.xml.ImportHandler;
 import org.apache.jackrabbit.core.xml.SessionImporter;
-import org.apache.jackrabbit.core.xml.SysViewSAXEventGenerator;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.commons.conversion.DefaultNamePathResolver;
@@ -63,7 +61,6 @@
 import org.slf4j.LoggerFactory;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
 
 import javax.jcr.AccessDeniedException;
 import javax.jcr.Credentials;
@@ -927,42 +924,6 @@
     /**
      * {@inheritDoc}
      */
-    public void exportDocumentView(String absPath, ContentHandler contentHandler,
-                                   boolean skipBinary, boolean noRecurse)
-            throws PathNotFoundException, SAXException, RepositoryException {
-        // check sanity of this session
-        sanityCheck();
-
-        Item item = getItem(absPath);
-        if (!item.isNode()) {
-            // there's a property, though not a node at the specified path
-            throw new PathNotFoundException(absPath);
-        }
-        new DocViewSAXEventGenerator((Node) item, noRecurse, skipBinary,
-                contentHandler).serialize();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void exportSystemView(String absPath, ContentHandler contentHandler,
-                                 boolean skipBinary, boolean noRecurse)
-            throws PathNotFoundException, SAXException, RepositoryException {
-        // check sanity of this session
-        sanityCheck();
-
-        Item item = getItem(absPath);
-        if (!item.isNode()) {
-            // there's a property, though not a node at the specified path
-            throw new PathNotFoundException(absPath);
-        }
-        new SysViewSAXEventGenerator((Node) item, noRecurse, skipBinary,
-                contentHandler).serialize();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
     public boolean isLive() {
         return alive;
     }
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/DocViewSAXEventGenerator.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/DocViewSAXEventGenerator.java	(revision 654751)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/DocViewSAXEventGenerator.java	(working copy)
@@ -1,222 +0,0 @@
-/*
- * 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.jackrabbit.core.xml;
-
-import org.apache.jackrabbit.spi.commons.conversion.NameException;
-import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.util.ISO9075;
-import org.apache.jackrabbit.value.ValueHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.AttributesImpl;
-
-import javax.jcr.Node;
-import javax.jcr.Property;
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * A <code>DocViewSAXEventGenerator</code> instance can be used to generate
- * SAX events representing the serialized form of an item in Document View XML.
- */
-public class DocViewSAXEventGenerator extends AbstractSAXEventGenerator {
-
-    private static Logger log = LoggerFactory.getLogger(DocViewSAXEventGenerator.class);
-
-    public static final String CDATA_TYPE = "CDATA";
-
-    // used to temporarily store properties of a node
-    private final List props;
-
-    /**
-     * Constructor
-     *
-     * @param node           the node state which should be serialized
-     * @param noRecurse      if true, only <code>node</code> and its properties
-     *                       will be serialized; otherwise the entire hierarchy
-     *                       starting with <code>node</code> will be serialized.
-     * @param skipBinary     flag governing whether binary properties are to be
-     *                       serialized.
-     * @param contentHandler the content handler to feed the SAX events to
-     * @throws RepositoryException if an error occurs
-     */
-    public DocViewSAXEventGenerator(Node node, boolean noRecurse,
-                                    boolean skipBinary,
-                                    ContentHandler contentHandler)
-            throws RepositoryException {
-        super(node, noRecurse, skipBinary, contentHandler);
-
-        props = new ArrayList();
-    }
-
-    private Name getQName(String rawName) throws RepositoryException {
-        try {
-            return resolver.getQName(rawName);
-        } catch (NameException e) {
-            // should never get here...
-            String msg = "internal error: failed to resolve namespace mappings";
-            log.error(msg, e);
-            throw new RepositoryException(msg, e);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void entering(Node node, int level)
-            throws RepositoryException, SAXException {
-        // nop
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void enteringProperties(Node node, int level)
-            throws RepositoryException, SAXException {
-        // reset list of properties
-        props.clear();
-    }
-
-    /**
-     * {@inheritDoc}
-     * <p/>
-     * See also {@link DocViewImportHandler#startElement(String, String, String, org.xml.sax.Attributes)}
-     * regarding special handling of multi-valued properties on import.
-     */
-    protected void leavingProperties(Node node, int level)
-            throws RepositoryException, SAXException {
-        String name = node.getName();
-        if (name.equals(jcrXMLText)) {
-            // the node represents xml character data
-            Iterator iter = props.iterator();
-            while (iter.hasNext()) {
-                Property prop = (Property) iter.next();
-                String propName = prop.getName();
-                if (propName.equals(jcrXMLCharacters)) {
-                    // assume jcr:xmlcharacters is single-valued
-                    char[] chars = prop.getValue().getString().toCharArray();
-                    contentHandler.characters(chars, 0, chars.length);
-                }
-            }
-        } else {
-            // regular node
-
-            // element name
-            String elemName;
-            if (node.getDepth() == 0) {
-                // root node needs a name
-                elemName = jcrRoot;
-            } else {
-                // encode node name to make sure it's a valid xml name
-                elemName = ISO9075.encode(name);
-            }
-
-            // attributes (properties)
-            AttributesImpl attrs = new AttributesImpl();
-            addNamespacePrefixes(level, attrs);
-            Iterator iter = props.iterator();
-            while (iter.hasNext()) {
-                Property prop = (Property) iter.next();
-                String propName = prop.getName();
-
-                if (prop.getDefinition().isMultiple()) {
-                    // todo proper multi-value serialization support
-                    // skip multi-valued properties for the time being
-                    // until a way of properly handling/detecting multi-valued
-                    // properties on re-import is found (see JCR-325);
-                    // see also DocViewImportHandler#startElement()
-
-                    // skipping multi-valued properties entirely is legal
-                    // according to "6.4.2.5 Multi-value Properties" of the
-                    // jsr-170 specification
-                    continue;
-                }
-
-                // attribute name (encode property name to make sure it's a valid xml name)
-                String attrName = ISO9075.encode(propName);
-                Name qName = getQName(attrName);
-
-                // attribute value
-                if (prop.getType() == PropertyType.BINARY && skipBinary) {
-                    // add empty attribute
-                    attrs.addAttribute(qName.getNamespaceURI(),
-                            qName.getLocalName(), attrName, CDATA_TYPE, "");
-                } else {
-                    StringBuffer attrValue = new StringBuffer();
-                    // serialize single-valued property
-                    attrValue.append(ValueHelper.serialize(prop.getValue(), false));
-                    attrs.addAttribute(qName.getNamespaceURI(),
-                            qName.getLocalName(), attrName, CDATA_TYPE,
-                            attrValue.toString());
-                }
-            }
-
-            // start element (node)
-            Name qName = getQName(elemName);
-            contentHandler.startElement(qName.getNamespaceURI(),
-                    qName.getLocalName(), elemName, attrs);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void leaving(Node node, int level)
-            throws RepositoryException, SAXException {
-        String name = node.getName();
-        if (name.equals(jcrXMLText)) {
-            // the node represents xml character data
-            // (already processed in leavingProperties(NodeImpl, int)
-            return;
-        }
-        // element name
-        String elemName;
-        if (node.getDepth() == 0) {
-            // root node needs a name
-            elemName = jcrRoot;
-        } else {
-            // encode node name to make sure it's a valid xml name
-            elemName = ISO9075.encode(name);
-        }
-
-        // end element (node)
-        Name qName = getQName(elemName);
-        contentHandler.endElement(qName.getNamespaceURI(), qName.getLocalName(),
-                elemName);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void entering(Property prop, int level)
-            throws RepositoryException, SAXException {
-        props.add(prop);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void leaving(Property prop, int level)
-            throws RepositoryException, SAXException {
-        // nop
-    }
-}
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/PropertyWrapper.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/PropertyWrapper.java	(revision 654751)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/PropertyWrapper.java	(working copy)
@@ -1,271 +0,0 @@
-/*
- * 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.jackrabbit.core.xml;
-
-import java.io.InputStream;
-import java.util.Calendar;
-
-import javax.jcr.AccessDeniedException;
-import javax.jcr.InvalidItemStateException;
-import javax.jcr.Item;
-import javax.jcr.ItemExistsException;
-import javax.jcr.ItemNotFoundException;
-import javax.jcr.ItemVisitor;
-import javax.jcr.Node;
-import javax.jcr.Property;
-import javax.jcr.ReferentialIntegrityException;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.Value;
-import javax.jcr.ValueFormatException;
-import javax.jcr.lock.LockException;
-import javax.jcr.nodetype.ConstraintViolationException;
-import javax.jcr.nodetype.NoSuchNodeTypeException;
-import javax.jcr.nodetype.PropertyDefinition;
-import javax.jcr.version.VersionException;
-
-/**
- * Provides a wrapper to an existing <code>Property</code> implementation.
- * Methods default to calling through to the wrapped property object.
- */
-class PropertyWrapper implements Property {
-
-    /** Wrapped property */
-    private final Property property;
-
-    /**
-     * Constructs a property adaptor wrapping the given property.
-     *
-     * @param property property to wrap
-     */
-    public PropertyWrapper(Property property) {
-        this.property = property;
-    }
-
-    /** {@inheritDoc} */
-    public boolean getBoolean() throws ValueFormatException,
-            RepositoryException {
-        return property.getBoolean();
-    }
-
-    /** {@inheritDoc} */
-    public Calendar getDate() throws ValueFormatException, RepositoryException {
-        return property.getDate();
-    }
-
-    /** {@inheritDoc} */
-    public PropertyDefinition getDefinition() throws RepositoryException {
-        return property.getDefinition();
-    }
-
-    /** {@inheritDoc} */
-    public double getDouble() throws ValueFormatException, RepositoryException {
-        return property.getDouble();
-    }
-
-    /** {@inheritDoc} */
-    public long getLength() throws ValueFormatException, RepositoryException {
-        return property.getLength();
-    }
-
-    /** {@inheritDoc} */
-    public long[] getLengths() throws ValueFormatException, RepositoryException {
-        return property.getLengths();
-    }
-
-    /** {@inheritDoc} */
-    public long getLong() throws ValueFormatException, RepositoryException {
-        return property.getLong();
-    }
-
-    /** {@inheritDoc} */
-    public Node getNode() throws ValueFormatException, RepositoryException {
-        return property.getNode();
-    }
-
-    /** {@inheritDoc} */
-    public InputStream getStream() throws ValueFormatException,
-            RepositoryException {
-        return property.getStream();
-    }
-
-    /** {@inheritDoc} */
-    public String getString() throws ValueFormatException, RepositoryException {
-        return property.getString();
-    }
-
-    /** {@inheritDoc} */
-    public int getType() throws RepositoryException {
-        return property.getType();
-    }
-
-    /** {@inheritDoc} */
-    public Value getValue() throws ValueFormatException, RepositoryException {
-        return property.getValue();
-    }
-
-    /** {@inheritDoc} */
-    public Value[] getValues() throws ValueFormatException, RepositoryException {
-        return property.getValues();
-    }
-
-    /** {@inheritDoc} */
-    public void setValue(Value value) throws ValueFormatException,
-            VersionException, LockException, ConstraintViolationException,
-            RepositoryException {
-        property.setValue(value);
-    }
-
-    /** {@inheritDoc} */
-    public void setValue(Value[] values) throws ValueFormatException,
-            VersionException, LockException, ConstraintViolationException,
-            RepositoryException {
-        property.setValue(values);
-    }
-
-    /** {@inheritDoc} */
-    public void setValue(String value) throws ValueFormatException,
-            VersionException, LockException, ConstraintViolationException,
-            RepositoryException {
-        property.setValue(value);
-    }
-
-    /** {@inheritDoc} */
-    public void setValue(String[] values) throws ValueFormatException,
-            VersionException, LockException, ConstraintViolationException,
-            RepositoryException {
-        property.setValue(values);
-    }
-
-    /** {@inheritDoc} */
-    public void setValue(InputStream value) throws ValueFormatException,
-            VersionException, LockException, ConstraintViolationException,
-            RepositoryException {
-        property.setValue(value);
-    }
-
-    /** {@inheritDoc} */
-    public void setValue(long value) throws ValueFormatException,
-            VersionException, LockException, ConstraintViolationException,
-            RepositoryException {
-        property.setValue(value);
-    }
-
-    /** {@inheritDoc} */
-    public void setValue(double value) throws ValueFormatException,
-            VersionException, LockException, ConstraintViolationException,
-            RepositoryException {
-        property.setValue(value);
-    }
-
-    /** {@inheritDoc} */
-    public void setValue(Calendar value) throws ValueFormatException,
-            VersionException, LockException, ConstraintViolationException,
-            RepositoryException {
-        property.setValue(value);
-    }
-
-    /** {@inheritDoc} */
-    public void setValue(boolean value) throws ValueFormatException,
-            VersionException, LockException, ConstraintViolationException,
-            RepositoryException {
-        property.setValue(value);
-    }
-
-    /** {@inheritDoc} */
-    public void setValue(Node value) throws ValueFormatException,
-            VersionException, LockException, ConstraintViolationException,
-            RepositoryException {
-        property.setValue(value);
-    }
-
-    /** {@inheritDoc} */
-    public void accept(ItemVisitor visitor) throws RepositoryException {
-        property.accept(visitor);
-    }
-
-    /** {@inheritDoc} */
-    public Item getAncestor(int depth) throws ItemNotFoundException,
-            AccessDeniedException, RepositoryException {
-        return property.getAncestor(depth);
-    }
-
-    /** {@inheritDoc} */
-    public int getDepth() throws RepositoryException {
-        return property.getDepth();
-    }
-
-    /** {@inheritDoc} */
-    public String getName() throws RepositoryException {
-        return property.getName();
-    }
-
-    /** {@inheritDoc} */
-    public Node getParent() throws ItemNotFoundException,
-            AccessDeniedException, RepositoryException {
-        return property.getParent();
-    }
-
-    /** {@inheritDoc} */
-    public String getPath() throws RepositoryException {
-        return property.getPath();
-    }
-
-    /** {@inheritDoc} */
-    public Session getSession() throws RepositoryException {
-        return property.getSession();
-    }
-
-    /** {@inheritDoc} */
-    public boolean isModified() {
-        return property.isModified();
-    }
-
-    /** {@inheritDoc} */
-    public boolean isNew() {
-        return property.isNew();
-    }
-
-    public boolean isNode() {
-        return property.isNode();
-    }
-
-    /** {@inheritDoc} */
-    public boolean isSame(Item otherItem) throws RepositoryException {
-        return property.isSame(otherItem);
-    }
-
-    /** {@inheritDoc} */
-    public void refresh(boolean keepChanges) throws InvalidItemStateException,
-            RepositoryException {
-        refresh(keepChanges);
-    }
-
-    /** {@inheritDoc} */
-    public void remove() throws VersionException, LockException,
-            ConstraintViolationException, RepositoryException {
-        property.remove();
-    }
-
-    /** {@inheritDoc} */
-    public void save() throws AccessDeniedException, ItemExistsException,
-            ConstraintViolationException, InvalidItemStateException,
-            ReferentialIntegrityException, VersionException, LockException,
-            NoSuchNodeTypeException, RepositoryException {
-        property.save();
-    }
-}
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/AbstractSAXEventGenerator.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/AbstractSAXEventGenerator.java	(revision 654751)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/AbstractSAXEventGenerator.java	(working copy)
@@ -1,519 +0,0 @@
-/*
- * 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.jackrabbit.core.xml;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
-import org.apache.jackrabbit.spi.commons.conversion.DefaultNamePathResolver;
-import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.spi.commons.namespace.SessionNamespaceResolver;
-import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
-import org.apache.jackrabbit.spi.commons.name.NameConstants;
-import org.apache.jackrabbit.value.StringValue;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.AttributesImpl;
-
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.Property;
-import javax.jcr.PropertyIterator;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.NamespaceException;
-import javax.jcr.Value;
-import javax.jcr.ValueFormatException;
-
-/**
- * <code>AbstractSAXEventGenerator</code> serves as the base class for
- * <code>SysViewSAXEventGenerator</code> and <code>DocViewSAXEventGenerator</code>
- * <p/>
- * It traverses a tree of <code>Node</code> & <code>Property</code>
- * instances, and calls the abstract methods
- * <ul>
- * <li><code>{@link #entering(Node, int)}</code></li>
- * <li><code>{@link #enteringProperties(Node, int)}</code></li>
- * <li><code>{@link #leavingProperties(Node, int)}</code></li>
- * <li><code>{@link #leaving(Node, int)}</code></li>
- * <li><code>{@link #entering(Property, int)}</code></li>
- * <li><code>{@link #leaving(Property, int)}</code></li>
- * </ul>
- * for every item it encounters.
- */
-abstract class AbstractSAXEventGenerator {
-
-    private static Logger log = LoggerFactory.getLogger(AbstractSAXEventGenerator.class);
-
-    /**
-     * the session to be used for resolving namespace mappings
-     */
-    protected final Session session;
-    /**
-     * the session's namespace resolver
-     */
-    protected final NamespaceResolver nsResolver;
-
-    protected final NamePathResolver resolver;
-
-    /**
-     * the content handler to feed the SAX events to
-     */
-    protected final ContentHandler contentHandler;
-
-    protected final Node startNode;
-    protected final boolean skipBinary;
-    protected final boolean noRecurse;
-
-    /**
-     * the set of namespace declarations that have already been serialized
-     */
-    protected NamespaceStack namespaces;
-
-    /**
-     * The jcr:primaryType property name (allowed for session-local prefix mappings)
-     */
-    protected final String jcrPrimaryType;
-    /**
-     * The jcr:mixinTypes property name (allowed for session-local prefix mappings)
-     */
-    protected final String jcrMixinTypes;
-    /**
-     * The jcr:uuid property name (allowed for session-local prefix mappings)
-     */
-    protected final String jcrUUID;
-    /**
-     * The jcr:root node name (allowed for session-local prefix mappings)
-     */
-    protected final String jcrRoot;
-    /**
-     * The jcr:xmltext node name (allowed for session-local prefix mappings)
-     */
-    protected final String jcrXMLText;
-    /**
-     * The jcr:xmlCharacters property name (allowed for session-local prefix mappings)
-     */
-    protected final String jcrXMLCharacters;
-
-    /**
-     * The mix:shareable node type.
-     */
-    private final String mixShareable;
-
-    /**
-     * The nt:share node type.
-     */
-    private final String ntShare;
-
-    /**
-     * Shareable nodes serialized so far (set of UUIDs).
-     */
-    private Set shareableNodeIds;
-
-    /**
-     * Constructor
-     *
-     * @param node           the node state which should be serialized
-     * @param noRecurse      if true, only <code>node</code> and its properties will
-     *                       be serialized; otherwise the entire hierarchy starting with
-     *                       <code>node</code> will be serialized.
-     * @param skipBinary     flag governing whether binary properties are to be serialized.
-     * @param contentHandler the content handler to feed the SAX events to
-     * @throws RepositoryException if an error occurs
-     */
-    protected AbstractSAXEventGenerator(Node node, boolean noRecurse,
-                                        boolean skipBinary,
-                                        ContentHandler contentHandler)
-            throws RepositoryException {
-        startNode = node;
-        session = node.getSession();
-        nsResolver = new SessionNamespaceResolver(session);
-
-        this.contentHandler = contentHandler;
-        this.skipBinary = skipBinary;
-        this.noRecurse = noRecurse;
-        // start with an empty set of known prefixes
-        this.namespaces = new NamespaceStack(null);
-
-        resolver = new DefaultNamePathResolver(nsResolver);
-
-        // resolve the names of some wellknown properties
-        // allowing for session-local prefix mappings
-        try {
-            jcrPrimaryType = resolver.getJCRName(NameConstants.JCR_PRIMARYTYPE);
-            jcrMixinTypes = resolver.getJCRName(NameConstants.JCR_MIXINTYPES);
-            jcrUUID = resolver.getJCRName(NameConstants.JCR_UUID);
-            jcrRoot = resolver.getJCRName(NameConstants.JCR_ROOT);
-            jcrXMLText = resolver.getJCRName(NameConstants.JCR_XMLTEXT);
-            jcrXMLCharacters = resolver.getJCRName(NameConstants.JCR_XMLCHARACTERS);
-            mixShareable = resolver.getJCRName(NameConstants.MIX_SHAREABLE);
-            ntShare = resolver.getJCRName(NameConstants.NT_SHARE);
-        } catch (NamespaceException e) {
-            // should never get here...
-            String msg = "internal error: failed to resolve namespace mappings";
-            log.error(msg, e);
-            throw new RepositoryException(msg, e);
-        }
-    }
-
-    /**
-     * Serializes the hierarchy of nodes and properties.
-     *
-     * @throws RepositoryException if an error occurs while traversing the hierarchy
-     * @throws SAXException        if an error occured while feeding the events
-     *                             to the content handler
-     */
-    public void serialize() throws RepositoryException, SAXException {
-        // start document and declare namespaces
-        contentHandler.startDocument();
-        startNamespaceDeclarations();
-
-        // serialize node and subtree
-        process(startNode, 0);
-
-        // clear namespace declarations and end document
-        endNamespaceDeclarations();
-        contentHandler.endDocument();
-    }
-
-    /**
-     * @throws RepositoryException
-     * @throws SAXException
-     */
-    protected void startNamespaceDeclarations()
-            throws RepositoryException, SAXException {
-        // start namespace declarations
-        String[] prefixes = session.getNamespacePrefixes();
-        for (int i = 0; i < prefixes.length; i++) {
-            String prefix = prefixes[i];
-            if (Name.NS_XML_PREFIX.equals(prefix)) {
-                // skip 'xml' prefix as this would be an illegal namespace declaration
-                continue;
-            }
-            String uri = session.getNamespaceURI(prefix);
-            contentHandler.startPrefixMapping(prefix, uri);
-        }
-    }
-
-    /**
-     * @throws RepositoryException
-     * @throws SAXException
-     */
-    protected void endNamespaceDeclarations()
-            throws RepositoryException, SAXException {
-        // end namespace declarations
-        String[] prefixes = session.getNamespacePrefixes();
-        for (int i = 0; i < prefixes.length; i++) {
-            String prefix = prefixes[i];
-            if (Name.NS_XML_PREFIX.equals(prefix)) {
-                // skip 'xml' prefix as this would be an illegal namespace declaration
-                continue;
-            }
-            contentHandler.endPrefixMapping(prefix);
-        }
-    }
-
-    /**
-     * Adds explicit <code>xmlns:prefix="uri"</code> attributes to the
-     * XML element as required (e.g., normally just on the root
-     * element). The effect is the same as setting the
-     * "<code>http://xml.org/sax/features/namespace-prefixes</code>"
-     * property on an SAX parser.
-     *
-     * @param level level of the current XML element
-     * @param attributes attributes of the current XML element
-     * @throws RepositoryException on a repository error
-     */
-    protected void addNamespacePrefixes(int level, AttributesImpl attributes)
-            throws RepositoryException {
-        String[] prefixes = session.getNamespacePrefixes();
-        NamespaceStack newNamespaces = null;
-
-        for (int i = 0; i < prefixes.length; i++) {
-            String prefix = prefixes[i];
-
-            if (prefix.length() > 0
-                    && !Name.NS_XML_PREFIX.equals(prefix)) {
-                String uri = session.getNamespaceURI(prefix);
-
-                // get the matching namespace from previous declarations
-                String mappedToNs = this.namespaces.getNamespaceURI(prefix);
-
-                if (!uri.equals(mappedToNs)) {
-                    // when not the same, add a declaration
-                    attributes.addAttribute(
-                        Name.NS_XMLNS_URI,
-                        prefix,
-                        Name.NS_XMLNS_PREFIX + ":" + prefix,
-                        "CDATA",
-                        uri);
-
-                    if (newNamespaces == null) {
-                        // replace current namespace stack when needed
-                        newNamespaces = new NamespaceStack(this.namespaces);
-                        this.namespaces = newNamespaces;
-                    }
-
-                    // remember the new declaration
-                    newNamespaces.setNamespacePrefix(prefix, uri);
-                }
-            }
-        }
-    }
-
-    /**
-     * @param node
-     * @param level
-     * @throws RepositoryException
-     * @throws SAXException
-     */
-    protected void process(Node node, int level)
-            throws RepositoryException, SAXException {
-
-        // enter node
-        entering(node, level);
-
-        // enter properties
-        enteringProperties(node, level);
-
-        // Collect all properties (and sort them, see JCR-1084)
-        SortedMap properties = collectProperties(node);
-
-        // serialize jcr:primaryType, jcr:mixinTypes & jcr:uuid first:
-        if (properties.containsKey(jcrPrimaryType)) {
-            process((Property) properties.remove(jcrPrimaryType), level + 1);
-        } else {
-            throw new RepositoryException(
-                    "Missing jcr:primaryType property: " + node.getPath());
-        }
-        if (properties.containsKey(jcrMixinTypes)) {
-            process((Property) properties.remove(jcrMixinTypes), level + 1);
-        }
-        if (properties.containsKey(jcrUUID)) {
-            process((Property) properties.remove(jcrUUID), level + 1);
-        }
-
-        // serialize remaining properties
-        Iterator iterator = properties.values().iterator();
-        while (iterator.hasNext()) {
-            process((Property) iterator.next(), level + 1);
-        }
-
-        // leaving properties
-        leavingProperties(node, level);
-
-        if (!noRecurse) {
-            // child nodes
-            NodeIterator nodeIter = node.getNodes();
-            while (nodeIter.hasNext()) {
-                // recurse
-                Node childNode = nodeIter.nextNode();
-                // remember the current namespace declarations
-                NamespaceStack previousNamespaces = this.namespaces;
-
-                process(childNode, level + 1);
-
-                // restore the effective namespace declarations
-                // (from before visiting the child node)
-                this.namespaces = previousNamespaces;
-            }
-        }
-
-        // leaving node
-        leaving(node, level);
-    }
-
-    /**
-     * Collect all properties of a node and return them as sorted map. Returns
-     * a smaller set if the node is shareable and has already been serialized.
-     *
-     * @param node node
-     * @return properties as sorted map
-     */
-    protected SortedMap collectProperties(Node node) throws RepositoryException {
-        SortedMap properties = new TreeMap();
-
-        // if node is shareable and has already been serialized, change its
-        // type to nt:share and process only the properties jcr:primaryType
-        // and jcr:uuid
-        if (node.isNodeType(mixShareable)) {
-            if (shareableNodeIds == null) {
-                shareableNodeIds = new HashSet();
-            }
-            if (!shareableNodeIds.add(node.getUUID())) {
-                if (node.hasProperty(jcrPrimaryType)) {
-                    Property property = node.getProperty(jcrPrimaryType);
-                    property = new PropertyWrapper(property) {
-                        public Value getValue() throws ValueFormatException,
-                                RepositoryException {
-                            return new StringValue(ntShare);
-                        }
-                    };
-                    properties.put(property.getName(), property);
-                } else {
-                    throw new RepositoryException(
-                            "Missing jcr:primaryType property: " + node.getPath());
-                }
-                if (node.hasProperty(jcrUUID)) {
-                    Property property = node.getProperty(jcrUUID);
-                    properties.put(property.getName(), property);
-                }
-                return properties;
-            }
-        }
-
-        // standard behaviour: return all properties
-        PropertyIterator propIter = node.getProperties();
-        while (propIter.hasNext()) {
-            Property property = propIter.nextProperty();
-            properties.put(property.getName(), property);
-        }
-        return properties;
-    }
-
-    /**
-     * @param prop
-     * @param level
-     * @throws RepositoryException
-     * @throws SAXException
-     */
-    protected void process(Property prop, int level)
-            throws RepositoryException, SAXException {
-        // serialize property
-        entering(prop, level);
-        leaving(prop, level);
-    }
-
-    /**
-     * @param node
-     * @param level
-     * @throws RepositoryException
-     * @throws SAXException
-     */
-    protected abstract void entering(Node node, int level)
-            throws RepositoryException, SAXException;
-
-    /**
-     * @param node
-     * @param level
-     * @throws RepositoryException
-     * @throws SAXException
-     */
-    protected abstract void enteringProperties(Node node, int level)
-            throws RepositoryException, SAXException;
-
-    /**
-     * @param node
-     * @param level
-     * @throws RepositoryException
-     * @throws SAXException
-     */
-    protected abstract void leavingProperties(Node node, int level)
-            throws RepositoryException, SAXException;
-
-    /**
-     * @param node
-     * @param level
-     * @throws RepositoryException
-     * @throws SAXException
-     */
-    protected abstract void leaving(Node node, int level)
-            throws RepositoryException, SAXException;
-
-    /**
-     * @param prop
-     * @param level
-     * @throws RepositoryException
-     * @throws SAXException
-     */
-    protected abstract void entering(Property prop, int level)
-            throws RepositoryException, SAXException;
-
-    /**
-     * @param prop
-     * @param level
-     * @throws RepositoryException
-     * @throws SAXException
-     */
-    protected abstract void leaving(Property prop, int level)
-            throws RepositoryException, SAXException;
-
-    /**
-     * Implements a simple stack of namespace declarations.
-     */
-    private static class NamespaceStack {
-
-        /**
-         * Parent stack (may be <code>null</code>)
-         */
-        private final NamespaceStack parent;
-
-        /**
-         * Local namespace declarations.
-         */
-        private final Map namespaces;
-
-        /**
-         * Instantiate a new stack
-         *
-         * @param parent parent stack (may be <code>null</code> for the initial stack)
-         */
-        public NamespaceStack(NamespaceStack parent) {
-            this.parent = parent;
-            this.namespaces = new HashMap();
-        }
-
-        /**
-         * Obtain namespace URI for a prefix
-         *
-         * @param prefix prefix
-         * @return namespace URI (or <code>null</code> when unknown)
-         */
-        public String getNamespaceURI(String prefix) {
-            String namespace = (String) namespaces.get(prefix);
-            if (namespace != null) {
-                // found in this element, return right away
-                return namespace;
-            } else if (parent != null) {
-                // ask parent, when present
-                return parent.getNamespaceURI(prefix);
-            } else {
-                return null;
-            }
-        }
-
-        /**
-         * Add a new prefix mapping
-         *
-         * @param prefix namespace prefix
-         * @param uri namespace URI
-         */
-        public void setNamespacePrefix(String prefix, String uri) {
-            namespaces.put(prefix, uri);
-        }
-
-    }
-
-}
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SysViewSAXEventGenerator.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SysViewSAXEventGenerator.java	(revision 654751)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SysViewSAXEventGenerator.java	(working copy)
@@ -1,304 +0,0 @@
-/*
- * 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.jackrabbit.core.xml;
-
-import org.apache.jackrabbit.spi.commons.conversion.NameResolver;
-import org.apache.jackrabbit.spi.commons.conversion.ParsingNameResolver;
-import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.value.ValueHelper;
-import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
-import org.apache.jackrabbit.spi.commons.name.NameConstants;
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.AttributesImpl;
-
-import javax.jcr.NamespaceException;
-import javax.jcr.Node;
-import javax.jcr.Property;
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.Value;
-import java.io.IOException;
-import java.io.Writer;
-
-/**
- * A <code>SysViewSAXEventGenerator</code> instance can be used to generate SAX events
- * representing the serialized form of an item in System View XML.
- */
-public class SysViewSAXEventGenerator extends AbstractSAXEventGenerator {
-
-    public static final String CDATA_TYPE = "CDATA";
-    public static final String ENUMERATION_TYPE = "ENUMERATION";
-
-    private static final String NS_XMLSCHEMA_INSTANCE_URI = "http://www.w3.org/2001/XMLSchema-instance";
-    private static final String NS_XMLSCHEMA_INSTANCE_PREFIX = "xsi";
-    private static final String NS_XMLSCHEMA_URI = "http://www.w3.org/2001/XMLSchema";
-    private static final String NS_XMLSCHEMA_PREFIX = "xs";
-
-    private static final Attributes ATTRS_EMPTY = new AttributesImpl();
-    private static final Attributes ATTRS_BINARY_ENCODED_VALUE;
-    static {
-        AttributesImpl attrs = new AttributesImpl();
-        attrs.addAttribute(
-                Name.NS_XMLNS_URI, NS_XMLSCHEMA_INSTANCE_PREFIX,
-                "xmlns:" + NS_XMLSCHEMA_INSTANCE_PREFIX,
-                CDATA_TYPE, NS_XMLSCHEMA_INSTANCE_URI);
-        attrs.addAttribute(
-                Name.NS_XMLNS_URI, NS_XMLSCHEMA_PREFIX,
-                "xmlns:" + NS_XMLSCHEMA_PREFIX,
-                CDATA_TYPE, NS_XMLSCHEMA_URI);
-        attrs.addAttribute(
-                NS_XMLSCHEMA_INSTANCE_URI, "type",
-                NS_XMLSCHEMA_INSTANCE_PREFIX + ":type",
-                CDATA_TYPE, NS_XMLSCHEMA_PREFIX + ":base64Binary");
-        ATTRS_BINARY_ENCODED_VALUE = attrs;
-    }
-
-    /**
-     * Name resolver for producing qualified XML names.
-     */
-    private final NameResolver resolver;
-
-    /**
-     * Constructor
-     *
-     * @param node           the node state which should be serialized
-     * @param noRecurse      if true, only <code>node</code> and its properties will
-     *                       be serialized; otherwise the entire hierarchy starting with
-     *                       <code>node</code> will be serialized.
-     * @param skipBinary     flag governing whether binary properties are to be serialized.
-     * @param contentHandler the content handler to feed the SAX events to
-     * @throws RepositoryException if an error occurs
-     */
-    public SysViewSAXEventGenerator(Node node, boolean noRecurse,
-                                    boolean skipBinary,
-                                    ContentHandler contentHandler)
-            throws RepositoryException {
-        super(node, noRecurse, skipBinary, contentHandler);
-        resolver = new ParsingNameResolver(NameFactoryImpl.getInstance(), nsResolver);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void entering(Node node, int level)
-            throws RepositoryException, SAXException {
-        AttributesImpl attrs = new AttributesImpl();
-        addNamespacePrefixes(level, attrs);
-        // name attribute
-        String nodeName;
-        if (node.getDepth() == 0) {
-            // root node needs a name
-            nodeName = jcrRoot;
-        } else {
-            // encode node name to make sure it's a valid xml name
-            nodeName = node.getName();
-        }
-
-        addAttribute(attrs, NameConstants.SV_NAME, CDATA_TYPE, nodeName);
-        // start node element
-        startElement(NameConstants.SV_NODE, attrs);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void enteringProperties(Node node, int level)
-            throws RepositoryException, SAXException {
-        // nop
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void leavingProperties(Node node, int level)
-            throws RepositoryException, SAXException {
-        // nop
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void leaving(Node node, int level)
-            throws RepositoryException, SAXException {
-        // end node element
-        endElement(NameConstants.SV_NODE);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void entering(Property prop, int level)
-            throws RepositoryException, SAXException {
-        AttributesImpl attrs = new AttributesImpl();
-        // name attribute
-        addAttribute(attrs, NameConstants.SV_NAME, CDATA_TYPE, prop.getName());
-        // type attribute
-        try {
-            String typeName = PropertyType.nameFromValue(prop.getType());
-            addAttribute(attrs, NameConstants.SV_TYPE, ENUMERATION_TYPE, typeName);
-        } catch (IllegalArgumentException e) {
-            // should never be getting here
-            throw new RepositoryException(
-                    "unexpected property-type ordinal: " + prop.getType(), e);
-        }
-
-        // start property element
-        startElement(NameConstants.SV_PROPERTY, attrs);
-
-        // values
-        if (prop.getType() == PropertyType.BINARY && skipBinary) {
-            // empty value element
-            startElement(NameConstants.SV_VALUE, new AttributesImpl());
-            endElement(NameConstants.SV_VALUE);
-        } else {
-            boolean multiValued = prop.getDefinition().isMultiple();
-            Value[] vals;
-            if (multiValued) {
-                vals = prop.getValues();
-            } else {
-                vals = new Value[]{prop.getValue()};
-            }
-            for (int i = 0; i < vals.length; i++) {
-                Value val = vals[i];
-
-                Attributes attributes = ATTRS_EMPTY;
-                boolean mustSendBinary = false;
-
-                if (val.getType() != PropertyType.BINARY) {
-                    String ser = val.getString();
-                    for (int ci = 0; ci < ser.length() && !mustSendBinary; ci++) {
-                        char c = ser.charAt(ci);
-                        if (c >= 0 && c < 32 && c != '\r' && c != '\n' && c != '\t') {
-                            mustSendBinary = true;
-                        }
-                    }
-
-                    if (mustSendBinary) {
-                        contentHandler.startPrefixMapping(NS_XMLSCHEMA_INSTANCE_PREFIX, NS_XMLSCHEMA_INSTANCE_URI);
-                        contentHandler.startPrefixMapping(NS_XMLSCHEMA_PREFIX, NS_XMLSCHEMA_URI);
-                        attributes = ATTRS_BINARY_ENCODED_VALUE;
-                    }
-                }
-
-                // start value element
-                startElement(NameConstants.SV_VALUE, attributes);
-
-                // characters
-                Writer writer = new Writer() {
-                    public void close() /*throws IOException*/ {
-                    }
-
-                    public void flush() /*throws IOException*/ {
-                    }
-
-                    public void write(char[] cbuf, int off, int len) throws IOException {
-                        try {
-                            contentHandler.characters(cbuf, off, len);
-                        } catch (SAXException se) {
-                            IOException ioe = new IOException(se.toString());
-                            ioe.initCause(se);
-                            throw ioe;
-                        }
-                    }
-                };
-                try {
-                    ValueHelper.serialize(val, false, mustSendBinary, writer);
-                    // no need to close our Writer implementation
-                    //writer.close();
-                } catch (IOException ioe) {
-                    // check if the exception wraps a SAXException
-                    // (see Writer.write(char[], int, int) above)
-                    Throwable t = ioe.getCause();
-                    if (t != null && t instanceof SAXException) {
-                        throw (SAXException) t;
-                    } else {
-                        throw new SAXException(ioe);
-                    }
-                }
-
-                // end value element
-                endElement(NameConstants.SV_VALUE);
-
-                if (mustSendBinary) {
-                    contentHandler.endPrefixMapping(NS_XMLSCHEMA_INSTANCE_PREFIX);
-                    contentHandler.endPrefixMapping(NS_XMLSCHEMA_PREFIX);
-                }
-            }
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void leaving(Property prop, int level)
-            throws RepositoryException, SAXException {
-        endElement(NameConstants.SV_PROPERTY);
-    }
-
-    //-------------------------------------------------------------< private >
-
-    /**
-     * Adds an attribute to the given XML attribute set. The local part of
-     * the given {@link Name} is assumed to be a valid XML NCName, i.e. it
-     * won't be encoded.
-     *
-     * @param attributes the XML attribute set
-     * @param name name of the attribute
-     * @param type XML type of the attribute
-     * @param value value of the attribute
-     * @throws NamespaceException if the namespace of the attribute is not found
-     */
-    private void addAttribute(
-            AttributesImpl attributes, Name name, String type, String value)
-            throws NamespaceException {
-        attributes.addAttribute(
-                name.getNamespaceURI(), name.getLocalName(),
-                resolver.getJCRName(name), type, value);
-    }
-
-    /**
-     * Starts an XML element. The local part of the given {@link Name} is
-     * assumed to be a valid XML NCName, i.e. it won't be encoded.
-     *
-     * @param name name of the element
-     * @param attributes XML attributes
-     * @throws NamespaceException if the namespace of the element is not found
-     */
-    private void startElement(Name name, Attributes attributes)
-            throws NamespaceException, SAXException {
-        contentHandler.startElement(
-                name.getNamespaceURI(), name.getLocalName(),
-                resolver.getJCRName(name), attributes);
-    }
-
-    /**
-     * Ends an XML element. The local part of the given {@link Name} is
-     * assumed to be a valid XML NCName, i.e. it won't be encoded.
-     *
-     * @param name name of the element
-     * @throws NamespaceException if the namespace of the element is not found
-     */
-    private void endElement(Name name)
-            throws NamespaceException, SAXException {
-        contentHandler.endElement(
-                name.getNamespaceURI(), name.getLocalName(),
-                resolver.getJCRName(name));
-    }
-
-}
Index: jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java
===================================================================
--- jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java	(revision 654751)
+++ jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java	(working copy)
@@ -16,6 +16,7 @@
  */
 package org.apache.jackrabbit.jcr2spi;
 
+import org.apache.jackrabbit.commons.AbstractSession;
 import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyManager;
 import org.apache.jackrabbit.jcr2spi.hierarchy.NodeEntry;
 import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyEntry;
@@ -29,8 +30,6 @@
 import org.apache.jackrabbit.jcr2spi.state.ItemState;
 import org.apache.jackrabbit.jcr2spi.state.NodeState;
 import org.apache.jackrabbit.jcr2spi.state.ItemStateFactory;
-import org.apache.jackrabbit.jcr2spi.xml.DocViewSAXEventGenerator;
-import org.apache.jackrabbit.jcr2spi.xml.SysViewSAXEventGenerator;
 import org.apache.jackrabbit.jcr2spi.xml.ImportHandler;
 import org.apache.jackrabbit.jcr2spi.xml.SessionImporter;
 import org.apache.jackrabbit.jcr2spi.xml.Importer;
@@ -86,25 +85,19 @@
 import javax.jcr.nodetype.ConstraintViolationException;
 import javax.jcr.version.VersionException;
 import javax.jcr.version.Version;
-import javax.xml.transform.sax.SAXTransformerFactory;
-import javax.xml.transform.sax.TransformerHandler;
-import javax.xml.transform.stream.StreamResult;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.TransformerException;
 import javax.xml.parsers.SAXParserFactory;
 import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.ParserConfigurationException;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
 import java.security.AccessControlException;
 import java.util.Map;
 
 /**
  * <code>SessionImpl</code>...
  */
-public class SessionImpl implements Session, ManagerProvider {
+public class SessionImpl extends AbstractSession implements ManagerProvider {
 
     private static Logger log = LoggerFactory.getLogger(SessionImpl.class);
 
@@ -424,72 +417,6 @@
     }
 
     /**
-     * @see javax.jcr.Session#exportSystemView(String, org.xml.sax.ContentHandler, boolean, boolean)
-     */
-    public void exportSystemView(String absPath, ContentHandler contentHandler, boolean skipBinary, boolean noRecurse) throws PathNotFoundException, SAXException, RepositoryException {
-        checkIsAlive();
-        Item item = getItem(absPath);
-        if (!item.isNode()) {
-            // a property instead of a node exists at the specified path
-            throw new PathNotFoundException(absPath);
-        }
-        new SysViewSAXEventGenerator((Node)item, noRecurse, skipBinary, contentHandler).serialize();
-    }
-
-    /**
-     * @see javax.jcr.Session#exportSystemView(String, OutputStream, boolean, boolean)
-     */
-    public void exportSystemView(String absPath, OutputStream out, boolean skipBinary, boolean noRecurse) throws IOException, PathNotFoundException, RepositoryException {
-        SAXTransformerFactory stf = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
-        try {
-            TransformerHandler th = stf.newTransformerHandler();
-            th.getTransformer().setOutputProperty(OutputKeys.METHOD, "xml");
-            th.getTransformer().setOutputProperty(OutputKeys.ENCODING, "UTF-8");
-            th.getTransformer().setOutputProperty(OutputKeys.INDENT, "no");
-            th.setResult(new StreamResult(out));
-
-            exportSystemView(absPath, th, skipBinary, noRecurse);
-        } catch (TransformerException te) {
-            throw new RepositoryException(te);
-        } catch (SAXException se) {
-            throw new RepositoryException(se);
-        }
-    }
-
-    /**
-     * @see javax.jcr.Session#exportDocumentView(String, org.xml.sax.ContentHandler, boolean, boolean)
-     */
-    public void exportDocumentView(String absPath, ContentHandler contentHandler, boolean skipBinary, boolean noRecurse) throws InvalidSerializedDataException, PathNotFoundException, SAXException, RepositoryException {
-        checkIsAlive();
-        Item item = getItem(absPath);
-        if (!item.isNode()) {
-            // a property instead of a node exists at the specified path
-            throw new PathNotFoundException(absPath);
-        }
-        new DocViewSAXEventGenerator((Node) item, noRecurse, skipBinary, contentHandler).serialize();
-    }
-
-    /**
-     * @see javax.jcr.Session#exportDocumentView(String, OutputStream, boolean, boolean)
-     */
-    public void exportDocumentView(String absPath, OutputStream out, boolean skipBinary, boolean noRecurse) throws InvalidSerializedDataException, IOException, PathNotFoundException, RepositoryException {
-        SAXTransformerFactory stf = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
-        try {
-            TransformerHandler th = stf.newTransformerHandler();
-            th.getTransformer().setOutputProperty(OutputKeys.METHOD, "xml");
-            th.getTransformer().setOutputProperty(OutputKeys.ENCODING, "UTF-8");
-            th.getTransformer().setOutputProperty(OutputKeys.INDENT, "no");
-            th.setResult(new StreamResult(out));
-
-            exportDocumentView(absPath, th, skipBinary, noRecurse);
-        } catch (TransformerException te) {
-            throw new RepositoryException(te);
-        } catch (SAXException se) {
-            throw new RepositoryException(se);
-        }
-    }
-
-    /**
      * @see javax.jcr.Session#setNamespacePrefix(String, String)
      * @see LocalNamespaceMappings#setNamespacePrefix(String, String)
      */
Index: jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/SysViewImportHandler.java
===================================================================
--- jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/SysViewImportHandler.java	(revision 654751)
+++ jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/SysViewImportHandler.java	(working copy)
@@ -37,6 +37,21 @@
  */
 class SysViewImportHandler extends TargetImportHandler {
 
+    /** Local part of <code>sv:node</code>. */
+    private static final String NODE = "node";
+
+    /** Local part of <code>sv:property</code>. */
+    private static final String PROPERTY = "property";
+
+    /** Local part of <code>sv:value</code>. */
+    private static final String VALUE = "value";
+
+    /** Local part of <code>sv:name</code>. */
+    private static final String NAME = "name";
+
+    /** Local part of <code>sv:type</code>. */
+    private static final String TYPE = "type";
+
     /**
      * stack of ImportState instances; an instance is pushed onto the stack
      * in the startElement method every time a sv:node element is encountered;
@@ -109,11 +124,11 @@
                     + namespaceURI));
         }
         // check element name
-        if (SysViewSAXEventGenerator.NODE_ELEMENT.equals(localName)) {
+        if (NODE.equals(localName)) {
             // sv:node element
 
             // node name (value of sv:name attribute)
-            String name = atts.getValue(SysViewSAXEventGenerator.PREFIXED_NAME_ATTRIBUTE);
+            String name = atts.getValue(Name.NS_SV_URI, NAME);
             if (name == null) {
                 throw new SAXException(new InvalidSerializedDataException(
                         "missing mandatory sv:name attribute of element sv:node"));
@@ -139,14 +154,14 @@
                 throw new SAXException(new InvalidSerializedDataException("illegal node name: " + name, e));
             }
             stack.push(state);
-        } else if (SysViewSAXEventGenerator.PROPERTY_ELEMENT.equals(localName)) {
+        } else if (PROPERTY.equals(localName)) {
             // sv:property element
 
             // reset temp fields
             currentPropValues.clear();
 
             // property name (value of sv:name attribute)
-            String name = atts.getValue(SysViewSAXEventGenerator.PREFIXED_NAME_ATTRIBUTE);
+            String name = atts.getValue(Name.NS_SV_URI, NAME);
             if (name == null) {
                 throw new SAXException(new InvalidSerializedDataException(
                         "missing mandatory sv:name attribute of element sv:property"));
@@ -159,13 +174,13 @@
                 throw new SAXException(new InvalidSerializedDataException("illegal property name: " + name, e));
             }
             // property type (sv:type attribute)
-            String type = atts.getValue(SysViewSAXEventGenerator.PREFIXED_TYPE_ATTRIBUTE);
+            String type = atts.getValue(Name.NS_SV_URI, TYPE);
             if (type == null) {
                 throw new SAXException(new InvalidSerializedDataException(
                         "missing mandatory sv:type attribute of element sv:property"));
             }
             currentPropType = PropertyType.valueFromName(type);
-        } else if (SysViewSAXEventGenerator.VALUE_ELEMENT.equals(localName)) {
+        } else if (VALUE.equals(localName)) {
             // sv:value element
 
             // reset temp fields
@@ -218,7 +233,7 @@
             throws SAXException {
         // check element name
         ImportState state = (ImportState) stack.peek();
-        if (SysViewSAXEventGenerator.NODE_ELEMENT.equals(localName)) {
+        if (NODE.equals(localName)) {
             // sv:node element
             if (!state.started) {
                 // need to start & end current node
@@ -230,7 +245,7 @@
             }
             // pop current state from stack
             stack.pop();
-        } else if (SysViewSAXEventGenerator.PROPERTY_ELEMENT.equals(localName)) {
+        } else if (PROPERTY.equals(localName)) {
             // sv:property element
 
             // check if all system properties (jcr:primaryType, jcr:uuid etc.)
@@ -282,7 +297,7 @@
             }
             // reset temp fields
             currentPropValues.clear();
-        } else if (SysViewSAXEventGenerator.VALUE_ELEMENT.equals(localName)) {
+        } else if (VALUE.equals(localName)) {
             // sv:value element
             currentPropValues.add(currentPropValue);
             // reset temp fields
Index: jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/DocViewSAXEventGenerator.java
===================================================================
--- jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/DocViewSAXEventGenerator.java	(revision 654751)
+++ jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/DocViewSAXEventGenerator.java	(working copy)
@@ -1,222 +0,0 @@
-/*
- * 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.jackrabbit.jcr2spi.xml;
-
-import org.apache.jackrabbit.spi.commons.conversion.NameException;
-import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.util.ISO9075;
-import org.apache.jackrabbit.value.ValueHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.AttributesImpl;
-
-import javax.jcr.Node;
-import javax.jcr.Property;
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * A <code>DocViewSAXEventGenerator</code> instance can be used to generate
- * SAX events representing the serialized form of an item in Document View XML.
- */
-public class DocViewSAXEventGenerator extends AbstractSAXEventGenerator {
-
-    private static Logger log = LoggerFactory.getLogger(DocViewSAXEventGenerator.class);
-
-    public static final String CDATA_TYPE = "CDATA";
-
-    // used to temporarily store properties of a node
-    private final List props;
-
-    /**
-     * Constructor
-     *
-     * @param node           the node state which should be serialized
-     * @param noRecurse      if true, only <code>node</code> and its properties
-     *                       will be serialized; otherwise the entire hierarchy
-     *                       starting with <code>node</code> will be serialized.
-     * @param skipBinary     flag governing whether binary properties are to be
-     *                       serialized.
-     * @param contentHandler the content handler to feed the SAX events to
-     * @throws RepositoryException if an error occurs
-     */
-    public DocViewSAXEventGenerator(Node node, boolean noRecurse,
-                                    boolean skipBinary,
-                                    ContentHandler contentHandler)
-            throws RepositoryException {
-        super(node, noRecurse, skipBinary, contentHandler);
-
-        props = new ArrayList();
-    }
-
-    private Name getName(String rawName) throws RepositoryException {
-        try {
-            return nameResolver.getQName(rawName);
-        } catch (NameException e) {
-            // should never get here...
-            String msg = "internal error: failed to resolve namespace mappings";
-            log.error(msg, e);
-            throw new RepositoryException(msg, e);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void entering(Node node, int level)
-            throws RepositoryException, SAXException {
-        // nop
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void enteringProperties(Node node, int level)
-            throws RepositoryException, SAXException {
-        // reset list of properties
-        props.clear();
-    }
-
-    /**
-     * {@inheritDoc}
-     * <p/>
-     * See also {@link DocViewImportHandler#startElement(String, String, String, org.xml.sax.Attributes)}
-     * regarding special handling of multi-valued properties on import.
-     */
-    protected void leavingProperties(Node node, int level)
-            throws RepositoryException, SAXException {
-        String name = node.getName();
-        if (name.equals(jcrXMLText)) {
-            // the node represents xml character data
-            Iterator iter = props.iterator();
-            while (iter.hasNext()) {
-                Property prop = (Property) iter.next();
-                String propName = prop.getName();
-                if (propName.equals(jcrXMLCharacters)) {
-                    // assume jcr:xmlcharacters is single-valued
-                    char[] chars = prop.getValue().getString().toCharArray();
-                    contentHandler.characters(chars, 0, chars.length);
-                }
-            }
-        } else {
-            // regular node
-
-            // element name
-            String elemName;
-            if (node.getDepth() == 0) {
-                // root node needs a name
-                elemName = jcrRoot;
-            } else {
-                // encode node name to make sure it's a valid xml name
-                elemName = ISO9075.encode(name);
-            }
-
-            // attributes (properties)
-            AttributesImpl attrs = new AttributesImpl();
-            addNamespacePrefixes(level, attrs);
-            Iterator iter = props.iterator();
-            while (iter.hasNext()) {
-                Property prop = (Property) iter.next();
-                String propName = prop.getName();
-
-                if (prop.getDefinition().isMultiple()) {
-                    // TODO: proper multi-value serialization support
-                    // skip multi-valued properties for the time being
-                    // until a way of properly handling/detecting multi-valued
-                    // properties on re-import is found (see JCR-325);
-                    // see also DocViewImportHandler#startElement()
-
-                    // skipping multi-valued properties entirely is legal
-                    // according to "6.4.2.5 Multi-value Properties" of the
-                    // jsr-170 specification
-                    continue;
-                }
-
-                // attribute name (encode property name to make sure it's a valid xml name)
-                String attrName = ISO9075.encode(propName);
-                Name qName = getName(attrName);
-
-                // attribute value
-                if (prop.getType() == PropertyType.BINARY && skipBinary) {
-                    // add empty attribute
-                    attrs.addAttribute(qName.getNamespaceURI(),
-                            qName.getLocalName(), attrName, CDATA_TYPE, "");
-                } else {
-                    StringBuffer attrValue = new StringBuffer();
-                    // serialize single-valued property
-                    attrValue.append(ValueHelper.serialize(prop.getValue(), false));
-                    attrs.addAttribute(qName.getNamespaceURI(),
-                            qName.getLocalName(), attrName, CDATA_TYPE,
-                            attrValue.toString());
-                }
-            }
-
-            // start element (node)
-            Name qName = getName(elemName);
-            contentHandler.startElement(qName.getNamespaceURI(),
-                    qName.getLocalName(), elemName, attrs);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void leaving(Node node, int level)
-            throws RepositoryException, SAXException {
-        String name = node.getName();
-        if (name.equals(jcrXMLText)) {
-            // the node represents xml character data
-            // (already processed in leavingProperties(NodeImpl, int)
-            return;
-        }
-        // element name
-        String elemName;
-        if (node.getDepth() == 0) {
-            // root node needs a name
-            elemName = jcrRoot;
-        } else {
-            // encode node name to make sure it's a valid xml name
-            elemName = ISO9075.encode(name);
-        }
-
-        // end element (node)
-        Name qName = getName(elemName);
-        contentHandler.endElement(qName.getNamespaceURI(), qName.getLocalName(),
-                elemName);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void entering(Property prop, int level)
-            throws RepositoryException, SAXException {
-        props.add(prop);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void leaving(Property prop, int level)
-            throws RepositoryException, SAXException {
-        // nop
-    }
-}
Index: jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/AbstractSAXEventGenerator.java
===================================================================
--- jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/AbstractSAXEventGenerator.java	(revision 654751)
+++ jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/AbstractSAXEventGenerator.java	(working copy)
@@ -1,444 +0,0 @@
-/*
- * 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.jackrabbit.jcr2spi.xml;
-
-import org.apache.jackrabbit.spi.commons.conversion.NameResolver;
-import org.apache.jackrabbit.spi.commons.conversion.ParsingNameResolver;
-import org.apache.jackrabbit.spi.commons.name.NameConstants;
-import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
-import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
-import org.apache.jackrabbit.spi.commons.namespace.SessionNamespaceResolver;
-import org.apache.jackrabbit.spi.Name;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.AttributesImpl;
-
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.Property;
-import javax.jcr.PropertyIterator;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * <code>AbstractSAXEventGenerator</code> serves as the base class for
- * <code>SysViewSAXEventGenerator</code> and <code>DocViewSAXEventGenerator</code>
- * <p/>
- * It traverses a tree of <code>Node</code> & <code>Property</code>
- * instances, and calls the abstract methods
- * <ul>
- * <li><code>{@link #entering(Node, int)}</code></li>
- * <li><code>{@link #enteringProperties(Node, int)}</code></li>
- * <li><code>{@link #leavingProperties(Node, int)}</code></li>
- * <li><code>{@link #leaving(Node, int)}</code></li>
- * <li><code>{@link #entering(Property, int)}</code></li>
- * <li><code>{@link #leaving(Property, int)}</code></li>
- * </ul>
- * for every item it encounters.
- */
-abstract class AbstractSAXEventGenerator {
-
-    private static Logger log = LoggerFactory.getLogger(AbstractSAXEventGenerator.class);
-
-    /**
-     * the session to be used for resolving namespace mappings
-     */
-    protected final Session session;
-    /**
-     * the name resolver
-     */
-    protected final NameResolver nameResolver;
-
-    /**
-     * the content handler to feed the SAX events to
-     */
-    protected final ContentHandler contentHandler;
-
-    protected final Node startNode;
-    protected final boolean skipBinary;
-    protected final boolean noRecurse;
-
-    /**
-     * the set of namespace declarations that have already been serialized
-     */
-    protected NamespaceStack namespaces;
-
-    /**
-     * The jcr:primaryType property name (allowed for session-local prefix mappings)
-     */
-    protected final String jcrPrimaryType;
-    /**
-     * The jcr:mixinTypes property name (allowed for session-local prefix mappings)
-     */
-    protected final String jcrMixinTypes;
-    /**
-     * The jcr:uuid property name (allowed for session-local prefix mappings)
-     */
-    protected final String jcrUUID;
-    /**
-     * The jcr:root node name (allowed for session-local prefix mappings)
-     */
-    protected final String jcrRoot;
-    /**
-     * The jcr:xmltext node name (allowed for session-local prefix mappings)
-     */
-    protected final String jcrXMLText;
-    /**
-     * The jcr:xmlCharacters property name (allowed for session-local prefix mappings)
-     */
-    protected final String jcrXMLCharacters;
-
-    /**
-     * Constructor
-     *
-     * @param node           the node state which should be serialized
-     * @param noRecurse      if true, only <code>node</code> and its properties will
-     *                       be serialized; otherwise the entire hierarchy starting with
-     *                       <code>node</code> will be serialized.
-     * @param skipBinary     flag governing whether binary properties are to be serialized.
-     * @param contentHandler the content handler to feed the SAX events to
-     * @throws RepositoryException if an error occurs
-     */
-    protected AbstractSAXEventGenerator(Node node, boolean noRecurse,
-                                        boolean skipBinary,
-                                        ContentHandler contentHandler)
-            throws RepositoryException {
-        startNode = node;
-        session = node.getSession();
-        NamespaceResolver nsResolver = new SessionNamespaceResolver(session);
-        nameResolver = new ParsingNameResolver(NameFactoryImpl.getInstance(), nsResolver);
-
-        this.contentHandler = contentHandler;
-        this.skipBinary = skipBinary;
-        this.noRecurse = noRecurse;
-        // start with an empty set of known prefixes
-        this.namespaces = new NamespaceStack(null);
-
-        // resolve the names of some wellknown properties
-        // allowing for session-local prefix mappings
-        jcrPrimaryType = nameResolver.getJCRName(NameConstants.JCR_PRIMARYTYPE);
-        jcrMixinTypes = nameResolver.getJCRName(NameConstants.JCR_MIXINTYPES);
-        jcrUUID = nameResolver.getJCRName(NameConstants.JCR_UUID);
-        jcrRoot = nameResolver.getJCRName(NameConstants.JCR_ROOT);
-        jcrXMLText = nameResolver.getJCRName(NameConstants.JCR_XMLTEXT);
-        jcrXMLCharacters = nameResolver.getJCRName(NameConstants.JCR_XMLCHARACTERS);
-    }
-
-    /**
-     * Serializes the hierarchy of nodes and properties.
-     *
-     * @throws RepositoryException if an error occurs while traversing the hierarchy
-     * @throws SAXException        if an error occured while feeding the events
-     *                             to the content handler
-     */
-    public void serialize() throws RepositoryException, SAXException {
-        // start document and declare namespaces
-        contentHandler.startDocument();
-        startNamespaceDeclarations();
-
-        // serialize node and subtree
-        process(startNode, 0);
-
-        // clear namespace declarations and end document
-        endNamespaceDeclarations();
-        contentHandler.endDocument();
-    }
-
-    /**
-     * @throws RepositoryException
-     * @throws SAXException
-     */
-    protected void startNamespaceDeclarations()
-            throws RepositoryException, SAXException {
-        // start namespace declarations
-        String[] prefixes = session.getNamespacePrefixes();
-        for (int i = 0; i < prefixes.length; i++) {
-            String prefix = prefixes[i];
-            if (Name.NS_XML_PREFIX.equals(prefix)) {
-                // skip 'xml' prefix as this would be an illegal namespace declaration
-                continue;
-            }
-            String uri = session.getNamespaceURI(prefix);
-            contentHandler.startPrefixMapping(prefix, uri);
-        }
-    }
-
-    /**
-     * @throws RepositoryException
-     * @throws SAXException
-     */
-    protected void endNamespaceDeclarations()
-            throws RepositoryException, SAXException {
-        // end namespace declarations
-        String[] prefixes = session.getNamespacePrefixes();
-        for (int i = 0; i < prefixes.length; i++) {
-            String prefix = prefixes[i];
-            if (Name.NS_XML_PREFIX.equals(prefix)) {
-                // skip 'xml' prefix as this would be an illegal namespace declaration
-                continue;
-            }
-            contentHandler.endPrefixMapping(prefix);
-        }
-    }
-
-    /**
-     * Adds explicit <code>xmlns:prefix="uri"</code> attributes to the
-     * XML element as required (e.g., normally just on the root
-     * element). The effect is the same as setting the
-     * "<code>http://xml.org/sax/features/namespace-prefixes</code>"
-     * property on an SAX parser.
-     *
-     * @param level level of the current XML element
-     * @param attributes attributes of the current XML element
-     * @throws RepositoryException on a repository error
-     */
-    protected void addNamespacePrefixes(int level, AttributesImpl attributes)
-            throws RepositoryException {
-        String[] prefixes = session.getNamespacePrefixes();
-        NamespaceStack newNamespaces = null;
-
-        for (int i = 0; i < prefixes.length; i++) {
-            String prefix = prefixes[i];
-
-            if (prefix.length() > 0
-                    && !Name.NS_XML_PREFIX.equals(prefix)) {
-                String uri = session.getNamespaceURI(prefix);
-
-                // get the matching namespace from previous declarations
-                String mappedToNs = this.namespaces.getNamespaceURI(prefix);
-
-                if (!uri.equals(mappedToNs)) {
-                    // when not the same, add a declaration
-                    attributes.addAttribute(
-                        Name.NS_XMLNS_URI,
-                        prefix,
-                        Name.NS_XMLNS_PREFIX + ":" + prefix,
-                        "CDATA",
-                        uri);
-
-                    if (newNamespaces == null) {
-                        // replace current namespace stack when needed
-                        newNamespaces = new NamespaceStack(this.namespaces);
-                        this.namespaces = newNamespaces;
-                    }
-
-                    // remember the new declaration
-                    newNamespaces.setNamespacePrefix(prefix, uri);
-                }
-            }
-        }
-    }
-
-    /**
-     * @param node
-     * @param level
-     * @throws RepositoryException
-     * @throws SAXException
-     */
-    protected void process(Node node, int level)
-            throws RepositoryException, SAXException {
-        // enter node
-        entering(node, level);
-
-        // enter properties
-        enteringProperties(node, level);
-
-        // serialize jcr:primaryType, jcr:mixinTypes & jcr:uuid first:
-        // jcr:primaryType
-        if (node.hasProperty(jcrPrimaryType)) {
-            process(node.getProperty(jcrPrimaryType), level + 1);
-        } else {
-            String msg = "internal error: missing jcr:primaryType property on node "
-                    + node.getPath();
-            log.debug(msg);
-            throw new RepositoryException(msg);
-        }
-        // jcr:mixinTypes
-        if (node.hasProperty(jcrMixinTypes)) {
-            process(node.getProperty(jcrMixinTypes), level + 1);
-        }
-        // jcr:uuid
-        if (node.hasProperty(jcrUUID)) {
-            process(node.getProperty(jcrUUID), level + 1);
-        }
-
-        // serialize remaining properties
-        PropertyIterator propIter = node.getProperties();
-        while (propIter.hasNext()) {
-            Property prop = propIter.nextProperty();
-            String name = prop.getName();
-            if (jcrPrimaryType.equals(name)
-                    || jcrMixinTypes.equals(name)
-                    || jcrUUID.equals(name)) {
-                continue;
-            }
-            // serialize property
-            process(prop, level + 1);
-        }
-
-        // leaving properties
-        leavingProperties(node, level);
-
-        if (!noRecurse) {
-            // child nodes
-            NodeIterator nodeIter = node.getNodes();
-            while (nodeIter.hasNext()) {
-                // recurse
-                Node childNode = nodeIter.nextNode();
-                // remember the current namespace declarations
-                NamespaceStack previousNamespaces = this.namespaces;
-
-                process(childNode, level + 1);
-
-                // restore the effective namespace declarations
-                // (from before visiting the child node)
-                this.namespaces = previousNamespaces;
-            }
-        }
-
-        // leaving node
-        leaving(node, level);
-    }
-
-    /**
-     * @param prop
-     * @param level
-     * @throws RepositoryException
-     * @throws SAXException
-     */
-    protected void process(Property prop, int level)
-            throws RepositoryException, SAXException {
-        // serialize property
-        entering(prop, level);
-        leaving(prop, level);
-    }
-
-    /**
-     * @param node
-     * @param level
-     * @throws RepositoryException
-     * @throws SAXException
-     */
-    protected abstract void entering(Node node, int level)
-            throws RepositoryException, SAXException;
-
-    /**
-     * @param node
-     * @param level
-     * @throws RepositoryException
-     * @throws SAXException
-     */
-    protected abstract void enteringProperties(Node node, int level)
-            throws RepositoryException, SAXException;
-
-    /**
-     * @param node
-     * @param level
-     * @throws RepositoryException
-     * @throws SAXException
-     */
-    protected abstract void leavingProperties(Node node, int level)
-            throws RepositoryException, SAXException;
-
-    /**
-     * @param node
-     * @param level
-     * @throws RepositoryException
-     * @throws SAXException
-     */
-    protected abstract void leaving(Node node, int level)
-            throws RepositoryException, SAXException;
-
-    /**
-     * @param prop
-     * @param level
-     * @throws RepositoryException
-     * @throws SAXException
-     */
-    protected abstract void entering(Property prop, int level)
-            throws RepositoryException, SAXException;
-
-    /**
-     * @param prop
-     * @param level
-     * @throws RepositoryException
-     * @throws SAXException
-     */
-    protected abstract void leaving(Property prop, int level)
-            throws RepositoryException, SAXException;
-
-    /**
-     * Implements a simple stack of namespace declarations.
-     */
-    private static class NamespaceStack {
-
-        /**
-         * Parent stack (may be <code>null</code>)
-         */
-        private final NamespaceStack parent;
-
-        /**
-         * Local namespace declarations.
-         */
-        private final Map namespaces;
-
-        /**
-         * Instantiate a new stack
-         *
-         * @param parent parent stack (may be <code>null</code> for the initial stack)
-         */
-        public NamespaceStack(NamespaceStack parent) {
-            this.parent = parent;
-            this.namespaces = new HashMap();
-        }
-
-        /**
-         * Obtain namespace URI for a prefix
-         *
-         * @param prefix prefix
-         * @return namespace URI (or <code>null</code> when unknown)
-         */
-        public String getNamespaceURI(String prefix) {
-            String namespace = (String) namespaces.get(prefix);
-            if (namespace != null) {
-                // found in this element, return right away
-                return namespace;
-            } else if (parent != null) {
-                // ask parent, when present
-                return parent.getNamespaceURI(prefix);
-            } else {
-                return null;
-            }
-        }
-
-        /**
-         * Add a new prefix mapping
-         *
-         * @param prefix namespace prefix
-         * @param uri namespace URI
-         */
-        public void setNamespacePrefix(String prefix, String uri) {
-            namespaces.put(prefix, uri);
-        }
-
-    }
-
-}
Index: jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/SysViewSAXEventGenerator.java
===================================================================
--- jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/SysViewSAXEventGenerator.java	(revision 654751)
+++ jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/SysViewSAXEventGenerator.java	(working copy)
@@ -1,267 +0,0 @@
-/*
- * 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.jackrabbit.jcr2spi.xml;
-
-import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.value.ValueHelper;
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.AttributesImpl;
-
-import javax.jcr.Node;
-import javax.jcr.Property;
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.Value;
-import java.io.IOException;
-import java.io.Writer;
-
-/**
- * A <code>SysViewSAXEventGenerator</code> instance can be used to generate SAX events
- * representing the serialized form of an item in System View XML.
- */
-public class SysViewSAXEventGenerator extends AbstractSAXEventGenerator {
-
-    /**
-     * The XML elements and attributes used in serialization
-     */
-    public static final String NODE_ELEMENT = "node";
-    public static final String PREFIXED_NODE_ELEMENT =
-        Name.NS_SV_PREFIX + ":" + NODE_ELEMENT;
-
-    public static final String PROPERTY_ELEMENT = "property";
-    public static final String PREFIXED_PROPERTY_ELEMENT =
-        Name.NS_SV_PREFIX + ":" + PROPERTY_ELEMENT;
-
-    public static final String VALUE_ELEMENT = "value";
-    public static final String PREFIXED_VALUE_ELEMENT =
-        Name.NS_SV_PREFIX + ":" + VALUE_ELEMENT;
-
-    public static final String NAME_ATTRIBUTE = "name";
-    public static final String PREFIXED_NAME_ATTRIBUTE =
-        Name.NS_SV_PREFIX + ":" + NAME_ATTRIBUTE;
-
-    public static final String TYPE_ATTRIBUTE = "type";
-    public static final String PREFIXED_TYPE_ATTRIBUTE =
-        Name.NS_SV_PREFIX + ":" + TYPE_ATTRIBUTE;
-
-    public static final String CDATA_TYPE = "CDATA";
-    public static final String ENUMERATION_TYPE = "ENUMERATION";
-
-    private static final String NS_XMLSCHEMA_INSTANCE_URI = "http://www.w3.org/2001/XMLSchema-instance";
-    private static final String NS_XMLSCHEMA_INSTANCE_PREFIX = "xsi";
-    private static final String NS_XMLSCHEMA_URI = "http://www.w3.org/2001/XMLSchema";
-    private static final String NS_XMLSCHEMA_PREFIX = "xs";
-
-    private static final Attributes ATTRS_EMPTY = new AttributesImpl();
-    private static final Attributes ATTRS_BINARY_ENCODED_VALUE;
-    static {
-        AttributesImpl attrs = new AttributesImpl();
-        attrs.addAttribute(Name.NS_XMLNS_URI, NS_XMLSCHEMA_INSTANCE_PREFIX, "xmlns:" + NS_XMLSCHEMA_INSTANCE_PREFIX, CDATA_TYPE, NS_XMLSCHEMA_INSTANCE_URI);
-        attrs.addAttribute(Name.NS_XMLNS_URI, NS_XMLSCHEMA_PREFIX, "xmlns:" + NS_XMLSCHEMA_PREFIX, CDATA_TYPE, NS_XMLSCHEMA_URI);
-        attrs.addAttribute(NS_XMLSCHEMA_INSTANCE_URI, "type", NS_XMLSCHEMA_INSTANCE_PREFIX + ":type", "CDATA", NS_XMLSCHEMA_PREFIX + ":base64Binary");
-        ATTRS_BINARY_ENCODED_VALUE = attrs;
-    }
-
-    /**
-     * Constructor
-     *
-     * @param node           the node state which should be serialized
-     * @param noRecurse      if true, only <code>node</code> and its properties will
-     *                       be serialized; otherwise the entire hierarchy starting with
-     *                       <code>node</code> will be serialized.
-     * @param skipBinary     flag governing whether binary properties are to be serialized.
-     * @param contentHandler the content handler to feed the SAX events to
-     * @throws RepositoryException if an error occurs
-     */
-    public SysViewSAXEventGenerator(Node node, boolean noRecurse,
-                                    boolean skipBinary,
-                                    ContentHandler contentHandler)
-            throws RepositoryException {
-        super(node, noRecurse, skipBinary, contentHandler);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void entering(Node node, int level)
-            throws RepositoryException, SAXException {
-        AttributesImpl attrs = new AttributesImpl();
-        addNamespacePrefixes(level, attrs);
-        // name attribute
-        String nodeName;
-        if (node.getDepth() == 0) {
-            // root node needs a name
-            nodeName = jcrRoot;
-        } else {
-            // encode node name to make sure it's a valid xml name
-            nodeName = node.getName();
-        }
-
-        attrs.addAttribute(Name.NS_SV_URI, NAME_ATTRIBUTE, PREFIXED_NAME_ATTRIBUTE,
-                CDATA_TYPE, nodeName);
-        // start node element
-        contentHandler.startElement(Name.NS_SV_URI, NODE_ELEMENT,
-                PREFIXED_NODE_ELEMENT, attrs);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void enteringProperties(Node node, int level)
-            throws RepositoryException, SAXException {
-        // nop
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void leavingProperties(Node node, int level)
-            throws RepositoryException, SAXException {
-        // nop
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void leaving(Node node, int level)
-            throws RepositoryException, SAXException {
-        // end node element
-        contentHandler.endElement(Name.NS_SV_URI, NODE_ELEMENT, PREFIXED_NODE_ELEMENT);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void entering(Property prop, int level)
-            throws RepositoryException, SAXException {
-        String propName = prop.getName();
-        AttributesImpl attrs = new AttributesImpl();
-        // name attribute
-        attrs.addAttribute(Name.NS_SV_URI, NAME_ATTRIBUTE, PREFIXED_NAME_ATTRIBUTE,
-                CDATA_TYPE, propName);
-        // type attribute
-        int type = prop.getType();
-        String typeName;
-        try {
-            typeName = PropertyType.nameFromValue(type);
-        } catch (IllegalArgumentException iae) {
-            // should never be getting here
-            throw new RepositoryException("unexpected property-type ordinal: "
-                    + type, iae);
-        }
-        attrs.addAttribute(Name.NS_SV_URI, TYPE_ATTRIBUTE, PREFIXED_TYPE_ATTRIBUTE,
-                ENUMERATION_TYPE, typeName);
-
-        // start property element
-        contentHandler.startElement(Name.NS_SV_URI, PROPERTY_ELEMENT,
-                PREFIXED_PROPERTY_ELEMENT, attrs);
-
-        // values
-        if (prop.getType() == PropertyType.BINARY && skipBinary) {
-            // empty value element
-            contentHandler.startElement(Name.NS_SV_URI, VALUE_ELEMENT,
-                    PREFIXED_VALUE_ELEMENT, new AttributesImpl());
-            contentHandler.endElement(Name.NS_SV_URI, VALUE_ELEMENT,
-                    PREFIXED_VALUE_ELEMENT);
-        } else {
-            boolean multiValued = prop.getDefinition().isMultiple();
-            Value[] vals;
-            if (multiValued) {
-                vals = prop.getValues();
-            } else {
-                vals = new Value[]{prop.getValue()};
-            }
-            for (int i = 0; i < vals.length; i++) {
-                Value val = vals[i];
-
-                Attributes attributes = ATTRS_EMPTY;
-                boolean mustSendBinary = false;
-
-                if (val.getType() != PropertyType.BINARY) {
-                    String ser = val.getString();
-                    for (int ci = 0; ci < ser.length() && mustSendBinary == false; ci++) {
-                        char c = ser.charAt(ci);
-                        if (c >= 0 && c < 32 && c != '\r' && c != '\n' && c != '\t') {
-                            mustSendBinary = true;
-                        }
-                    }
-
-                    if (mustSendBinary) {
-                        contentHandler.startPrefixMapping(NS_XMLSCHEMA_INSTANCE_PREFIX, NS_XMLSCHEMA_INSTANCE_URI);
-                        contentHandler.startPrefixMapping(NS_XMLSCHEMA_PREFIX, NS_XMLSCHEMA_URI);
-                        attributes = ATTRS_BINARY_ENCODED_VALUE;
-                    }
-                }
-
-                // start value element
-                contentHandler.startElement(Name.NS_SV_URI, VALUE_ELEMENT,
-                        PREFIXED_VALUE_ELEMENT, attributes);
-
-                // characters
-                Writer writer = new Writer() {
-                    public void close() /*throws IOException*/ {
-                    }
-
-                    public void flush() /*throws IOException*/ {
-                    }
-
-                    public void write(char[] cbuf, int off, int len) throws IOException {
-                        try {
-                            contentHandler.characters(cbuf, off, len);
-                        } catch (SAXException se) {
-                            throw new IOException(se.toString());
-                        }
-                    }
-                };
-                try {
-                    ValueHelper.serialize(val, false, mustSendBinary, writer);
-                    // no need to close our Writer implementation
-                    //writer.close();
-                } catch (IOException ioe) {
-                    // check if the exception wraps a SAXException
-                    // (see Writer.write(char[], int, int) above)
-                    Throwable t = ioe.getCause();
-                    if (t != null && t instanceof SAXException) {
-                        throw (SAXException) t;
-                    } else {
-                        throw new SAXException(ioe);
-                    }
-                }
-
-                // end value element
-                contentHandler.endElement(Name.NS_SV_URI, VALUE_ELEMENT,
-                        PREFIXED_VALUE_ELEMENT);
-
-                if (mustSendBinary) {
-                    contentHandler.endPrefixMapping(NS_XMLSCHEMA_INSTANCE_PREFIX);
-                    contentHandler.endPrefixMapping(NS_XMLSCHEMA_PREFIX);
-                }
-            }
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void leaving(Property prop, int level)
-            throws RepositoryException, SAXException {
-        contentHandler.endElement(Name.NS_SV_URI, PROPERTY_ELEMENT,
-                PREFIXED_PROPERTY_ELEMENT);
-    }
-}
