You are viewing a plain text version of this content. The canonical link for it is here.
Posted to slide-dev@jakarta.apache.org by st...@apache.org on 2004/08/24 11:51:55 UTC

cvs commit: jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/xml AbstractSAXEventGenerator.java DocViewImportHandler.java DocViewSAXEventGenerator.java ImportHandler.java SysViewImportHandler.java SysViewSAXEventGenerator.java

stefan      2004/08/24 02:51:55

  Modified:    proposals/jcrri/src/org/apache/slide/jcr/core
                        AccessManagerImpl.java ItemImpl.java NodeImpl.java
                        RepositoryFactory.java RepositoryImpl.java
                        Test.java TicketImpl.java WorkspaceImpl.java
               proposals/jcrri/src/org/apache/slide/jcr/core/version
                        GenericVersionSelector.java VersionSelector.java
  Added:       proposals/jcrri/src/org/apache/slide/jcr/core/xml
                        AbstractSAXEventGenerator.java
                        DocViewImportHandler.java
                        DocViewSAXEventGenerator.java ImportHandler.java
                        SysViewImportHandler.java
                        SysViewSAXEventGenerator.java
  Removed:     proposals/jcrri/src/org/apache/slide/jcr/core
                        AbstractSAXEventGenerator.java
                        DocViewSAXEventGenerator.java
                        SysViewSAXEventGenerator.java
  Log:
  system/doc view import and moving import/export related code to its own sub-package 'xml'
  
  Revision  Changes    Path
  1.13      +4 -4      jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/AccessManagerImpl.java
  
  Index: AccessManagerImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/AccessManagerImpl.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- AccessManagerImpl.java	2 Aug 2004 16:21:04 -0000	1.12
  +++ AccessManagerImpl.java	24 Aug 2004 09:51:50 -0000	1.13
  @@ -29,7 +29,7 @@
    * @author Stefan Guggisberg
    * @version $Revision$, $Date$
    */
  -class AccessManagerImpl extends AbstractAccessManager {
  +public class AccessManagerImpl extends AbstractAccessManager {
   
       private static Logger log = Logger.getLogger(AccessManagerImpl.class);
   
  @@ -49,7 +49,7 @@
        * @param permissions
        * @return
        */
  -    boolean isGranted(ItemId id, long permissions) throws ItemNotFoundException, RepositoryException {
  +    public boolean isGranted(ItemId id, long permissions) throws ItemNotFoundException, RepositoryException {
   	return (getPermissions(id) & permissions) == permissions;
       }
   
  @@ -57,7 +57,7 @@
        * @param id
        * @return
        */
  -    long getPermissions(ItemId id) throws ItemNotFoundException, RepositoryException {
  +    public long getPermissions(ItemId id) throws ItemNotFoundException, RepositoryException {
   	// @todo implement resource-based access control
   
   	return PermissionImpl.ALL_VALUES;
  
  
  
  1.20      +7 -7      jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ItemImpl.java
  
  Index: ItemImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ItemImpl.java,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -r1.19 -r1.20
  --- ItemImpl.java	18 Aug 2004 13:16:27 -0000	1.19
  +++ ItemImpl.java	24 Aug 2004 09:51:50 -0000	1.20
  @@ -47,26 +47,26 @@
    * @author Stefan Guggisberg
    * @version $Revision$, $Date$
    */
  -abstract class ItemImpl implements Item, ItemStateListener {
  +public abstract class ItemImpl implements Item, ItemStateListener {
   
       private static Logger log = Logger.getLogger(ItemImpl.class);
   
       // some constants used in derived classes
       // system properties (values are system generated)
       // jcr:uuid
  -    protected static final QName PROPNAME_UUID =
  +    public static final QName PROPNAME_UUID =
   	    new QName(NamespaceRegistryImpl.NS_JCR_URI, "uuid");
       // jcr:primaryType
  -    protected static final QName PROPNAME_PRIMARYTYPE =
  +    public static final QName PROPNAME_PRIMARYTYPE =
   	    new QName(NamespaceRegistryImpl.NS_JCR_URI, "primaryType");
       // jcr:mixinTypes
  -    protected static final QName PROPNAME_MIXINTYPES =
  +    public static final QName PROPNAME_MIXINTYPES =
   	    new QName(NamespaceRegistryImpl.NS_JCR_URI, "mixinTypes");
       // jcr:created
  -    protected static final QName PROPNAME_CREATED =
  +    public static final QName PROPNAME_CREATED =
   	    new QName(NamespaceRegistryImpl.NS_JCR_URI, "created");
       // jcr:lastModified
  -    protected static final QName PROPNAME_LAST_MODIFIED =
  +    public static final QName PROPNAME_LAST_MODIFIED =
   	    new QName(NamespaceRegistryImpl.NS_JCR_URI, "lastModified");
   
       protected static final int STATUS_NORMAL = 0;
  
  
  
  1.32      +3 -2      jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/NodeImpl.java
  
  Index: NodeImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/NodeImpl.java,v
  retrieving revision 1.31
  retrieving revision 1.32
  diff -u -r1.31 -r1.32
  --- NodeImpl.java	18 Aug 2004 13:20:20 -0000	1.31
  +++ NodeImpl.java	24 Aug 2004 09:51:50 -0000	1.32
  @@ -43,6 +43,7 @@
    * <code>NodeImpl</code> implements the <code>Node</code> interface.
    *
    * @author Stefan Guggisberg
  + * @author Tobias Strasser
    * @version $Revision$, $Date$
    */
   public class NodeImpl extends ItemImpl implements Node {
  @@ -1980,7 +1981,7 @@
   	ArrayList preds = new ArrayList();
   	boolean found = false;
   	if (values != null) {
  -	    for (int i = 0, j = 0; i < values.length; i++) {
  +	    for (int i = 0; i < values.length; i++) {
   		if (values[i].getString().equals(v.getUUID())) {
   		    found = true;
   		} else {
  
  
  
  1.16      +7 -5      jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/RepositoryFactory.java
  
  Index: RepositoryFactory.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/RepositoryFactory.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- RepositoryFactory.java	2 Aug 2004 16:21:05 -0000	1.15
  +++ RepositoryFactory.java	24 Aug 2004 09:51:51 -0000	1.16
  @@ -319,8 +319,9 @@
   		return repConfig;
   	    }
   	}
  -	log.error("The repository " + name + " was not found in the config file " + configId);
  -	throw new RepositoryException("The repository " + name + " was not found in the config file " + configId);
  +	String msg = "The repository " + name + " was not found in the config file " + configId;
  +	log.error(msg);
  +	throw new RepositoryException(msg);
       }
   
       /**
  @@ -450,8 +451,9 @@
   	    }
   	    fs.init();
   	} catch (Exception e) {
  -	    log.error("Cannot instantiate implementing class " + className, e);
  -	    throw new RepositoryException("Cannot instantiate implementing class " + className, e);
  +	    String msg = "Cannot instantiate implementing class " + className;
  +	    log.error(msg, e);
  +	    throw new RepositoryException(msg, e);
   	}
   	return fs;
       }
  
  
  
  1.21      +2 -2      jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/RepositoryImpl.java
  
  Index: RepositoryImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/RepositoryImpl.java,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -r1.20 -r1.21
  --- RepositoryImpl.java	2 Aug 2004 16:21:05 -0000	1.20
  +++ RepositoryImpl.java	24 Aug 2004 09:51:51 -0000	1.21
  @@ -294,7 +294,7 @@
   	}
       }
   
  -    NamespaceRegistry getNamespaceRegistry() {
  +    NamespaceRegistryImpl getNamespaceRegistry() {
   	return nsReg;
       }
   
  
  
  
  1.15      +16 -64    jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/Test.java
  
  Index: Test.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/Test.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- Test.java	18 Aug 2004 13:19:41 -0000	1.14
  +++ Test.java	24 Aug 2004 09:51:51 -0000	1.15
  @@ -25,7 +25,8 @@
   import javax.jcr.nodetype.NodeTypeManager;
   import javax.jcr.util.TraversingItemVisitor;
   import java.io.*;
  -import java.util.*;
  +import java.util.Calendar;
  +import java.util.Properties;
   
   public class Test {
       private static Logger log = Logger.getLogger(Test.class);
  @@ -44,9 +45,6 @@
   	Ticket t = r.login(new SimpleCredentials("anonymous", "".toCharArray()), null);
   	Workspace wsp = t.getWorkspace();
   
  -	//wsp.exportSysView("/", new FileOutputStream("d:/temp/sv_export0.xml"), true, false);
  -	wsp.exportDocView("/", new FileOutputStream("d:/temp/dv_export0.xml"), true, false);
  -
   	NodeTypeManager ntMgr = wsp.getNodeTypeManager();
   	NodeTypeIterator ntIter = ntMgr.getAllNodeTypes();
   	while (ntIter.hasNext()) {
  @@ -59,70 +57,24 @@
   	System.out.println();
   
   	Node root = t.getRootNode();
  -
  +/*
  +	String svExportFilePath = "d:/temp/sv_export0.xml";
  +	String dvExportFilePath = "d:/temp/dv_export0.xml";
  +	String importTargetName = "sandbox";
  +
  +	wsp.exportSysView("/", new FileOutputStream(svExportFilePath), true, false);
  +	wsp.exportDocView("/", new FileOutputStream(dvExportFilePath), true, false);
  +	if (!root.hasNode(importTargetName)) {
  +	    root.addNode(importTargetName, "nt:unstructured");
  +	}
  +	FileInputStream fin = new FileInputStream(svExportFilePath);
  +	t.importXML("/" + importTargetName, fin);
  +	t.save();
  +*/
   	String ntName = root.getProperty("jcr:primaryType").getString();
   	t.setNamespacePrefix("bla", "http://www.jcp.org/jcr/nt/1.0");
   	ntName = root.getProperty("jcr:primaryType").getString();
   	t.setNamespacePrefix("nt", "http://www.jcp.org/jcr/nt/1.0");
  -
  -
  -	
  -
  -	TreeMap descendants = new TreeMap(new Comparator() {
  -	    public int compare(Object o1, Object o2) {
  -		Path p1 = (Path) o1;
  -		Path p2 = (Path) o2;
  -		if (p1.equals(p2)) {
  -		    return 0;
  -		}
  -		try {
  -		    if (p1.isAncestorOf(p2)) {
  -			return -1;
  -		    } else if (p1.isDescendantOf(p2)) {
  -			return 1;
  -		    }
  -		} catch (MalformedPathException mpe) {
  -		    log.warn("inconsistent hierarchy state", mpe);
  -		}
  -		// the 2 paths are not on the same graph;
  -		// do string comparison of individual path elements
  -		Path.PathElement[] pea1 = p1.getElements();
  -		Path.PathElement[] pea2 = p2.getElements();
  -		for (int i = 0; i < pea1.length; i++) {
  -		    if (i >= pea2.length) {
  -			return 1;
  -		    }
  -		    String s1 = pea1[i].toString();
  -		    String s2 = pea2[i].toString();
  -		    int result = s1.compareTo(s2);
  -		    if (result != 0) {
  -			return result;
  -		    }
  -		}
  -		return 0;
  -	    }
  -	});
  -
  -	String[] paths = new String[] {
  -	    "/b/f/m",
  -	    "/b",
  -	    "/a/d/j",
  -	    "/a/c",
  -	    "/a/d/i",
  -	    "/b/e",
  -	    "/b/f/m",
  -	};
  -	for (int pi = 0; pi < paths.length; pi++) {
  -	    descendants.put(Path.create(paths[pi], (NamespaceResolver) wsp.getNamespaceRegistry(), true), paths[pi]);
  -	}
  -	Iterator piter = descendants.values().iterator();
  -	while (piter.hasNext()) {
  -	    System.out.println(piter.next());
  -	}
  -
  -
  -
  -
   
   	System.out.println("initial...");
   	System.out.println();
  
  
  
  1.22      +8 -19     jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/TicketImpl.java
  
  Index: TicketImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/TicketImpl.java,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- TicketImpl.java	18 Aug 2004 13:15:53 -0000	1.21
  +++ TicketImpl.java	24 Aug 2004 09:51:51 -0000	1.22
  @@ -19,6 +19,7 @@
   import org.apache.slide.jcr.core.nodetype.*;
   import org.apache.slide.jcr.core.state.NodeState;
   import org.apache.slide.jcr.core.state.TicketItemStateManager;
  +import org.apache.slide.jcr.core.xml.ImportHandler;
   import org.xml.sax.*;
   import org.xml.sax.helpers.XMLReaderFactory;
   
  @@ -453,10 +454,8 @@
   	    log.error(msg);
   	    throw new RepositoryException(msg);
   	}
  -	Node parent = (Node) item;
  -
  -	// @todo implement ContentHandler for asynchronuos import of document xml view
  -	throw new RepositoryException("Ticket.getImportContentHandler() is not implemented yet.");
  +	NodeImpl parent = (NodeImpl) item;
  +	return new ImportHandler(parent, rep.getNamespaceRegistry(), this);
       }
   
       /**
  @@ -466,7 +465,7 @@
   	    throws IOException, PathNotFoundException, ItemExistsException,
   	    ConstraintViolationException, InvalidSerializedDataException,
   	    RepositoryException {
  -	ContentHandler handler = getImportContentHandler(parentAbsPath);
  +	ImportHandler handler = (ImportHandler) getImportContentHandler(parentAbsPath);
   	try {
   	    XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
   /*
  @@ -475,19 +474,7 @@
   	    parser.setFeature("http://apache.org/xml/features/validation/schema-full-checking", true);
   */
   	    parser.setContentHandler(handler);
  -	    parser.setErrorHandler(new ErrorHandler() {
  -		public void error(SAXParseException exception) /*throws SAXException*/ {
  -		    log.error("error encountered while parsing XML stream", exception);
  -		}
  -
  -		public void fatalError(SAXParseException exception) /*throws SAXException*/ {
  -		    log.error("fatal error encountered while parsing XML stream", exception);
  -		}
  -
  -		public void warning(SAXParseException exception) /*throws SAXException*/ {
  -		    log.warn("warning encountered while parsing XML stream", exception);
  -		}
  -	    });
  +	    parser.setErrorHandler(handler);
   /*
   	    // validate against system view schema
   	    URL urlSchema = this.class.getClassLoader().getResource("javax/jcr/systemview.xsd");
  @@ -578,6 +565,8 @@
   	return nsMappings.getPrefix(uri);
       }
   
  +
  +    //------------------------------------------------------< locking support >
       /**
        * @see Ticket#addLockToken(String)
        */
  
  
  
  1.15      +18 -9     jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/WorkspaceImpl.java
  
  Index: WorkspaceImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/WorkspaceImpl.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- WorkspaceImpl.java	2 Aug 2004 16:21:05 -0000	1.14
  +++ WorkspaceImpl.java	24 Aug 2004 09:51:51 -0000	1.15
  @@ -18,6 +18,8 @@
   import org.apache.log4j.Logger;
   import org.apache.slide.jcr.core.nodetype.*;
   import org.apache.slide.jcr.core.state.*;
  +import org.apache.slide.jcr.core.xml.DocViewSAXEventGenerator;
  +import org.apache.slide.jcr.core.xml.SysViewSAXEventGenerator;
   import org.apache.slide.jcr.util.uuid.UUID;
   import org.apache.xml.serialize.OutputFormat;
   import org.apache.xml.serialize.XMLSerializer;
  @@ -473,11 +475,17 @@
   						     NodeTypeRegistry ntReg,
   						     HierarchyManagerImpl srcHierMgr,
   						     PersistentItemStateManager srcStateMgr,
  -						     PersistentItemStateManager destStateMgr)
  +						     PersistentItemStateManager destStateMgr,
  +						     boolean clone)
   	    throws RepositoryException {
   	PersistentNodeState newState;
   	try {
  -	    String uuid = UUID.randomUUID().toString();	// create new version 4 uuid
  +	    String uuid;
  +	    if (clone) {
  +		uuid = srcState.getUUID();
  +	    } else {
  +		uuid = UUID.randomUUID().toString();	// create new version 4 uuid
  +	    }
   	    newState = destStateMgr.createNodeState(uuid, srcState.getNodeTypeName(), parentUUID);
   	    // copy node state
   	    // @todo special handling required for nodes with special semantics (e.g. those defined by mix:versionable, et.al.)
  @@ -491,7 +499,7 @@
   		NodeState srcChildState = (NodeState) srcStateMgr.getItemState(new NodeId(entry.getUUID()));
   		// recursive copying of child node
   		PersistentNodeState newChildState = copyNodeState(srcChildState, uuid,
  -			ntReg, srcHierMgr, srcStateMgr, destStateMgr);
  +			ntReg, srcHierMgr, srcStateMgr, destStateMgr, clone);
   		// persist new child node
   		newChildState.store();
   		// add new child node entry to new node
  @@ -525,7 +533,7 @@
   							     PersistentItemStateManager srcStateMgr,
   							     PersistentItemStateManager destStateMgr)
   	    throws RepositoryException {
  -	// @todo special handling required for properties with special semantics (e.g. those defined by mix:versionable, et.al.)
  +	// @todo special handling required for properties with special semantics (e.g. those defined by mix:versionable, mix:lockable, et.al.)
   	PersistentPropertyState newState;
   	try {
   	    newState = destStateMgr.createPropertyState(parentUUID, propName);
  @@ -566,7 +574,8 @@
   				     HierarchyManagerImpl destHierMgr,
   				     AccessManagerImpl accessMgr,
   				     NamespaceResolver nsResolver,
  -				     NodeTypeRegistry ntReg)
  +				     NodeTypeRegistry ntReg,
  +				     boolean clone)
   	    throws ConstraintViolationException, AccessDeniedException,
   	    PathNotFoundException, ItemExistsException, RepositoryException {
   
  @@ -645,7 +654,7 @@
   
   	// create deep copy of source node state
   	PersistentNodeState newState = copyNodeState(srcState, destParentState.getUUID(),
  -		ntReg, srcHierMgr, srcStateMgr, destStateMgr);
  +		ntReg, srcHierMgr, srcStateMgr, destStateMgr, clone);
   
   	// add to new parent
   	destParentState.addChildNodeEntry(destName.getName(), newState.getUUID());
  @@ -722,7 +731,7 @@
   	internalCopy(srcAbsPath, persistentStateMgr, hierMgr,
   		destAbsPath, destStateMgr, destHierMgr,
   		ticket.getAccessManager(), ticket.getNamespaceResolver(),
  -		rep.getNodeTypeRegistry());
  +		rep.getNodeTypeRegistry(), true);
       }
   
       /**
  @@ -735,7 +744,7 @@
   	internalCopy(srcAbsPath, persistentStateMgr, hierMgr,
   		destAbsPath, persistentStateMgr, hierMgr,
   		ticket.getAccessManager(), ticket.getNamespaceResolver(),
  -		rep.getNodeTypeRegistry());
  +		rep.getNodeTypeRegistry(), false);
       }
   
       /**
  
  
  
  1.2       +2 -2      jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/version/GenericVersionSelector.java
  
  Index: GenericVersionSelector.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/version/GenericVersionSelector.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- GenericVersionSelector.java	18 Aug 2004 13:20:18 -0000	1.1
  +++ GenericVersionSelector.java	24 Aug 2004 09:51:54 -0000	1.2
  @@ -27,7 +27,7 @@
    * 'returnLatest' flag is set to <code>true</code>, the latest version is
    * returned.
    *
  - * @author tripod
  + * @author Tobias Strasser
    * @version $Revision$, $Date$
    */
   public class GenericVersionSelector implements VersionSelector {
  
  
  
  1.2       +2 -2      jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/version/VersionSelector.java
  
  Index: VersionSelector.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/version/VersionSelector.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- VersionSelector.java	18 Aug 2004 13:20:18 -0000	1.1
  +++ VersionSelector.java	24 Aug 2004 09:51:54 -0000	1.2
  @@ -23,7 +23,7 @@
    * This Interface defines the version selector that needs to provide a version,
    * given some hints and a version history
    * 
  - * @author tripod
  + * @author Tobias Strasser
    * @version $Revision$, $Date$
    */
   public interface VersionSelector {
  
  
  
  1.1                  jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/xml/AbstractSAXEventGenerator.java
  
  Index: AbstractSAXEventGenerator.java
  ===================================================================
  /*
   * Copyright 2002-2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.slide.jcr.core.xml;
  
  import org.apache.slide.jcr.core.state.NodeState;
  import org.apache.slide.jcr.core.state.PropertyState;
  import org.apache.slide.jcr.core.state.ItemStateProvider;
  import org.apache.slide.jcr.core.state.ItemStateException;
  import org.apache.slide.jcr.core.*;
  import org.apache.log4j.Logger;
  import org.xml.sax.ContentHandler;
  import org.xml.sax.SAXException;
  
  import javax.jcr.RepositoryException;
  import javax.jcr.access.Permission;
  import java.util.Iterator;
  
  /**
   * <code>AbstractSAXEventGenerator</code> serves as the base class for
   * <code>SysViewSAXEventGenerator</code> and <code>DocViewSAXEventGenerator</code>
   * <p/>
   * It traverses a tree of <code>NodeState</code> & <code>PropertyState</code>
   * instances, and calls the abstract methods
   * <ul>
   * <li><code>{@link #entering(NodeState, org.apache.slide.jcr.core.QName, int)}</code></li>
   * <li><code>{@link #enteringProperties(NodeState, org.apache.slide.jcr.core.QName, int)}</code></li>
   * <li><code>{@link #leavingProperties(NodeState, org.apache.slide.jcr.core.QName, int)}</code></li>
   * <li><code>{@link #leaving(NodeState, org.apache.slide.jcr.core.QName, int)}</code></li>
   * <li><code>{@link #entering(PropertyState, int)}</code></li>
   * <li><code>{@link #leaving(PropertyState, int)}</code></li>
   * </ul>
   * for every item state that is granted read access.
   *
   * @author Stefan Guggisberg
   * @version $Revision: 1.1 $, $Date: 2004/08/24 09:51:55 $
   */
  abstract class AbstractSAXEventGenerator {
  
      private static Logger log = Logger.getLogger(AbstractSAXEventGenerator.class);
  
      protected final ItemStateProvider stateProvider;
      protected final NamespaceRegistryImpl nsReg;
      protected final AccessManagerImpl accessMgr;
      protected final ContentHandler contentHandler;
      protected final NodeState startNodeState;
      protected final QName startNodeName;
      protected final boolean binaryAsLink;
      protected final boolean noRecurse;
  
      // dummy name for root node (jcr:root)
      public static final QName NODENAME_ROOT =
  	    new QName(NamespaceRegistryImpl.NS_JCR_URI, "root");
      // jcr:uuid
      protected static final QName PROPNAME_UUID = ItemImpl.PROPNAME_UUID;
      // jcr:primaryType
      protected static final QName PROPNAME_PRIMARYTYPE = ItemImpl.PROPNAME_PRIMARYTYPE;
      // jcr:mixinTypes
      protected static final QName PROPNAME_MIXINTYPES = ItemImpl.PROPNAME_MIXINTYPES;
  
      /**
       * Constructor
       *
       * @param nodeState      the node state which should be serialized
       * @param noRecurse      if true, only <code>nodeState</code> and its properties will
       *                       be serialized; otherwise the entire hierarchy starting with
       *                       <code>nodeState</code> will be serialized.
       * @param binaryAsLink   specifies if binary properties are turned into links
       * @param nodeName       name of the node to be serialized
       * @param stateProvider  item state provider for retrieving child item state
       * @param nsReg          the namespace registry to be used for namespace declarations
       * @param accessMgr      the access manager
       * @param contentHandler the content handler to feed the SAX events to
       */
      protected AbstractSAXEventGenerator(NodeState nodeState, QName nodeName,
  					boolean noRecurse, boolean binaryAsLink,
  					ItemStateProvider stateProvider,
  					NamespaceRegistryImpl nsReg,
  					AccessManagerImpl accessMgr,
  					ContentHandler contentHandler) {
  	this.stateProvider = stateProvider;
  	this.nsReg = nsReg;
  	this.accessMgr = accessMgr;
  	startNodeState = nodeState;
  	startNodeName = nodeName;
  	this.contentHandler = contentHandler;
  	this.binaryAsLink = binaryAsLink;
  	this.noRecurse = noRecurse;
      }
  
      /**
       * Serializes the hierarchy of nodes and properties.
       *
       * @throws javax.jcr.RepositoryException if an error occurs while traversing the hierarchy
       * @throws org.xml.sax.SAXException      if an error occured while feeding the events to the content handler
       */
      public void serialize() throws RepositoryException, SAXException {
  	contentHandler.startDocument();
  	// namespace declarations
  	documentPrefixMappings();
  	// start serializing node state(s)
  	process(startNodeState, startNodeName, 0);
  
  	contentHandler.endDocument();
      }
  
      /**
       *
       * @throws RepositoryException
       * @throws SAXException
       */
      protected void documentPrefixMappings() throws RepositoryException, SAXException {
  	// namespace declarations
  	String[] prefixes = nsReg.getPrefixes();
  	for (int i = 0; i < prefixes.length; i++) {
  	    String prefix = prefixes[i];
  	    String uri = nsReg.getURI(prefix);
  	    contentHandler.startPrefixMapping(prefix, uri);
  	}
      }
  
      /**
       * @param nodeState
       * @param level
       * @throws RepositoryException
       * @throws SAXException
       */
      protected void process(NodeState nodeState, QName nodeName, int level)
  	    throws RepositoryException, SAXException {
  
  	// enter node
  	entering(nodeState, nodeName, level);
  
  	// enter properties
  	enteringProperties(nodeState, nodeName, level);
  
  	// serialize jcr:primaryType, jcr:mixinTypes & jcr:uuid first:
  	// jcr:primaryType
  	if (nodeState.hasPropertyEntry(PROPNAME_PRIMARYTYPE)) {
  	    process(nodeState.getPropertyEntry(PROPNAME_PRIMARYTYPE), nodeState.getUUID(), level + 1);
  	} else {
  	    String msg = "internal error: missing jcr:primaryType property on node " + nodeState.getUUID();
  	    log.error(msg);
  	    throw new RepositoryException(msg);
  	}
  	// jcr:mixinTypes
  	if (nodeState.hasPropertyEntry(PROPNAME_MIXINTYPES)) {
  	    process(nodeState.getPropertyEntry(PROPNAME_MIXINTYPES), nodeState.getUUID(), level + 1);
  	}
  	// jcr:uuid
  	if (nodeState.hasPropertyEntry(PROPNAME_UUID)) {
  	    process(nodeState.getPropertyEntry(PROPNAME_UUID), nodeState.getUUID(), level + 1);
  	}
  
  	// serialize remaining properties
  	Iterator iter = nodeState.getPropertyEntries().iterator();
  	while (iter.hasNext()) {
  	    NodeState.PropertyEntry pe = (NodeState.PropertyEntry) iter.next();
  	    if (PROPNAME_PRIMARYTYPE.equals(pe.getName()) ||
  		    PROPNAME_MIXINTYPES.equals(pe.getName()) ||
  		    PROPNAME_UUID.equals(pe.getName())) {
  		continue;
  	    }
  	    PropertyId propId = new PropertyId(nodeState.getUUID(), pe.getName());
  	    // check read access
  	    if (accessMgr.isGranted(propId, Permission.READ_ITEM)) {
  		// serialize property
  		process(pe, nodeState.getUUID(), level + 1);
  	    }
  	}
  
  	// leaving properties
  	leavingProperties(nodeState, nodeName, level);
  
  	if (!noRecurse) {
  	    // child nodes
  	    iter = nodeState.getChildNodeEntries().iterator();
  	    while (iter.hasNext()) {
  		NodeState.ChildNodeEntry cne = (NodeState.ChildNodeEntry) iter.next();
  		NodeId childId = new NodeId(cne.getUUID());
  		// check read access
  		if (accessMgr.isGranted(childId, Permission.READ_ITEM)) {
  		    NodeState childState;
  		    try {
  			childState = (NodeState) stateProvider.getItemState(childId);
  		    } catch (ItemStateException ise) {
  			String msg = "internal error: failed to retrieve state of node " + childId;
  			log.error(msg, ise);
  			throw new RepositoryException(msg, ise);
  		    }
  		    // recurse
  		    process(childState, cne.getName(), level + 1);
  		}
  	    }
  	}
  
  	// leaving node
  	leaving(nodeState, nodeName, level);
      }
  
      /**
       *
       * @param propEntry
       * @param parentUUID
       * @param level
       * @throws RepositoryException
       * @throws SAXException
       */
      protected void process(NodeState.PropertyEntry propEntry, String parentUUID, int level)
  	    throws RepositoryException, SAXException {
  	PropertyId propId = new PropertyId(parentUUID, propEntry.getName());
  	try {
  	    PropertyState propState = (PropertyState) stateProvider.getItemState(propId);
  	    // serialize property
  	    entering(propState, level);
  	    leaving(propState, level);
  	} catch (ItemStateException ise) {
  	    String msg = "internal error: failed to retrieve state of property " + propId;
  	    log.error(msg, ise);
  	    throw new RepositoryException(msg, ise);
  	}
      }
  
      /**
       *
       * @param state
       * @param name
       * @param level
       * @throws RepositoryException
       * @throws SAXException
       */
      abstract protected void entering(NodeState state, QName name, int level)
  	    throws RepositoryException, SAXException;
  
      /**
       *
       * @param state
       * @param name
       * @param level
       * @throws RepositoryException
       * @throws SAXException
       */
      abstract protected void enteringProperties(NodeState state, QName name, int level)
  	    throws RepositoryException, SAXException;
  
      /**
       *
       * @param state
       * @param name
       * @param level
       * @throws RepositoryException
       * @throws SAXException
       */
      abstract protected void leavingProperties(NodeState state, QName name, int level)
  	    throws RepositoryException, SAXException;
  
      /**
       *
       * @param state
       * @param name
       * @param level
       * @throws RepositoryException
       * @throws SAXException
       */
      abstract protected void leaving(NodeState state, QName name, int level)
  	    throws RepositoryException, SAXException;
  
      /**
       *
       * @param state
       * @param level
       * @throws RepositoryException
       * @throws SAXException
       */
      abstract protected void entering(PropertyState state, int level)
  	    throws RepositoryException, SAXException;
  
      /**
       *
       * @param state
       * @param level
       * @throws RepositoryException
       * @throws SAXException
       */
      abstract protected void leaving(PropertyState state, int level)
  	    throws RepositoryException, SAXException;
  }
  
  
  
  1.1                  jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/xml/DocViewImportHandler.java
  
  Index: DocViewImportHandler.java
  ===================================================================
  /*
   * Copyright 2002-2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.slide.jcr.core.xml;
  
  import org.apache.log4j.Logger;
  import org.apache.slide.jcr.core.nodetype.NodeTypeRegistry;
  import org.apache.slide.jcr.core.TicketImpl;
  import org.apache.slide.jcr.core.NodeImpl;
  import org.apache.slide.jcr.core.QName;
  import org.xml.sax.Attributes;
  import org.xml.sax.ContentHandler;
  import org.xml.sax.SAXException;
  import org.xml.sax.helpers.DefaultHandler;
  
  import javax.jcr.RepositoryException;
  import java.util.Stack;
  
  /**
   * <code>DocViewImportHandler</code>  ...
   *
   * @author Stefan Guggisberg
   * @version $Revision: 1.1 $, $Date: 2004/08/24 09:51:55 $
   */
  class DocViewImportHandler extends DefaultHandler {
  
      private static Logger log = Logger.getLogger(DocViewImportHandler.class);
  
      private Stack parents;
      private TicketImpl ticket;
  
      DocViewImportHandler(NodeImpl importTargetNode, TicketImpl ticket) {
  	this.ticket = ticket;
  	parents = new Stack();
  
  	parents.push(importTargetNode);
      }
  
      //-------------------------------------------------------< ContentHandler >
      /**
       * @see ContentHandler#startElement(String, String, String, Attributes)
       */
      public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
  	try {
  	    String nodeName;
  	    if (qName == null || "".equals(qName)) {
  		nodeName = new QName(namespaceURI, localName).toJCRName(ticket.getNamespaceResolver());
  	    } else {
  		nodeName = qName;
  	    }
  
  	    // @todo how should 'system' properties be handled in document view (e.g. jcr:primaryType,jcr:mixinTypes, jcr:uuid)?
  	    NodeImpl currentParent = (NodeImpl) parents.peek();
  	    currentParent = (NodeImpl) currentParent.addNode(nodeName, NodeTypeRegistry.NT_UNSTRUCTURED.toJCRName(ticket.getNamespaceResolver()));
  	    parents.push(currentParent);
  
  	    // properties
  	    for (int i = 0; i < atts.getLength(); i++) {
  		String propName;
  		if (atts.getQName(i) == null || "".equals(atts.getQName(i))) {
  		    propName = new QName(atts.getURI(i), atts.getLocalName(i)).toJCRName(ticket.getNamespaceResolver());
  		} else {
  		    propName = atts.getQName(i);
  		}
  		String value = atts.getValue(i);
  		currentParent.setProperty(propName, value);
  	    }
  	} catch (RepositoryException re) {
  	    throw new SAXException(re);
  	}
      }
  
      /**
       * @see ContentHandler#characters(char[], int, int)
       */
      public void characters(char ch[], int start, int length) throws SAXException {
  	// character data in document view:
  	// store as jcr:xmlcharacters property of jcr:xmltext node
  	// (need to store as node in order to maintain ordering)
  	try {
  	    NodeImpl currentParent = (NodeImpl) parents.peek();
  	    NodeImpl txtNode = (NodeImpl) currentParent.addNode(DocViewSAXEventGenerator.NODENAME_XMLTEXT.toJCRName(ticket.getNamespaceResolver()));
  	    txtNode.setProperty(DocViewSAXEventGenerator.PROPNAME_XMLCHARACTERS.toJCRName(ticket.getNamespaceResolver()),
  		    new String(ch, start, length));
  	} catch (RepositoryException re) {
  	    throw new SAXException(re);
  	}
      }
  
      /**
       * @see ContentHandler#endElement(String, String, String)
       */
      public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
  	parents.pop();
      }
  }
  
  
  
  1.1                  jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/xml/DocViewSAXEventGenerator.java
  
  Index: DocViewSAXEventGenerator.java
  ===================================================================
  /*
   * Copyright 2002-2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.slide.jcr.core.xml;
  
  import org.apache.log4j.Logger;
  import org.apache.slide.jcr.core.*;
  import org.apache.slide.jcr.core.state.ItemStateProvider;
  import org.apache.slide.jcr.core.state.NodeState;
  import org.apache.slide.jcr.core.state.PropertyState;
  import org.apache.slide.jcr.util.Base64;
  import org.apache.xml.utils.XMLChar;
  import org.xml.sax.ContentHandler;
  import org.xml.sax.SAXException;
  import org.xml.sax.helpers.AttributesImpl;
  
  import javax.jcr.InvalidSerializedDataException;
  import javax.jcr.PropertyType;
  import javax.jcr.RepositoryException;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.StringWriter;
  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.
   *
   * @author Stefan Guggisberg
   * @version $Revision: 1.1 $, $Date: 2004/08/24 09:51:55 $
   */
  public class DocViewSAXEventGenerator extends AbstractSAXEventGenerator {
  
      private static Logger log = Logger.getLogger(DocViewSAXEventGenerator.class);
  
      protected final HierarchyManager hierMgr;
  
      public static final String CDATA_TYPE = "CDATA";
  
      // jcr:xmltext
      public static final QName NODENAME_XMLTEXT =
  	    new QName(NamespaceRegistryImpl.NS_JCR_URI, "xmltext");
      // jcr:xmltext
      public static final QName PROPNAME_XMLCHARACTERS =
  	    new QName(NamespaceRegistryImpl.NS_JCR_URI, "xmlcharacters");
  
      // used to temporarily store properties of a node
      private final List props;
  
      /**
       * Constructor
       *
       * @param nodeState      the node state which should be serialized
       * @param nodeName       name of the node to be serialized
       * @param noRecurse      if true, only <code>nodeState</code> and its properties will
       *                       be serialized; otherwise the entire hierarchy starting with
       *                       <code>nodeState</code> will be serialized.
       * @param binaryAsLink   specifies if binary properties are turned into links
       * @param stateProvider  item state provider for retrieving child item state
       * @param nsReg          the namespace registry to be used for namespace declarations
       * @param accessMgr      the access manager
       * @param hierMgr        the hierarchy manager used to resolve paths
       * @param contentHandler the content handler to feed the SAX events to
       */
      public DocViewSAXEventGenerator(NodeState nodeState, QName nodeName,
  				    boolean noRecurse, boolean binaryAsLink,
  				    ItemStateProvider stateProvider,
  				    NamespaceRegistryImpl nsReg,
  				    AccessManagerImpl accessMgr,
  				    HierarchyManager hierMgr,
  				    ContentHandler contentHandler) {
  	super(nodeState, nodeName, noRecurse, binaryAsLink,
  		stateProvider, nsReg, accessMgr, contentHandler);
  	this.hierMgr = hierMgr;
  
  	props = new ArrayList();
      }
  
      /**
       * @see AbstractSAXEventGenerator#entering(NodeState, QName, int)
       */
      protected void entering(NodeState state, QName name, int level)
  	    throws RepositoryException, SAXException {
  	// nop
      }
  
      /**
       * @see AbstractSAXEventGenerator#enteringProperties(NodeState, QName, int)
       */
      protected void enteringProperties(NodeState state, QName name, int level)
  	    throws RepositoryException, SAXException {
  	// reset list of properties
  	props.clear();
      }
  
      /**
       * @see AbstractSAXEventGenerator#leavingProperties(NodeState, QName, int)
       */
      protected void leavingProperties(NodeState state, QName name, int level)
  	    throws RepositoryException, SAXException {
  	if (name.equals(NODENAME_XMLTEXT)) {
  	    // the node represents xml character data
  	    Iterator iter = props.iterator();
  	    while (iter.hasNext()) {
  		PropertyState propState = (PropertyState) iter.next();
  		QName propName = propState.getName();
  		if (propName.equals(PROPNAME_XMLCHARACTERS)) {
  		    InternalValue val = propState.getValues()[0];
  		    char[] chars = val.toJCRValue(nsReg).getString().toCharArray();
  		    contentHandler.characters(chars, 0, chars.length);
  		}
  	    }
  	} else {
  	    // regalur node
  
  	    // element name
  	    String elemName;
  	    if (state.getParentUUIDs().size() == 0) {
  		// root node needs a name
  		elemName = NODENAME_ROOT.toJCRName(nsReg);
  	    } else {
  		elemName = name.toJCRName(nsReg);
  	    }
  	    if (!XMLChar.isValidName(elemName)) {
  		throw new InvalidSerializedDataException("the node name is not a valid xml element name: " + elemName);
  	    }
  
  	    // attributes (properties)
  	    AttributesImpl attrs = new AttributesImpl();
  	    Iterator iter = props.iterator();
  	    while (iter.hasNext()) {
  		PropertyState propState = (PropertyState) iter.next();
  		QName propName = propState.getName();
  		// attribute name
  		String attrName = propState.getName().toJCRName(nsReg);
  		if (!XMLChar.isValidName(attrName)) {
  		    throw new InvalidSerializedDataException("the property name is not a valid xml attribute name: " + attrName);
  		}
  		// attribute value
  		String attrValue;
  		int type = propState.getType();
  		// process property value (guaranteed to be single-valued and non-null)
  		InternalValue val = propState.getValues()[0];
  		if (type == PropertyType.BINARY) {
  		    if (binaryAsLink) {
  			attrValue = hierMgr.getPath(new PropertyId(propState.getParentUUID(), propState.getName())).toJCRPath(nsReg);
  		    } else {
  			// binary data, base64 encoding required
  			BLOBFileValue blob = (BLOBFileValue) val.internalValue();
  			InputStream in = blob.getStream();
  			StringWriter writer = new StringWriter();
  			try {
  			    Base64.encode(in, writer);
  			    in.close();
  			    writer.close();
  			} catch (IOException ioe) {
  			    // check if the exception wraps a SAXException
  			    Throwable t = ioe.getCause();
  			    if (t != null && t instanceof SAXException) {
  				throw (SAXException) t;
  			    } else {
  				throw new SAXException(ioe);
  			    }
  			}
  			attrValue = writer.toString();
  		    }
  		} else {
  		    attrValue = val.toJCRValue(nsReg).getString();
  		}
  		attrs.addAttribute(propName.getNamespaceURI(), propName.getLocalName(), propName.toJCRName(nsReg), CDATA_TYPE, attrValue);
  	    }
  	    // start element (node)
  	    contentHandler.startElement(name.getNamespaceURI(), name.getLocalName(), elemName, attrs);
  	}
      }
  
      /**
       * @see AbstractSAXEventGenerator#leaving(NodeState, QName, int)
       */
      protected void leaving(NodeState state, QName name, int level)
  	    throws RepositoryException, SAXException {
  	if (name.equals(NODENAME_XMLTEXT)) {
  	    // the node represents xml character data
  	    // (already processed in leavingProperties(NodeState, QName, int)
  	    return;
  	}
  	// element name
  	String elemName;
  	if (state.getParentUUIDs().size() == 0) {
  	    // root node needs a name
  	    elemName = NODENAME_ROOT.toJCRName(nsReg);
  	} else {
  	    elemName = name.toJCRName(nsReg);
  	}
  
  	// end element (node)
  	contentHandler.endElement(name.getNamespaceURI(), name.getLocalName(), elemName);
      }
  
      /**
       * @see AbstractSAXEventGenerator#entering(PropertyState, int)
       */
      protected void entering(PropertyState state, int level)
  	    throws RepositoryException, SAXException {
  	// @todo should properties declared in the 'jcr:' namespace be skipped in the document view export?
  /*
  	// skip 'system' properties (e.g. jcr:primaryType, jcr:mixinTypes, jcr:uuid)
  	if (NamespaceRegistryImpl.NS_JCR_URI.equals(state.getName().getNamespaceURI())) {
  	    return;
  	}
  */
  	// collect property state in temporary list (will be processed in leavingProperties(NodeState, QName, int)
  	InternalValue[] values = state.getValues();
  	if (values != null && values.length > 0) {
  	    if (values.length != 1) {
  		throw new InvalidSerializedDataException("unable to serialize multi-valued property in document view: " + state.getName().toJCRName(nsReg));
  	    }
  	    if (values[0] != null) {
  		props.add(state);
  	    }
  	}
      }
  
      /**
       * @see AbstractSAXEventGenerator#leaving(PropertyState, int)
       */
      protected void leaving(PropertyState state, int level)
  	    throws RepositoryException, SAXException {
  	// nop
      }
  }
  
  
  
  1.1                  jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/xml/ImportHandler.java
  
  Index: ImportHandler.java
  ===================================================================
  /*
   * Copyright 2002-2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.slide.jcr.core.xml;
  
  import org.apache.log4j.Logger;
  import org.apache.slide.jcr.core.*;
  import org.xml.sax.*;
  import org.xml.sax.helpers.DefaultHandler;
  
  import javax.jcr.NamespaceException;
  import javax.jcr.RepositoryException;
  
  /**
   * An <code>ImportHandler</code> instance can be used to import serialized
   * data in System View XML or Document View XML. The actual task of importing
   * is delegated to specialized <code>ContentHandler</code>s (i.e.
   * <code>SysViewImportHandler</code> and <code>DocViewImportHandler</code>).
   *
   * @author Stefan Guggisberg
   * @version $Revision: 1.1 $, $Date: 2004/08/24 09:51:55 $
   */
  public class ImportHandler extends DefaultHandler {
  
      private static Logger log = Logger.getLogger(ImportHandler.class);
  
      protected Locator locator;
      protected ContentHandler targetHandler;
  
      protected TicketImpl ticket;
      protected NodeImpl importTargetNode;
      protected NamespaceRegistryImpl nsReg;
      protected boolean systemViewXML;
      protected boolean initialized;
  
      public ImportHandler(NodeImpl importTargetNode, NamespaceRegistryImpl nsReg, TicketImpl ticket) {
  	this.importTargetNode = importTargetNode;
  	this.ticket = ticket;
  	this.nsReg = nsReg;
      }
  
      //---------------------------------------------------------< ErrorHandler >
      /**
       * @see ErrorHandler#warning(SAXParseException)
       */
      public void warning(SAXParseException e) throws SAXException {
  	// log exception and carry on...
  	log.warn("warning encountered at line: " + e.getLineNumber() + ", column: " + e.getColumnNumber() + " while parsing XML stream", e);
      }
  
      /**
       * @see ErrorHandler#error(org.xml.sax.SAXParseException)
       */
      public void error(SAXParseException e) throws SAXException {
  	// log exception and carry on...
  	log.error("error encountered at line: " + e.getLineNumber() + ", column: " + e.getColumnNumber() + " while parsing XML stream", e);
      }
  
      /**
       * @see ErrorHandler#fatalError(SAXParseException)
       */
      public void fatalError(SAXParseException e) throws SAXException {
  	// log and re-throw exception
  	log.error("fatal error encountered at line: " + e.getLineNumber() + ", column: " + e.getColumnNumber() + " while parsing XML stream", e);
  	throw e;
      }
  
      //-------------------------------------------------------< ContentHandler >
      /**
       * @see ContentHandler#startDocument()
       */
      public void startDocument() throws SAXException {
  	systemViewXML = false;
  	initialized = false;
  	targetHandler = null;
      }
  
      /**
       * @see ContentHandler#endDocument()
       */
      public void endDocument() throws SAXException {
  	// delegate to target handler
  	targetHandler.endDocument();
      }
  
      /**
       * @see ContentHandler#startPrefixMapping(String, String)
       */
      public void startPrefixMapping(String prefix, String uri) throws SAXException {
  	try {
  	    String oldPrefix = ticket.getNamespacePrefix(uri);
  	    // namespace is already registered; check prefix
  	    if (!oldPrefix.equals(prefix)) {
  		// namespace is mapped to different prefix;
  		// try to remap it to given prefix
  		try {
  		    ticket.setNamespacePrefix(prefix, uri);
  		} catch (RepositoryException re) {
  		    throw new SAXException("failed to remap namespace " + uri + " to prefix " + prefix, re);
  		}
  	    }
  	} catch (NamespaceException nse) {
  	    // namespace is not yet registered, try to register it
  	    try {
  		nsReg.registerNamespace(prefix, uri);
  	    } catch (RepositoryException re) {
  		throw new SAXException("failed to register namespace " + uri + " with prefix " + prefix, re);
  	    }
  	}
      }
  
      /**
       * @see ContentHandler#startElement(String, String, String, Attributes)
       */
      public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
  	if (!initialized) {
  	    // the namespace of the first element determines the type of XML
  	    // (system view/document view)
  	    String nsURI;
  	    if (qName == null || "".equals(qName)) {
  		nsURI = namespaceURI;
  	    } else {
  		try {
  		    nsURI = QName.fromJCRName(qName, ticket.getNamespaceResolver()).getNamespaceURI();
  		} catch (RepositoryException re) {
  		    throw new SAXException("failed to determine namespace of element " + qName, re);
  		}
  	    }
  	    systemViewXML = NamespaceRegistryImpl.NS_SV_URI.equals(nsURI);
  
  	    if (systemViewXML) {
  		targetHandler = new SysViewImportHandler(importTargetNode, ticket);
  	    } else {
  		targetHandler = new DocViewImportHandler(importTargetNode, ticket);
  	    }
  	    targetHandler.startDocument();
  	    initialized = true;
  	}
  
  	// delegate to target handler
  	targetHandler.startElement(namespaceURI, localName, qName, atts);
      }
  
      /**
       * @see ContentHandler#characters(char[], int, int)
       */
      public void characters(char ch[], int start, int length) throws SAXException {
  	// delegate to target handler
  	targetHandler.characters(ch, start, length);
      }
  
      /**
       * @see ContentHandler#endElement(String, String, String)
       */
      public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
  	// delegate to target handler
  	targetHandler.endElement(namespaceURI, localName, qName);
      }
  
      /**
       * @see ContentHandler#setDocumentLocator(Locator)
       */
      public void setDocumentLocator(Locator locator) {
  	this.locator = locator;
      }
  }
  
  
  
  1.1                  jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/xml/SysViewImportHandler.java
  
  Index: SysViewImportHandler.java
  ===================================================================
  /*
   * Copyright 2002-2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.slide.jcr.core.xml;
  
  import org.apache.log4j.Logger;
  import org.apache.slide.jcr.util.Base64;
  import org.apache.slide.jcr.util.ValueHelper;
  import org.apache.slide.jcr.core.*;
  import org.xml.sax.ContentHandler;
  import org.xml.sax.Attributes;
  import org.xml.sax.SAXException;
  import org.xml.sax.helpers.DefaultHandler;
  
  import javax.jcr.*;
  import javax.jcr.nodetype.NodeDef;
  import javax.jcr.nodetype.PropertyDef;
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.Stack;
  
  /**
   * <code>SysViewImportHandler</code>  ...
   *
   * @author Stefan Guggisberg
   * @version $Revision: 1.1 $, $Date: 2004/08/24 09:51:55 $
   */
  class SysViewImportHandler extends DefaultHandler {
      private static Logger log = Logger.getLogger(SysViewImportHandler.class);
  
      private TicketImpl ticket;
  
      /**
       * stack of ImportState instances; an instance is pushed onto the stack
       * in the startElement method every time a sv:node element is encountered;
       * the same instance is popped from the stack in the endElement method
       * when the corresponding sv:node element is encountered.
       */
      private Stack stateStack = new Stack();
  
      /**
       * fields used temporarily while processing sv:property and sv:value elements
       */
      private QName currentPropName;
      private int currentPropType = PropertyType.UNDEFINED;
      private ArrayList currentPropValues;
      private StringBuffer currentPropValue;
  
      SysViewImportHandler(NodeImpl importTargetNode, TicketImpl ticket) {
  	ImportState state = new ImportState();
  	state.node = importTargetNode;
  	this.ticket = ticket;
  	stateStack.push(state);
      }
  
      //-------------------------------------------------------< ContentHandler >
      /**
       * @see ContentHandler#startElement(String, String, String, Attributes)
       */
      public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
  	try {
  	    String elemName;
  	    String nsURI;
  	    if (qName == null || "".equals(qName)) {
  		nsURI = namespaceURI;
  		elemName = localName;
  	    } else {
  		nsURI = QName.fromJCRName(qName, ticket.getNamespaceResolver()).getNamespaceURI();
  		elemName = QName.fromJCRName(qName, ticket.getNamespaceResolver()).getLocalName();
  	    }
  	    // check namespace
  	    if (!NamespaceRegistryImpl.NS_SV_URI.equals(nsURI)) {
  		throw new SAXException(new InvalidSerializedDataException("invalid namespace for element in system view xml document: " + nsURI));
  	    }
  	    // check element name
  	    if (SysViewSAXEventGenerator.NODE_ELEMENT.equals(elemName)) {
  		// sv:node element
  
  		// node name (sv:name attribute)
  		String name = atts.getValue(SysViewSAXEventGenerator.NS_SV_URI, SysViewSAXEventGenerator.NAME_ATTRIBUTE);
  		if (name == null) {
  		    // try qualified name
  		    name = atts.getValue(SysViewSAXEventGenerator.NS_SV_PREFIX + ":" + SysViewSAXEventGenerator.NAME_ATTRIBUTE);
  		}
  		if (name == null) {
  		    throw new SAXException(new InvalidSerializedDataException("missing mandatory sv:name attributeof element sv:node"));
  		}
  
  		ImportState current = (ImportState) stateStack.peek();
  		if (current.node == null) {
  		    // need to create current node first
  		    createNode(current);
  		}
  
  		// push new ImportState instance onto the stack
  		ImportState state = new ImportState();
  		state.parent = current.node;
  		state.nodeName = QName.fromJCRName(name, ticket.getNamespaceResolver());
  		stateStack.push(state);
  	    } else if (SysViewSAXEventGenerator.PROPERTY_ELEMENT.equals(elemName)) {
  		// sv:property element
  
  		// reset temp fields
  		currentPropValues = new ArrayList();
  
  		// property name (sv:name attribute)
  		String name = atts.getValue(SysViewSAXEventGenerator.NS_SV_URI, SysViewSAXEventGenerator.NAME_ATTRIBUTE);
  		if (name == null) {
  		    // try qualified name
  		    name = atts.getValue(SysViewSAXEventGenerator.NS_SV_PREFIX + ":" + SysViewSAXEventGenerator.NAME_ATTRIBUTE);
  		}
  		if (name == null) {
  		    throw new SAXException(new InvalidSerializedDataException("missing mandatory sv:name attributeof element sv:property"));
  		}
  		currentPropName = QName.fromJCRName(name, ticket.getNamespaceResolver());
  		// property type (sv:type attribute)
  		String type = atts.getValue(SysViewSAXEventGenerator.NS_SV_URI, SysViewSAXEventGenerator.TYPE_ATTRIBUTE);
  		if (type == null) {
  		    // try qualified name
  		    type = atts.getValue(SysViewSAXEventGenerator.NS_SV_PREFIX + ":" + SysViewSAXEventGenerator.TYPE_ATTRIBUTE);
  		}
  		if (type == null) {
  		    throw new SAXException(new InvalidSerializedDataException("missing mandatory sv:type attributeof element sv:property"));
  		}
  		currentPropType = PropertyType.valueFromName(type);
  	    } else if (SysViewSAXEventGenerator.VALUE_ELEMENT.equals(elemName)) {
  		// sv:value element
  
  		// reset temp fields
  		currentPropValue = new StringBuffer();
  	    } else {
  		throw new SAXException(new InvalidSerializedDataException("unexpected element found in system view xml document: " + elemName));
  	    }
  	} catch (RepositoryException re) {
  	    throw new SAXException(re);
  	}
      }
  
      /**
       * @see ContentHandler#characters(char[], int, int)
       */
      public void characters(char ch[], int start, int length) throws SAXException {
  	if (currentPropValue != null) {
  	    // property value (character data of sv:value element)
  	    currentPropValue.append(ch, start, length);
  	}
      }
  
      /**
       * @see ContentHandler#endElement(String, String, String)
       */
      public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
  	try {
  	    String elemName;
  	    if (qName == null || "".equals(qName)) {
  		elemName = localName;
  	    } else {
  		elemName = QName.fromJCRName(qName, ticket.getNamespaceResolver()).getLocalName();
  	    }
  	    // check element name
  	    ImportState current = (ImportState) stateStack.peek();
  	    if (SysViewSAXEventGenerator.NODE_ELEMENT.equals(elemName)) {
  		// sv:node element
  		if (current.node == null) {
  		    // need to create current node first
  		    createNode(current);
  		}
  		// pop current state from stack
  		stateStack.pop();
  	    } else if (SysViewSAXEventGenerator.PROPERTY_ELEMENT.equals(elemName)) {
  		// sv:property element
  
  		// check if all system properties (jcr:primaryType, jcr:uuid etc.)
  		// have been collected and create node as necessary
  		if (currentPropName.equals(ItemImpl.PROPNAME_PRIMARYTYPE)) {
  		    current.primaryType = QName.fromJCRName((String) currentPropValues.get(0), ticket.getNamespaceResolver());
  		} else if (currentPropName.equals(ItemImpl.PROPNAME_MIXINTYPES)) {
  		    if (current.mixinTypes == null) {
  			current.mixinTypes = new ArrayList(currentPropValues.size());
  		    }
  		    for (int i = 0; i < currentPropValues.size(); i++) {
  			QName mixin = QName.fromJCRName((String) currentPropValues.get(i), ticket.getNamespaceResolver());
  			current.mixinTypes.add(mixin);
  		    }
  		} else if (currentPropName.equals(ItemImpl.PROPNAME_UUID)) {
  		    current.uuid = (String) currentPropValues.get(0);
  		    // jcr:uuid is the last system property; we can assume that all
  		    // required system properties have been collected by now
  		    if (current.node == null) {
  			// now that we're collected all required system properties
  			// we're ready to create the node
  			createNode(current);
  		    }
  		} else {
  		    // non-system property encountered; we can assume that all
  		    // required system properties have been collected by now
  		    if (current.node == null) {
  			// now that we're collected all required system properties
  			// we're ready to create the node
  			createNode(current);
  		    }
  
  		    // convert values to native type and set property
  		    Value[] vals = new Value[currentPropValues.size()];
  		    for (int i = 0; i < currentPropValues.size(); i++) {
  			String value = (String) currentPropValues.get(i);
  			if (currentPropType == PropertyType.BINARY) {
  			    // base64 encoded binary value
  			    ByteArrayOutputStream baos = new ByteArrayOutputStream();
  			    try {
  				Base64.decode(value, baos);
  				baos.close();
  			    } catch (IOException ioe) {
  				throw new SAXException("failed to decode binary value", ioe);
  			    }
  			    vals[i] = new BinaryValue(baos.toByteArray());
  			} else {
  			    vals[i] = ValueHelper.convert(value, currentPropType);
  			}
  		    }
  		    String name = currentPropName.toJCRName(ticket.getNamespaceResolver());
  		    if (current.node.hasProperty(name)) {
  			PropertyDef def = current.node.getProperty(name).getDefinition();
  			if (!def.isProtected()) {
  			    current.node.setProperty(name, vals);
  			}
  		    } else {
  			current.node.setProperty(name, vals);
  		    }
  		}
  
  		// reset temp fields
  		currentPropValues = null;
  	    } else if (SysViewSAXEventGenerator.VALUE_ELEMENT.equals(elemName)) {
  		// sv:value element
  		currentPropValues.add(currentPropValue.toString());
  		// reset temp fields
  		currentPropValue = null;
  	    } else {
  		throw new SAXException(new InvalidSerializedDataException("invalid element in system view xml document: " + elemName));
  	    }
  
  	} catch (RepositoryException re) {
  	    throw new SAXException(re);
  	}
      }
  
      private void createNode(ImportState state) throws RepositoryException {
  	if (state.primaryType == null) {
  	    throw new InvalidSerializedDataException("missing mandatory jcr:primaryType property");
  	}
  	if (state.uuid != null) {
  	    // @todo what are the semantics of the uuid with respect to import?
  	    // move existing node with given uuid to current position?
  	    // create with new uuid? what about reference values refering to given uuid?
  	}
  	String nodeName = state.nodeName.toJCRName(ticket.getNamespaceResolver());
  	String typeName = state.primaryType.toJCRName(ticket.getNamespaceResolver());
  
  	if (state.parent.hasNode(nodeName)) {
  	    NodeDef def = state.parent.getNode(nodeName).getDefinition();
  	    if (def.isProtected() || def.isAutoCreate()) {
  		// @todo how to handle protected/auto-created child node?
  	    }
  	}
  
  	state.node = (NodeImpl) state.parent.addNode(nodeName, typeName);
  	if (state.mixinTypes != null) {
  	    for (int i = 0; i < state.mixinTypes.size(); i++) {
  		String mixinName = ((QName) state.mixinTypes.get(i)).toJCRName(ticket.getNamespaceResolver());
  		state.node.addMixin(mixinName);
  	    }
  	}
      }
  
      //--------------------------------------------------------< inner classes >
      class ImportState {
  	QName primaryType = null;
  	ArrayList mixinTypes = null;
  	String uuid = null;
  
  	QName nodeName = null;
  	NodeImpl parent = null;
  	NodeImpl node = null;
      }
  }
  
  
  
  1.1                  jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/xml/SysViewSAXEventGenerator.java
  
  Index: SysViewSAXEventGenerator.java
  ===================================================================
  /*
   * Copyright 2002-2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.slide.jcr.core.xml;
  
  import org.apache.log4j.Logger;
  import org.apache.slide.jcr.core.*;
  import org.apache.slide.jcr.core.state.ItemStateProvider;
  import org.apache.slide.jcr.core.state.NodeState;
  import org.apache.slide.jcr.core.state.PropertyState;
  import org.apache.slide.jcr.util.Base64;
  import org.xml.sax.ContentHandler;
  import org.xml.sax.SAXException;
  import org.xml.sax.helpers.AttributesImpl;
  
  import javax.jcr.PropertyType;
  import javax.jcr.RepositoryException;
  import java.io.IOException;
  import java.io.InputStream;
  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.
   *
   * @author Stefan Guggisberg
   * @version $Revision: 1.1 $, $Date: 2004/08/24 09:51:55 $
   */
  public class SysViewSAXEventGenerator extends AbstractSAXEventGenerator {
  
      private static Logger log = Logger.getLogger(SysViewSAXEventGenerator.class);
  
      protected final HierarchyManager hierMgr;
  
      /**
       * The XML elements and attributes used in serialization
       */
      public static final String NODE_ELEMENT = "node";
      public static final String PROPERTY_ELEMENT = "property";
      public static final String VALUE_ELEMENT = "value";
  
      public static final String NAME_ATTRIBUTE = "name";
      public static final String TYPE_ATTRIBUTE = "type";
      public static final String CDATA_TYPE = "CDATA";
      public static final String ENUMERATION_TYPE = "ENUMERATION";
  
      public static final String NS_SV_PREFIX = NamespaceRegistryImpl.NS_SV_PREFIX;
      public static final String NS_SV_URI = NamespaceRegistryImpl.NS_SV_URI;
  
      /**
       * Constructor
       *
       * @param nodeState      the node state which should be serialized
       * @param nodeName       name of the node to be serialized
       * @param noRecurse      if true, only <code>nodeState</code> and its properties will
       *                       be serialized; otherwise the entire hierarchy starting with
       *                       <code>nodeState</code> will be serialized.
       * @param binaryAsLink   specifies if binary properties are turned into links
       * @param stateProvider  item state provider for retrieving child item state
       * @param nsReg          the namespace registry to be used for namespace declarations
       * @param accessMgr      the access manager
       * @param hierMgr        the hierarchy manager used to resolve paths
       * @param contentHandler the content handler to feed the SAX events to
       */
      public SysViewSAXEventGenerator(NodeState nodeState, QName nodeName,
  				    boolean noRecurse, boolean binaryAsLink,
  				    ItemStateProvider stateProvider,
  				    NamespaceRegistryImpl nsReg,
  				    AccessManagerImpl accessMgr,
  				    HierarchyManager hierMgr,
  				    ContentHandler contentHandler) {
  	super(nodeState, nodeName, noRecurse, binaryAsLink,
  		stateProvider, nsReg, accessMgr, contentHandler);
  	this.hierMgr = hierMgr;
      }
  
      /**
       * @see AbstractSAXEventGenerator#entering(NodeState, QName, int)
       */
      protected void entering(NodeState state, QName name, int level)
  	    throws RepositoryException, SAXException {
  	AttributesImpl attrs = new AttributesImpl();
  	// name attribute
  	String nodeName;
  	if (state.getParentUUIDs().size() == 0) {
  	    // use dummy name for root node
  	    nodeName = NODENAME_ROOT.toJCRName(nsReg);
  	} else {
  	    nodeName = name.toJCRName(nsReg);
  	}
  	attrs.addAttribute(NS_SV_URI, NAME_ATTRIBUTE, NS_SV_PREFIX + ":" + NAME_ATTRIBUTE, CDATA_TYPE, nodeName);
  	// start node element
  	contentHandler.startElement(NS_SV_URI, NODE_ELEMENT, NS_SV_PREFIX + ":" + NODE_ELEMENT, attrs);
      }
  
      /**
       * @see AbstractSAXEventGenerator#enteringProperties(NodeState, QName, int)
       */
      protected void enteringProperties(NodeState state, QName name, int level)
  	    throws RepositoryException, SAXException {
  	// nop
      }
  
      /**
       * @see AbstractSAXEventGenerator#leavingProperties(NodeState, QName, int)
       */
      protected void leavingProperties(NodeState state, QName name, int level)
  	    throws RepositoryException, SAXException {
  	// nop
      }
  
      /**
       * @see AbstractSAXEventGenerator#leaving(NodeState, QName, int)
       */
      protected void leaving(NodeState state, QName name, int level)
  	    throws RepositoryException, SAXException {
  	// end node element
  	contentHandler.endElement(NS_SV_URI, NODE_ELEMENT, NS_SV_PREFIX + ":" + NODE_ELEMENT);
      }
  
      /**
       * @see AbstractSAXEventGenerator#entering(PropertyState, int)
       */
      protected void entering(PropertyState state, int level)
  	    throws RepositoryException, SAXException {
  	String name = state.getName().toJCRName(nsReg);
  	AttributesImpl attrs = new AttributesImpl();
  	// name attribute
  	attrs.addAttribute(NS_SV_URI, NAME_ATTRIBUTE, NS_SV_PREFIX + ":" + NAME_ATTRIBUTE, CDATA_TYPE, name);
  	// type attribute
  	int type = state.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);
  	}
  	if (type == PropertyType.BINARY && binaryAsLink) {
  	    typeName = PropertyType.TYPENAME_SOFTLINK;
  	}
  	attrs.addAttribute(NS_SV_URI, TYPE_ATTRIBUTE, NS_SV_PREFIX + ":" + TYPE_ATTRIBUTE, ENUMERATION_TYPE, typeName);
  
  	// start property element
  	contentHandler.startElement(NS_SV_URI, PROPERTY_ELEMENT, NS_SV_PREFIX + ":" + PROPERTY_ELEMENT, attrs);
  
  	// values
  	InternalValue[] values = state.getValues();
  	if (values != null && values.length > 0) {
  	    for (int i = 0; i < values.length; i++) {
  		if (values[i] != null) {
  		    // start value element
  		    contentHandler.startElement(NS_SV_URI, VALUE_ELEMENT, NS_SV_PREFIX + ":" + VALUE_ELEMENT, new AttributesImpl());
  
  		    // characters
  		    if (type == PropertyType.BINARY) {
  			if (binaryAsLink) {
  			    String path = hierMgr.getPath(new PropertyId(state.getParentUUID(), state.getName())).toJCRPath(nsReg);
  			    char[] chars = path.toCharArray();
  			    contentHandler.characters(chars, 0, chars.length);
  			} else {
  			    // binary data, base64 encoding required
  			    BLOBFileValue blob = (BLOBFileValue) values[i].internalValue();
  			    InputStream in = blob.getStream();
  			    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 {
  				Base64.encode(in, writer);
  				in.close();
  				writer.close();
  			    } catch (IOException ioe) {
  				// check if the exception wraps a SAXException
  				Throwable t = ioe.getCause();
  				if (t != null && t instanceof SAXException) {
  				    throw (SAXException) t;
  				} else {
  				    throw new SAXException(ioe);
  				}
  			    }
  			}
  		    } else {
  			char chars[] = values[i].toJCRValue(nsReg).getString().toCharArray();
  			contentHandler.characters(chars, 0, chars.length);
  		    }
  
  		    // end value element
  		    contentHandler.endElement(NS_SV_URI, VALUE_ELEMENT, NS_SV_PREFIX + ":" + VALUE_ELEMENT);
  		}
  	    }
  	}
      }
  
      /**
       * @see AbstractSAXEventGenerator#leaving(PropertyState, int)
       */
      protected void leaving(PropertyState state, int level)
  	    throws RepositoryException, SAXException {
  	contentHandler.endElement(NS_SV_URI, PROPERTY_ELEMENT, NS_SV_PREFIX + ":" + PROPERTY_ELEMENT);
      }
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: slide-dev-help@jakarta.apache.org