jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mreut...@apache.org
Subject 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/
Date Wed, 02 Mar 2005 18:11:51 GMT
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



Mime
View raw message