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