Author: rhauch
Date: 2009-04-16 11:26:06 -0400 (Thu, 16 Apr 2009)
New Revision: 833
Added:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/TestLexicon.java
trunk/dna-jcr/src/test/resources/repositoryForTckTests.xml
trunk/dna-jcr/src/test/resources/repositoryStubImpl.properties
Log:
DNA-360 JcrSession.importXml and getContentHandler Are Not Implemented
Applied the patch, which implements Session.importXml and getContentHandler.
SerializationTest was commented back out (relative to the patch), since it tests the
similar methods in Workspace, and these are not yet implemented.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-04-16 14:53:11
UTC (rev 832)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-04-16 15:26:06
UTC (rev 833)
@@ -915,6 +915,31 @@
String primaryNodeTypeName )
throws ItemExistsException, PathNotFoundException, VersionException,
ConstraintViolationException, LockException,
RepositoryException {
+ return this.addNode(relPath, primaryNodeTypeName, null);
+ }
+
+ /**
+ * Adds the a new node with the given primary type (if specified) at the given
relative path with the given UUID (if
+ * specified).
+ *
+ * @param relPath the at which the new node should be created
+ * @param primaryNodeTypeName the desired primary type for the new node; null value
indicates that the default primary type
+ * from the appropriate definition for this node should be used
+ * @param desiredUuid the UUID (for the jcr.uuid property) of this node; may be null
+ * @return the newly created node
+ * @throws ItemExistsException if an item at the specified path already exists and
same-name siblings are not allowed.
+ * @throws PathNotFoundException if the specified path implies intermediary nodes
that do not exist.
+ * @throws VersionException not thrown at this time, but included for compatibility
with the specification
+ * @throws ConstraintViolationException if the change would violate a node type or
implementation-specific constraint.
+ * @throws LockException not thrown at this time, but included for compatibility with
the specification
+ * @throws RepositoryException if another error occurs
+ * @see #addNode(String, String)
+ */
+ final AbstractJcrNode addNode( String relPath,
+ String primaryNodeTypeName,
+ UUID desiredUuid )
+ throws ItemExistsException, PathNotFoundException, VersionException,
ConstraintViolationException, LockException,
+ RepositoryException {
// Determine the path ...
NodeEditor editor = null;
Path path = null;
@@ -976,7 +1001,7 @@
}
// Create the child ...
- ChildNode child = editor.createChild(childName, null, childPrimaryTypeName);
+ ChildNode child = editor.createChild(childName, desiredUuid,
childPrimaryTypeName);
return cache.findJcrNode(child.getUuid());
}
Added: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java
(rev 0)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java 2009-04-16
15:26:06 UTC (rev 833)
@@ -0,0 +1,465 @@
+/*
+ * JBoss DNA (
http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.jcr;
+
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+import java.util.UUID;
+import javax.jcr.ImportUUIDBehavior;
+import javax.jcr.ItemExistsException;
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.nodetype.ConstraintViolationException;
+import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.common.text.XmlNameEncoder;
+import org.jboss.dna.common.util.Base64;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * Content handler that provides SAX-based event handling that maps incoming documents to
the repository based on the
+ * functionality described in section 7.3 of the JCR 1.0.1 specification.
+ * <p>
+ * Each content handler is only intended to be used once and discarded. This class is
<b>NOT</b> thread-safe.
+ * </p>
+ *
+ * @see JcrSession#getImportContentHandler(String, int)
+ * @see JcrWorkspace#getImportContentHandler(String, int)
+ */
+@NotThreadSafe
+class JcrContentHandler extends DefaultHandler {
+
+ /**
+ * Encoder to properly escape XML names.
+ *
+ * @see XmlNameEncoder
+ */
+ protected static final TextDecoder SYSTEM_VIEW_NAME_DECODER = new XmlNameEncoder();
+
+ protected static final TextDecoder DOCUMENT_VIEW_NAME_DECODER = new
JcrDocumentViewExporter.JcrDocumentViewPropertyEncoder();
+
+ protected final JcrSession session;
+ protected final int uuidBehavior;
+ protected final SaveMode saveMode;
+
+ protected final String primaryTypeName;
+ protected final String mixinTypesName;
+ protected final String uuidName;
+
+ private AbstractJcrNode currentNode;
+ private ContentHandler delegate;
+
+ enum SaveMode {
+ WORKSPACE,
+ SESSION
+ }
+
+ JcrContentHandler( JcrSession session,
+ Path parentPath,
+ int uuidBehavior,
+ SaveMode saveMode ) throws PathNotFoundException,
RepositoryException {
+ assert session != null;
+ assert parentPath != null;
+ assert uuidBehavior == ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW
+ || uuidBehavior ==
ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING
+ || uuidBehavior ==
ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING
+ || uuidBehavior == ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW;
+
+ this.session = session;
+ this.currentNode = (AbstractJcrNode)session.getNode(parentPath);
+ this.uuidBehavior = uuidBehavior;
+ this.saveMode = saveMode;
+
+ this.primaryTypeName =
JcrLexicon.PRIMARY_TYPE.getString(this.session.namespaces());
+ this.mixinTypesName =
JcrLexicon.MIXIN_TYPES.getString(this.session.namespaces());
+ this.uuidName = JcrLexicon.UUID.getString(this.session.namespaces());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xml.sax.ContentHandler#characters(char[], int, int)
+ */
+ @Override
+ public void characters( char[] ch,
+ int start,
+ int length ) throws SAXException {
+ assert this.delegate != null;
+ delegate.characters(ch, start, length);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String,
java.lang.String)
+ */
+ @Override
+ public void endElement( String uri,
+ String localName,
+ String name ) throws SAXException {
+ assert this.delegate != null;
+ delegate.endElement(uri, localName, name);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String,
java.lang.String, org.xml.sax.Attributes)
+ */
+ @Override
+ public void startElement( String uri,
+ String localName,
+ String name,
+ Attributes atts ) throws SAXException {
+ checkDelegate(uri);
+ assert this.delegate != null;
+
+ delegate.startElement(uri, localName, name, atts);
+ }
+
+ private void checkDelegate( String namespaceUri ) {
+ if (delegate != null) return;
+
+ if (JcrSvLexicon.Namespace.URI.equals(namespaceUri)) {
+ this.delegate = new SystemViewContentHandler(this.currentNode);
+ } else {
+ this.delegate = new DocumentViewContentHandler(this.currentNode);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String,
java.lang.String)
+ */
+ @Override
+ public void startPrefixMapping( String prefix,
+ String uri ) throws SAXException {
+ try {
+ // Read from the workspace's DNA registry, as its semantics are more
friendly
+ NamespaceRegistry registry =
session.workspace().context().getNamespaceRegistry();
+
+ String existingUri = registry.getNamespaceForPrefix(prefix);
+
+ if (existingUri != null) {
+ if (existingUri.equals(uri)) {
+ // prefix/uri mapping is already in registry
+ return;
+ }
+
+ throw new RepositoryException("Prefix " + prefix + " is
already permanently mapped");
+ }
+
+ // Register through the JCR workspace to ensure consistency
+ session.getWorkspace().getNamespaceRegistry().registerNamespace(prefix,
uri);
+ } catch (RepositoryException re) {
+ throw new EnclosingSAXException(re);
+ }
+ }
+
+ class EnclosingSAXException extends SAXException {
+
+ /**
+ */
+ private static final long serialVersionUID = -1044992767566435542L;
+
+ /**
+ * @param e
+ */
+ EnclosingSAXException( Exception e ) {
+ super(e);
+
+ }
+
+ }
+
+ private class SystemViewContentHandler extends DefaultHandler {
+ private Stack<AbstractJcrNode> parentStack;
+
+ private final String svNameName;
+ private final String svTypeName;
+
+ private String currentNodeName;
+ private String currentPropName;
+ private int currentPropType;
+
+ private StringBuffer valueBuffer;
+ private Map<String, List<Value>> currentProps;
+
+ /**
+ * @param currentNode
+ */
+ SystemViewContentHandler( AbstractJcrNode currentNode ) {
+ super();
+ this.parentStack = new Stack<AbstractJcrNode>();
+ this.parentStack.push(currentNode);
+
+ this.currentProps = new HashMap<String, List<Value>>();
+ this.valueBuffer = new StringBuffer();
+
+ this.svNameName = JcrSvLexicon.NAME.getString(session.namespaces());
+ this.svTypeName = JcrSvLexicon.TYPE.getString(session.namespaces());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xml.sax.ContentHandler#startElement(java.lang.String,
java.lang.String, java.lang.String,
+ * org.xml.sax.Attributes)
+ */
+ @Override
+ public void startElement( String uri,
+ String localName,
+ String name,
+ Attributes atts ) throws SAXException {
+ if ("node".equals(localName)) {
+ if (currentNodeName != null) {
+ addNodeIfPending();
+ }
+
+ currentNodeName =
atts.getValue(SYSTEM_VIEW_NAME_DECODER.decode(svNameName));
+ } else if ("property".equals(localName)) {
+ currentPropName =
atts.getValue(SYSTEM_VIEW_NAME_DECODER.decode(svNameName));
+ currentPropType = PropertyType.valueFromName(atts.getValue(svTypeName));
+ currentProps.put(currentPropName, new ArrayList<Value>());
+ } else if (!"value".equals(localName)) {
+ throw new IllegalStateException("Unexpected element '" +
name + "' in system view");
+ }
+ }
+
+ private void addNodeIfPending() throws SAXException {
+ if (currentNodeName != null) {
+ try {
+ AbstractJcrNode parentNode = parentStack.peek();
+
+ UUID uuid = null;
+ List<Value> rawUuid = currentProps.get(uuidName);
+
+ if (rawUuid != null) {
+ assert rawUuid.size() == 1;
+ uuid = UUID.fromString(rawUuid.get(0).getString());
+ }
+
+ AbstractJcrNode newNode = parentNode.addNode(currentNodeName,
+
currentProps.get(primaryTypeName).get(0).getString(),
+ uuid);
+
+ for (Map.Entry<String, List<Value>> entry :
currentProps.entrySet()) {
+ if (entry.getKey().equals(primaryTypeName)) {
+ continue;
+ }
+
+ if (entry.getKey().equals(mixinTypesName)) {
+ for (Value value : entry.getValue()) {
+ newNode.addMixin(value.getString());
+ }
+ continue;
+ }
+
+ if (entry.getKey().equals(uuidName)) {
+ continue;
+ }
+
+ List<Value> values = entry.getValue();
+
+ if (values.size() == 1) {
+ newNode.setProperty(entry.getKey(), values.get(0));
+ } else {
+ newNode.setProperty(entry.getKey(), values.toArray(new
Value[values.size()]));
+ }
+ }
+
+ parentStack.push(newNode);
+ currentProps.clear();
+ } catch (RepositoryException re) {
+ throw new EnclosingSAXException(re);
+ }
+ }
+ }
+
+ @Override
+ public void endElement( String uri,
+ String localName,
+ String name ) throws SAXException {
+ if ("node".equals(localName)) {
+ addNodeIfPending();
+ currentNodeName = null;
+ parentStack.pop();
+ } else if ("value".equals(localName)) {
+ String s = valueBuffer.toString();
+ try {
+ if (currentPropType == PropertyType.BINARY) {
+ ByteArrayInputStream is = new
ByteArrayInputStream(Base64.decode(s, Base64.URL_SAFE));
+
currentProps.get(currentPropName).add(session.getValueFactory().createValue(is));
+ } else {
+
currentProps.get(currentPropName).add(session.getValueFactory().createValue(SYSTEM_VIEW_NAME_DECODER.decode(s),
+
currentPropType));
+ }
+ } catch (RepositoryException re) {
+ throw new EnclosingSAXException(re);
+ }
+ valueBuffer = new StringBuffer();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xml.sax.ContentHandler#characters(char[], int, int)
+ */
+ @Override
+ public void characters( char[] ch,
+ int start,
+ int length ) {
+ valueBuffer.append(ch, start, length);
+
+ }
+ }
+
+ private class DocumentViewContentHandler extends DefaultHandler {
+ private Stack<AbstractJcrNode> parentStack;
+
+ /**
+ * @param currentNode
+ */
+ DocumentViewContentHandler( AbstractJcrNode currentNode ) {
+ super();
+ this.parentStack = new Stack<AbstractJcrNode>();
+ parentStack.push(currentNode);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xml.sax.ContentHandler#startElement(java.lang.String,
java.lang.String, java.lang.String,
+ * org.xml.sax.Attributes)
+ */
+ @Override
+ public void startElement( String uri,
+ String localName,
+ String name,
+ Attributes atts ) throws SAXException {
+ try {
+ String primaryTypeName =
atts.getValue(JcrContentHandler.this.primaryTypeName);
+ String rawUuid = atts.getValue(uuidName);
+ UUID uuid = (rawUuid != null ? UUID.fromString(rawUuid) : null);
+ AbstractJcrNode parentNode = parentStack.peek();
+
+ if (uuid != null) {
+ AbstractJcrNode existingNodeWithUuid =
(AbstractJcrNode)session.getNodeByUUID(rawUuid);
+ if (existingNodeWithUuid != null) {
+ switch (uuidBehavior) {
+ case
ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING:
+ parentNode =
(AbstractJcrNode)existingNodeWithUuid.getParent();
+ existingNodeWithUuid.remove();
+ break;
+ case ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW:
+ uuid = UUID.randomUUID();
+ break;
+ case
ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING:
+ if
(existingNodeWithUuid.path().isAtOrAbove(parentStack.firstElement().path())) {
+ throw new ConstraintViolationException();
+ }
+ existingNodeWithUuid.remove();
+ break;
+ case ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW:
+ throw new ItemExistsException();
+ }
+ }
+ }
+
+ name = DOCUMENT_VIEW_NAME_DECODER.decode(name);
+ AbstractJcrNode currentNode = parentNode.addNode(name, primaryTypeName,
uuid);
+
+ for (int i = 0; i < atts.getLength(); i++) {
+ if (JcrContentHandler.this.primaryTypeName.equals(atts.getQName(i)))
{
+ continue;
+ }
+
+ if (mixinTypesName.equals(atts.getQName(i))) {
+ currentNode.addMixin(atts.getValue(i));
+ continue;
+ }
+
+ if (uuidName.equals(atts.getQName(i))) {
+ continue;
+ }
+
+ // We may want to use the workspace context here so that we only use
the permanent namespace mappings
+ // Name propName =
session.executionContext.getValueFactories().getNameFactory().create(atts.getQName(i));
+ // String value =
DOCUMENT_VIEW_NAME_DECODER.decode(atts.getValue(i));
+ String value = atts.getValue(i);
+ String propertyName =
DOCUMENT_VIEW_NAME_DECODER.decode(atts.getQName(i));
+ currentNode.setProperty(propertyName, value);
+ }
+
+ parentStack.push(currentNode);
+ } catch (RepositoryException re) {
+ throw new EnclosingSAXException(re);
+ }
+
+ }
+
+ @Override
+ public void endElement( String uri,
+ String localName,
+ String name ) {
+ parentStack.pop();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xml.sax.ContentHandler#characters(char[], int, int)
+ */
+ @Override
+ public void characters( char[] ch,
+ int start,
+ int length ) throws SAXException {
+ try {
+ NamespaceRegistry namespaces =
session.getExecutionContext().getNamespaceRegistry();
+ Node parentNode = parentStack.peek();
+ Node currentNode =
parentNode.addNode(JcrLexicon.XMLTEXT.getString(namespaces),
+
JcrNtLexicon.UNSTRUCTURED.getString(namespaces));
+ String s = new String(ch, start, length);
+ currentNode.setProperty(JcrLexicon.XMLCHARACTERS.getString(namespaces),
s);
+
+ } catch (RepositoryException re) {
+ throw new EnclosingSAXException(re);
+ }
+ }
+ }
+}
Property changes on: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-04-16 14:53:11 UTC
(rev 832)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-04-16 15:26:06 UTC
(rev 833)
@@ -23,6 +23,7 @@
*/
package org.jboss.dna.jcr;
+import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.AccessControlException;
@@ -32,7 +33,9 @@
import java.util.Set;
import java.util.UUID;
import javax.jcr.Credentials;
+import javax.jcr.InvalidSerializedDataException;
import javax.jcr.Item;
+import javax.jcr.ItemExistsException;
import javax.jcr.ItemNotFoundException;
import javax.jcr.NamespaceException;
import javax.jcr.Node;
@@ -46,6 +49,7 @@
import javax.jcr.ValueFactory;
import javax.jcr.ValueFormatException;
import javax.jcr.Workspace;
+import javax.jcr.nodetype.ConstraintViolationException;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
@@ -60,9 +64,15 @@
import org.jboss.dna.graph.property.Path;
import org.jboss.dna.graph.property.ValueFactories;
import org.jboss.dna.graph.property.basic.LocalNamespaceRegistry;
+import org.jboss.dna.jcr.JcrContentHandler.EnclosingSAXException;
+import org.jboss.dna.jcr.JcrContentHandler.SaveMode;
import org.jboss.dna.jcr.JcrNamespaceRegistry.Behavior;
import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
/**
* @author John Verhaeg
@@ -355,12 +365,13 @@
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Session#getImportContentHandler(java.lang.String, int)
*/
public ContentHandler getImportContentHandler( String parentAbsPath,
- int uuidBehavior ) {
- throw new UnsupportedOperationException();
+ int uuidBehavior ) throws
PathNotFoundException, RepositoryException {
+ Path parentPath =
this.executionContext.getValueFactories().getPathFactory().create(parentAbsPath);
+
+ return new JcrContentHandler(this, parentPath, uuidBehavior, SaveMode.SESSION);
}
/**
@@ -595,13 +606,29 @@
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Session#importXML(java.lang.String, java.io.InputStream, int)
*/
public void importXML( String parentAbsPath,
InputStream in,
- int uuidBehavior ) {
- throw new UnsupportedOperationException();
+ int uuidBehavior ) throws IOException,
InvalidSerializedDataException, RepositoryException {
+
+ try {
+ XMLReader parser = XMLReaderFactory.createXMLReader();
+ parser.setContentHandler(getImportContentHandler(parentAbsPath,
uuidBehavior));
+ parser.parse(new InputSource(in));
+ } catch (EnclosingSAXException ese) {
+ Exception cause = ese.getException();
+ if (cause instanceof ItemExistsException) {
+ throw (ItemExistsException)cause;
+ } else if (cause instanceof ConstraintViolationException) {
+ throw (ConstraintViolationException)cause;
+ }
+ throw new RepositoryException(cause);
+ } catch (SAXParseException se) {
+ throw new InvalidSerializedDataException(se);
+ } catch (SAXException se) {
+ throw new RepositoryException(se);
+ }
}
/**
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-04-16 14:53:11 UTC
(rev 832)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-04-16 15:26:06 UTC
(rev 833)
@@ -27,11 +27,14 @@
import java.net.URI;
import java.security.AccessControlContext;
import java.security.AccessController;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.jcr.Credentials;
-import javax.jcr.Repository;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.jackrabbit.test.JCRTestSuite;
@@ -50,6 +53,7 @@
import org.apache.jackrabbit.test.api.SetPropertyDoubleTest;
import org.apache.jackrabbit.test.api.SetPropertyInputStreamTest;
import org.apache.jackrabbit.test.api.SetPropertyLongTest;
+import org.apache.jackrabbit.test.api.SetPropertyNodeTest;
import org.apache.jackrabbit.test.api.SetPropertyStringTest;
import org.apache.jackrabbit.test.api.SetPropertyValueTest;
import org.apache.jackrabbit.test.api.SetValueBinaryTest;
@@ -69,9 +73,11 @@
import org.apache.jackrabbit.test.api.WorkspaceCopyBetweenWorkspacesReferenceableTest;
import org.apache.jackrabbit.test.api.WorkspaceCopyBetweenWorkspacesSameNameSibsTest;
import org.apache.jackrabbit.test.api.WorkspaceCopyBetweenWorkspacesTest;
-import org.jboss.dna.graph.DnaLexicon;
+import org.apache.jackrabbit.test.api.WorkspaceCopyVersionableTest;
+import org.apache.jackrabbit.test.api.WorkspaceMoveVersionableTest;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.JcrMixLexicon;
import org.jboss.dna.graph.JcrNtLexicon;
import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.connector.RepositoryConnection;
@@ -202,7 +208,7 @@
addTestSuite(SetPropertyDoubleTest.class);
addTestSuite(SetPropertyInputStreamTest.class);
addTestSuite(SetPropertyLongTest.class);
- // addTestSuite(SetPropertyNodeTest.class);
+ addTestSuite(SetPropertyNodeTest.class);
addTestSuite(SetPropertyStringTest.class);
addTestSuite(SetPropertyValueTest.class);
addTestSuite(SetPropertyConstraintViolationExceptionTest.class);
@@ -228,16 +234,16 @@
// addTestSuite(WorkspaceCopyReferenceableTest.class);
// addTestSuite(WorkspaceCopySameNameSibsTest.class);
// addTestSuite(WorkspaceCopyTest.class);
- // addTestSuite(WorkspaceCopyVersionableTest.class);
+ addTestSuite(WorkspaceCopyVersionableTest.class);
// addTestSuite(WorkspaceMoveReferenceableTest.class);
// addTestSuite(WorkspaceMoveSameNameSibsTest.class);
// addTestSuite(WorkspaceMoveTest.class);
- // addTestSuite(WorkspaceMoveVersionableTest.class);
- //
+ addTestSuite(WorkspaceMoveVersionableTest.class);
+
addTestSuite(RepositoryLoginTest.class);
// addTestSuite(ImpersonateTest.class);
// addTestSuite(CheckPermissionTest.class);
- //
+
// addTestSuite(DocumentViewImportTest.class);
// addTestSuite(SerializationTest.class);
@@ -257,7 +263,7 @@
// addTest(org.apache.jackrabbit.test.api.observation.TestAll.suite());
// addTest(org.apache.jackrabbit.test.api.version.TestAll.suite());
// addTest(org.apache.jackrabbit.test.api.lock.TestAll.suite());
- // addTest(org.apache.jackrabbit.test.api.util.TestAll.suite());
+ addTest(org.apache.jackrabbit.test.api.util.TestAll.suite());
}
}
@@ -265,11 +271,11 @@
* Concrete implementation of {@link RepositoryStub} based on DNA-specific
configuration.
*/
public static class InMemoryRepositoryStub extends RepositoryStub {
- private Repository repository;
- protected RepositoryConnection connection;
+ private JcrRepository repository;
+ protected InMemoryRepositorySource source;
protected AccessControlContext accessControlContext =
AccessController.getContext();
- private Credentials credentials = new Credentials() {
+ private Credentials superUserCredentials = new Credentials() {
private static final long serialVersionUID = 1L;
@SuppressWarnings( "unused" )
@@ -278,17 +284,29 @@
}
};
- protected ExecutionContext executionContext = new ExecutionContext() {
+ private Credentials readWriteCredentials = new Credentials() {
+ private static final long serialVersionUID = 1L;
- @Override
- public ExecutionContext create( AccessControlContext accessControlContext )
{
- return executionContext;
+ @SuppressWarnings( "unused" )
+ public AccessControlContext getAccessControlContext() {
+ return accessControlContext;
}
};
+ private Credentials readOnlyCredentials = new Credentials() {
+ private static final long serialVersionUID = 1L;
+
+ @SuppressWarnings( "unused" )
+ public AccessControlContext getAccessControlContext() {
+ return accessControlContext;
+ }
+ };
+
+ protected ExecutionContext executionContext = new ExecutionContext();
+
protected RepositoryConnectionFactory connectionFactory = new
RepositoryConnectionFactory() {
public RepositoryConnection createConnection( String sourceName ) {
- return connection;
+ return source.getConnection();
}
};
@@ -296,29 +314,27 @@
super(env);
// Create the in-memory (DNA) repository
- InMemoryRepositorySource source = new InMemoryRepositorySource();
+ source = new InMemoryRepositorySource();
// Various calls will fail if you do not set a non-null name for the source
source.setName("TestRepositorySource");
+ // Make sure the path to the namespaces exists ...
+ Graph graph = Graph.create(source.getName(), connectionFactory,
executionContext);
+
graph.create("/jcr:system").and().create("/jcr:system/dna:namespaces");
+
// Wrap a connection to the in-memory (DNA) repository in a (JCR) repository
Map<Options, String> options =
Collections.singletonMap(Options.PROJECT_NODE_TYPES, "false");
- connection = source.getConnection();
+
repository = new JcrRepository(executionContext.create(accessControlContext),
connectionFactory, source.getName(),
null, options);
+ RepositoryNodeTypeManager nodeTypes = repository.getRepositoryTypeManager();
- // Make sure the path to the namespaces exists ...
- Graph graph = Graph.create(source.getName(), connectionFactory,
executionContext);
-
graph.create("/jcr:system").and().create("/jcr:system/dna:namespaces");
-
// Set up some sample nodes in the graph to match the expected test
configuration
try {
+ nodeTypes.registerNodeTypes(new TckTestNodeTypeSource(executionContext,
nodeTypes));
- // TODO: Should there be an easier way to define these since they will be
needed for all JCR repositories?
-
executionContext.getNamespaceRegistry().register(DnaLexicon.Namespace.PREFIX,
DnaLexicon.Namespace.URI);
-
executionContext.getNamespaceRegistry().register(JcrLexicon.Namespace.PREFIX,
JcrLexicon.Namespace.URI);
-
executionContext.getNamespaceRegistry().register(JcrNtLexicon.Namespace.PREFIX,
JcrNtLexicon.Namespace.URI);
-
executionContext.getNamespaceRegistry().register(JcrSvLexicon.Namespace.PREFIX,
JcrSvLexicon.Namespace.URI);
+
executionContext.getNamespaceRegistry().register(TestLexicon.Namespace.PREFIX,
TestLexicon.Namespace.URI);
Path destinationPath =
executionContext.getValueFactories().getPathFactory().create("/");
GraphImporter importer = new GraphImporter(graph);
@@ -341,9 +357,7 @@
*/
@Override
public Credentials getSuperuserCredentials() {
- // TODO: Why must we override this method? The default TCK implementation
just returns a particular instance of
- // SimpleCredentials.
- return credentials;
+ return superUserCredentials;
}
/**
@@ -353,9 +367,7 @@
*/
@Override
public Credentials getReadOnlyCredentials() {
- // TODO: Why must we override this method? The default TCK implementation
just returns a particular instance of
- // SimpleCredentials.
- return credentials;
+ return readOnlyCredentials;
}
/**
@@ -365,9 +377,7 @@
*/
@Override
public Credentials getReadWriteCredentials() {
- // TODO: Why must we override this method? The default TCK implementation
just returns a particular instance of
- // SimpleCredentials.
- return credentials;
+ return readWriteCredentials;
}
/**
@@ -376,10 +386,88 @@
* @see org.apache.jackrabbit.test.RepositoryStub#getRepository()
*/
@Override
- public Repository getRepository() {
+ public JcrRepository getRepository() {
return repository;
}
}
+ static class TckTestNodeTypeSource extends AbstractJcrNodeTypeSource {
+ /** The list of node types. */
+ private final List<JcrNodeType> nodeTypes;
+
+ TckTestNodeTypeSource( ExecutionContext context,
+ RepositoryNodeTypeManager nodeTypeManager ) {
+ super(null);
+
+ nodeTypes = new ArrayList<JcrNodeType>();
+
+ JcrNodeType base = nodeTypeManager.getNodeType(JcrNtLexicon.BASE);
+
+ if (base == null) {
+ String baseTypeName =
JcrNtLexicon.BASE.getString(context.getNamespaceRegistry());
+ String namespaceTypeName =
TestLexicon.NO_SAME_NAME_SIBS.getString(context.getNamespaceRegistry());
+ throw new
IllegalStateException(JcrI18n.supertypeNotFound.text(baseTypeName, namespaceTypeName));
+ }
+
+ JcrNodeType referenceable =
nodeTypeManager.getNodeType(JcrMixLexicon.REFERENCEABLE);
+
+ if (referenceable == null) {
+ String baseTypeName =
JcrMixLexicon.REFERENCEABLE.getString(context.getNamespaceRegistry());
+ String namespaceTypeName =
TestLexicon.REFERENCEABLE_UNSTRUCTURED.getString(context.getNamespaceRegistry());
+ throw new
IllegalStateException(JcrI18n.supertypeNotFound.text(baseTypeName, namespaceTypeName));
+ }
+
+ JcrNodeType unstructured =
nodeTypeManager.getNodeType(JcrNtLexicon.UNSTRUCTURED);
+
+ if (unstructured == null) {
+ String baseTypeName =
JcrNtLexicon.UNSTRUCTURED.getString(context.getNamespaceRegistry());
+ String namespaceTypeName =
TestLexicon.REFERENCEABLE_UNSTRUCTURED.getString(context.getNamespaceRegistry());
+ throw new
IllegalStateException(JcrI18n.supertypeNotFound.text(baseTypeName, namespaceTypeName));
+ }
+
+ // Stubbing in child node and property definitions for now
+ JcrNodeType noSameNameSibs = new JcrNodeType(
+ context,
+ NO_NODE_TYPE_MANAGER,
+ TestLexicon.NO_SAME_NAME_SIBS,
+ Arrays.asList(new JcrNodeType[]
{base}),
+ NO_PRIMARY_ITEM_NAME,
+ Arrays.asList(new
JcrNodeDefinition[] {new JcrNodeDefinition(
+
context,
+
null,
+
ALL_NODES,
+
OnParentVersionBehavior.VERSION.getJcrValue(),
+
false,
+
false,
+
false,
+
false,
+
JcrNtLexicon.UNSTRUCTURED,
+
new JcrNodeType[] {base}),}),
+ NO_PROPERTIES, NOT_MIXIN,
UNORDERABLE_CHILD_NODES);
+
+ JcrNodeType referenceableUnstructured = new JcrNodeType(
+ context,
+
NO_NODE_TYPE_MANAGER,
+
TestLexicon.REFERENCEABLE_UNSTRUCTURED,
+ Arrays.asList(new
JcrNodeType[] {unstructured, referenceable}),
+ NO_PRIMARY_ITEM_NAME,
NO_CHILD_NODES, NO_PROPERTIES,
+ NOT_MIXIN,
UNORDERABLE_CHILD_NODES);
+
+ nodeTypes.addAll(Arrays.asList(new JcrNodeType[] {referenceableUnstructured,
noSameNameSibs}));
+
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.jcr.JcrNodeTypeSource#getNodeTypes()
+ */
+ @Override
+ public Collection<JcrNodeType> getDeclaredNodeTypes() {
+ return nodeTypes;
+ }
+
+ }
+
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/TestLexicon.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/TestLexicon.java 2009-04-16 14:53:11 UTC
(rev 832)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/TestLexicon.java 2009-04-16 15:26:06 UTC
(rev 833)
@@ -46,5 +46,8 @@
public static final Name CONSTRAINED_PATH = new BasicName(Namespace.URI,
"constrainedPath");
public static final Name CONSTRAINED_REFERENCE = new BasicName(Namespace.URI,
"constrainedReference");
public static final Name CONSTRAINED_STRING = new BasicName(Namespace.URI,
"constrainedString");
-
+
+ public static final Name REFERENCEABLE_UNSTRUCTURED = new BasicName(Namespace.URI,
"referenceableUnstructured");
+ public static final Name NO_SAME_NAME_SIBS = new BasicName(Namespace.URI,
"noSameNameSibs");
+
}
Modified: trunk/dna-jcr/src/test/resources/repositoryForTckTests.xml
===================================================================
--- trunk/dna-jcr/src/test/resources/repositoryForTckTests.xml 2009-04-16 14:53:11 UTC
(rev 832)
+++ trunk/dna-jcr/src/test/resources/repositoryForTckTests.xml 2009-04-16 15:26:06 UTC
(rev 833)
@@ -28,7 +28,8 @@
xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
xmlns:dna="http://www.jboss.org/dna/1.0"
jcr:primaryType="nt:unstructured">
- <nt:unstructured jcr:name="node1"
prop1="<foo&foo>" >
+ <nt:unstructured jcr:name="serializationNode" />
+ <nt:unstructured jcr:name="node1"
prop1="<foo&foo>">
<!--
This stanza checks for the jcr:xmltext special case for export as per JCR
1.0.1 section 6.4.2.3
-->
Modified: trunk/dna-jcr/src/test/resources/repositoryStubImpl.properties
===================================================================
--- trunk/dna-jcr/src/test/resources/repositoryStubImpl.properties 2009-04-16 14:53:11 UTC
(rev 832)
+++ trunk/dna-jcr/src/test/resources/repositoryStubImpl.properties 2009-04-16 15:26:06 UTC
(rev 833)
@@ -7,5 +7,30 @@
javax.jcr.tck.propertyname1=prop1
javax.jcr.tck.propertyname2=prop2
javax.jcr.tck.workspacename=
-javax.jcr.tck.nodetype=nt:unstructured
+javax.jcr.tck.nodetype=dnatest\:referenceableUnstructured
javax.jcr.tck.nodetypenochildren=dna:namespace
+javax.jcr.tck.sourceFolderName=source
+javax.jcr.tck.targetFolderName=target
+javax.jcr.tck.rootNodeName=rootNode
+javax.jcr.tck.propertySkipped=propertySkipped
+javax.jcr.tck.propertyValueMayChange=propertyValueMayChange
+javax.jcr.tck.nodeTypesTestNode=nodeTypesTestNode
+javax.jcr.tck.mixinTypeTestNode=mixinTypeTestNode
+javax.jcr.tck.propertyTypesTestNode=propertyTypesTestNode
+javax.jcr.tck.sameNameChildrenTestNode=sameNameChildrenTestNode
+javax.jcr.tck.multiValuePropertiesTestNode=multiValuePropertiesTestNode
+javax.jcr.tck.referenceableNodeTestNode=referenceableNodeTestNode
+javax.jcr.tck.orderChildrenTestNode=orderChildrenTestNode
+javax.jcr.tck.namespaceTestNode=namespaceTestNode
+javax.jcr.tck.sameNameSibsFalseChildNodeDefinition=dnatest\:noSameNameSibs
+javax.jcr.tck.stringTestProperty=stringTestProperty
+javax.jcr.tck.binaryTestProperty=binaryTestProperty
+javax.jcr.tck.dateTestProperty=dateTestProperty
+javax.jcr.tck.longTestProperty=longTestProperty
+javax.jcr.tck.doubleTestProperty=doubleTestProperty
+javax.jcr.tck.booleanTestProperty=booleanTestProperty
+javax.jcr.tck.nameTestProperty=nameTestProperty
+javax.jcr.tck.pathTestProperty=pathTestProperty
+javax.jcr.tck.referenceTestProperty=referenceTestProperty
+javax.jcr.tck.multiValueTestProperty=multiValueTestProperty
+javax.jcr.tck.NodeTest.testAddNodeItemExistsException.nodetype=dnatest\:noSameNameSibs
\ No newline at end of file