You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by mr...@apache.org on 2005/03/02 19:11:51 UTC
svn commit: r155937 - in incubator/jackrabbit/trunk: applications/test/
applications/test/repository/nodetypes/ src/test/org/apache/jackrabbit/test/
src/test/org/apache/jackrabbit/test/api/
Author: mreutegg
Date: Wed Mar 2 10:11:49 2005
New Revision: 155937
URL: http://svn.apache.org/viewcvs?view=rev&rev=155937
Log:
Initial checkin of SysView export test.
Added:
incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/SerializationContext.java (with props)
incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/SerializationTest.java (with props)
incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/TreeComparator.java (with props)
Modified:
incubator/jackrabbit/trunk/applications/test/repository/nodetypes/custom_nodetypes.xml
incubator/jackrabbit/trunk/applications/test/repositoryStubImpl.properties
incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/AbstractJCRTest.java
Modified: incubator/jackrabbit/trunk/applications/test/repository/nodetypes/custom_nodetypes.xml
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/applications/test/repository/nodetypes/custom_nodetypes.xml?view=diff&r1=155936&r2=155937
==============================================================================
--- incubator/jackrabbit/trunk/applications/test/repository/nodetypes/custom_nodetypes.xml (original)
+++ incubator/jackrabbit/trunk/applications/test/repository/nodetypes/custom_nodetypes.xml Wed Mar 2 10:11:49 2005
@@ -30,7 +30,7 @@
<propertyDef name="test:computeOnParentVersionProp" type="String" autoCreate="false" mandatory="false" onParentVersion="COMPUTE" protected="false" multiple="false" />
<propertyDef name="test:ignoreOnParentVersionProp" type="String" autoCreate="false" mandatory="false" onParentVersion="IGNORE" protected="false" multiple="false" />
<propertyDef name="test:abortOnParentVersionProp" type="String" autoCreate="false" mandatory="false" onParentVersion="ABORT" protected="false" multiple="false" />
- <childNodeDef name="*" defaultPrimaryType="" autoCreate="false" mandatory="false" onParentVersion="COPY" protected="false" sameNameSibs="false">
+ <childNodeDef name="*" defaultPrimaryType="test:versionable" autoCreate="false" mandatory="false" onParentVersion="COPY" protected="false" sameNameSibs="false">
<requiredPrimaryTypes>
<requiredPrimaryType>nt:base</requiredPrimaryType>
</requiredPrimaryTypes>
Modified: incubator/jackrabbit/trunk/applications/test/repositoryStubImpl.properties
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/applications/test/repositoryStubImpl.properties?view=diff&r1=155936&r2=155937
==============================================================================
--- incubator/jackrabbit/trunk/applications/test/repositoryStubImpl.properties (original)
+++ incubator/jackrabbit/trunk/applications/test/repositoryStubImpl.properties Wed Mar 2 10:11:49 2005
@@ -178,6 +178,63 @@
# valid node type that can be added as child of nodetype 2
javax.jcr.tck.NodeOrderableChildNodesTest.testOrderBeforeUnsupportedRepositoryOperationException.nodetype3=nt:hierarchyNode
+# ------------------------------------------------------------------------------
+# observation configuration
+# ------------------------------------------------------------------------------
+
+# Configuration settings for the serialization.
+# Note that the serialization test tries to use as many features of the repository
+# as possible, but fails silently if a feature is not available. You have to
+# specify all of the following configuration entries, even if your repository does
+# not support the feature that is associated with them.
+
+# Root node for the example tree
+javax.jcr.tck.SerializationTest.testroot=/testdata/serialization
+
+# Node type to use for the example tree. Specify a node type that allows complex trees and all property types if possible
+javax.jcr.tck.SerializationTest.nodetype=nt:unstructured
+
+# Name of the nodes for source and target tree
+javax.jcr.tck.SerializationTest.sourceFolderName=source
+javax.jcr.tck.SerializationTest.targetFolderName=target
+javax.jcr.tck.SerializationTest.rootNodeName=test
+
+# List the properties whose values may change during serialization/deserialization. For example,
+# the UUID of a node is unique in the repository, so it will have to change when you re-import
+# a tree at a different location.
+javax.jcr.tck.SerializationTest.propertyValueMayChange= jcr:created jcr:uuid jcr:versionHistory jcr:baseVersion jcr:predecessors P_Reference
+
+# The name of the test node types. For easier diagnostics, the node types have names
+# that tell you the kind of information they store
+javax.jcr.tck.SerializationTest.nodeTypesTestNode=NodeTypes
+javax.jcr.tck.SerializationTest.mixinTypeTestNode=MixinTypes
+javax.jcr.tck.SerializationTest.propertyTypesTestNode=PropertyTypes
+javax.jcr.tck.SerializationTest.sameNameChildrenTestNode=SameNameChildren
+javax.jcr.tck.SerializationTest.multiValuePropertiesTestNode=MultiValueProperties
+javax.jcr.tck.SerializationTest.referenceableNodeTestNode=ReferenceableNode
+javax.jcr.tck.SerializationTest.orderChildrenTestNode=OrderChildren
+javax.jcr.tck.SerializationTest.namespaceTestNode=Namespace
+
+# The name of the test property types.
+javax.jcr.tck.SerializationTest.stringTestProperty=P_String
+javax.jcr.tck.SerializationTest.binaryTestProperty=P_Binary
+javax.jcr.tck.SerializationTest.dateTestProperty=P_Date
+javax.jcr.tck.SerializationTest.longTestProperty=P_Long
+javax.jcr.tck.SerializationTest.doubleTestProperty=P_Double
+javax.jcr.tck.SerializationTest.booleanTestProperty=P_Boolean
+javax.jcr.tck.SerializationTest.nameTestProperty=P_Name
+javax.jcr.tck.SerializationTest.pathTestProperty=P_Path
+javax.jcr.tck.SerializationTest.referenceTestProperty=P_Reference
+javax.jcr.tck.SerializationTest.multiValueTestProperty=P_MultiValue
+
+# Test method: testVersioningExceptionSessionFileChild
+# specified nodetype must be versionable and allow child nodes of the same type.
+javax.jcr.tck.SerializationTest.testVersioningExceptionSessionFileChild.nodetype=test:versionable
+
+# Test method: testVersioningExceptionSessionFileParent
+# specified nodetype must be versionable and allow child nodes of the same type.
+javax.jcr.tck.SerializationTest.testVersioningExceptionSessionFileParent.nodetype=test:versionable
+
# ==============================================================================
# JAVAX.JCR.QUERY CONFIGURATION
# ==============================================================================
@@ -264,4 +321,3 @@
# Test class: MergeNodeTest
javax.jcr.tck.MergeNodeTest.nodetype=test:versionable
-
Modified: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/AbstractJCRTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/AbstractJCRTest.java?view=diff&r1=155936&r2=155937
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/AbstractJCRTest.java (original)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/AbstractJCRTest.java Wed Mar 2 10:11:49 2005
@@ -288,7 +288,12 @@
StringTokenizer names = new StringTokenizer(testPath, "/");
Node currentNode = root;
while (names.hasMoreTokens()) {
- currentNode = currentNode.addNode(names.nextToken(), testNodeType);
+ String name = names.nextToken();
+ if (currentNode.hasNode(name)) {
+ currentNode = currentNode.getNode(name);
+ } else {
+ currentNode = currentNode.addNode(name, testNodeType);
+ }
}
testRootNode = currentNode;
}
@@ -320,7 +325,7 @@
}
}
- protected String getProperty(String name) throws RepositoryException {
+ public String getProperty(String name) throws RepositoryException {
String testCaseName = getName();
String testClassName = getClass().getName();
String testPackName = "";
Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/SerializationContext.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/SerializationContext.java?view=auto&rev=155937
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/SerializationContext.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/SerializationContext.java Wed Mar 2 10:11:49 2005
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * 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.jackrabbit.test.api;
+
+import org.apache.jackrabbit.test.AbstractJCRTest;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * Encapsulates the various properties that are needed for a serialization test
+ * case.
+ */
+class SerializationContext {
+
+ private AbstractJCRTest baseTest;
+ public String testroot;
+ public String nodetype;
+ public String sourceFolderName;
+ public String targetFolderName;
+ public String rootNodeName;
+
+ public String propertyValueMayChange;
+
+ public String nodeTypesTestNode;
+ public String mixinTypeTestNode;
+ public String propertyTypesTestNode;
+ public String sameNameChildrenTestNode;
+ public String multiValuePropertiesTestNode;
+ public String referenceableNodeTestNode;
+ public String orderChildrenTestNode;
+ public String namespaceTestNode;
+
+ public String stringTestProperty;
+ public String binaryTestProperty;
+ public String dateTestProperty;
+ public String longTestProperty;
+ public String doubleTestProperty;
+ public String booleanTestProperty;
+ public String nameTestProperty;
+ public String pathTestProperty;
+ public String referenceTestProperty;
+ public String multiValueTestProperty;
+
+ public SerializationContext(AbstractJCRTest test) throws RepositoryException {
+ // creates a serialization context based on a test class
+ baseTest = test;
+
+ testroot = get("testroot");
+ nodetype = get("nodetype");
+ sourceFolderName = get("sourceFolderName");
+ targetFolderName = get("targetFolderName");
+ rootNodeName = get("rootNodeName");
+
+ propertyValueMayChange = " " + get("propertyValueMayChange") + " ";
+
+ nodeTypesTestNode = get("nodeTypesTestNode");
+ mixinTypeTestNode = get("mixinTypeTestNode");
+ propertyTypesTestNode = get("propertyTypesTestNode");
+ sameNameChildrenTestNode = get("sameNameChildrenTestNode");
+ multiValuePropertiesTestNode = get("multiValuePropertiesTestNode");
+ referenceableNodeTestNode = get("referenceableNodeTestNode");
+ orderChildrenTestNode = get("orderChildrenTestNode");
+ namespaceTestNode = get("namespaceTestNode");
+
+ stringTestProperty = get("stringTestProperty");
+ binaryTestProperty = get("binaryTestProperty");
+ dateTestProperty = get("dateTestProperty");
+ longTestProperty = get("longTestProperty");
+ doubleTestProperty = get("doubleTestProperty");
+ booleanTestProperty = get("booleanTestProperty");
+ nameTestProperty = get("nameTestProperty");
+ pathTestProperty = get("pathTestProperty");
+ referenceTestProperty = get("referenceTestProperty");
+ multiValueTestProperty = get("multiValueTestProperty");
+ }
+
+ private String get(String name) throws RepositoryException {
+ String value = baseTest.getProperty(name);
+ if (value == null) {
+ throw new NullPointerException("Property '" + name + "' is not defined.");
+ }
+ return value;
+ }
+
+}
Propchange: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/SerializationContext.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/SerializationTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/SerializationTest.java?view=auto&rev=155937
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/SerializationTest.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/SerializationTest.java Wed Mar 2 10:11:49 2005
@@ -0,0 +1,465 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * 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.jackrabbit.test.api;
+
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.apache.jackrabbit.test.NotExecutableException;
+import org.xml.sax.helpers.XMLReaderFactory;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import javax.jcr.lock.LockException;
+import javax.jcr.lock.Lock;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.Workspace;
+import javax.jcr.Session;
+import javax.jcr.RepositoryException;
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.ItemExistsException;
+import java.io.File;
+import java.io.IOException;
+import java.io.FileInputStream;
+import java.io.StringReader;
+import java.io.Reader;
+import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
+
+/**
+ * <code>SerializationTest</code> contains the test cases for the method
+ * <code>Workspace.exportSysView()</code> and <code>Session.importSysView()</code>.
+ * <p/>
+ * This class exports and re-imports the repository. The tests check for
+ * differences between the original and the re-imported repository.
+ *
+ * @test
+ * @sources SerializationTest.java
+ * @executeClass org.apache.jackrabbit.test.api.SerializationTest
+ * @keywords level2
+ */
+public class SerializationTest extends AbstractJCRTest {
+ private Workspace workspace;
+ private File file;
+ private TreeComparator treeComparator;
+
+ private final boolean CONTENTHANDLER = true, STREAM = false;
+ private final boolean WORKSPACE = true, SESSION = false;
+ private final boolean SKIPBINARY = true, SAVEBINARY = false;
+ private final boolean NORECURSE = true, RECURSE = false;
+
+ private Session session;
+
+ protected void setUp() throws RepositoryException, Exception {
+ super.setUp();
+
+ session = superuser;
+ workspace = session.getWorkspace();
+ file = File.createTempFile("test", ".xml");
+ log.print("Tempfile: " + file.getAbsolutePath());
+
+ SerializationContext sc = new SerializationContext(this);
+ treeComparator = new TreeComparator(sc, session);
+ treeComparator.createComplexTree(treeComparator.WORKSPACE);
+ }
+
+ protected void tearDown() throws Exception {
+ file.delete();
+ super.tearDown();
+ }
+
+ /**
+ * Imports a tree directly below a node that is checked in. This should
+ * fail, because you need to check out the node before you can make any
+ * changes to it or its children.
+ */
+ public void testVersioningExceptionSessionFileParent()
+ throws RepositoryException, NotExecutableException, IOException {
+ Node n = initVersioningException(true);
+
+ FileInputStream in = new FileInputStream(file);
+ try {
+ session.importXML(n.getPath(), in);
+ fail("Importing to a checked-in node must throw a ConstraintViolationException.");
+ } catch (ConstraintViolationException e) {
+ // success
+ }
+ }
+
+ /**
+ * Imports a tree below a child node of a checked-in node. This should fail,
+ * because you need to check out the node before you can make any changes to
+ * it or its children.
+ */
+ public void testVersioningExceptionSessionFileChild()
+ throws RepositoryException, NotExecutableException, IOException {
+ Node n = initVersioningException(false);
+ FileInputStream in = new FileInputStream(file);
+ try {
+ session.importXML(n.getPath(), in);
+ fail("Importing to a child of a checked-in node must throw a ConstraintViolationException.");
+ } catch (ConstraintViolationException e) {
+ // success
+ }
+ }
+
+ /**
+ * Creates a simple target tree consisting of a checked-in node and an
+ * ordinary child node below. Throws a {@link NotExecutableException} if
+ * {@link #testNodeType} is not versionable.
+ *
+ * @param returnParent Whether the method returns a checked-in parent or the
+ * child of a checked-in parent.
+ * @return The requested node (a node that is checked in or that has a
+ * parent that is checked in).
+ */
+ private Node initVersioningException(boolean returnParent) throws RepositoryException, NotExecutableException, IOException {
+ Node vNode = testRootNode.addNode(nodeName1, testNodeType);
+ if (!vNode.isNodeType(mixVersionable)) {
+ throw new NotExecutableException("NodeType: " + testNodeType + " is not versionable");
+ }
+ Node vChild = vNode.addNode(nodeName2, testNodeType);
+ session.save();
+ vNode.checkin();
+
+ exportRepository(SKIPBINARY, RECURSE);
+
+ if (returnParent) {
+ return vNode;
+ } else {
+ return vChild;
+ }
+ }
+
+ /**
+ * Tests whether importing a tree respects locking.
+ */
+ public void testLockException() throws RepositoryException, IOException {
+ Repository repository = session.getRepository();
+ exportRepository(SKIPBINARY, RECURSE);
+ if (repository.getDescriptor("OPTION_LOCKING_SUPPORTED") != null) {
+ //A LockException is thrown if a lock prevents the addition of the subtree.
+ Node lNode = testRootNode.addNode("lNode");
+ lNode.addMixin("mix:lockable");
+ Lock lock = lNode.lock(true, true);
+ session.removeLockToken(lock.getLockToken()); //remove the token, so the lock is for me, too
+ FileInputStream in = new FileInputStream(file);
+ try {
+ session.importXML(lNode.getPath(), in);
+ fail("De-serializing to a locked node must throw a lock exception.");
+ } catch (LockException e) {
+ // success
+ }
+ } else {
+ log.println("Locking not supported.");
+ }
+ }
+
+ /**
+ * Tests whether importing an invalid XML file throws a SAX exception. The
+ * file used here is more or less garbage.
+ */
+ public void testInvalidXmlThrowsSaxException() {
+ StringReader in = new StringReader("<this is not a <valid> <xml> file/>");
+ ContentHandler ih = null;
+ try {
+ ih = session.getImportContentHandler(treeComparator.targetFolder);
+ } catch (RepositoryException e) {
+ fail("ImportHandler not created: " + e);
+ }
+ helpTestSaxException(ih, in, "session");
+
+ try {
+ ih = workspace.getImportContentHandler(treeComparator.targetFolder, 0);
+ } catch (RepositoryException e) {
+ fail("ImportHandler not created: " + e);
+ }
+ helpTestSaxException(ih, in, "workspace");
+ }
+
+ /**
+ * Helper method for testSaxException.
+ *
+ * @param ih
+ * @param in
+ */
+ private void helpTestSaxException(ContentHandler ih, Reader in, String mode) {
+ XMLReader parser = null;
+ try {
+ parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
+ parser.setContentHandler(ih);
+ parser.setErrorHandler((ErrorHandler) ih);
+ try {
+ parser.parse(new InputSource(in));
+ } catch (IOException e) {
+ fail("Input stream not available for parsing: " + e);
+ }
+ fail("Parsing an invalid XML file with via " + mode + " ContentHandler did not throw a SAXException.");
+ } catch (SAXException e) {
+ // success
+ }
+ }
+
+ /**
+ * Supplying an invalid repository path for import must throw a
+ * PathNotFoundException
+ */
+ public void testGetImportContentHandlerExceptions() throws RepositoryException {
+ //Specifying a path that does not exist throws a PathNotFound exception
+ try {
+ session.getImportContentHandler(treeComparator.targetFolder + "/thisIsNotAnExistingNode");
+ fail("Specifying a non-existing path must throw a PathNotFoudException.");
+ } catch (PathNotFoundException e) {
+ // success
+ }
+ }
+
+ /**
+ * Tests the exception when importing: If the parent node does not exist.
+ */
+ public void testSessionImportXmlExceptions() throws RepositoryException, IOException {
+ exportRepository(SKIPBINARY, RECURSE);
+ FileInputStream in = new FileInputStream(file);
+
+ // If no node exists at parentAbsPath, a PathNotFoundException is thrown.
+ try {
+ session.importXML(treeComparator.targetFolder + "/thisNodeDoesNotExist", in);
+ fail("Importing to a non-existing node does not throw a PathNotFoundException.");
+ } catch (PathNotFoundException e) {
+ // success
+ }
+ }
+
+ /**
+ * Tests the exceptions when importing: If the parent node does not exist,
+ * and if an IO error occurs.
+ */
+ public void testWorkspaceImportXmlExceptions() throws RepositoryException, IOException {
+ exportRepository(SKIPBINARY, RECURSE);
+ FileInputStream in = new FileInputStream(file);
+
+ //If no node exists at parentAbsPath, a PathNotFoundException is thrown.
+ try {
+ workspace.importXML(treeComparator.targetFolder + "/thisNodeDoesNotExist", in, 0);
+ fail("Importing to a non-existing node does not throw a PathNotFoundException.");
+ } catch (PathNotFoundException e) {
+ // success
+ }
+ }
+
+ /**
+ * Tries to overwrite an existing node. This only works for nodes that do
+ * not allow same-name siblings.
+ */
+ public void testSessionImportXmlOverwriteException() throws RepositoryException, IOException {
+ //If deserialization would overwrite an existing item, an ItemExistsException is thrown.
+
+ //create a folder node and a child node
+ Node folder = null, subfolder = null;
+ FileOutputStream out;
+ FileInputStream in = null;
+ folder = testRootNode.addNode("myFolder", "nt:folder");
+ subfolder = folder.addNode("mySubFolder", "nt:folder");
+ session.save();
+ out = new FileOutputStream(file);
+ session.exportSysView(subfolder.getPath(), out, true, true);
+ subfolder.addNode("mySubSubFolder", "nt:folder");
+ subfolder.remove();
+ session.save();
+ in = new FileInputStream(file);
+
+ try {
+ session.importXML(folder.getPath(), in);
+ session.save();
+ fail("Overwriting an existing node during import must throw an ItemExistsException");
+ } catch (ItemExistsException e) {
+ // success
+ }
+ }
+
+ /**
+ * Makes sure that importing into the session does not save anything if the
+ * session is closed.
+ */
+ public void testSessionImportXml() throws RepositoryException, IOException {
+ FileInputStream in = new FileInputStream(file);
+ exportRepository(SAVEBINARY, RECURSE);
+ session.importXML(treeComparator.targetFolder, in);
+
+ // after logout/login, no nodes are in the session
+ session.logout();
+ superuser = null; //so tearDown won't fail
+
+ session = helper.getReadWriteSession();
+ treeComparator.compare(treeComparator.CHECK_EMPTY);
+ }
+
+ public void testExportSysView_stream_workspace_skipBinary_noRecurse() throws IOException, RepositoryException {
+ doTest(STREAM, WORKSPACE, SKIPBINARY, NORECURSE);
+ }
+
+ public void testExportSysView_stream_workspace_skipBinary_recurse() throws IOException, RepositoryException {
+ doTest(STREAM, WORKSPACE, SKIPBINARY, RECURSE);
+ }
+
+ public void testExportSysView_stream_workspace_saveBinary_noRecurse() throws IOException, RepositoryException {
+ doTest(STREAM, WORKSPACE, SAVEBINARY, NORECURSE);
+ }
+
+ public void testExportSysView_stream_workspace_saveBinary_recurse() throws IOException, RepositoryException {
+ doTest(STREAM, WORKSPACE, SAVEBINARY, RECURSE);
+ }
+
+ public void testExportSysView_stream_session_skipBinary_noRecurse() throws IOException, RepositoryException {
+ doTest(STREAM, SESSION, SKIPBINARY, NORECURSE);
+ }
+
+ public void testExportSysView_stream_session_skipBinary_recurse() throws IOException, RepositoryException {
+ doTest(STREAM, SESSION, SKIPBINARY, RECURSE);
+ }
+
+ public void testExportSysView_stream_session_saveBinary_noRecurse() throws IOException, RepositoryException {
+ doTest(STREAM, SESSION, SAVEBINARY, NORECURSE);
+ }
+
+ public void testExportSysView_stream_session_saveBinary_recurse() throws IOException, RepositoryException {
+ doTest(STREAM, SESSION, SAVEBINARY, RECURSE);
+ }
+
+ public void testExportSysView_handler_workspace_skipBinary_noRecurse() throws IOException, RepositoryException {
+ doTest(CONTENTHANDLER, WORKSPACE, SKIPBINARY, NORECURSE);
+ }
+
+ public void testExportSysView_handler_workspace_skipBinary_recurse() throws IOException, RepositoryException {
+ doTest(CONTENTHANDLER, WORKSPACE, SKIPBINARY, RECURSE);
+ }
+
+ public void testExportSysView_handler_workspace_saveBinary_noRecurse() throws IOException, RepositoryException {
+ doTest(CONTENTHANDLER, WORKSPACE, SAVEBINARY, NORECURSE);
+ }
+
+ public void testExportSysView_handler_workspace_saveBinary_recurse() throws IOException, RepositoryException {
+ doTest(CONTENTHANDLER, WORKSPACE, SAVEBINARY, RECURSE);
+ }
+
+ public void testExportSysView_handler_session_skipBinary_noRecurse() throws IOException, RepositoryException {
+ doTest(CONTENTHANDLER, SESSION, SKIPBINARY, NORECURSE);
+ }
+
+ public void testExportSysView_handler_session_skipBinary_recurse() throws IOException, RepositoryException {
+ doTest(CONTENTHANDLER, SESSION, SKIPBINARY, RECURSE);
+ }
+
+ public void testExportSysView_handler_session_saveBinary_noRecurse() throws IOException, RepositoryException {
+ doTest(CONTENTHANDLER, SESSION, SAVEBINARY, NORECURSE);
+ }
+
+ public void testExportSysView_handler_session_saveBinary_recurse() throws IOException, RepositoryException {
+ doTest(CONTENTHANDLER, SESSION, SAVEBINARY, RECURSE);
+ }
+
+ /**
+ * Exports the tree at source node, imports it at the traget node, and
+ * compares the source and target tree.
+ *
+ * @param handler true = use content handler for import, false = use the
+ * importXML method
+ * @param workspace true = import to the workspace, false = import to the
+ * session (export is from session anyway)
+ * @param skipBinary true = skip binary properties. The binary properties
+ * are omitted (without any replacement)
+ * @param noRecurse true = export only top node, false = export entire
+ * subtree
+ */
+ private void doTest(boolean handler, boolean workspace, boolean skipBinary, boolean noRecurse)
+ throws RepositoryException, IOException {
+ exportRepository(skipBinary, noRecurse);
+ importRepository(handler, workspace);
+ treeComparator.showTree();
+ treeComparator.compare(skipBinary, noRecurse);
+ }
+
+ /**
+ * Exports the repository to a temporary file using the system view
+ * serialization.
+ *
+ * @param skipBinary true = omit any binary properties (without any
+ * replacement)
+ * @param noRecurse true = save only top node, false = save entire subtree
+ * @throws IOException
+ */
+ private void exportRepository(boolean skipBinary, boolean noRecurse) throws IOException {
+ FileOutputStream out;
+ try {
+ out = new FileOutputStream(file);
+ session.refresh(false); //move the workspace into the session, then save it. The workspace is always valid, the session not necessarily.
+ session.exportSysView(treeComparator.getSourceRootPath(), out, skipBinary, noRecurse);
+ } catch (RepositoryException e) {
+ fail("Could not export the repository: " + e);
+ }
+ }
+
+ /**
+ * Imports the repository
+ *
+ * @param useHandler True = use the import handler, false = use file input
+ * stream
+ * @param workspace True = import into workspace, false = import into
+ * session
+ */
+ public void importRepository(boolean useHandler, boolean workspace) throws RepositoryException, IOException {
+ FileInputStream in = null;
+ try {
+ in = new FileInputStream(file);
+ } catch (FileNotFoundException e) {
+ fail("Input file not opened: " + e);
+ }
+
+ if (useHandler) {
+ if (workspace) {
+ ContentHandler ih = this.workspace.getImportContentHandler(treeComparator.targetFolder, 0);
+ try {
+ XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
+ parser.setContentHandler(ih);
+ parser.setErrorHandler((ErrorHandler) ih);
+ parser.parse(new InputSource(in));
+ } catch (SAXException e) {
+ fail("Error while parsing the imported repository: " + e);
+ }
+ } else {
+ ContentHandler ih = session.getImportContentHandler(treeComparator.targetFolder);
+ try {
+ XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
+ parser.setContentHandler(ih);
+ parser.setErrorHandler((ErrorHandler) ih);
+ parser.parse(new InputSource(in));
+ } catch (SAXException e) {
+ fail("Error while parsing the imported repository: " + e);
+ }
+ }
+ } else {
+ if (workspace) {
+ this.workspace.importXML(treeComparator.targetFolder, in, 0);
+ } else {
+ session.importXML(treeComparator.targetFolder, in);
+ }
+ }
+ }
+}
\ No newline at end of file
Propchange: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/SerializationTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/TreeComparator.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/TreeComparator.java?view=auto&rev=155937
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/TreeComparator.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/TreeComparator.java Wed Mar 2 10:11:49 2005
@@ -0,0 +1,573 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * 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.jackrabbit.test.api;
+
+import org.apache.jackrabbit.test.AbstractJCRTest;
+
+import javax.jcr.Session;
+import javax.jcr.Workspace;
+import javax.jcr.Item;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.NameValue;
+import javax.jcr.PathValue;
+import javax.jcr.NodeIterator;
+import javax.jcr.PropertyIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
+import javax.jcr.Value;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.nodetype.NodeTypeManager;
+import javax.jcr.nodetype.NodeTypeIterator;
+import javax.jcr.nodetype.NodeType;
+import java.util.Calendar;
+import java.io.ByteArrayInputStream;
+
+/**
+ * <code>TreeComparator</code> compares two trees. This allows re-use for
+ * different tests, and it allows to test a function on any tree, not just a
+ * simple example node.
+ * <p/>
+ * TreeComparator also creates an example tree that contains as many features as
+ * possible.
+ */
+class TreeComparator extends AbstractJCRTest {
+ public SerializationContext sc;
+
+ public final boolean WORKSPACE = true;
+ public final boolean SESSION = false;
+
+ public final int CHECK_EMPTY = -1;
+ public final int IGNORE = 0;
+ public final int CHECK_SAME = 1;
+
+ public int check = CHECK_SAME;
+
+ private Session session;
+ private Workspace workspace;
+
+ public boolean skipBinary = false, noRecurse = false;
+ public String sourceFolder, targetFolder;
+ public String root;
+
+ public TreeComparator(SerializationContext sc, Session s) throws Exception {
+ this.sc = sc;
+ setUp();
+ session = s;
+ workspace = session.getWorkspace();
+ init();
+ }
+
+ /**
+ * Makes sure that the source and target folder exist, and are empty
+ */
+ private void init() throws RepositoryException {
+ root = sc.testroot;
+ sourceFolder = root + "/" + sc.sourceFolderName;
+ targetFolder = root + "/" + sc.targetFolderName;
+
+ // make sure the node does not have a and target sub node.
+ try {
+ session.getItem(sourceFolder).remove();
+ session.save();
+ } catch (PathNotFoundException e) {
+ // item does not exist
+ }
+ try {
+ Item tgt = session.getItem(targetFolder);
+ tgt.remove();
+ session.save();
+ } catch (PathNotFoundException e) {
+ // item does not exist
+ }
+
+ // add the source and target nodes
+ Node rootNode = (Node) session.getItem(root);
+ rootNode.addNode(sc.sourceFolderName);
+ rootNode.addNode(sc.targetFolderName);
+ session.save();
+ }
+
+ /**
+ * Creates an example tree in the workspace.
+ */
+ public void createExampleTree() {
+ createExampleTree(true);
+ }
+
+ /**
+ * Creates a simple example tree. Use this tree for general repository
+ * functions, such as serialization, namespaces and versioning.
+ * <p/>
+ * The beauty of this is that the tree contains exactly the features that
+ * are supported by the repository. Any repository exceptions that occur are
+ * displayed on "out", but are otherwise ignored.
+ *
+ * @param save If true, the example tree is saved to the workspace. If
+ * false, it remains in the session.
+ */
+ public void createExampleTree(boolean save) {
+ try {
+ Node src = (Node) session.getItem(sourceFolder);
+ Node root = src.addNode(sc.rootNodeName);
+ root.addNode(nodeName1);
+ root.addNode(nodeName2, testNodeType);
+ byte[] byteArray = {(byte) 0, (byte) 255, (byte) 167, (byte) 100, (byte) 21, (byte) 6, (byte) 19, (byte) 71, (byte) 221};
+ root.setProperty(propertyName1, new ByteArrayInputStream(byteArray));
+ root.setProperty(nodeName3, "hello");
+ } catch (Exception e) {
+ log.println("Error while creating example tree: " + e.getMessage());
+ }
+ if (save) {
+ try {
+ session.save();
+ } catch (RepositoryException e) {
+ fail("Cannot save the example tree to the repository: " + e);
+ }
+ }
+ }
+
+ /**
+ * Creates a complex example tree in the workspace
+ */
+ public void createComplexTree() {
+ createComplexTree(true);
+ }
+
+ /**
+ * Creates a complex example tree that uses as many features of the
+ * repository as possible
+ *
+ * @param save Save the tree to the workspace. If false, the tree remains in
+ * the session.
+ */
+ public void createComplexTree(boolean save) {
+ Node rootNode = null;
+ Node nt = null;
+ Node pt = null;
+ Node mvp = null;
+ Node referenceable = null;
+ try {
+ Node src = (Node) session.getItem(sourceFolder);
+ rootNode = src.addNode(sc.rootNodeName);
+ nt = rootNode.addNode(sc.nodeTypesTestNode);
+ rootNode.addNode(sc.mixinTypeTestNode);
+ pt = rootNode.addNode(sc.propertyTypesTestNode);
+ rootNode.addNode(sc.sameNameChildrenTestNode);
+ mvp = rootNode.addNode(sc.multiValuePropertiesTestNode);
+ referenceable = rootNode.addNode(sc.referenceableNodeTestNode);
+ rootNode.addNode(sc.orderChildrenTestNode);
+ rootNode.addNode(sc.namespaceTestNode);
+ } catch (RepositoryException e) {
+ log.println("Error while creating example tree: " + e.getMessage());
+ }
+
+ // Add nodes with mixin types
+ NodeTypeManager ntmgr = null;
+ NodeTypeIterator types = null;
+ try {
+ ntmgr = workspace.getNodeTypeManager();
+ types = ntmgr.getMixinNodeTypes();
+ } catch (RepositoryException e) {
+ fail("Cannot access NodeType iterator: " + e);
+ }
+ while (types.hasNext()) {
+ NodeType t = (NodeType) types.next();
+ String name = t.getName();
+ name = "Node_" + name.replaceAll(":", "_");
+
+ Node n = null;
+ try {
+ n = nt.addNode(name);
+ n.addMixin(t.getName());
+ // try saving, because some exceptions are trown only at save time
+ session.save();
+ } catch (RepositoryException e) {
+ log.println("Cannot create node with mixin node type: " + e);
+ // if saving failed for a node, then remove it again (or else the next save will fail on it)
+ try {
+ n.remove();
+ } catch (RepositoryException e1) {
+ log.println("Could not remove node: " + e);
+ }
+ }
+ }
+
+ // Create all property types
+ try {
+ // String
+ pt.setProperty(sc.stringTestProperty, "This is a string.");
+ // Binary
+ byte[] byteArray = {(byte) 0, (byte) 255, (byte) 167, (byte) 100, (byte) 21, (byte) 6, (byte) 19, (byte) 71, (byte) 221};
+ pt.setProperty(sc.binaryTestProperty, new ByteArrayInputStream(byteArray));
+ // Date
+ Calendar c = Calendar.getInstance();
+ c.set(2005, 6, 21, 13, 30, 5);
+ pt.setProperty(sc.dateTestProperty, c);
+ // Long
+ pt.setProperty(sc.longTestProperty, (long) (1 / 3));
+ // Double
+ pt.setProperty(sc.doubleTestProperty, (double) Math.PI);
+ // Boolean
+ pt.setProperty(sc.booleanTestProperty, true);
+ // Name
+ pt.setProperty(sc.nameTestProperty, NameValue.valueOf(jcrPrimaryType));
+ // Path
+ pt.setProperty(sc.pathTestProperty, PathValue.valueOf("paths/dont/have/to/point/anywhere"));
+ // Reference: Note that I only check if the node exists. We do not specify what happens with
+ // the UUID during serialization.
+ if (!referenceable.isNodeType(mixReferenceable)) {
+ referenceable.addMixin(mixReferenceable);
+ }
+ pt.setProperty(sc.referenceTestProperty, referenceable);
+
+ // Create a boolean property on the root node, so I can test noRecurse and skipBinary at the same time
+ rootNode.setProperty(sc.binaryTestProperty, new ByteArrayInputStream(byteArray));
+ session.save();
+ } catch (Exception e) {
+ fail("Could not add property: " + e);
+ }
+
+ // multi value properties
+ String[] s = {"one", "two", "three"};
+ try {
+ mvp.setProperty(sc.multiValueTestProperty, s);
+ session.save();
+ } catch (RepositoryException e) {
+ log.println("Could not create multi-value property: " + e);
+ }
+
+ // Save to the workspace. Note that export is from session anyway.
+ if (save) {
+ try {
+ session.save();
+ } catch (RepositoryException e) {
+ fail("Cannot save the example tree to the repository: " + e);
+ }
+ }
+ }
+
+ /**
+ * Compares the trees in the source and target folder.
+ *
+ * @param skipBinary True if skipbinary is set, so binary properties are not
+ * in the taget tree.
+ * @param noRecurse True if noRecurse is used, so only the top node and its
+ * properties are in the target tree.
+ */
+ public void compare(boolean skipBinary, boolean noRecurse) {
+ this.skipBinary = skipBinary;
+ this.noRecurse = noRecurse;
+ compare();
+ }
+
+ /**
+ * Compares the source and target tree.
+ */
+ public void compare() {
+ compare(CHECK_SAME);
+ }
+
+ /**
+ * Compares the source and target tree.
+ *
+ * @param check CHECK_SAME checks if the two trees have the same nodes and
+ * properties. CHECK_EMPTY checks that the target tree is
+ * empty.
+ */
+ public void compare(int check) {
+ this.check = check;
+ compare(sourceFolder + "/" + sc.rootNodeName, 0);
+ }
+
+ /**
+ * Compares two nodes in the source and target tree
+ *
+ * @param sourcePath The path of the node in the source tree
+ * @param level The level of depth in the tree
+ */
+ public void compare(String sourcePath, int level) {
+ Node source = null;
+ Node target = null;
+
+ // get the source path
+ try {
+ source = (Node) session.getItem(sourcePath);
+ } catch (RepositoryException e) {
+ fail("Could not read source node " + sourcePath + ": " + e.getMessage());
+ }
+
+ // get the target path
+ String targetPath = getTargetPath(sourcePath);
+ try {
+ session.getItem(targetFolder);
+ } catch (RepositoryException e) {
+ fail("Target folder not found: " + e);
+ }
+
+ // Check noRecurse: After top level, the target tree must be empty
+ if (noRecurse && level == 1) {
+ check = CHECK_EMPTY;
+ }
+
+ // compare source and target
+ if (check == CHECK_SAME) {
+ try {
+ target = (Node) session.getItem(targetPath);
+ } catch (RepositoryException e) {
+ showTree();
+ fail("Could not read target node " + targetPath + ": " + e);
+ }
+ compareNodes(source, target);
+ } else if (check == CHECK_EMPTY) {
+ try {
+ session.getItem(targetPath);
+ fail("The item " + targetPath + " must not be available.");
+ } catch (RepositoryException e) {
+ }
+ }
+
+ // iterate through all child nodes of the source tree
+ try {
+ NodeIterator ni = source.getNodes();
+ while (ni.hasNext()) {
+ Node n = (Node) ni.next();
+ compare(n.getPath(), level + 1);
+ }
+ } catch (RepositoryException e) {
+ fail("Error while iterating through child nodes: " + e);
+ }
+ }
+
+ /**
+ * Compares two nodes, a and b
+ *
+ * @param a The node in the source tree
+ * @param b The same node in the target tree
+ */
+ public void compareNodes(Node a, Node b) {
+ try {
+ log.println("Comparing " + a.getPath() + " to " + b.getPath());
+ } catch (RepositoryException e) {
+ fail("Nodes not available: " + e.getMessage());
+ }
+
+ // check primary node type
+ String primaryTypeA = null, primaryTypeB = null;
+ try {
+ primaryTypeA = a.getProperty(jcrPrimaryType).getName();
+ primaryTypeB = b.getProperty(jcrPrimaryType).getName();
+ } catch (RepositoryException e) {
+ fail("Primary node type not available: " + e);
+ }
+ assertEquals("Primary node type has changed.", primaryTypeA, primaryTypeB);
+
+ compareProperties(a, b);
+ }
+
+ /**
+ * Compares all the properties of the two nodes a and b
+ *
+ * @param a The node in the source tree.
+ * @param b The node in the target tree.
+ */
+ public void compareProperties(Node a, Node b) {
+ PropertyIterator ai = null;
+ try {
+ ai = a.getProperties();
+ } catch (RepositoryException e) {
+ fail("Cannot access properties: " + e);
+ }
+ while (ai.hasNext()) {
+ Property pa = (Property) ai.next();
+ String pName = null;
+ int pType = 0;
+
+ try {
+ pName = pa.getName();
+ if (pa.getDefinition().isMultiple()) {
+ pType = -9999;
+ } else {
+ pType = pa.getValue().getType();
+ }
+ } catch (RepositoryException e) {
+ fail("Cannot access property information: " + e);
+ }
+
+ Property pb = null;
+ try {
+ pb = b.getProperty(pName);
+ //fail if the property is there but should not be
+ if (skipBinary && pType == PropertyType.BINARY) {
+ fail("Property '" + pName + "' must not be available if skipBinary=true.");
+ }
+
+ } catch (RepositoryException e) {
+ //fail if the property is not there but should
+ if (!(skipBinary && pType == PropertyType.BINARY)) {
+ fail("Property '" + pName + "' not available: " + e);
+ }
+ }
+
+ //if the property should be available and is available, then compare source and target value
+ if (!(skipBinary && pType == PropertyType.BINARY)) {
+ compareProperties(pa, pb);
+ }
+
+ }
+
+ }
+
+ /**
+ * Compares two properties a and b.
+ *
+ * @param a The property in the source tree.
+ * @param b The property in the target tree.
+ */
+ public void compareProperties(Property a, Property b) {
+ String nodeName = null, propertyName = null;
+ boolean isMultiple = false;
+ try {
+ nodeName = a.getParent().getName();
+ propertyName = a.getName();
+ isMultiple = a.getDefinition().isMultiple();
+ } catch (RepositoryException e) {
+ fail("Cannot access property information: " + e);
+ }
+
+ if (!propertyValueMayChange(propertyName)) {
+ if (isMultiple) {
+ try {
+ compareValues(nodeName, propertyName, a.getValues(), b.getValues());
+ } catch (RepositoryException e) {
+ fail("Could not access property values: " + e);
+ }
+ } else {
+ try {
+ compareValue(nodeName, propertyName, a.getValue(), b.getValue());
+ } catch (RepositoryException e) {
+ fail("Could not access property value: " + e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Compares a set of multi-value properties.
+ *
+ * @param n Name of the node.
+ * @param p Name of the property.
+ * @param a Value (array) of the property in the source tree.
+ * @param b Value (array) of the property in the target tree.
+ */
+ public void compareValues(String n, String p, Value[] a, Value[] b) {
+ assertEquals("Multi-value property '" + p + "' of node '" + n + "' has changed length: ", a.length, b.length);
+ for (int t = 0; t < a.length; t++) {
+ compareValue(n, p, a[t], b[t]);
+ }
+ }
+
+ /**
+ * Compares the value of two properties
+ *
+ * @param n Name of the node.
+ * @param p Name of the property.
+ * @param a Value of the property in the source tree.
+ * @param b Value of the property in the target tree.
+ */
+ public void compareValue(String n, String p, Value a, Value b) {
+ if (!propertyValueMayChange(p)) {
+ try {
+ assertEquals("Properties '" + p + "' of node '" + n + "' have different values.", a.getString(), b.getString());
+ } catch (RepositoryException e) {
+ fail("Cannot access the content of the property value: " + e);
+ }
+ }
+ }
+
+ /**
+ * Returns whether the value of the property may change in serialization.
+ * For example, the last changed date of a node may change when the node is
+ * re-imported. The values that may change are declared in the config file.
+ *
+ * @param propertyName The property name you want to check
+ * @return True or false to indicate whether the value may or may not
+ * change.
+ */
+ public boolean propertyValueMayChange(String propertyName) {
+ if (sc.propertyValueMayChange.indexOf(" " + propertyName + " ") < 0) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Returns the path to the source root.
+ *
+ * @return The path to the source root.
+ */
+ public String getSourceRootPath() {
+ return sourceFolder + "/" + sc.rootNodeName;
+ }
+
+ /**
+ * Returns the path to the target root.
+ *
+ * @return The path to the target root.
+ */
+ private String getTargetPath(String sourcePath) {
+ String targetPath = sourcePath.replaceAll(sourceFolder, targetFolder);
+ return targetPath;
+ }
+
+ /**
+ * Displays the current source and target tree for debug/information
+ * purpose
+ */
+ public void showTree() {
+ Node n = null;
+ try {
+ n = (Node) session.getItem(sc.testroot);
+ showTree(n, 0);
+ } catch (RepositoryException e) {
+ log.println("Cannot display tree diagnostics: " + e);
+ }
+ }
+
+ /**
+ * Recursive display of source and target tree
+ */
+ public void showTree(Node n, int level) throws RepositoryException {
+ for (int t = 0; t < level; t++) {
+ log.print("-");
+ }
+ log.print(n.getName() + " ");
+ log.print(n.getPrimaryNodeType().getName() + " [ ");
+ PropertyIterator pi = n.getProperties();
+ while (pi.hasNext()) {
+ Property p = (Property) pi.next();
+ log.print(p.getName() + " ");
+ }
+ log.println("]");
+
+ NodeIterator ni = n.getNodes();
+ while (ni.hasNext()) {
+ showTree((Node) ni.next(), level + 1);
+ }
+ }
+}
\ No newline at end of file
Propchange: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/TreeComparator.java
------------------------------------------------------------------------------
svn:eol-style = native