jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mreut...@apache.org
Subject svn commit: r158049 - in incubator/jackrabbit/trunk: applications/test/ src/test/org/apache/jackrabbit/test/api/
Date Fri, 18 Mar 2005 10:43:06 GMT
Author: mreutegg
Date: Fri Mar 18 02:43:04 2005
New Revision: 158049

URL: http://svn.apache.org/viewcvs?view=rev&rev=158049
Log:
Level 1 test cases for system view export.

Added:
    incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/Base64.java   (with props)
    incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/ExportSysViewTest.java   (with props)
    incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/SysViewContentHandler.java   (with props)
Modified:
    incubator/jackrabbit/trunk/applications/test/repositoryStubImpl.properties
    incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/TestAll.java

Modified: incubator/jackrabbit/trunk/applications/test/repositoryStubImpl.properties
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/applications/test/repositoryStubImpl.properties?view=diff&r1=158048&r2=158049
==============================================================================
--- incubator/jackrabbit/trunk/applications/test/repositoryStubImpl.properties (original)
+++ incubator/jackrabbit/trunk/applications/test/repositoryStubImpl.properties Fri Mar 18 02:43:04 2005
@@ -268,6 +268,9 @@
 # specified nodetype must be versionable and allow child nodes of the same type.
 javax.jcr.tck.SerializationTest.testVersioningExceptionSessionFileParent.nodetype=test:versionable
 
+# Test class: ExportSysViewTest
+javax.jcr.tck.ExportSysViewTest.testroot=/testdata
+
 # ==============================================================================
 # JAVAX.JCR.QUERY CONFIGURATION
 # ==============================================================================

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/Base64.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/Base64.java?view=auto&rev=158049
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/Base64.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/Base64.java Fri Mar 18 02:43:04 2005
@@ -0,0 +1,262 @@
+/*
+ * 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 java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+
+/**
+ * <code>Base64</code> provides Base64 encoding/decoding of strings and streams.
+ * NOTE: This is a copy of the original org.apache.jackrabbit.core.util.Base64
+ * class to not introduce a dependency to jackrabbit from the test classes.
+ */
+public class Base64 {
+    // charset used for base64 encoded data (7-bit ASCII)
+    private static final String CHARSET = "US-ASCII";
+
+    // encoding table (the 64 valid base64 characters)
+    private static final char[] BASE64CHARS =
+            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
+
+    // decoding table (used to lookup original 6-bit with base64 character as table index)
+    private static final byte[] DECODETABLE = new byte[128];
+
+    static {
+        // initialize decoding table
+        for (int i = 0; i < DECODETABLE.length; i++) {
+            DECODETABLE[i] = 0x7f;
+        }
+        // build decoding table
+        for (int i = 0; i < BASE64CHARS.length; i++) {
+            DECODETABLE[BASE64CHARS[i]] = (byte) i;
+        }
+    }
+
+    // pad character
+    private static final char BASE64PAD = '=';
+
+    /**
+     * empty private constructor
+     */
+    private Base64() {
+    }
+
+    /**
+     * Calculates the size (i.e. number of bytes) of the base64 encoded output
+     * given the length (i.e. number of bytes) of the data to be encoded.
+     *
+     * @param dataLength length (i.e. number of bytes) of the data to be encoded
+     * @return size (i.e. number of bytes) of the base64 encoded output
+     */
+    public static long calcEncodedLength(long dataLength) {
+        long encLen = dataLength * 4 / 3;
+        encLen += (encLen + 4) % 4;
+        return encLen;
+    }
+
+    /**
+     * Pessimistically guesses the size (i.e. number of bytes) of the decoded output
+     * given the length (i.e. number of bytes) of the base64 encoded data.
+     *
+     * @param encLength length (i.e. number of bytes) of the base64 encoded data
+     * @return size (i.e. number of bytes) of the decoded output
+     */
+    public static long guessDecodedLength(long encLength) {
+        long decLen = encLength * 3 / 4;
+        return decLen + 3;
+    }
+
+    /**
+     * Outputs base64 representation of the specified stream data to an <code>OutputStream</code>.
+     *
+     * @param in     stream data to be encoded
+     * @param writer writer to output the encoded data
+     */
+    public static void encode(InputStream in, Writer writer)
+            throws IOException {
+        // encode stream data in chunks;
+        // chunksize must be a multiple of 3 in order
+        // to avoid padding within output
+        byte[] buffer = new byte[9 * 1024];
+        int read = 0;
+        while ((read = in.read(buffer)) > 0) {
+            encode(buffer, 0, read, writer);
+        }
+    }
+
+    /**
+     * Outputs base64 representation of the specified stream data to an <code>OutputStream</code>.
+     *
+     * @param in  stream data to be encoded
+     * @param out stream where the encoded data should be written to
+     */
+    public static void encode(InputStream in, OutputStream out)
+            throws IOException {
+        Writer writer = new OutputStreamWriter(out, CHARSET);
+        encode(in, writer);
+    }
+
+    /**
+     * Outputs base64 representation of the specified data to an <code>OutputStream</code>.
+     *
+     * @param data   data to be encoded
+     * @param off    offset within data at which to start encoding
+     * @param len    length of data to encode
+     * @param writer writer to output the encoded data
+     */
+    public static void encode(byte[] data, int off, int len, Writer writer)
+            throws IOException {
+        if (len == 0) {
+            return;
+        }
+        if (len < 0 || off >= data.length
+                || len + off > data.length) {
+            throw new IllegalArgumentException();
+        }
+        char[] enc = new char[4];
+        while (len >= 3) {
+            int i = ((data[off] & 0xff) << 16)
+                    + ((data[off + 1] & 0xff) << 8)
+                    + (data[off + 2] & 0xff);
+            enc[0] = BASE64CHARS[i >> 18];
+            enc[1] = BASE64CHARS[(i >> 12) & 0x3f];
+            enc[2] = BASE64CHARS[(i >> 6) & 0x3f];
+            enc[3] = BASE64CHARS[i & 0x3f];
+            writer.write(enc, 0, 4);
+            off += 3;
+            len -= 3;
+        }
+        // add padding if necessary
+        if (len == 1) {
+            int i = data[off] & 0xff;
+            enc[0] = BASE64CHARS[i >> 2];
+            enc[1] = BASE64CHARS[(i << 4) & 0x3f];
+            enc[2] = BASE64PAD;
+            enc[3] = BASE64PAD;
+            writer.write(enc, 0, 4);
+        } else if (len == 2) {
+            int i = ((data[off] & 0xff) << 8) + (data[off + 1] & 0xff);
+            enc[0] = BASE64CHARS[i >> 10];
+            enc[1] = BASE64CHARS[(i >> 4) & 0x3f];
+            enc[2] = BASE64CHARS[(i << 2) & 0x3f];
+            enc[3] = BASE64PAD;
+            writer.write(enc, 0, 4);
+        }
+    }
+
+    /**
+     * Decode base64 encoded data.
+     *
+     * @param reader reader for the base64 encoded data to be decoded
+     * @param out    stream where the decoded data should be written to
+     */
+    public static void decode(Reader reader, OutputStream out) throws IOException {
+        char[] chunk = new char[8192];
+        int read;
+        while ((read = reader.read(chunk)) > -1) {
+            decode(chunk, 0, read, out);
+        }
+    }
+
+    /**
+     * Decode base64 encoded data. The data read from the inputstream is
+     * assumed to be of charset "US-ASCII".
+     *
+     * @param in  inputstream of the base64 encoded data to be decoded
+     * @param out stream where the decoded data should be written to
+     */
+    public static void decode(InputStream in, OutputStream out) throws IOException {
+        decode(new InputStreamReader(in, CHARSET), out);
+    }
+
+    /**
+     * Decode base64 encoded data.
+     *
+     * @param data the base64 encoded data to be decoded
+     * @param out  stream where the decoded data should be written to
+     */
+    public static void decode(String data, OutputStream out) throws IOException {
+        char[] chars = data.toCharArray();
+        decode(chars, 0, chars.length, out);
+    }
+
+    /**
+     * Decode base64 encoded data.
+     *
+     * @param chars the base64 encoded data to be decoded
+     * @param out   stream where the decoded data should be written to
+     */
+    public static void decode(char[] chars, OutputStream out) throws IOException {
+        decode(chars, 0, chars.length, out);
+    }
+
+    /**
+     * Decode base64 encoded data.
+     *
+     * @param chars the base64 encoded data to be decoded
+     * @param off   offset within data at which to start decoding
+     * @param len   length of data to decode
+     * @param out   stream where the decoded data should be written to
+     */
+    public static void decode(char[] chars, int off, int len, OutputStream out) throws IOException {
+        if (len == 0) {
+            return;
+        }
+        if (len < 0 || off >= chars.length
+                || len + off > chars.length) {
+            throw new IllegalArgumentException();
+        }
+        char[] chunk = new char[4];
+        byte[] dec = new byte[3];
+        int posChunk = 0;
+        // decode in chunks of 4 characters
+        for (int i = off; i < (off + len); i++) {
+            char c = chars[i];
+            if (c < DECODETABLE.length && DECODETABLE[c] != 0x7f
+                    || c == BASE64PAD) {
+                chunk[posChunk++] = c;
+                if (posChunk == chunk.length) {
+                    int b0 = DECODETABLE[chunk[0]];
+                    int b1 = DECODETABLE[chunk[1]];
+                    int b2 = DECODETABLE[chunk[2]];
+                    int b3 = DECODETABLE[chunk[3]];
+                    if (chunk[3] == BASE64PAD && chunk[2] == BASE64PAD) {
+                        dec[0] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3);
+                        out.write(dec, 0, 1);
+                    } else if (chunk[3] == BASE64PAD) {
+                        dec[0] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3);
+                        dec[1] = (byte) (b1 << 4 & 0xf0 | b2 >> 2 & 0xf);
+                        out.write(dec, 0, 2);
+                    } else {
+                        dec[0] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3);
+                        dec[1] = (byte) (b1 << 4 & 0xf0 | b2 >> 2 & 0xf);
+                        dec[2] = (byte) (b2 << 6 & 0xc0 | b3 & 0x3f);
+                        out.write(dec, 0, 3);
+                    }
+                    posChunk = 0;
+                }
+            } else {
+                throw new IllegalArgumentException("specified data is not base64 encoded");
+            }
+        }
+    }
+}

Propchange: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/Base64.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/ExportSysViewTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/ExportSysViewTest.java?view=auto&rev=158049
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/ExportSysViewTest.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/ExportSysViewTest.java Fri Mar 18 02:43:04 2005
@@ -0,0 +1,246 @@
+/*
+ * 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.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.InputSource;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+import javax.jcr.Workspace;
+import javax.jcr.Session;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import java.io.File;
+import java.io.IOException;
+import java.io.BufferedOutputStream;
+import java.io.FileOutputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+
+/**
+ * <code>ExportSysViewTest</code> tests the SysView Export of a tree given by a
+ * node path. This is done with checking the SAX events of the sysview export
+ * against the items found by a traverse of the given tree.
+ *
+ * @test
+ * @sources ExportSysViewTest.java
+ * @executeClass org.apache.jackrabbit.test.api.ExportSysViewTest
+ * @keywords level1
+ */
+public class ExportSysViewTest extends AbstractJCRTest {
+
+    private Workspace workspace;
+    private File file;
+
+    private final boolean WORKSPACE = true, SESSION = false;
+    private final boolean SKIPBINARY = true, SAVEBINARY = false;
+    private final boolean NORECURSE = true, RECURSE = false;
+
+    private Session session;
+    private String testPath;
+    private Node testNode;
+
+
+    protected void setUp() throws Exception {
+        isReadOnly = true;
+        session = helper.getReadOnlySession();
+        workspace = session.getWorkspace();
+        file = File.createTempFile("SysViewExportTest", ".xml");
+
+        super.setUp();
+        this.testPath = testRoot;
+        this.testNode = (Node) session.getItem(testPath);
+    }
+
+    protected void tearDown() throws Exception {
+        file.delete();
+        super.tearDown();
+    }
+
+    /*
+    // tests with content handler
+    public void testExportSysView_handler_workspace_skipBinary_noRecurse()
+            throws IOException, RepositoryException, SAXException, IOException {
+        doTestWithHandler(WORKSPACE, SKIPBINARY, NORECURSE);
+    }
+
+    public void testExportSysView_handler_workspace_skipBinary_recurse()
+            throws IOException, RepositoryException, SAXException, IOException {
+        doTestWithHandler(WORKSPACE, SKIPBINARY, RECURSE);
+    }
+
+    public void testExportSysView_handler_workspace_saveBinary_noRecurse()
+            throws IOException, RepositoryException, SAXException, IOException {
+        doTestWithHandler(WORKSPACE, SAVEBINARY, NORECURSE);
+    }
+
+    public void testExportSysView_handler_workspace_saveBinary_recurse()
+            throws IOException, RepositoryException, SAXException, IOException {
+        doTestWithHandler(WORKSPACE, SAVEBINARY, RECURSE);
+    }
+  */
+
+    public void testExportSysView_handler_session_skipBinary_noRecurse()
+            throws IOException, RepositoryException, SAXException, IOException {
+        doTestWithHandler(SESSION, SKIPBINARY, NORECURSE);
+    }
+
+    public void testExportSysView_handler_session_skipBinary_recurse()
+            throws IOException, RepositoryException, SAXException, IOException {
+        doTestWithHandler(SESSION, SKIPBINARY, RECURSE);
+    }
+
+    public void testExportSysView_handler_session_saveBinary_noRecurse()
+            throws IOException, RepositoryException, SAXException, IOException {
+        doTestWithHandler(SESSION, SAVEBINARY, NORECURSE);
+    }
+
+    public void testExportSysView_handler_session_saveBinary_recurse()
+            throws IOException, RepositoryException, SAXException, IOException {
+        doTestWithHandler(SESSION, SAVEBINARY, RECURSE);
+    }
+
+    /*
+       // tests with output stream
+       public void testExportSysView_stream_workspace_skipBinary_noRecurse()
+               throws IOException, RepositoryException, SAXException {
+           doTestWithStream(WORKSPACE, SKIPBINARY, NORECURSE);
+       }
+
+       public void testExportSysView_stream_workspace_skipBinary_recurse()
+               throws IOException, RepositoryException, SAXException {
+           doTestWithStream(WORKSPACE, SKIPBINARY, RECURSE);
+       }
+
+       public void testExportSysView_stream_workspace_saveBinary_noRecurse()
+               throws IOException, RepositoryException, SAXException {
+           doTestWithStream(WORKSPACE, SAVEBINARY, NORECURSE);
+       }
+
+       public void testExportSysView_stream_workspace_saveBinary_recurse()
+               throws IOException, RepositoryException, SAXException {
+           doTestWithStream(WORKSPACE, SAVEBINARY, RECURSE);
+       }
+      */
+
+    public void testExportSysView_stream_session_skipBinary_recurse()
+            throws IOException, RepositoryException, SAXException {
+        doTestWithStream(SESSION, SKIPBINARY, RECURSE);
+    }
+
+    public void testExportSysView_stream_session_skipBinary_noRecurse()
+            throws IOException, RepositoryException, SAXException {
+        doTestWithStream(SESSION, SKIPBINARY, NORECURSE);
+    }
+
+    public void testExportSysView_stream_session_saveBinary_noRecurse()
+            throws IOException, RepositoryException, SAXException {
+        doTestWithStream(SESSION, SAVEBINARY, NORECURSE);
+    }
+
+    public void testExportSysView_stream_session_saveBinary_recurse()
+            throws IOException, RepositoryException, SAXException {
+        doTestWithStream(SESSION, SAVEBINARY, RECURSE);
+    }
+
+    /**
+     * @throws RepositoryException
+     * @throws SAXException
+     * @throws IOException
+     */
+    public void doTestWithHandler(boolean workspace, boolean skipBinary, boolean noRecurse)
+            throws RepositoryException, SAXException, IOException {
+
+        ContentHandler contentHandler;
+        try {
+
+            contentHandler = new SysViewContentHandler(testPath, session, skipBinary, noRecurse);
+
+            if (workspace) {
+                //workspace.exportSysView(testPath, contentHandler, skipBinary, noRecurse);
+            } else {
+                session.exportSysView(testPath, contentHandler, skipBinary, noRecurse);
+            }
+        } catch (RepositoryException re) {
+            fail("Could not initialize the contenthandler due to: " + re.toString());
+        }
+    }
+
+    /**
+     * @throws RepositoryException
+     * @throws SAXException
+     * @throws IOException
+     */
+    public void doTestWithStream(boolean workSpace,
+                                 boolean skipBinary, boolean noRecurse)
+            throws RepositoryException, SAXException, IOException {
+
+        BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(file));
+
+        Session thisSession = session;
+        if (workSpace) {
+            thisSession = workspace.getSession();
+        }
+        try {
+            thisSession.exportSysView(testPath, os, false, false);
+            SysViewParser parser = new SysViewParser(testPath, thisSession, SAVEBINARY, RECURSE);
+            parser.parse(file);
+        } catch (RepositoryException re) {
+            fail("Could not initialize the contenthandler due to: " + re.toString());
+        } finally {
+            os.close();
+        }
+
+    }
+
+    /**
+     * class to parse the XML file generated by the sysview export using an
+     * OutputStream
+     */
+    protected class SysViewParser {
+        //todo : test encoding of exported file
+        // the path to the exported file
+        String filePath;
+        // the absolut path to the node which was exported
+        String nodePath;
+        Node node;
+        XMLReader parser;
+        SysViewContentHandler handler;
+
+        public SysViewParser(String nodePath, Session session, boolean skipBinary, boolean noRecurse)
+                throws SAXException, RepositoryException {
+            this.nodePath = nodePath;
+            this.handler = new SysViewContentHandler(nodePath, session, skipBinary, noRecurse);
+            parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
+            parser.setContentHandler(this.handler);
+        }
+
+        public void parse(File file) throws IOException, SAXException {
+            FileInputStream in = null;
+            try {
+                in = new FileInputStream(file);
+            } catch (FileNotFoundException e) {
+                fail("Input file not opened: " + e);
+            }
+            InputSource source = new InputSource(in);
+            parser.parse(source);
+        }
+    }
+}
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/ExportSysViewTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/SysViewContentHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/SysViewContentHandler.java?view=auto&rev=158049
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/SysViewContentHandler.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/SysViewContentHandler.java Fri Mar 18 02:43:04 2005
@@ -0,0 +1,705 @@
+/*
+ * 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.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.Session;
+import javax.jcr.Item;
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.NodeIterator;
+import javax.jcr.PropertyType;
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.PropertyIterator;
+import javax.jcr.Property;
+import javax.jcr.Value;
+import javax.jcr.ValueFormatException;
+import javax.jcr.RangeIterator;
+import java.io.IOException;
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Stack;
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/**
+ * ContentHandler implementation which checks if the system view export of
+ * a node tree is compliant to the specification.
+ */
+class SysViewContentHandler extends DefaultHandler {
+
+    // the session used
+    protected Session session;
+    // the path to start from
+    protected String path;
+    // the choices
+    boolean skipBinary;
+    boolean noRecurse;
+    // the nodeElem in process
+    NodeElemData currentNodeElem;
+    // the parenNodetElem of the currentNodeElem
+    NodeElemData parentNodeElem;
+    // the propElem in process
+    PropElemData currentPropElem;
+    // the valueElem in process
+    protected StringBuffer currentValue;
+    // the value(s) of the current propElem e.g if multiple values
+    protected ArrayList currentValues;
+    // prefix mapping data
+    protected HashMap prefixes;
+    // if the first node is yet treated
+    protected boolean testRootDone;
+    // The stack holding the opened nodeElems
+    Stack nodeElemStack;
+
+    // resolved QNames for well known node and property names
+    private String jcrRoot;
+    private String jcrPrimaryType;
+    private String jcrMixinTypes;
+    private String jcrUuid;
+    private String svNode;
+    private String svProperty;
+    private String svName;
+    private String svType;
+    private String svValue;
+    private String mixReferenceable;
+
+    /**
+     * Constructor
+     * @param path Thepath to the  root node of the tree to be exported.
+     * @param session The session used.
+     * @param skipBinary Boolean if the binary properties are not exported.
+     * @param noRecurse Boolean if only the root node of the tree should be exported.
+     */
+    public  SysViewContentHandler(String path, Session session,
+                                  boolean skipBinary, boolean noRecurse) throws RepositoryException {
+        this.session =  session;
+        this.path = path;
+        this.skipBinary = skipBinary;
+        this.noRecurse = noRecurse;
+
+        jcrRoot = session.getNamespacePrefix(AbstractJCRTest.NS_JCR_URI) + ":root";
+        jcrPrimaryType = session.getNamespacePrefix(AbstractJCRTest.NS_JCR_URI) + ":primaryType";
+        jcrMixinTypes = session.getNamespacePrefix(AbstractJCRTest.NS_JCR_URI) + ":mixinTypes";
+        jcrUuid = session.getNamespacePrefix(AbstractJCRTest.NS_JCR_URI) + ":uuid";
+        svNode = session.getNamespacePrefix(AbstractJCRTest.NS_SV_URI) + ":node";
+        svProperty = session.getNamespacePrefix(AbstractJCRTest.NS_SV_URI) + ":property";
+        svName = session.getNamespacePrefix(AbstractJCRTest.NS_SV_URI) + ":name";
+        svType = session.getNamespacePrefix(AbstractJCRTest.NS_SV_URI) + ":type";
+        svValue = session.getNamespacePrefix(AbstractJCRTest.NS_SV_URI) + ":value";
+        mixReferenceable = session.getNamespacePrefix(AbstractJCRTest.NS_MIX_URI) + ":referenceable";
+    }
+
+    /**
+     * Check if the given path is valid.
+     * Init the neccessary data.
+     * @throws SAXException
+     */
+    public void startDocument() throws SAXException {
+        try {
+            // Check the given path, init the treeState stack
+            Item item = session.getItem(path);
+            checkCondition("TestPath "+path+" is not a path to a node.", item.isNode());
+            nodeElemStack = new Stack();
+            currentNodeElem = new NodeElemData();
+            currentNodeElem.name = item.getName();
+            currentNodeElem.node = (Node) item;
+            currentNodeElem.path = path;
+            prefixes = new HashMap();
+            testRootDone = false;
+        } catch (PathNotFoundException pe) {
+            checkCondition("TestPath " + path + " is not a valid path."
+                    + pe.toString(), false);
+        } catch (RepositoryException re) {
+            checkCondition("Could not determine test node: "
+                    + re.toString(), false);
+        }
+    }
+
+    // Collect all prefix mappings.
+    public void startPrefixMapping(String prefix, String uri) {
+        prefixes.put(prefix,uri);
+    }
+
+
+    public void startElement(String uri, String localName,
+            String qName, Attributes attributes) throws SAXException {
+
+        try {
+            if (qName.equals(svNode)) {
+                //attribute sv:name
+                String nodeName = attributes.getValue(svName);
+                if (noRecurse) {
+                    if (!testRootDone) {
+                        nodeElemStack.push(currentNodeElem);
+                        testRootDone = true;
+                        // correct root name?
+                        if (currentNodeElem.node.getDepth()==0) {
+                            checkCondition("Exported Root node has not the required " +
+                                "element name 'jcr:root'.", nodeName.equals(jcrRoot));
+                        }
+                        // nothing else to do here
+                    }
+                    // rootNode yet done
+                    else {
+                        // only the testRootNode should be exported.
+                        checkCondition("Child Node Element of testRoot Node " +
+                            "element found although noRecursive is true.", !testRootDone);
+                    }
+
+                }
+                else {
+                    if (!testRootDone) {
+                        nodeElemStack.push(currentNodeElem);
+                        testRootDone = true;
+                        // correct root name?
+                        if (currentNodeElem.node.getDepth()==0) {
+                            checkCondition("Exported Root node has not the required " +
+                                "element name 'jcr:root'.", nodeName.equals(jcrRoot));
+                        }
+                        // nothing else to do here
+                    }
+                    // Collect the exported data in a NodeElemData object.
+                    // every occurrence of an opened sv:node element
+                    // creates such an object which will be put on the nodeElemStack.
+                    // As this element will be popped from the stack when the node element
+                    // is closed, the latest element on the stack represents the parent
+                    // node element of the current node element.
+                    else {
+                        parentNodeElem = (NodeElemData) nodeElemStack.pop();
+
+                        // get the node(s) with the found nodeName
+                        NodeIterator nodeIter = parentNodeElem.node.getNodes(nodeName);
+
+                        // create a new nodeElemData for this new node elem in process
+                        currentNodeElem = new NodeElemData();
+                        currentNodeElem.name = nodeName;
+
+                        long size = getSize(nodeIter);
+                        if (size >= 1) {
+                            // Find the index of the child node,
+                            // collect the childElems data of the parent
+                            // ie for every name we count the number of child nodes with that name.
+                            // Also get the child node with the correct index given by the
+                            // position the node elem is found in the exported tree.
+                            if (parentNodeElem.childNodeElemNames.containsKey(nodeName)) {
+                                ChildNodeElem child =
+                                    (ChildNodeElem) parentNodeElem.childNodeElemNames.get(nodeName);
+                                child.number++;
+                                currentNodeElem.index = child.number;
+                                // get the node
+                                String relPath = currentNodeElem.name + "[" + child.number + "]";
+                                currentNodeElem.node = parentNodeElem.node.getNode(relPath);
+                                currentNodeElem.path = currentNodeElem.node.getPath();
+                                parentNodeElem.childNodeElemNames.put(nodeName,child);
+                            }
+                            else {
+                                ChildNodeElem child = new ChildNodeElem();
+                                child.name = nodeName;
+                                child.number = 1;
+                                currentNodeElem.index = child.number;
+                                // get the node
+                                String relPath = currentNodeElem.name + "[" + child.number + "]";
+                                currentNodeElem.node = parentNodeElem.node.getNode(relPath);
+                                currentNodeElem.path = currentNodeElem.node.getPath();
+                                parentNodeElem.childNodeElemNames.put(nodeName,child);
+                            }
+                        }
+                        else {
+                            // no node found, this is an error.
+                            checkCondition("No child node of node "+ parentNodeElem.path
+                                    + " found with name:  "  + nodeName,false);
+                        }
+                        // push the parent data and the current node element data on the stack
+                        nodeElemStack.push(parentNodeElem);
+                        nodeElemStack.push(currentNodeElem);
+                    }
+                }
+            }
+
+            // Collect the property data found in a PropElemData object.
+            // Collect the value(s) found in an ArrayList.
+            else if (qName.equals(svProperty)) {
+                currentPropElem = new PropElemData();
+                currentPropElem.name = attributes.getValue(svName);
+                currentPropElem.typeName = attributes.getValue(svType);
+                currentPropElem.type = PropertyType.valueFromName(currentPropElem.typeName);
+                currentPropElem.values = new ArrayList();
+            }
+
+            else if (qName.equals(svValue)) {
+                // init
+                currentValue = new StringBuffer();
+            }
+            else {
+                // invalid element name is used
+                checkCondition("Invalid element name " + qName
+                        + " in SysView export found",false);
+            }
+        } catch (PathNotFoundException pne) {
+                checkCondition("Item not found during exportSysViewTest: "
+                        + pne.toString(), false);
+        } catch (RepositoryException re) {
+            // what here?
+        }
+    }
+
+    // Collect the value data
+    public void characters(char[] ch, int start, int length) throws SAXException {
+        if (currentValue != null)
+            currentValue.append(ch, start, length);
+    }
+
+
+    public void endElement (String uri, String localName, String qName)
+            throws SAXException {
+
+        try {
+            // The value is held in a ArrayList
+            // ignoring if it is a  multivalue property or not.
+            if (qName.equals(svValue)) {
+                if (currentValue != null) {
+                    String val = currentValue.toString();
+                    if (currentPropElem.type != PropertyType.BINARY ||
+                            (currentPropElem.type == PropertyType.BINARY && !skipBinary))
+                        currentPropElem.values.add(val);
+                }
+            }
+
+            else if (qName.equals(svProperty)) {
+                // we know all props are exported before the first node
+                currentNodeElem = (NodeElemData) nodeElemStack.pop();
+                currentNodeElem.propElems.add(currentPropElem);
+                nodeElemStack.push(currentNodeElem);
+            }
+
+            else if (qName.equals(svNode)) {
+                currentNodeElem = (NodeElemData) nodeElemStack.peek();
+                // now check all the stuff
+                if (currentNodeElem.node == null) {
+                    checkCondition("Tree structure of exported node does " +
+                        "not match the tree structure of the repository.", false);
+                }
+                else {
+                    // position of jcr:primaryType, jcr:mixinTypes and jcr:uuid if present
+                    checkPropOrder(currentNodeElem);
+                    // number of child nodes ok?
+                    checkChildren(currentNodeElem, noRecurse);
+                    // props and their values ok?
+                    try {
+                        checkAllProps(currentNodeElem, skipBinary);
+                        // remove from the stack
+                        nodeElemStack.pop();
+                    }
+                    catch (IOException ioe) {
+                        checkCondition("Error in Base64 encoding " +
+                                "of a binary property value: " + ioe.toString(), false);
+                    }
+                }
+            }
+            else {
+                // invalid element name is used
+                checkCondition("Invalid element name " + qName +
+                        " in SysView export found",false);
+            }
+        } catch (PathNotFoundException pne) {
+            checkCondition("Item not found during exportSysViewTest: " +
+                    pne.toString(), false);
+        }
+        catch (RepositoryException re) {
+            // what here?
+        }
+    }
+
+    public void endDocument() throws SAXException {
+        // check the prefixes exported
+        try {
+            NamespaceRegistry nsr = session.getWorkspace().getNamespaceRegistry();
+            String[] registeredPrefixes = nsr.getPrefixes();
+            // check against the found prefixes
+            checkCondition("Size of included prefixes is not the size of " +
+                    "registered prefixes", registeredPrefixes.length == prefixes.size()) ;
+            for (int i=0; i<registeredPrefixes.length;i++) {
+                String prefix = registeredPrefixes[1];
+                String uri = nsr.getURI(prefix);
+                checkCondition("Registered prefix "+prefix + " not included",
+                    prefixes.containsKey(prefix) && prefixes.get(prefix).equals(uri) );
+            }
+        } catch (RepositoryException re) {
+            //
+        }
+    }
+
+    // helpers for test result forward
+    private void checkCondition(String str, boolean bool) throws SAXException {
+        if (!bool)
+            throw new SAXException(new ConditionException(str));
+    }
+
+    public class ConditionException extends SAXException {
+        public ConditionException(String message) {
+            super(message);
+        }
+    }
+
+    //--------------helper methods to check the data ---------------------------------
+    /**
+     * Checks the correct position of the jcr:primarType, jcr:mixinTypes
+     * and jcr:uuid in the property elements of the given nodeElem.
+     * @param nodeElem
+     * @throws RepositoryException
+     */
+    private void checkPropOrder(NodeElemData nodeElem)
+            throws RepositoryException, SAXException {
+
+        boolean jcrPrimaryTypeFound = false;
+        boolean jcrMixinTypesFound = true;
+        boolean uuidFound = true;
+        PropElemData propElem = (PropElemData) nodeElem.propElems.get(0);
+        jcrPrimaryTypeFound = (jcrPrimaryType.equals(propElem.name));
+        checkCondition("Exported property jcr:primaryType of node " + nodeElem.path +
+                " is not at the first position.", jcrPrimaryTypeFound);
+
+        if (nodeElem.node.hasProperty(jcrMixinTypes)) {
+            PropElemData propElem2 = (PropElemData) nodeElem.propElems.get(1);
+            jcrMixinTypesFound = (jcrMixinTypes.equals(propElem2.name));
+            checkCondition("Exported property jcr:jcrMixinTypes of node " + nodeElem.path +
+                " is not at the second position.", jcrMixinTypesFound);
+
+            NodeType[] mixins = nodeElem.node.getMixinNodeTypes();
+            for (int j=0; j<mixins.length; j++) {
+                if (mixins[j].getName().equals(mixReferenceable)) {
+                uuidFound = (jcrUuid.equals(((PropElemData)nodeElem.propElems.get(2)).name));
+                checkCondition("Exported property jcr:uuid of node " + nodeElem.path +
+                        " is not at the third position.", uuidFound);
+                }
+            }
+        }
+    }
+
+
+    /**
+     * Checks the values of all exported properties of a given node.
+     *
+     * @param nodeElem The nodeElem of the given node.
+     * @param skipBinary Boolean if the binary properties should be exported.
+     * @throws RepositoryException
+     * @throws SAXException
+     * @throws IOException
+     */
+    private void checkAllProps(NodeElemData nodeElem, boolean skipBinary)
+            throws RepositoryException, SAXException, IOException {
+
+        boolean allFound = false;
+        boolean correctVal = false;
+        Node node = nodeElem.node;
+        ArrayList propElems = nodeElem.propElems;
+        long binaryCounter = 0;
+
+        // no props exported
+        if (propElems.size() == 0) {
+            // if node has properties they should be of Binary type and skipBinary should be true
+            if (node.hasProperties()) {
+                if (skipBinary) {
+                    PropertyIterator iter = node.getProperties();
+                    while (iter.hasNext()) {
+                        Property prop = iter.nextProperty();
+                        checkCondition("Property " + prop.getName() + " of node "
+                            + node.getPath() + " is not exported.", prop.getType()== PropertyType.BINARY);
+                    }
+                }
+                else {
+                    checkCondition("One or more properties of node "
+                        + node.getPath() + " are not exported.", false);
+                }
+            }
+            else {
+                // ok
+            }
+        }
+        else {
+            // compare the propElems with the properties of the given node
+            for (int i = 0; i < propElems.size() -1; i++) {
+                correctVal = false;
+                PropElemData propElem = (PropElemData) propElems.get(i);
+                int propType = propElem.type;
+                if (node.hasProperty(propElem.name)) {
+                    Property prop = node.getProperty(propElem.name);
+                    // compare the propTypes
+                    correctVal = (propType == prop.getType());
+                    checkCondition("Property type of property " + propElem.name
+                                + " of node " + nodeElem.path + " is not exported correctly."
+                            + "expected: "+prop.getType()+" received: "+propType, correctVal);
+
+                    // property which should be exported
+                    if (propType == PropertyType.BINARY && !skipBinary ||
+                            propType != PropertyType.BINARY) {
+                        try {
+                            int size = propElem.values.size();
+
+                            // multivalue property with empty value array
+                            if (size == 0) {
+                                if (prop.getDefinition().isMultiple()) {
+                                    long length = prop.getValues().length;
+                                    checkCondition("Value of property " + prop.getPath() +
+                                             " is not exported.", length == 0);
+                                }
+                                else {
+                                    checkCondition("Singler value property " + prop.getPath() +
+                                             " with no value is exported.", false);
+                                }
+                            }
+
+                            // single value property or multivalue property with one value
+                            if (size == 1) {
+                                String str = "";
+                                if (prop.getDefinition().isMultiple()) {
+                                    str = (prop.getValues()[0]).getString();
+                                }
+                                else {
+                                    str = prop.getString();
+                                }
+                                str = escapeString(str);
+                                String val = (String) propElem.values.get(0);
+
+                               if (prop.getType() == PropertyType.BINARY) {
+                                    // decode value
+                                    val = decodeBase64(val);
+                                }
+                                correctVal = (str.equals(val));
+                                checkCondition("Property value of property " + propElem.name
+                                    + " of node " + nodeElem.path + " is not exported correctly:" +
+                                        " expected value: "+str+" found value: "+val, correctVal);
+                            }
+
+                            // multivalue property with several values
+                            else {
+                                Value[] vals = prop.getValues();
+                                checkCondition("Number of exported values of property " +
+                                        prop.getPath() + " does not match the number " +
+                                        "its values", vals.length == size);
+                                for (int j = 0; j < size -1; j++) {
+                                    // we know that the order of the values
+                                    // of a mulitval prop is preserved during export
+                                    String val = (String)propElem.values.get(i);
+
+                                    if (prop.getType() == PropertyType.BINARY) {
+                                        // decode value
+                                        val = decodeBase64(val);
+                                    }
+                                    String str = vals[j].getString();
+                                    str = escapeString(str);
+                                    correctVal = (val.equals(str));
+                                    checkCondition("Property value of property " + propElem.name
+                                            + " of node " + nodeElem.path +
+                                            " is not exported correctly.", correctVal);
+                                }
+                            }
+                        } catch (ValueFormatException vfe ) {
+                                checkCondition("Error during retreiviing the value(s)" +
+                                        " of property " + prop.getPath() + vfe.toString()
+                                        + " .", false);
+                        }
+                    }
+                    // skipBinary true and propType is Binary, should be skipped
+                    else {
+                        checkCondition("Binary property "+ prop.getPath()
+                                + " exported although skipBinary flag is true.", false);
+                    }
+                }
+                // given node has no property with the name given by the prop element
+                else {
+                    checkCondition("Property element " + propElem.name
+                            + " found but node " + nodeElem.node.getPath() +
+                            " does not have a property with that name", false);
+                }
+            }
+            // compare the sizes here
+            if (skipBinary) {
+                PropertyIterator propIter = node.getProperties();
+                while (propIter.hasNext()) {
+                    if (propIter.nextProperty().getType() == PropertyType.BINARY) {
+                        binaryCounter++;
+                    }
+                }
+            }
+
+            long otherSize = getSize(node.getProperties());
+            allFound = (propElems.size() + binaryCounter == otherSize);
+            checkCondition("Not all properties of node " +
+                    nodeElem.path + " are exported.", allFound);
+        }
+    }
+
+    /**
+     * Counts the number of child nodes exported and compare with the number
+     * of child nodes of a given node.
+     * @param nodeElem The node to check.
+     * @param noRecurse Boolean if child nodes should be exported at all.
+     * @throws RepositoryException
+     * @throws SAXException
+     */
+    private void checkChildren(NodeElemData nodeElem, boolean noRecurse)
+            throws RepositoryException, SAXException {
+
+        Hashtable childElemsFound = nodeElem.childNodeElemNames;
+        boolean totalSumOk = false;
+        boolean partialSumOk = true;
+        if (noRecurse) {
+            totalSumOk = (childElemsFound.size() == 0);
+        }
+        else {
+            // all children found if number of node.getNodes(name) is the same as found
+            // in childElemsFound and if sum(number of nodeGetNodes(names))
+            // == number of node.getNodes()
+            long childrenFound = 0;
+            NodeIterator nodeIter = nodeElem.node.getNodes();
+
+            long children = getSize(nodeIter);
+            for (Enumeration e = childElemsFound.elements();  e.hasMoreElements();) {
+                ChildNodeElem child = (ChildNodeElem) e.nextElement();
+                String name = child.name;
+                long number = child.number;
+
+                NodeIterator iter = nodeElem.node.getNodes(name);
+                long size = 0;
+
+                size = getSize(iter);
+                if (size != number) {
+                    partialSumOk = false;
+                    break;
+                }
+                else {
+                    childrenFound += number;
+                }
+            }
+            totalSumOk = (children == childrenFound);
+            checkCondition("The number of child nodes of node" + nodeElem.path +
+                    " which are exported does not match the number of its child nodes.",
+                    totalSumOk && partialSumOk);
+        }
+    }
+
+    // helper methods
+    /**
+     * Decodes Base64 encoded binary values.
+     * @param str the string to decode
+     * @return
+     * @throws IOException
+     */
+    private String decodeBase64(String str) throws IOException {
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        Base64.decode(str, bos);
+        String decoded = bos.toString("UTF-8");
+        return decoded;
+    }
+
+    /**
+     * Escapes the predefined entity references in XML.
+     * @param str
+     * @return  the escaped string
+     */
+    private String escapeString (String str) {
+        String orig = str;
+        String amp = "&";
+        String less = "<";
+        String great = ">";
+        String apo = "'";
+        String quot = "\"";
+
+        String r_amp = "&amp;";
+        String r_less = "&lt;";
+        String r_great = "&gt;";
+        String r_apo = "&apos;";
+        String r_quot = "&quot;";
+
+        String repl = orig.replaceAll(amp, r_amp);
+        repl =  repl.replaceAll(less, r_less);
+        repl =  repl.replaceAll(great, r_great);
+        repl =  repl.replaceAll(apo, r_apo);
+        repl =  repl.replaceAll(quot, r_quot);
+        return repl;
+    }
+
+    /**
+     *
+     * @param it
+     * @return
+     */
+    private long getSize(RangeIterator it) {
+        long size = it.getSize();
+        if (size != -1) {
+            return size;
+        }
+        size = 0;
+        while (it.hasNext()) {
+            it.next();
+            size++;
+        }
+        return size;
+    }
+
+   //---------------- helper classes for collecting the xml data found ----------------
+
+    /**
+     * Node data class holding the collected data found during event processing.
+     */
+    private class NodeElemData {
+        // Name of the node
+        String name;
+        // the number of the occurence of this name as child element name
+        // this is then the same as the index of this node.
+        long index;
+        // the path of the node
+        String path;
+        // List of PropElemData
+        ArrayList  propElems = new ArrayList();
+        // the node itself
+        Node node;
+        // the current position of the child node in process among its same name siblings.
+        // /the index of the child node in proces is therefore position+1)
+        int position = 0;
+        // the childNodeElems (stored are key: name and
+        // value: number of the same name siblings)
+        Hashtable childNodeElemNames = new Hashtable();
+    }
+
+    /**
+     * Property data of the current property element.
+     */
+    private class PropElemData {
+        String name;
+        String typeName;
+        int type;
+        ArrayList values;
+    }
+
+    /**
+     * Child node data.
+     */
+    private class ChildNodeElem {
+        String name;
+        long number;
+    }
+}

Propchange: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/SysViewContentHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/TestAll.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/TestAll.java?view=diff&r1=158048&r2=158049
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/TestAll.java (original)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/TestAll.java Fri Mar 18 02:43:04 2005
@@ -63,6 +63,8 @@
         suite.addTestSuite(SessionReadMethodsTest.class);
         suite.addTestSuite(WorkspaceReadMethodsTest.class);
 
+        suite.addTestSuite(ExportSysViewTest.class);
+
         // level 2 tests
         suite.addTestSuite(AddNodeTest.class);
         suite.addTestSuite(NamespaceRegistryTest.class);



Mime
View raw message