You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by th...@apache.org on 2010/04/30 18:37:54 UTC

svn commit: r939734 - in /jackrabbit/sandbox/jackrabbit-j3/src: main/java/org/apache/jackrabbit/j3/ main/java/org/apache/jackrabbit/j3/api/ main/java/org/apache/jackrabbit/j3/api/management/ main/java/org/apache/jackrabbit/j3/data/ main/java/org/apache...

Author: thomasm
Date: Fri Apr 30 16:37:54 2010
New Revision: 939734

URL: http://svn.apache.org/viewvc?rev=939734&view=rev
Log:
Data store.

Added:
    jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/RandomInputStream.java
    jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestLargeObject.java
Modified:
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/RepositoryImpl.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/SessionImpl.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/ValueFactoryImpl.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/api/JackrabbitRepository.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/api/management/DataStoreGarbageCollector.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/data/GarbageCollector.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Bundle.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/StorageSession.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Val.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcStorage.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcStorageSession.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/mem/MemStorageSession.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/LobStore.java
    jackrabbit/sandbox/jackrabbit-j3/src/site/resources/images/drawing.png
    jackrabbit/sandbox/jackrabbit-j3/src/site/resources/images/drawing.svg
    jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestAll.java
    jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestBundle.java

Modified: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/RepositoryImpl.java?rev=939734&r1=939733&r2=939734&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/RepositoryImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/RepositoryImpl.java Fri Apr 30 16:37:54 2010
@@ -58,11 +58,12 @@ public class RepositoryImpl implements J
     private final WeakHashMap<SessionImpl, RepositoryImpl> sessions = new WeakHashMap<SessionImpl, RepositoryImpl>();
     private final Cache<Val, NodeData> readOnlyCache = new Cache<Val, NodeData>(Constants.MEM_CACHE_PER_REPOSITORY);
     private final HashMap<String, ValueImpl> descriptors = new HashMap<String, ValueImpl>();
-    private final LobStore lobStore = new LobStore(this);
+    private final LobStore lobStore = new LobStore();
     private final NodeTypeRegistry ntReg = new NodeTypeRegistry();
     private final ValueFactoryImpl valueFactory;
     private final QueryObjectModelFactoryImpl qomFactory;
 
+    private boolean init;
     private boolean closed;
     private LockSystem lockSystem;
 
@@ -112,15 +113,25 @@ public class RepositoryImpl implements J
         if (credentials == null) {
             credentials = ANONYMOUS_CREDENTIALS;
         }
-        if (credentials instanceof SimpleCredentials) {
-            SimpleCredentials sc = (SimpleCredentials) credentials;
-            String userId = sc.getUserID();
-            StorageSession storageSession = storage.openSession(userId, sc.getPassword());
-            SessionImpl session = new SessionImpl(this, sc, storageSession, workspaceName, log);
-            sessions.put(session, this);
-            return session;
+        if (!(credentials instanceof SimpleCredentials)) {
+            throw ExceptionFactory.login();
         }
-        throw ExceptionFactory.login();
+        SimpleCredentials sc = (SimpleCredentials) credentials;
+        String userId = sc.getUserID();
+        StorageSession storageSession = storage.openSession(userId, sc.getPassword());
+        SessionImpl session = new SessionImpl(this, sc, storageSession, workspaceName, log);
+        initRepository(storageSession);
+        sessions.put(session, this);
+        return session;
+    }
+
+    private synchronized void initRepository(StorageSession session) {
+        if (init) {
+            return;
+        }
+        lobStore.setDataStore(session.getDataStore());
+        init = true;
+
     }
 
     public synchronized void close(SessionImpl session) {

Modified: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/SessionImpl.java?rev=939734&r1=939733&r2=939734&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/SessionImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/SessionImpl.java Fri Apr 30 16:37:54 2010
@@ -50,6 +50,7 @@ import javax.transaction.xa.XAException;
 import javax.transaction.xa.XAResource;
 import javax.transaction.xa.Xid;
 import org.apache.jackrabbit.j3.api.JackrabbitSession;
+import org.apache.jackrabbit.j3.data.DataStore;
 import org.apache.jackrabbit.j3.lock.LockManagerImpl;
 import org.apache.jackrabbit.j3.mc.McException;
 import org.apache.jackrabbit.j3.mc.NodeData;

Modified: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/ValueFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/ValueFactoryImpl.java?rev=939734&r1=939733&r2=939734&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/ValueFactoryImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/ValueFactoryImpl.java Fri Apr 30 16:37:54 2010
@@ -169,7 +169,7 @@ public class ValueFactoryImpl implements
         return new ValueImpl(val, this);
     }
 
-    static InputStream getInputStream(Val value, ValueFactoryImpl factory) throws ValueFormatException {
+    static InputStream getInputStream(Val value, ValueFactoryImpl factory) throws RepositoryException {
         switch (value.getType()) {
         case PropertyType.BINARY:
             return new ByteArrayInputStream(value.getBytes());
@@ -177,7 +177,7 @@ public class ValueFactoryImpl implements
             if (factory == null) {
                 throw ExceptionFactory.illegalArgument("Need a lob store for binary reference: {0}", value.getString());
             }
-            return factory.lobStore.getInputStream(value.getString());
+            return factory.lobStore.getInputStream(value);
         case Val.TYPE_MULTI_VALUE:
             throw ExceptionFactory.valueFormat("The property is multi-valued");
         }

Modified: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/api/JackrabbitRepository.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/api/JackrabbitRepository.java?rev=939734&r1=939733&r2=939734&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/api/JackrabbitRepository.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/api/JackrabbitRepository.java Fri Apr 30 16:37:54 2010
@@ -17,10 +17,8 @@
 package org.apache.jackrabbit.j3.api;
 
 import javax.jcr.Credentials;
-import javax.jcr.LoginException;
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
-import org.apache.jackrabbit.j3.SessionImpl;
 
 /**
  * A Jackrabbit repository.

Modified: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/api/management/DataStoreGarbageCollector.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/api/management/DataStoreGarbageCollector.java?rev=939734&r1=939733&r2=939734&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/api/management/DataStoreGarbageCollector.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/api/management/DataStoreGarbageCollector.java Fri Apr 30 16:37:54 2010
@@ -37,22 +37,6 @@ import javax.jcr.RepositoryException;
 public interface DataStoreGarbageCollector {
 
     /**
-     * Set the delay between scanning items.
-     * The main scan loop sleeps this many milliseconds after
-     * scanning a node. The default is 0, meaning the scan should run at full speed.
-     *
-     * @param millis the number of milliseconds to sleep
-     */
-    void setSleepBetweenNodes(long millis);
-
-    /**
-     * Get the delay between scanning items.
-     *
-     * @return the number of milliseconds to sleep
-     */
-    long getSleepBetweenNodes();
-
-    /**
      * Set the event listener. If set, the event listener will be called
      * for each item that is scanned. This mechanism can be used
      * to display the progress.

Modified: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/data/GarbageCollector.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/data/GarbageCollector.java?rev=939734&r1=939733&r2=939734&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/data/GarbageCollector.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/data/GarbageCollector.java Fri Apr 30 16:37:54 2010
@@ -55,7 +55,6 @@ import javax.jcr.observation.Observation
  * <p>
  * Example code to run the data store garbage collection:
  * <pre>
- * JackrabbitRepositoryFactory jf = (JackrabbitRepositoryFactory) factory;
  * RepositoryManager m = factory.getRepositoryManager((JackrabbitRepository) rep);
  * GarbageCollector gc = m.createDataStoreGarbageCollector();
  * try {
@@ -73,10 +72,6 @@ public class GarbageCollector implements
 
     private MarkEventListener callback;
 
-    private long sleepBetweenNodes;
-
-    private int testDelay;
-
     private final DataStore store;
 
     private long startScanTimestamp;
@@ -115,23 +110,6 @@ public class GarbageCollector implements
         }
     }
 
-    public void setSleepBetweenNodes(long millis) {
-        this.sleepBetweenNodes = millis;
-    }
-
-    public long getSleepBetweenNodes() {
-        return sleepBetweenNodes;
-    }
-
-    /**
-     * When testing the garbage collection, a delay is used instead of simulating concurrent access.
-     *
-     * @param testDelay the delay in milliseconds
-     */
-    public void setTestDelay(int testDelay) {
-        this.testDelay = testDelay;
-    }
-
     public void setMarkEventListener(MarkEventListener callback) {
         this.callback = callback;
     }
@@ -159,7 +137,7 @@ public class GarbageCollector implements
 
         // adding a link to a BLOB updates the modified date
         // reading usually doesn't, but when scanning, it does
-        recurse(session.getRootNode(), sleepBetweenNodes);
+        recurse(session.getRootNode());
     }
 
     /**
@@ -195,14 +173,7 @@ public class GarbageCollector implements
         return store;
     }
 
-    private void recurse(final Node n, long sleep) throws RepositoryException {
-        if (sleep > 0) {
-            try {
-                Thread.sleep(sleep);
-            } catch (InterruptedException e) {
-                // ignore
-            }
-        }
+    private void recurse(final Node n) throws RepositoryException {
         if (callback != null) {
             callback.beforeScanning(n);
         }
@@ -231,7 +202,7 @@ public class GarbageCollector implements
         }
         try {
             for (NodeIterator it = n.getNodes(); it.hasNext();) {
-                recurse(it.nextNode(), sleep);
+                recurse(it.nextNode());
             }
         } catch (InvalidItemStateException e) {
             LOG.debug("Node removed concurrently - ignoring", e);
@@ -325,13 +296,6 @@ public class GarbageCollector implements
         }
 
         public void onEvent(EventIterator events) {
-            if (testDelay > 0) {
-                try {
-                    Thread.sleep(testDelay);
-                } catch (InterruptedException e) {
-                    // ignore
-                }
-            }
             while (events.hasNext()) {
                 Event event = events.nextEvent();
                 try {
@@ -340,7 +304,7 @@ public class GarbageCollector implements
                         Item item = session.getItem(path);
                         if (item.isNode()) {
                             Node n = (Node) item;
-                            recurse(n, testDelay);
+                            recurse(n);
                         }
                     } catch (PathNotFoundException e) {
                         // ignore

Modified: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Bundle.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Bundle.java?rev=939734&r1=939733&r2=939734&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Bundle.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Bundle.java Fri Apr 30 16:37:54 2010
@@ -434,7 +434,7 @@ public class Bundle {
             return Val.get(array);
         }
         case BINARY_REFERENCE:
-            return Val.get(PropertyType.BINARY, readString());
+            return Val.get(Val.TYPE_BINARY_REFERENCE, readString());
         case BOOLEAN_TRUE:
             return Val.TRUE;
         case BOOLEAN_FALSE:

Modified: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/StorageSession.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/StorageSession.java?rev=939734&r1=939733&r2=939734&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/StorageSession.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/StorageSession.java Fri Apr 30 16:37:54 2010
@@ -16,45 +16,150 @@
  */
 package org.apache.jackrabbit.j3.mc;
 
+import org.apache.jackrabbit.j3.data.DataStore;
+
 /**
  * A session bound to a storage.
  */
 public interface StorageSession {
 
+    /**
+     * The id of the main (default) workspace.
+     */
     int MAIN_WORKSPACE_ID = 0;
 
+    /**
+     * Get the id of the root node.
+     *
+     * @return the root node id
+     */
     Val getRootNodeId();
 
+    /**
+     * Read the node.
+     *
+     * @param nodeId the node id
+     * @return the node
+     */
     NodeData getNode(Val nodeId);
 
+    /**
+     * Create a new node id.
+     *
+     * @param parentNodeId the parent node (may not be used)
+     * @param workspaceId the workspace id
+     * @param relPath the path relative to the parent (may not be used)
+     * @return the node id
+     */
     Val newNodeId(Val parentNodeId, int workspaceId, Val relPath);
 
+    /**
+     * Calculate the workspace id from the node id.
+     *
+     * @param nodeId the node id
+     * @return the workspace id
+     */
     int getWorkspaceId(Val nodeId);
 
+    /**
+     *
+     * @param nodeId
+     * @param newWorkspaceId
+     * @return
+     */
     Val convertNodeId(Val nodeId, int newWorkspaceId);
 
+    /**
+     * Store the transaction.
+     *
+     * @param date the date
+     * @param nodes the changed nodes
+     * @param events the events
+     */
     void store(long date, NodeData[] nodes, Bundle[] events);
 
+    /**
+     * Read events from the event journal.
+     *
+     * @param date the date of the first event (-1 to read the next page)
+     * @param size the size the number of elements to read at most
+     * @return the bundles the event bundles
+     */
     Bundle[] getEvents(long date, int size);
 
+    /**
+     * Convert a node identifier to a node id.
+     *
+     * @param id the identifier
+     * @return the node id
+     */
     Val convertIdentifierToNodeId(String id);
 
+    /**
+     * Convert a node id to a node identifier.
+     *
+     * @param nodeId the node id
+     * @return the identifier
+     */
     String convertNodeIdToIdentifier(Val nodeId);
 
+    /**
+     * Close the session.
+     */
     void close();
 
+    /**
+     * Check whether this session supports the event journal.
+     *
+     * @return true if it does
+     */
     boolean supportsEventJournal();
 
+    /**
+     * Check whether this session support temporary storage.
+     *
+     * @return true if it does
+     */
     boolean supportsTemp();
 
-    boolean supportsNodeIdsWithoutPath();
-
+    /**
+     * Store into the temporary area.
+     *
+     * @param block the block id
+     * @param nodes the nodes
+     * @param events the events (may be null)
+     */
     void storeTemp(int block, NodeData[] nodes, Bundle[] events);
 
+    /**
+     * Read a temporary block.
+     *
+     * @param block the block
+     * @return the nodes
+     */
     NodeData[] getTempNodes(int block);
 
+    /**
+     * Read a temporary block.
+     *
+     * @param block the block
+     * @return the events
+     */
     Bundle[] getTempEvents(int block);
 
+    /**
+     * Clear the temporary area.
+     *
+     * @param nodes clear nodes
+     * @param events clear events
+     */
     void clearTemp(boolean nodes, boolean events);
 
+    /**
+     * Get the data store.
+     *
+     * @return the data store
+     */
+    DataStore getDataStore();
+
 }

Modified: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Val.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Val.java?rev=939734&r1=939733&r2=939734&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Val.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Val.java Fri Apr 30 16:37:54 2010
@@ -250,7 +250,7 @@ public class Val implements Comparable<V
         case PropertyType.URI:
         case PropertyType.WEAKREFERENCE:
             return cache(type, x);
-        case PropertyType.BINARY:
+        case TYPE_BINARY_REFERENCE:
             return cache(TYPE_BINARY_REFERENCE, x);
         }
         throw ExceptionFactory.illegalArgument("type: {0}, value: {0}", type, x);

Modified: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcStorage.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcStorage.java?rev=939734&r1=939733&r2=939734&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcStorage.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcStorage.java Fri Apr 30 16:37:54 2010
@@ -21,6 +21,9 @@ import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
+import javax.jcr.RepositoryException;
+import org.apache.jackrabbit.j3.data.DataStore;
+import org.apache.jackrabbit.j3.data.FileDataStore;
 import org.apache.jackrabbit.j3.mc.NodeData;
 import org.apache.jackrabbit.j3.mc.Storage;
 import org.apache.jackrabbit.j3.mc.StorageSession;
@@ -51,6 +54,8 @@ public class JdbcStorage implements Stor
     private Connection connLock;
     private PreparedStatement prepUpdateSetting;
 
+    private DataStore dataStore;
+
     public JdbcStorage(String url) {
         this.url = url;
     }
@@ -128,7 +133,17 @@ public class JdbcStorage implements Stor
                 session.store(0, new NodeData[] { root }, null);
                 nextBaseNodeId++;
             }
-
+            ResultSet rs = stat.executeQuery("call database_path()");
+            rs.next();
+            String homeDir = rs.getString(1);
+            if (homeDir != null) {
+                dataStore = new FileDataStore();
+                try {
+                    dataStore.init(homeDir);
+                } catch (RepositoryException e) {
+                    throw ExceptionFactory.mcException(e);
+                }
+            }
         } catch (SQLException e) {
             throw ExceptionFactory.mcException(e);
         }
@@ -181,4 +196,8 @@ public class JdbcStorage implements Stor
         return rootNodeId;
     }
 
+    DataStore getDataStore() {
+        return dataStore;
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcStorageSession.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcStorageSession.java?rev=939734&r1=939733&r2=939734&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcStorageSession.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcStorageSession.java Fri Apr 30 16:37:54 2010
@@ -22,6 +22,7 @@ import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.HashMap;
+import org.apache.jackrabbit.j3.data.DataStore;
 import org.apache.jackrabbit.j3.mc.Bundle;
 import org.apache.jackrabbit.j3.mc.NodeData;
 import org.apache.jackrabbit.j3.mc.StorageSession;
@@ -264,10 +265,6 @@ public class JdbcStorageSession implemen
         return true;
     }
 
-    public boolean supportsNodeIdsWithoutPath() {
-        return true;
-    }
-
     public NodeData[] getTempNodes(int block) {
         ArrayList<NodeData> list = new ArrayList<NodeData>();
         try {
@@ -304,4 +301,8 @@ public class JdbcStorageSession implemen
         }
     }
 
+    public DataStore getDataStore() {
+        return storage.getDataStore();
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/mem/MemStorageSession.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/mem/MemStorageSession.java?rev=939734&r1=939733&r2=939734&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/mem/MemStorageSession.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/mem/MemStorageSession.java Fri Apr 30 16:37:54 2010
@@ -17,6 +17,7 @@
 package org.apache.jackrabbit.j3.mc.mem;
 
 import java.util.HashMap;
+import org.apache.jackrabbit.j3.data.DataStore;
 import org.apache.jackrabbit.j3.mc.Bundle;
 import org.apache.jackrabbit.j3.mc.NodeData;
 import org.apache.jackrabbit.j3.mc.StorageSession;
@@ -86,10 +87,6 @@ public class MemStorageSession implement
         return false;
     }
 
-    public boolean supportsNodeIdsWithoutPath() {
-        return true;
-    }
-
     public Bundle[] getEvents(long date, int size) {
         throw ExceptionFactory.unsupportedOperation();
     }
@@ -110,4 +107,8 @@ public class MemStorageSession implement
         throw ExceptionFactory.unsupportedOperation();
     }
 
+    public DataStore getDataStore() {
+        return null;
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/LobStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/LobStore.java?rev=939734&r1=939733&r2=939734&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/LobStore.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/LobStore.java Fri Apr 30 16:37:54 2010
@@ -17,12 +17,14 @@
 package org.apache.jackrabbit.j3.util;
 
 import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.SequenceInputStream;
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
-import org.apache.jackrabbit.j3.RepositoryImpl;
+import org.apache.jackrabbit.j3.data.DataIdentifier;
+import org.apache.jackrabbit.j3.data.DataRecord;
 import org.apache.jackrabbit.j3.data.DataStore;
 import org.apache.jackrabbit.j3.mc.Val;
 
@@ -31,24 +33,53 @@ import org.apache.jackrabbit.j3.mc.Val;
  */
 public class LobStore {
 
-    private final RepositoryImpl rep;
+    private DataStore dataStore;
 
-    public LobStore(RepositoryImpl rep) {
-        this.rep = rep;
+    public void setDataStore(DataStore store) {
+        this.dataStore = store;
     }
 
-    public InputStream getInputStream(String ref) {
-        // TODO Auto-generated method stub
-        return null;
+    public DataStore getDataStore() {
+        return dataStore;
     }
 
-    public DataStore getDataStore() {
-        return null;
+    public InputStream getInputStream(Val ref) throws RepositoryException {
+        String s = ref.getString();
+        s = s.substring(0, s.lastIndexOf(':'));
+        DataIdentifier id = new DataIdentifier(s);
+        DataRecord rec = dataStore.getRecordIfStored(id);
+        return rec.getStream();
+    }
+
+    private String create(InputStream stream) throws RepositoryException {
+        DataRecord rec = dataStore.addRecord(stream);
+        String ref = rec.getIdentifier().toString();
+        return ref + ":" + rec.getLength();
     }
 
     public Val createValue(InputStream in) throws RepositoryException {
         try {
+            if (dataStore == null) {
+                try {
+                    ByteArrayOutputStream out = new ByteArrayOutputStream();
+                    byte[] buff = new byte[1024];
+                    while (true) {
+                        int len = in.read(buff);
+                        if (len < 0) {
+                            break;
+                        }
+                        out.write(buff, 0, len);
+                    }
+                    return Val.get(out.toByteArray());
+                } catch (IOException e) {
+                    throw ExceptionFactory.repository(e, "Could not read from stream");
+                }
+            }
             int min = getMinRecordLength();
+            if (min == Integer.MAX_VALUE) {
+                String ref = create(in);
+                return Val.get(Val.TYPE_BINARY_REFERENCE, ref);
+            }
             int maxMemorySize = min - 1;
             byte[] buffer = new byte[maxMemorySize];
             int pos = 0, len = maxMemorySize;
@@ -85,12 +116,7 @@ public class LobStore {
     }
 
     private int getMinRecordLength() {
-        return Integer.MAX_VALUE;
-    }
-
-    private String create(InputStream stream) {
-        // TODO Auto-generated method stub
-        return null;
+        return dataStore == null ? Integer.MAX_VALUE : dataStore.getMinRecordLength();
     }
 
     public boolean isStored(Val value) {
@@ -103,8 +129,8 @@ public class LobStore {
         return false;
     }
 
-    public long getLength(Val value) {
-        String s = value.getString();
+    public long getLength(Val ref) {
+        String s = ref.getString();
         try {
             return Long.parseLong(s.substring(s.lastIndexOf(':')));
         } catch (Exception e) {

Modified: jackrabbit/sandbox/jackrabbit-j3/src/site/resources/images/drawing.png
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/site/resources/images/drawing.png?rev=939734&r1=939733&r2=939734&view=diff
==============================================================================
Binary files - no diff available.

Modified: jackrabbit/sandbox/jackrabbit-j3/src/site/resources/images/drawing.svg
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/site/resources/images/drawing.svg?rev=939734&r1=939733&r2=939734&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/site/resources/images/drawing.svg (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/site/resources/images/drawing.svg Fri Apr 30 16:37:54 2010
@@ -16,7 +16,7 @@
    version="1.1"
    inkscape:version="0.47 r22583"
    sodipodi:docname="drawing.svg"
-   inkscape:export-filename="/Users/tmueller/drawing.png"
+   inkscape:export-filename="/Users/tmueller/jackrabbit/sandbox/jackrabbit-j3/src/site/resources/images/drawing.png"
    inkscape:export-xdpi="48.380001"
    inkscape:export-ydpi="48.380001">
   <defs
@@ -226,9 +226,9 @@
      borderopacity="1.0"
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
-     inkscape:zoom="0.66873709"
-     inkscape:cx="256.23266"
-     inkscape:cy="646.80961"
+     inkscape:zoom="0.47286853"
+     inkscape:cx="36.408726"
+     inkscape:cy="665.93735"
      inkscape:document-units="px"
      inkscape:current-layer="layer1"
      showgrid="false"
@@ -238,7 +238,7 @@
      inkscape:window-height="852"
      inkscape:window-x="0"
      inkscape:window-y="0"
-     inkscape:window-maximized="1" />
+     inkscape:window-maximized="0" />
   <metadata
      id="metadata7">
     <rdf:RDF>
@@ -288,7 +288,7 @@
        id="rect3884"
        style="fill:#3b0000;fill-opacity:1;stroke:#000000;stroke-width:1.0269829;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;filter:url(#filter3910)" />
     <rect
-       style="fill:#ffb200;fill-opacity:1;stroke:#000000;stroke-width:1.28393507;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       style="fill:#ddff55;fill-opacity:1;stroke:#000000;stroke-width:1.28393507000000007;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
        id="rect3757"
        width="625.69257"
        height="257.26605"
@@ -302,17 +302,18 @@
        height="114.40515"
        width="467.24728"
        id="rect3876"
-       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;filter:url(#filter3878)" />
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;filter:url(#filter3878)"
+       transform="matrix(1.2842992,0,0,0.99915362,-201.41663,0.07175458)" />
     <rect
        y="822.29254"
        x="439.7944"
        height="70.267014"
        width="224.79643"
        id="rect3788"
-       style="fill:#ffff00;fill-opacity:1;stroke:#000000;stroke-width:1.27992463;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       style="fill:#eeffaa;fill-opacity:1;stroke:#000000;stroke-width:1.27992463000000001;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
        rx="21.82123" />
     <rect
-       style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:1.0269829;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       style="fill:#ccff00;fill-opacity:1;stroke:#000000;stroke-width:1.02698289999999992;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
        id="rect3759"
        width="627.96228"
        height="251.57126"
@@ -320,7 +321,7 @@
        y="318.27814"
        rx="23.700001" />
     <rect
-       style="fill:#ffff00;fill-opacity:1;stroke:#000000;stroke-width:1.23394859;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       style="fill:#eeffaa;fill-opacity:1;stroke:#000000;stroke-width:1.23394859000000001;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
        id="rect3674"
        width="209.09579"
        height="70.213562"
@@ -328,33 +329,34 @@
        y="823.32568"
        rx="23.700001" />
     <rect
-       style="fill:#0048ff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       style="fill:#aad400;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.16024995000000009;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
        id="rect2859"
-       width="467.24728"
+       width="628.9989"
        height="114.40515"
-       x="215.58446"
+       x="53.832813"
        y="22.030411"
-       rx="23.700001" />
+       rx="31.904467" />
     <text
        xml:space="preserve"
        style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
-       x="245.14754"
+       x="77.758507"
        y="90.5858"
        id="text2861"><tspan
          sodipodi:role="line"
          id="tspan2863"
-         x="245.14754"
-         y="90.5858">App</tspan></text>
+         x="77.758507"
+         y="90.5858"
+         style="font-size:32">App</tspan></text>
     <text
        xml:space="preserve"
        style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
-       x="62.45303"
-       y="286.31436"
+       x="82.246674"
+       y="282.08487"
        id="text2949"><tspan
          sodipodi:role="line"
          id="tspan2951"
-         x="62.45303"
-         y="286.31436">Jackrabbit 3</tspan></text>
+         x="82.246674"
+         y="282.08487">Jackrabbit 3</tspan></text>
     <text
        xml:space="preserve"
        style="font-size:32px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
@@ -395,24 +397,24 @@
     <text
        xml:space="preserve"
        style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
-       x="246.70222"
+       x="81.418549"
        y="179.09171"
        id="text3024"
        sodipodi:linespacing="125%"><tspan
          sodipodi:role="line"
          id="tspan3026"
-         x="246.70222"
-         y="179.09171">JCR API</tspan></text>
+         x="81.418549"
+         y="179.09171">JCR API (+ Jackrabbit API)</tspan></text>
     <text
        xml:space="preserve"
        style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
-       x="243.10457"
+       x="77.820892"
        y="619.8031"
        id="text3028"
        sodipodi:linespacing="125%"><tspan
          sodipodi:role="line"
          id="tspan3030"
-         x="243.10457"
+         x="77.820892"
          y="619.8031">Micro Kernel API</tspan></text>
     <text
        xml:space="preserve"
@@ -556,7 +558,7 @@
          sodipodi:role="line"
          id="tspan3164"
          x="466.52975"
-         y="368.64398">Change</tspan></text>
+         y="368.64398">ChangeSet</tspan></text>
     <text
        xml:space="preserve"
        style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
@@ -567,6 +569,6 @@
          sodipodi:role="line"
          id="tspan3168"
          x="466.52975"
-         y="418.74646">Cache</tspan></text>
+         y="418.74646">LobStore</tspan></text>
   </g>
 </svg>

Added: jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/RandomInputStream.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/RandomInputStream.java?rev=939734&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/RandomInputStream.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/RandomInputStream.java Fri Apr 30 16:37:54 2010
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.j3;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * An input stream that returns pseudo-random bytes.
+ */
+public class RandomInputStream extends InputStream {
+
+    private static final long MUL = 0x5DEECE66DL;
+    private static final long ADD = 0xBL;
+    private static final long MASK = (1L << 48) - 1;
+    private static final int DEFAULT_MAX_READ_BLOCK_SIZE = 15;
+
+    private final long initialSeed;
+    private final long len;
+    private long markedState;
+    private long pos;
+    private long markedPos;
+    private long state;
+    private int maxReadBlockSize;
+
+    public String toString() {
+        return "new RandomInputStream(" + initialSeed + ", " + len + ")";
+    }
+
+    public RandomInputStream(long seed, long len) {
+        this(seed, len, DEFAULT_MAX_READ_BLOCK_SIZE);
+    }
+
+    public static void compareStreams(InputStream a, InputStream b) throws IOException {
+        a = new BufferedInputStream(a);
+        b = new BufferedInputStream(b);
+        long pos = 0;
+        while (true) {
+            int x = a.read();
+            int y = b.read();
+            if (x == -1 || y == -1) {
+                if (x == y) {
+                    break;
+                }
+            }
+            if (x != y) {
+                throw new IOException("Incorrect byte at position " + pos + ": x=" + x + " y=" + y);
+            }
+        }
+    }
+
+    public RandomInputStream(long seed, long len, int maxReadBlockSize) {
+        this.initialSeed = seed;
+        this.len = len;
+        this.maxReadBlockSize = maxReadBlockSize;
+        setSeed(seed);
+        reset();
+    }
+
+    public long skip(long n) {
+        n = getReadBlock(n);
+        if (n == 0) {
+            return -1;
+        }
+        pos += n;
+        return n;
+    }
+
+    private int getReadBlock(long n) {
+        if (n > (len - pos)) {
+            n = (len - pos);
+        }
+        if (n > maxReadBlockSize) {
+            n = maxReadBlockSize;
+        } else if (n < 0) {
+            n = 0;
+        }
+        return (int) n;
+    }
+
+    public int read(byte[] b, int off, int len) {
+        if (pos >= this.len) {
+            return -1;
+        }
+        len = getReadBlock(len);
+        if (len == 0) {
+            return -1;
+        }
+        for (int i = 0; i < len; i++) {
+            b[off + i] = (byte) (next() & 255);
+        }
+        pos += len;
+        return len;
+    }
+
+    public int read(byte[] b) {
+        return read(b, 0, b.length);
+    }
+
+    public void close() {
+        pos = len;
+    }
+
+    private void setSeed(long seed) {
+        markedState = (seed ^ MUL) & MASK;
+    }
+
+    private int next() {
+        state = (state * MUL + ADD) & MASK;
+        return (int) (state >>> (48 - 32));
+    }
+
+    public void reset() {
+        pos = markedPos;
+        state = markedState;
+    }
+
+    public int read() {
+        if (pos >= len) {
+            return -1;
+        }
+        pos++;
+        return next() & 255;
+    }
+
+    public boolean markSupported() {
+        return true;
+    }
+
+    public void mark(int readlimit) {
+        markedPos = pos;
+        markedState = state;
+    }
+
+}

Modified: jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestAll.java?rev=939734&r1=939733&r2=939734&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestAll.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestAll.java Fri Apr 30 16:37:54 2010
@@ -35,11 +35,19 @@ public class TestAll {
         TestSuite suite = new TestSuite("org.apache.jackrabbit.j3");
 
         int todo;
+
+        // integrated lob storage
+        // database data store: should use the session to access the binary
+        // (like this we can also restrict on temporary storage per session)
+
         // ability to disable the even journal (for each session?)
+
         // XA API
-        // integrated lob storage
+
         // virtual repository
+
         // session attribute to request cache size (only smaller except if in admin group)
+
         // Repository.OPTION_JOURNALED_OBSERVATION_SUPPORTED
         // external events
         // ability to auto-delete old event journal entries
@@ -60,6 +68,7 @@ public class TestAll {
         suite.addTestSuite(TestCache.class);
         suite.addTestSuite(TestCreateNodesTraverse.class);
         suite.addTestSuite(TestEventJournal.class);
+        suite.addTestSuite(TestLargeObject.class);
 
         for (int i = 0; i < TestBase.URL.length; i++) {
             suite.addTestSuite(TestConcurrentWrite.class);

Modified: jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestBundle.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestBundle.java?rev=939734&r1=939733&r2=939734&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestBundle.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestBundle.java Fri Apr 30 16:37:54 2010
@@ -113,7 +113,7 @@ public class TestBundle extends TestCase
         testLength(Val.get(PropertyType.PATH, "/xyz/abc"));
         testLength(Val.get(PropertyType.REFERENCE, "abc:def"));
         testLength(Val.get(PropertyType.WEAKREFERENCE, "abc:def"));
-        testLength(Val.get(PropertyType.BINARY, "0x1234"));
+        testLength(Val.get(Val.TYPE_BINARY_REFERENCE, "0x1234"));
         testLength(Val.get("long string with strange characters äöü \u1234"));
         testLength(Val.get(new byte[1024]));
         testLength(Val.get(new byte[1024 * 1024]));

Added: jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestLargeObject.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestLargeObject.java?rev=939734&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestLargeObject.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestLargeObject.java Fri Apr 30 16:37:54 2010
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.j3;
+
+import java.io.InputStream;
+import javax.jcr.Binary;
+import javax.jcr.Node;
+import javax.jcr.Session;
+import javax.jcr.ValueFactory;
+
+/**
+ * Tests large objects.
+ */
+public class TestLargeObject extends TestBase {
+
+    public void test() throws Exception {
+        Node n = session.getRootNode().addNode("testLargeObject");
+        session.save();
+        ValueFactory vf = session.getValueFactory();
+        Binary b = vf.createBinary(createRandomStream());
+        n.setProperty("data", b);
+        session.save();
+
+        Session session2 = openSession();
+        Node n2 = session2.getNode("/testLargeObject");
+        InputStream in = n2.getProperty("data").getBinary().getStream();
+        RandomInputStream.compareStreams(createRandomStream(), in);
+        session2.logout();
+
+        n.remove();
+        session.save();
+    }
+
+    private InputStream createRandomStream() {
+        return new RandomInputStream(1, 1000000);
+    }
+
+}