Index: src/test/java/org/apache/jackrabbit/core/nodetype/xml/TestAll.java
===================================================================
--- src/test/java/org/apache/jackrabbit/core/nodetype/xml/TestAll.java	(revision 544329)
+++ src/test/java/org/apache/jackrabbit/core/nodetype/xml/TestAll.java	(working copy)
@@ -76,7 +76,7 @@
         InputStream xml =
             getClass().getClassLoader().getResourceAsStream(TEST_NODETYPES);
 
-        types = NodeTypeReader.read(xml);
+        types = NodeTypeReader.read(xml, null);
 
         registry = new SimpleNamespaceRegistry();
         registry.registerNamespace("test", TEST_NAMESPACE);
@@ -569,7 +569,7 @@
             NodeTypeWriter.write(xml, types, registry);
             byte[] bytes = xml.toByteArray();
             NodeTypeDef[] output =
-                NodeTypeReader.read(new ByteArrayInputStream(bytes));
+                NodeTypeReader.read(new ByteArrayInputStream(bytes), null);
             assertTrue("write output", Arrays.equals(types, output));
         } catch (InvalidNodeTypeDefException e) {
             fail(e.getMessage());
Index: src/test/java/org/apache/jackrabbit/core/nodetype/compact/CompactNodeTypeDefTest.java
===================================================================
--- src/test/java/org/apache/jackrabbit/core/nodetype/compact/CompactNodeTypeDefTest.java	(revision 544329)
+++ src/test/java/org/apache/jackrabbit/core/nodetype/compact/CompactNodeTypeDefTest.java	(working copy)
@@ -106,7 +106,7 @@
         Reader reader = new InputStreamReader(
             getClass().getClassLoader().getResourceAsStream(TEST_FILE));
         CompactNodeTypeDefReader cndReader =
-            new CompactNodeTypeDefReader(reader, TEST_FILE);
+            new CompactNodeTypeDefReader(null, reader, TEST_FILE);
         List ntdList = cndReader.getNodeTypeDefs();
         NamespaceMapping nsm = cndReader.getNamespaceMapping();
         NodeTypeDef ntd = (NodeTypeDef)ntdList.get(0);
@@ -122,7 +122,7 @@
         CompactNodeTypeDefWriter.write(ntdList, nsm, sw);
 
         // Rerun the reader on the product of the writer
-        cndReader = new CompactNodeTypeDefReader(new StringReader(sw.toString()), TEST_FILE);
+        cndReader = new CompactNodeTypeDefReader(null, new StringReader(sw.toString()), TEST_FILE);
         ntdList = cndReader.getNodeTypeDefs();
         ntd = (NodeTypeDef)ntdList.get(0);
 
Index: src/main/java/org/apache/jackrabbit/core/persistence/xml/XMLPersistenceManager.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/persistence/xml/XMLPersistenceManager.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/persistence/xml/XMLPersistenceManager.java	(working copy)
@@ -22,7 +22,6 @@
 import org.apache.jackrabbit.core.fs.FileSystem;
 import org.apache.jackrabbit.core.fs.FileSystemException;
 import org.apache.jackrabbit.core.fs.FileSystemResource;
-import org.apache.jackrabbit.core.fs.local.LocalFileSystem;
 import org.apache.jackrabbit.core.nodetype.NodeDefId;
 import org.apache.jackrabbit.core.nodetype.PropDefId;
 import org.apache.jackrabbit.core.persistence.AbstractPersistenceManager;
@@ -33,11 +32,7 @@
 import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.persistence.PMContext;
 import org.apache.jackrabbit.core.state.PropertyState;
-import org.apache.jackrabbit.core.persistence.util.BLOBStore;
-import org.apache.jackrabbit.core.persistence.util.FileSystemBLOBStore;
-import org.apache.jackrabbit.core.persistence.util.ResourceBasedBLOBStore;
 import org.apache.jackrabbit.core.util.DOMWalker;
-import org.apache.jackrabbit.core.value.BLOBFileValue;
 import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.name.QName;
 import org.apache.jackrabbit.util.Text;
@@ -46,7 +41,6 @@
 
 import javax.jcr.PropertyType;
 import java.io.BufferedWriter;
-import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -116,10 +110,6 @@
 
     // file system where the item state is stored
     private FileSystem itemStateFS;
-    // file system where BLOB data is stored
-    private FileSystem blobFS;
-    // BLOBStore that manages BLOB data in the file system
-    private BLOBStore blobStore;
 
     /**
      * Template for the subdirectory path for the files associated with
@@ -334,44 +324,9 @@
             while (walker.iterateElements(VALUE_ELEMENT)) {
                 // read serialized value
                 String content = walker.getContent();
-                if (PropertyType.STRING == type) {
-                    // STRING value can be empty; ignore length
+                // STRING value can be empty; ignore length
+                if (PropertyType.STRING == type || content.length() > 0) {
                     values.add(InternalValue.valueOf(content, type));
-                } else if (content.length() > 0) {
-                    // non-empty non-STRING value
-                    if (type == PropertyType.BINARY) {
-                        try {
-                            // special handling required for binary value:
-                            // the value stores the id of the BLOB data
-                            // in the BLOB store
-                            if (blobStore instanceof ResourceBasedBLOBStore) {
-                                // optimization: if the BLOB store is resource-based
-                                // retrieve the resource directly rather than having
-                                // to read the BLOB from an input stream
-                                FileSystemResource fsRes =
-                                        ((ResourceBasedBLOBStore) blobStore).getResource(content);
-                                values.add(InternalValue.create(fsRes));
-                            } else {
-                                InputStream in = blobStore.get(content);
-                                try {
-                                    values.add(InternalValue.create(in, false));
-                                } finally {
-                                    try {
-                                        in.close();
-                                    } catch (IOException e) {
-                                        // ignore
-                                    }
-                                }
-                            }
-                        } catch (Exception e) {
-                            String msg = "error while reading serialized binary value";
-                            log.debug(msg);
-                            throw new ItemStateException(msg, e);
-                        }
-                    } else {
-                        // non-empty non-STRING non-BINARY value
-                        values.add(InternalValue.valueOf(content, type));
-                    }
                 } else {
                     // empty non-STRING value
                     log.warn(state.getPropertyId() + ": ignoring empty value of type "
@@ -419,16 +374,6 @@
 
         itemStateFS = new BasedFileSystem(context.getFileSystem(), "/data");
 
-        /**
-         * store BLOB data in local file system in a sub directory
-         * of the workspace home directory
-         */
-        LocalFileSystem blobFS = new LocalFileSystem();
-        blobFS.setRoot(new File(context.getHomeDir(), "blobs"));
-        blobFS.init();
-        this.blobFS = blobFS;
-        blobStore = new FileSystemBLOBStore(blobFS);
-
         initialized = true;
     }
 
@@ -440,19 +385,7 @@
             throw new IllegalStateException("not initialized");
         }
 
-        try {
-            // close BLOB file system
-            blobFS.close();
-            blobFS = null;
-            blobStore = null;
-            /**
-             * there's no need close the item state store because it
-             * is based in the workspace's file system which is
-             * closed by the repository
-             */
-        } finally {
-            initialized = false;
-        }
+        initialized = false;
     }
 
     /**
@@ -664,48 +597,7 @@
                         writer.write("\t\t<" + VALUE_ELEMENT + ">");
                         InternalValue val = values[i];
                         if (val != null) {
-                            if (type == PropertyType.BINARY) {
-                                // special handling required for binary value:
-                                // put binary value in BLOB store
-                                BLOBFileValue blobVal = (BLOBFileValue) val.internalValue();
-                                InputStream in = blobVal.getStream();
-                                String blobId = blobStore.createId(state.getPropertyId(), i);
-                                try {
-                                    blobStore.put(blobId, in, blobVal.getLength());
-                                } finally {
-                                    try {
-                                        in.close();
-                                    } catch (IOException e) {
-                                        // ignore
-                                    }
-                                }
-                                // store id of BLOB as property value
-                                writer.write(blobId);
-                                // replace value instance with value backed by resource
-                                // in BLOB store and discard old value instance (e.g. temp file)
-                                if (blobStore instanceof ResourceBasedBLOBStore) {
-                                    // optimization: if the BLOB store is resource-based
-                                    // retrieve the resource directly rather than having
-                                    // to read the BLOB from an input stream
-                                    FileSystemResource fsRes =
-                                            ((ResourceBasedBLOBStore) blobStore).getResource(blobId);
-                                    values[i] = InternalValue.create(fsRes);
-                                } else {
-                                    in = blobStore.get(blobId);
-                                    try {
-                                        values[i] = InternalValue.create(in, false);
-                                    } finally {
-                                        try {
-                                            in.close();
-                                        } catch (IOException e) {
-                                            // ignore
-                                        }
-                                    }
-                                }
-                                blobVal.discard();
-                            } else {
-                                writer.write(Text.encodeIllegalXMLCharacters(val.toString()));
-                            }
+                            writer.write(Text.encodeIllegalXMLCharacters(val.toString()));
                         }
                         writer.write("</" + VALUE_ELEMENT + ">\n");
                     }
@@ -753,20 +645,6 @@
             throw new IllegalStateException("not initialized");
         }
 
-        // delete binary values (stored as files)
-        InternalValue[] values = state.getValues();
-        if (values != null) {
-            for (int i = 0; i < values.length; i++) {
-                InternalValue val = values[i];
-                if (val != null) {
-                    if (val.getType() == PropertyType.BINARY) {
-                        BLOBFileValue blobVal = (BLOBFileValue) val.internalValue();
-                        // delete blob file and prune empty parent folders
-                        blobVal.delete(true);
-                    }
-                }
-            }
-        }
         // delete property file
         String propFilePath = buildPropFilePath(state.getPropertyId());
         FileSystemResource propFile = new FileSystemResource(itemStateFS, propFilePath);
Index: src/main/java/org/apache/jackrabbit/core/persistence/db/DatabasePersistenceManager.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/persistence/db/DatabasePersistenceManager.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/persistence/db/DatabasePersistenceManager.java	(working copy)
@@ -22,8 +22,6 @@
 import org.apache.jackrabbit.core.fs.local.LocalFileSystem;
 import org.apache.jackrabbit.core.persistence.AbstractPersistenceManager;
 import org.apache.jackrabbit.core.persistence.PMContext;
-import org.apache.jackrabbit.core.persistence.util.BLOBStore;
-import org.apache.jackrabbit.core.persistence.util.FileSystemBLOBStore;
 import org.apache.jackrabbit.core.persistence.util.Serializer;
 import org.apache.jackrabbit.core.state.ChangeLog;
 import org.apache.jackrabbit.core.state.ItemState;
@@ -83,8 +81,6 @@
     protected String schema;
     protected String schemaObjectPrefix;
 
-    protected boolean externalBLOBs;
-
     // initial size of buffer used to serialize objects
     protected static final int INITIAL_BUFFER_SIZE = 1024;
 
@@ -121,34 +117,12 @@
     protected String nodeReferenceSelectExistSQL;
     protected String nodeReferenceDeleteSQL;
 
-    // SQL statements for BLOB management
-    // (if <code>externalBLOBs==false</code>)
-    protected String blobInsertSQL;
-    protected String blobUpdateSQL;
-    protected String blobSelectSQL;
-    protected String blobSelectExistSQL;
-    protected String blobDeleteSQL;
-
-
-
     /**
-     * file system where BLOB data is stored
-     * (if <code>externalBLOBs==true</code>)
-     */
-    protected FileSystem blobFS;
-    /**
-     * BLOBStore that manages BLOB data in the file system
-     * (if <code>externalBLOBs==true</code>)
-     */
-    protected BLOBStore blobStore;
-
-    /**
      * Creates a new <code>DatabasePersistenceManager</code> instance.
      */
     public DatabasePersistenceManager() {
         schema = "default";
         schemaObjectPrefix = "";
-        externalBLOBs = true;
         initialized = false;
     }
 
@@ -171,18 +145,6 @@
         this.schema = schema;
     }
 
-    public boolean isExternalBLOBs() {
-        return externalBLOBs;
-    }
-
-    public void setExternalBLOBs(boolean externalBLOBs) {
-        this.externalBLOBs = externalBLOBs;
-    }
-
-    public void setExternalBLOBs(String externalBLOBs) {
-        this.externalBLOBs = Boolean.valueOf(externalBLOBs).booleanValue();
-    }
-
     //---------------------------------------------------< PersistenceManager >
     /**
      * {@inheritDoc}
@@ -207,23 +169,6 @@
         // prepare statements
         initPreparedStatements();
 
-        if (externalBLOBs) {
-            /**
-             * store BLOBs in local file system in a sub directory
-             * of the workspace home directory
-             */
-            LocalFileSystem blobFS = new LocalFileSystem();
-            blobFS.setRoot(new File(context.getHomeDir(), "blobs"));
-            blobFS.init();
-            this.blobFS = blobFS;
-            blobStore = new FileSystemBLOBStore(blobFS);
-        } else {
-            /**
-             * store BLOBs in db
-             */
-            blobStore = new DbBLOBStore();
-        }
-
         initialized = true;
     }
 
@@ -242,13 +187,6 @@
             }
             preparedStatements.clear();
 
-            if (externalBLOBs) {
-                // close BLOB file system
-                blobFS.close();
-                blobFS = null;
-            }
-            blobStore = null;
-
             // close jdbc connection
             closeConnection(con);
 
@@ -380,7 +318,7 @@
 
                 in = rs.getBinaryStream(1);
                 PropertyState state = createNew(id);
-                Serializer.deserialize(state, in, blobStore);
+                Serializer.deserialize(state, in);
 
                 return state;
             } catch (Exception e) {
@@ -459,7 +397,7 @@
             ByteArrayOutputStream out =
                     new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
             // serialize property state
-            Serializer.serialize(state, out, blobStore);
+            Serializer.serialize(state, out);
 
             // we are synchronized on this instance, therefore we do not
             // not have to additionally synchronize on the sql statement
@@ -503,28 +441,6 @@
             throw new IllegalStateException("not initialized");
         }
 
-        // make sure binary values (BLOBs) are properly removed
-        InternalValue[] values = state.getValues();
-        if (values != null) {
-            for (int i = 0; i < values.length; i++) {
-                InternalValue val = values[i];
-                if (val != null) {
-                    if (val.getType() == PropertyType.BINARY) {
-                        BLOBFileValue blobVal = (BLOBFileValue) val.internalValue();
-                        // delete internal resource representation of BLOB value
-                        blobVal.delete(true);
-                        // also remove from BLOBStore
-                        String blobId = blobStore.createId(state.getPropertyId(), i);
-                        try {
-                            blobStore.remove(blobId);
-                        } catch (Exception e) {
-                            log.warn("failed to remove from BLOBStore: " + blobId, e);
-                        }
-                    }
-                }
-            }
-        }
-
         try {
             // we are synchronized on this instance, therefore we do not
             // not have to additionally synchronize on the sql statement
@@ -1066,21 +982,6 @@
                 + schemaObjectPrefix + "REFS where NODE_ID = ?";
         nodeReferenceDeleteSQL = "delete from "
                 + schemaObjectPrefix + "REFS where NODE_ID = ?";
-
-        if (!externalBLOBs) {
-            blobInsertSQL = "insert into "
-                    + schemaObjectPrefix + "BINVAL (BINVAL_DATA, BINVAL_ID) values (?, ?)";
-            blobUpdateSQL = "update "
-                    + schemaObjectPrefix + "BINVAL set BINVAL_DATA = ? where BINVAL_ID = ?";
-            blobSelectSQL =
-                    "select BINVAL_DATA from "
-                    + schemaObjectPrefix + "BINVAL where BINVAL_ID = ?";
-            blobSelectExistSQL =
-                    "select 1 from "
-                    + schemaObjectPrefix + "BINVAL where BINVAL_ID = ?";
-            blobDeleteSQL = "delete from "
-                    + schemaObjectPrefix + "BINVAL where BINVAL_ID = ?";
-        }
     }
 
     /**
@@ -1121,14 +1022,6 @@
                 nodeReferenceSelectExistSQL, con.prepareStatement(nodeReferenceSelectExistSQL));
         preparedStatements.put(
                 nodeReferenceDeleteSQL, con.prepareStatement(nodeReferenceDeleteSQL));
-
-        if (!externalBLOBs) {
-            preparedStatements.put(blobInsertSQL, con.prepareStatement(blobInsertSQL));
-            preparedStatements.put(blobUpdateSQL, con.prepareStatement(blobUpdateSQL));
-            preparedStatements.put(blobSelectSQL, con.prepareStatement(blobSelectSQL));
-            preparedStatements.put(blobSelectExistSQL, con.prepareStatement(blobSelectExistSQL));
-            preparedStatements.put(blobDeleteSQL, con.prepareStatement(blobDeleteSQL));
-        }
     }
 
     //--------------------------------------------------------< inner classes >
@@ -1171,74 +1064,4 @@
         }
     }
 
-    class DbBLOBStore implements BLOBStore {
-        /**
-         * {@inheritDoc}
-         */
-        public String createId(PropertyId id, int index) {
-            // the blobId is a simple string concatenation of id plus index
-            StringBuffer sb = new StringBuffer();
-            sb.append(id.toString());
-            sb.append('[');
-            sb.append(index);
-            sb.append(']');
-            return sb.toString();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public InputStream get(String blobId) throws Exception {
-            synchronized (blobSelectSQL) {
-                Statement stmt = executeStmt(blobSelectSQL, new Object[]{blobId});
-                final ResultSet rs = stmt.getResultSet();
-                if (!rs.next()) {
-                    closeResultSet(rs);
-                    throw new Exception("no such BLOB: " + blobId);
-                }
-                InputStream in = rs.getBinaryStream(1);
-                if (in == null) {
-                    // some databases treat zero-length values as NULL;
-                    // return empty InputStream in such a case
-                    closeResultSet(rs);
-                    return new ByteArrayInputStream(new byte[0]);
-                }
-
-                /**
-                 * return an InputStream wrapper in order to
-                 * close the ResultSet when the stream is closed
-                 */
-                return new FilterInputStream(in) {
-                    public void close() throws IOException {
-                        in.close();
-                        // now it's safe to close ResultSet
-                        closeResultSet(rs);
-                    }
-                };
-            }
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public synchronized void put(String blobId, InputStream in, long size)
-                throws Exception {
-            Statement stmt = executeStmt(blobSelectExistSQL, new Object[]{blobId});
-            ResultSet rs = stmt.getResultSet();
-            // a BLOB exists if the result has at least one entry
-            boolean exists = rs.next();
-            closeResultSet(rs);
-
-            String sql = (exists) ? blobUpdateSQL : blobInsertSQL;
-            executeStmt(sql, new Object[]{new SizedInputStream(in, size), blobId});
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public synchronized boolean remove(String blobId) throws Exception {
-            Statement stmt = executeStmt(blobDeleteSQL, new Object[]{blobId});
-            return stmt.getUpdateCount() == 1;
-        }
-    }
 }
Index: src/main/java/org/apache/jackrabbit/core/persistence/db/OraclePersistenceManager.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/persistence/db/OraclePersistenceManager.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/persistence/db/OraclePersistenceManager.java	(working copy)
@@ -116,10 +116,6 @@
     public void init(PMContext context) throws Exception {
         super.init(context);
 
-        if (!externalBLOBs) {
-            blobStore = new OracleBLOBStore();
-        }
-
         // initialize oracle.sql.BLOB class & constants
 
         // use the Connection object for using the exact same
@@ -190,7 +186,7 @@
             ByteArrayOutputStream out =
                     new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
             // serialize property state
-            Serializer.serialize(state, out, blobStore);
+            Serializer.serialize(state, out);
 
             // we are synchronized on this instance, therefore we do not
             // not have to additionally synchronize on the sql statement
@@ -364,32 +360,4 @@
         freeTemporary.invoke(blob, null);
     }
 
-    //--------------------------------------------------------< inner classes >
-    class OracleBLOBStore extends DbBLOBStore {
-        /**
-         * {@inheritDoc}
-         */
-        public synchronized void put(String blobId, InputStream in, long size)
-                throws Exception {
-            Statement stmt = executeStmt(blobSelectExistSQL, new Object[]{blobId});
-            ResultSet rs = stmt.getResultSet();
-            // a BLOB exists if the result has at least one entry
-            boolean exists = rs.next();
-            closeResultSet(rs);
-
-            Blob blob = null;
-            try {
-                String sql = (exists) ? blobUpdateSQL : blobInsertSQL;
-                blob = createTemporaryBlob(in);
-                executeStmt(sql, new Object[]{blob, blobId});
-            } finally {
-                if (blob != null) {
-                    try {
-                        freeTemporaryBlob(blob);
-                    } catch (Exception ignore) {
-                    }
-                }
-            }
-        }
-    }
 }
Index: src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java	(working copy)
@@ -33,8 +33,6 @@
 import org.apache.jackrabbit.core.persistence.bundle.util.ErrorHandling;
 import org.apache.jackrabbit.core.persistence.bundle.util.StringIndex;
 import org.apache.jackrabbit.core.persistence.util.Serializer;
-import org.apache.jackrabbit.core.persistence.util.BLOBStore;
-import org.apache.jackrabbit.core.persistence.util.FileSystemBLOBStore;
 import org.apache.jackrabbit.core.fs.FileSystemResource;
 import org.apache.jackrabbit.core.fs.FileSystem;
 import org.apache.jackrabbit.core.fs.local.LocalFileSystem;
@@ -154,9 +152,6 @@
     protected PreparedStatement nodeReferenceSelect;
     protected PreparedStatement nodeReferenceDelete;
 
-    /** file system where BLOB data is stored */
-    protected CloseableBLOBStore blobStore;
-
     /** the index for local names */
     private StringIndex nameIndex;
 
@@ -288,23 +283,6 @@
     }
 
     /**
-     * Returns if uses external (filesystem) blob store.
-     * @return if uses external (filesystem) blob store.
-     */
-    public boolean isExternalBLOBs() {
-        return externalBLOBs;
-    }
-
-    /**
-     * Sets the flag for external (filesystem) blob store usage.
-     * @param externalBLOBs a value of "true" indicates that an external blob
-     *        store is to be used.
-     */
-    public void setExternalBLOBs(boolean externalBLOBs) {
-        this.externalBLOBs = externalBLOBs;
-    }
-
-    /**
      * Checks if consistency check is enabled.
      * @return <code>true</code> if consistenct check is enabled.
      */
@@ -539,8 +517,6 @@
         checkSchema();
 
         // create correct blob store
-        blobStore = createBlobStore();
-
         // prepare statements
         if (getStorageModel() == SM_BINARY_KEYS) {
             bundleInsert = con.prepareStatement("insert into " + schemaObjectPrefix + "BUNDLE (BUNDLE_DATA, NODE_ID) values (?, ?)");
@@ -564,8 +540,7 @@
             nodeReferenceDelete = con.prepareStatement("delete from " + schemaObjectPrefix + "REFS where NODE_ID_HI = ? and NODE_ID_LO = ?");
         }
         // load namespaces
-        binding = new BundleBinding(errorHandling, blobStore, getNsIndex(), getNameIndex());
-        binding.setMinBlobSize(minBlobSize);
+        binding = new BundleBinding(errorHandling, getNsIndex(), getNameIndex());
 
         initialized = true;
 
@@ -574,18 +549,6 @@
         }
     }
 
-    /**
-     * Creates a suitable blobstore
-     * @return a blobstore
-     * @throws Exception if an unspecified error occurs
-     */
-    protected CloseableBLOBStore createBlobStore() throws Exception {
-        if (useLocalFsBlobStore()) {
-            return createLocalFSBlobStore(context);
-        } else {
-            return createDBBlobStore(context);
-        }
-    }
 
     /**
      * Returns the local name index
@@ -627,40 +590,6 @@
     }
 
     /**
-     * Creates a blob store that is based on a local fs. This is called by
-     * init if {@link #useLocalFsBlobStore()} returns <code>true</code>.
-     *
-     * @param context the persistence manager context
-     * @return a blob store
-     * @throws Exception if an error occurs.
-     */
-    protected CloseableBLOBStore createLocalFSBlobStore(PMContext context)
-            throws Exception {
-        /**
-         * store blob's in local file system in a sub directory
-         * of the workspace home directory
-         */
-        LocalFileSystem blobFS = new LocalFileSystem();
-        blobFS.setRoot(new File(context.getHomeDir(), "blobs"));
-        blobFS.init();
-        return new FSBlobStore(blobFS);
-    }
-
-    /**
-     * Creates a blob store that uses the database. This is called by
-     * init if {@link #useDbBlobStore()} returns <code>true</code>.
-     *
-     * @param context the persistence manager context
-     *
-     * @return a blob store
-     * @throws Exception if an error occurs.
-     */
-    protected CloseableBLOBStore createDBBlobStore(PMContext context)
-            throws Exception {
-        return new DbBlobStore();
-    }
-
-    /**
      * Performs a consistency check.
      */
     private void checkConsistency() {
@@ -826,10 +755,6 @@
 
             // close jdbc connection
             con.close();
-
-            // close blob store
-            blobStore.close();
-            blobStore = null;
         } finally {
             initialized = false;
         }
@@ -1178,167 +1103,4 @@
         return name;
     }
 
-    /**
-     * Helper interface for closeable stores
-     */
-    protected static interface CloseableBLOBStore extends BLOBStore {
-        void close();
-    }
-
-    /**
-     * own implementation of the filesystem blob store that uses a different
-     * blob-id scheme.
-     */
-    protected class FSBlobStore extends FileSystemBLOBStore implements CloseableBLOBStore {
-
-        private FileSystem fs;
-
-        public FSBlobStore(FileSystem fs) {
-            super(fs);
-            this.fs = fs;
-        }
-
-        public String createId(PropertyId id, int index) {
-            return buildBlobFilePath(null, id, index).toString();
-        }
-
-        public void close() {
-            try {
-                fs.close();
-                fs = null;
-            } catch (Exception e) {
-                // ignore
-            }
-        }
-    }
-
-    /**
-     * Implementation of a blob store that stores the data inside the database
-     */
-    protected class DbBlobStore implements CloseableBLOBStore {
-
-        protected PreparedStatement blobInsert;
-        protected PreparedStatement blobUpdate;
-        protected PreparedStatement blobSelect;
-        protected PreparedStatement blobSelectExist;
-        protected PreparedStatement blobDelete;
-
-        public DbBlobStore() throws SQLException {
-            blobInsert =
-                    con.prepareStatement("insert into "
-                    + schemaObjectPrefix + "BINVAL (BINVAL_DATA, BINVAL_ID) values (?, ?)");
-            blobUpdate =
-                    con.prepareStatement("update "
-                    + schemaObjectPrefix + "BINVAL set BINVAL_DATA = ? where BINVAL_ID = ?");
-            blobSelect =
-                    con.prepareStatement("select BINVAL_DATA from "
-                    + schemaObjectPrefix + "BINVAL where BINVAL_ID = ?");
-            blobSelectExist =
-                    con.prepareStatement("select 1 from "
-                    + schemaObjectPrefix + "BINVAL where BINVAL_ID = ?");
-            blobDelete =
-                    con.prepareStatement("delete from "
-                    + schemaObjectPrefix + "BINVAL where BINVAL_ID = ?");
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public String createId(PropertyId id, int index) {
-            StringBuffer buf = new StringBuffer();
-            buf.append(id.getParentId().toString());
-            buf.append('.');
-            buf.append(getNsIndex().stringToIndex(id.getName().getNamespaceURI()));
-            buf.append('.');
-            buf.append(getNameIndex().stringToIndex(id.getName().getLocalName()));
-            buf.append('.');
-            buf.append(index);
-            return buf.toString();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public InputStream get(String blobId) throws Exception {
-            PreparedStatement stmt = blobSelect;
-            synchronized (stmt) {
-                try {
-                    stmt.setString(1, blobId);
-                    stmt.execute();
-                    final ResultSet rs = stmt.getResultSet();
-                    if (!rs.next()) {
-                        closeResultSet(rs);
-                        throw new Exception("no such BLOB: " + blobId);
-                    }
-                    InputStream in = rs.getBinaryStream(1);
-                    if (in == null) {
-                        // some databases treat zero-length values as NULL;
-                        // return empty InputStream in such a case
-                        closeResultSet(rs);
-                        return new ByteArrayInputStream(new byte[0]);
-                    }
-
-                    /**
-                     * return an InputStream wrapper in order to
-                     * close the ResultSet when the stream is closed
-                     */
-                    return new FilterInputStream(in) {
-                        public void close() throws IOException {
-                            in.close();
-                            // now it's safe to close ResultSet
-                            closeResultSet(rs);
-                        }
-                    };
-                } finally {
-                    resetStatement(stmt);
-                }
-            }
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public synchronized void put(String blobId, InputStream in, long size)
-                throws Exception {
-            PreparedStatement stmt = blobSelectExist;
-            try {
-                stmt.setString(1, blobId);
-                stmt.execute();
-                ResultSet rs = stmt.getResultSet();
-                // a BLOB exists if the result has at least one entry
-                boolean exists = rs.next();
-                resetStatement(stmt);
-                closeResultSet(rs);
-
-                stmt = (exists) ? blobUpdate : blobInsert;
-                stmt.setBinaryStream(1, in, (int) size);
-                stmt.setString(2, blobId);
-                stmt.executeUpdate();
-            } finally {
-                resetStatement(stmt);
-            }
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public synchronized boolean remove(String blobId) throws Exception {
-            PreparedStatement stmt = blobDelete;
-            try {
-                stmt.setString(1, blobId);
-                return stmt.executeUpdate() == 1;
-            } finally {
-                resetStatement(stmt);
-            }
-        }
-
-        public void close() {
-            closeStatement(blobInsert);
-            closeStatement(blobUpdate);
-            closeStatement(blobSelect);
-            closeStatement(blobSelectExist);
-            closeStatement(blobDelete);
-        }
-    }
-
 }
Index: src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java	(working copy)
@@ -27,8 +27,6 @@
 import org.apache.jackrabbit.core.persistence.bundle.util.BundleBinding;
 import org.apache.jackrabbit.core.persistence.bundle.util.TrackingInputStream;
 import org.apache.jackrabbit.core.persistence.util.Serializer;
-import org.apache.jackrabbit.core.persistence.util.BLOBStore;
-import org.apache.jackrabbit.core.persistence.util.FileSystemBLOBStore;
 import org.apache.jackrabbit.core.NodeId;
 import org.apache.jackrabbit.core.PropertyId;
 import org.apache.jackrabbit.core.state.ItemStateException;
@@ -75,28 +73,7 @@
     /** initial size of buffer used to serialize objects */
     protected static final int INITIAL_BUFFER_SIZE = 1024;
 
-    /** file system where BLOB data is stored */
-    protected BundleFsPersistenceManager.CloseableBLOBStore blobStore;
-
     /**
-     * Default blocksize for BLOB filesystem:
-     * @see #setBlobFSBlockSize(String)
-     */
-    private int blobFSBlockSize = 0;
-
-    /**
-     * Default initial cache size for BLOB filesystem: 100, req. 25KB
-     * @see #setBlobFSInitialCacheSize(String)
-     */
-    private int blobFSInitialCache = 100;
-
-    /**
-     * Default max cache size for BLOB filesystem: 4000, req. 1000KB
-     * @see #setBlobFSMaximumCacheSize(String)
-     */
-    private int blobFSMaximumCache = 4000;
-
-    /**
      * Default blocksize for item filesystem:
      * @see #setItemFSBlockSize(String)
      */
@@ -115,12 +92,6 @@
     private int itemFSMaximumCache = 4000;
 
     /**
-     * the minimum size of a property until it gets written to the blob store
-     * @see #setMinBlobSize(String)
-     */
-    private int minBlobSize = 0x1000;
-
-    /**
      * the filesystem where the items are stored
      */
     private FileSystem itemFs;
@@ -140,102 +111,7 @@
      */
     private String name = super.toString();
 
-
     /**
-     * Returns the configured block size of the blob cqfs
-     * @return the block size.
-     */
-    public String getBlobFSBlockSize() {
-        return String.valueOf(blobFSBlockSize);
-    }
-
-    /**
-     * Sets the block size of the blob fs and controlls how blobs are handled.
-     * <br>
-     * If the size is > 0, it must be a power of 2 and is used as blocksize
-     * for the cqfs. blobs are then stored within that cqfs. A call to
-     * {@link #useCqFsBlobStore()} will return <code>true</code>.
-     * <br>
-     * If the size is 0, the cqfs is not used at all, and the blobs are stored
-     * within the workspace's physical filesystem. A call to
-     * {@link #useLocalFsBlobStore()} will return <code>true</code>.
-     * <br>
-     * If the size is &lt; 0, the cqfs is not used at all, and the blobls are
-     * stored within the item filesystem. A call to
-     * {@link #useItemBlobStore()} will return <code>true</code>.
-     * <br>
-     * Please note that not all binary properties are considered as blobs. They
-     * are only stored in the respective blob store, if their size exceeds
-     * {@link #getMinBlobSize()}.
-     *
-     * @param size the block size
-     */
-    public void setBlobFSBlockSize(String size) {
-        this.blobFSBlockSize = Integer.decode(size).intValue();
-    }
-
-    /**
-     * Returns <code>true</code> if the blobs are stored in the DB.
-     * @return <code>true</code> if the blobs are stored in the DB.
-     */
-    public boolean useItemBlobStore() {
-        return blobFSBlockSize < 0;
-    }
-
-    /**
-     * Returns <code>true</code> if the blobs are stored in the local fs.
-     * @return <code>true</code> if the blobs are stored in the local fs.
-     */
-    public boolean useLocalFsBlobStore() {
-        return blobFSBlockSize == 0;
-    }
-
-    /**
-     * Returns <code>true</code> if the blobs are stored in the cqfs.
-     * @return <code>true</code> if the blobs are stored in the cqfs.
-     */
-    public boolean useCqFsBlobStore() {
-        return blobFSBlockSize > 0;
-    }
-
-    /**
-     * Returns the configured inital cache size of the blobfs.
-     * @return the configured inital cache size of the blobfs.
-     */
-    public String getBlobFSInitialCacheSize() {
-        return String.valueOf(blobFSInitialCache);
-    }
-
-    /**
-     * Sets the initial cache size of the blob fs. This only applies to cqfs
-     * base blobstores, i.e. if {@link #useCqFsBlobStore()} returns
-     * <code>true</code>.
-     * @param size the initial size
-     */
-    public void setBlobFSInitialCacheSize(String size) {
-        this.blobFSInitialCache = Integer.decode(size).intValue();
-    }
-
-    /**
-     * Returns the configured maximal size of the blobfs.
-     * @return the configured maximal size of the blobfs.
-     */
-    public String getBlobFSMaximumCacheSize() {
-        return String.valueOf(blobFSMaximumCache);
-    }
-
-    /**
-     * Sets the maximal cache size of the blob fs. This only applies to cqfs
-     * base blobstores, i.e. if {@link #useCqFsBlobStore()} returns
-     * <code>true</code>.
-     * @param size the maximal size
-     */
-    public void setBlobFSMaximumCacheSize(String size) {
-        this.blobFSMaximumCache = Integer.decode(size).intValue();
-    }
-
-
-    /**
      * Returns the configured block size of the item cqfs
      * @return the block size.
      */
@@ -294,24 +170,6 @@
     }
 
     /**
-     * Returns the miminum blob size.
-     * @return the miminum blob size.
-     */
-    public int getMinBlobSize() {
-        return minBlobSize;
-    }
-
-    /**
-     * Sets the minumum blob size. This size defines the threshhold of which
-     * size a property is included in the bundle or is stored in the blob store.
-     *
-     * @param minBlobSize
-     */
-    public void setMinBlobSize(String minBlobSize) {
-        this.minBlobSize = Integer.decode(minBlobSize).intValue();
-    }
-
-    /**
      * Sets the error handling behaviour of this manager. See {@link ErrorHandling}
      * for details about the flags.
      *
@@ -343,35 +201,10 @@
         // create item fs
         if (itemFSBlockSize == 0) {
             itemFs = new BasedFileSystem(context.getFileSystem(), "items");
-        } else {
-            /*
-            CQFileSystem cqfs = new CQFileSystem();
-            cqfs.setPath(new File(context.getHomeDir(), "items.dat").getCanonicalPath());
-            cqfs.setAutoRepair(false);
-            cqfs.setAutoSync(false);
-            cqfs.setBlockSize(itemFSBlockSize);
-            cqfs.setCacheInitialBlocks(itemFSInitialCache);
-            cqfs.setCacheMaximumBlocks(itemFSMaximumCache);
-            cqfs.init();
-            itemFs = cqfs;
-            */
         }
 
-        // create correct blob store
-        if (useLocalFsBlobStore()) {
-            LocalFileSystem blobFS = new LocalFileSystem();
-            blobFS.setRoot(new File(context.getHomeDir(), "blobs"));
-            blobFS.init();
-            blobStore = new BundleFsPersistenceManager.FSBlobStore(blobFS);
-        } else if (useItemBlobStore()) {
-            blobStore = new BundleFsPersistenceManager.FSBlobStore(itemFs);
-        } else /* useCqFsBlobStore() */ {
-//blobStore = createCQFSBlobStore(context);
-        }
-
         // load namespaces
-        binding = new BundleBinding(errorHandling, blobStore, getNsIndex(), getNameIndex());
-        binding.setMinBlobSize(minBlobSize);
+        binding = new BundleBinding(errorHandling, getNsIndex(), getNameIndex());
 
         initialized = true;
     }
@@ -385,9 +218,6 @@
         }
 
         try {
-            // close blob store
-            blobStore.close();
-            blobStore = null;
             itemFs.close();
             itemFs = null;
         } finally {
@@ -643,38 +473,4 @@
         return name;
     }
 
-    /**
-     * Helper interface for closeable stores
-     */
-    protected static interface CloseableBLOBStore extends BLOBStore {
-        void close();
-    }
-
-    /**
-     * own implementation of the filesystem blob store that uses a different
-     * blob-id scheme.
-     */
-    private class FSBlobStore extends FileSystemBLOBStore implements BundleFsPersistenceManager.CloseableBLOBStore {
-
-        private FileSystem fs;
-
-        public FSBlobStore(FileSystem fs) {
-            super(fs);
-            this.fs = fs;
-        }
-
-        public String createId(PropertyId id, int index) {
-            return buildBlobFilePath(null, id, index).toString();
-        }
-
-        public void close() {
-            try {
-                fs.close();
-                fs = null;
-            } catch (Exception e) {
-                // ignore
-            }
-        }
-    }
-
 }
\ No newline at end of file
Index: src/main/java/org/apache/jackrabbit/core/persistence/bundle/OraclePersistenceManager.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/persistence/bundle/OraclePersistenceManager.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/persistence/bundle/OraclePersistenceManager.java	(working copy)
@@ -46,14 +46,6 @@
     /** the cvs/svn id */
     static final String CVS_ID = "$URL$ $Rev$ $Date$";
 
-    /**
-     * Creates a new oracle persistence manager
-     */
-    public OraclePersistenceManager() {
-        // enable db blob support
-        setExternalBLOBs(false);
-    }
-
     public void init(PMContext context) throws Exception {
         // init default values
         if (getDriver() == null) {
Index: src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/NodePropBundle.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/NodePropBundle.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/NodePropBundle.java	(working copy)
@@ -29,7 +29,6 @@
 import org.apache.jackrabbit.core.PropertyId;
 import org.apache.jackrabbit.core.persistence.PersistenceManager;
 import org.apache.jackrabbit.core.value.InternalValue;
-import org.apache.jackrabbit.core.value.BLOBFileValue;
 import org.apache.jackrabbit.core.state.PropertyState;
 import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.nodetype.NodeDefId;
@@ -344,10 +343,7 @@
      * @param state the property state
      */
     public void addProperty(PropertyState state) {
-        PropertyEntry old = (PropertyEntry) properties.put(state.getName(), new PropertyEntry(state));
-        if (old != null) {
-            old.destroy();
-        }
+        properties.put(state.getName(), new PropertyEntry(state));
     }
 
     /**
@@ -405,10 +401,7 @@
      * @param name the name of the property
      */
     public void removeProperty(QName name) {
-        PropertyEntry pe = (PropertyEntry) properties.remove(name);
-        if (pe != null) {
-            pe.destroy();
-        }
+        properties.remove(name);
     }
 
     /**
@@ -676,22 +669,6 @@
             this.modCount = modCount;
         }
 
-        /**
-         * Destroys this property state and deletes temporary blob file values.
-         */
-        private void destroy() {
-            if (type == PropertyType.BINARY) {
-                // destroy binary property values
-                for (int i=0; i<values.length; i++) {
-                    if (values[i].internalValue() instanceof BLOBFileValue) {
-                        ((BLOBFileValue) values[i].internalValue()).delete(true);
-                    }
-                }
-            }
-        }
-
-
     }
 
-
 }
Index: src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/BundleBinding.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/BundleBinding.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/BundleBinding.java	(working copy)
@@ -18,12 +18,11 @@
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.apache.jackrabbit.core.persistence.util.BLOBStore;
-import org.apache.jackrabbit.core.persistence.util.ResourceBasedBLOBStore;
 import org.apache.jackrabbit.core.NodeId;
 import org.apache.jackrabbit.core.PropertyId;
 import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.core.value.BLOBFileValue;
+import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.core.nodetype.NodeDefId;
 import org.apache.jackrabbit.core.nodetype.PropDefId;
 import org.apache.jackrabbit.name.QName;
@@ -57,13 +56,12 @@
      * Creates a new bundle binding
      *
      * @param errorHandling the error handling
-     * @param blobStore the blobstore for retrieving blobs
      * @param nsIndex the namespace index
      * @param nameIndex the name index
      */
-    public BundleBinding(ErrorHandling errorHandling, BLOBStore blobStore,
+    public BundleBinding(ErrorHandling errorHandling,
                          StringIndex nsIndex, StringIndex nameIndex) {
-        super(errorHandling, blobStore, nsIndex, nameIndex);
+        super(errorHandling, nsIndex, nameIndex);
     }
 
     /**
@@ -318,33 +316,6 @@
         for (int i = 0; i < count; i++) {
             InternalValue val;
             switch (type) {
-                case PropertyType.BINARY:
-                    int size = in.readInt();
-                    if (size == -1) {
-                        blobIds[i] = in.readUTF();
-                        try {
-                            if (blobStore instanceof ResourceBasedBLOBStore) {
-                                val = InternalValue.create(((ResourceBasedBLOBStore) blobStore).getResource(blobIds[i]));
-                            } else {
-                                val = InternalValue.create(blobStore.get(blobIds[i]), false);
-                            }
-                        } catch (IOException e) {
-                            if (errorHandling.ignoreMissingBlobs()) {
-                                log.warn("Ignoring error while reading blob-resource: " + e);
-                                val = InternalValue.create(new byte[0]);
-                            } else {
-                                throw e;
-                            }
-                        } catch (Exception e) {
-                            throw new IOException("Unable to create property value: " + e.toString());
-                        }
-                    } else {
-                        // short values into memory
-                        byte[] data = new byte[size];
-                        in.readFully(data);
-                        val = InternalValue.create(data);
-                    }
-                    break;
                 case PropertyType.DOUBLE:
                     val = InternalValue.create(in.readDouble());
                     break;
@@ -546,92 +517,6 @@
         for (int i = 0; i < values.length; i++) {
             InternalValue val = values[i];
             switch (state.getType()) {
-                case PropertyType.BINARY:
-                    // special handling required for binary value:
-                    // spool binary value to file in blob store
-                    BLOBFileValue blobVal = (BLOBFileValue) val.internalValue();
-                    long size = blobVal.getLength();
-                    if (size < 0) {
-                        log.warn("Blob has negative size. Potential loss of data. " +
-                            "id={} idx={}", state.getId(), String.valueOf(i));
-                        out.writeInt(0);
-                        values[i] = InternalValue.create(new byte[0]);
-                        blobVal.discard();
-                    } else if (size > minBlobSize) {
-                        out.writeInt(-1);
-                        String blobId = state.getBlobId(i);
-                        if (blobId == null) {
-                            try {
-                                InputStream in = blobVal.getStream();
-                                try {
-                                    blobId = blobStore.createId(state.getId(), i);
-                                    blobStore.put(blobId, in, size);
-                                    state.setBlobId(blobId, i);
-                                } finally {
-                                    try {
-                                        in.close();
-                                    } catch (IOException e) {
-                                        // ignore
-                                    }
-                                }
-                            } catch (Exception e) {
-                                String msg = "Error while storing blob. id="
-                                        + state.getId() + " idx=" + i + " size=" + size;
-                                log.error(msg, e);
-                                throw new IOException(msg);
-                            }
-                            try {
-                                // replace value instance with value
-                                // backed by resource in blob store and delete temp file
-                                if (blobStore instanceof ResourceBasedBLOBStore) {
-                                    values[i] = InternalValue.create(((ResourceBasedBLOBStore) blobStore).getResource(blobId));
-                                } else {
-                                    values[i] = InternalValue.create(blobStore.get(blobId), false);
-                                }
-                            } catch (Exception e) {
-                                log.error("Error while reloading blob. truncating. id=" + state.getId() +
-                                        " idx=" + i + " size=" + size, e);
-                                values[i] = InternalValue.create(new byte[0]);
-                            }
-                            blobVal.discard();
-                        }
-                        // store id of blob as property value
-                        out.writeUTF(blobId);   // value
-                    } else {
-                        // delete evt. blob
-                        out.writeInt((int) size);
-                        byte[] data = new byte[(int) size];
-                        try {
-                            InputStream in = blobVal.getStream();
-                            try {
-                                int pos = 0;
-                                while (pos < size) {
-                                    int n = in.read(data, pos, (int) size-pos);
-                                    if (n < 0) {
-                                        throw new EOFException();
-                                    }
-                                    pos += n;
-                                }
-                            } finally {
-                                try {
-                                    in.close();
-                                } catch (IOException e) {
-                                    // ignore
-                                }
-                            }
-                        } catch (Exception e) {
-                            String msg = "Error while storing blob. id="
-                                    + state.getId() + " idx=" + i + " size=" + size;
-                            log.error(msg, e);
-                            throw new IOException(msg);
-                        }
-                        out.write(data, 0, data.length);
-                        // replace value instance with value
-                        // backed by resource in blob store and delete temp file
-                        values[i] = InternalValue.create(data);
-                        blobVal.discard();
-                    }
-                    break;
                 case PropertyType.DOUBLE:
                     out.writeDouble(((Double) val.internalValue()).doubleValue());
                     break;
Index: src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ItemStateBinding.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ItemStateBinding.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ItemStateBinding.java	(working copy)
@@ -16,10 +16,6 @@
  */
 package org.apache.jackrabbit.core.persistence.bundle.util;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.jackrabbit.core.persistence.util.BLOBStore;
-import org.apache.jackrabbit.core.persistence.util.ResourceBasedBLOBStore;
 import org.apache.jackrabbit.core.persistence.PersistenceManager;
 import org.apache.jackrabbit.core.state.NodeReferencesId;
 import org.apache.jackrabbit.core.state.NodeReferences;
@@ -28,7 +24,6 @@
 import org.apache.jackrabbit.core.PropertyId;
 import org.apache.jackrabbit.core.NodeId;
 import org.apache.jackrabbit.core.value.InternalValue;
-import org.apache.jackrabbit.core.value.BLOBFileValue;
 import org.apache.jackrabbit.core.nodetype.NodeDefId;
 import org.apache.jackrabbit.core.nodetype.PropDefId;
 import org.apache.jackrabbit.name.QName;
@@ -36,9 +31,7 @@
 
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
-import java.io.EOFException;
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -56,11 +49,6 @@
     static final String CVS_ID = "$URL$ $Rev$ $Date$";
 
     /**
-     * default logger
-     */
-    private static Logger log = LoggerFactory.getLogger(ItemStateBinding.class);
-
-    /**
      * serialization version 1
      */
     public final static int VERSION_1 = 1;
@@ -81,16 +69,6 @@
     protected final StringIndex nameIndex;
 
     /**
-     * the blob store
-     */
-    protected final BLOBStore blobStore;
-
-    /**
-     * minimum size of binaries to store in blob store
-     */
-    protected long minBlobSize = 0x4000; // 16k
-
-    /**
      * the error handling
      */
     protected final ErrorHandling errorHandling;
@@ -99,40 +77,17 @@
      * Creates a new item state binding
      *
      * @param errorHandling the error handing configuration
-     * @param blobStore the blobstore
      * @param nsIndex the namespace index
      * @param nameIndex the name index
      */
     public ItemStateBinding(ErrorHandling errorHandling,
-                            BLOBStore blobStore,
                             StringIndex nsIndex, StringIndex nameIndex) {
         this.errorHandling = errorHandling;
         this.nsIndex = nsIndex;
         this.nameIndex = nameIndex;
-        this.blobStore = blobStore;
     }
 
     /**
-     * Returns the minimum blob size
-     * @see #setMinBlobSize(long) for details.
-     * @return the minimum blob size
-     */
-    public long getMinBlobSize() {
-        return minBlobSize;
-    }
-
-    /**
-     * Sets the minimum blob size. Binary values that are shorted than this given
-     * size will be inlined in the serialization stream, binary value that are
-     * longer, will be stored in the blob store. default is 4k.
-     *
-     * @param minBlobSize the minimum blob size.
-     */
-    public void setMinBlobSize(long minBlobSize) {
-        this.minBlobSize = minBlobSize;
-    }
-
-    /**
      * Deserializes a <code>NodeReferences</code> from the data input stream.
      *
      * @param in the input stream
@@ -146,7 +101,7 @@
             throws IOException {
         NodeReferences state = new NodeReferences(id);
         int count = in.readInt();   // count & version
-        int version = (count >> 24) | 0x0ff;
+        // int version = (count >> 24) | 0x0ff;
         count &= 0x00ffffff;
         for (int i = 0; i < count; i++) {
             state.addReference(readPropertyId(in));    // propertyId
@@ -293,34 +248,6 @@
         for (int i = 0; i < count; i++) {
             InternalValue val;
             switch (type) {
-                case PropertyType.BINARY:
-                    int size = in.readInt();
-                    if (size == -1) {
-                        String s = in.readUTF();
-                        try {
-                            if (blobStore instanceof ResourceBasedBLOBStore) {
-                                val = InternalValue.create(
-                                        ((ResourceBasedBLOBStore) blobStore).getResource(s));
-                            } else {
-                                val = InternalValue.create(blobStore.get(s), false);
-                            }
-                        } catch (IOException e) {
-                            if (errorHandling.ignoreMissingBlobs()) {
-                                log.warn("Ignoring error while reading blob-resource: " + e);
-                                val = InternalValue.create(new byte[0]);
-                            } else {
-                                throw e;
-                            }
-                        } catch (Exception e) {
-                            throw new IOException("Unable to create property value: " + e.toString());
-                        }
-                    } else {
-                        // short values into memory
-                        byte[] data = new byte[size];
-                        in.readFully(data);
-                        val = InternalValue.create(data);
-                    }
-                    break;
                 case PropertyType.DOUBLE:
                     val = InternalValue.create(in.readDouble());
                     break;
@@ -341,10 +268,7 @@
                     // Strings are serialized as <length><byte[]>
                     int len = in.readInt();
                     byte[] bytes = new byte[len];
-                    int pos=0;
-                    while (pos < len) {
-                        pos+= in.read(bytes, pos, len-pos);
-                    }
+                    in.readFully(bytes);
                     val = InternalValue.valueOf(new String(bytes, "UTF-8"), type);
             }
             values[i] = val;
@@ -373,68 +297,6 @@
         for (int i = 0; i < values.length; i++) {
             InternalValue val = values[i];
             switch (state.getType()) {
-                case PropertyType.BINARY:
-                    try {
-                        // special handling required for binary value:
-                        // spool binary value to file in blob store
-                        BLOBFileValue blobVal = (BLOBFileValue) val.internalValue();
-                        long size = blobVal.getLength();
-                        if (size > minBlobSize) {
-                            out.writeInt(-1);
-                            InputStream in = blobVal.getStream();
-                            String blobId = blobStore.createId((PropertyId) state.getId(), i);
-                            try {
-                                blobStore.put(blobId, in, size);
-                            } finally {
-                                try {
-                                    in.close();
-                                } catch (IOException e) {
-                                    // ignore
-                                }
-                            }
-                            // store id of blob as property value
-                            out.writeUTF(blobId);   // value
-                            // replace value instance with value
-                            // backed by resource in blob store and delete temp file
-                            if (blobStore instanceof ResourceBasedBLOBStore) {
-                                values[i] = InternalValue.create(((ResourceBasedBLOBStore) blobStore).getResource(blobId));
-                            } else {
-                                values[i] = InternalValue.create(blobStore.get(blobId), false);
-                            }
-                            blobVal.discard();
-                        } else {
-                            // delete evt. blob
-                            out.writeInt((int) size);
-                            byte[] data = new byte[(int) size];
-                            InputStream in = blobVal.getStream();
-                            try {
-                                int pos = 0;
-                                while (pos < size) {
-                                    int n = in.read(data, pos, (int) size-pos);
-                                    if (n < 0) {
-                                        throw new EOFException();
-                                    }
-                                    pos += n;
-                                }
-                            } finally {
-                                try {
-                                    in.close();
-                                } catch (IOException e) {
-                                    // ignore
-                                }
-                            }
-                            out.write(data, 0, data.length);
-                            // replace value instance with value
-                            // backed by resource in blob store and delete temp file
-                            values[i] = InternalValue.create(data);
-                            blobVal.discard();
-                        }
-                    } catch (IOException e) {
-                        throw e;
-                    } catch (Exception e) {
-                        throw new IOException("Error converting: " + e.toString());
-                    }
-                    break;
                 case PropertyType.DOUBLE:
                     out.writeDouble(((Double) val.internalValue()).doubleValue());
                     break;
Index: src/main/java/org/apache/jackrabbit/core/persistence/bundle/Oracle9PersistenceManager.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/persistence/bundle/Oracle9PersistenceManager.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/persistence/bundle/Oracle9PersistenceManager.java	(working copy)
@@ -34,8 +34,6 @@
 import java.sql.Blob;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
 
 /**
  * <code>OracleLegacyPersistenceManager</code> provides support for Oracle jdbc
@@ -102,13 +100,6 @@
     /**
      * @inheritDoc
      */
-    protected BundleDbPersistenceManager.CloseableBLOBStore createDBBlobStore(PMContext context) throws Exception {
-        return new OracleBLOBStore();
-    }
-
-    /**
-     * @inheritDoc
-     */
     protected synchronized void storeBundle(NodePropBundle bundle)
             throws ItemStateException {
         PreparedStatement stmt = null;
@@ -242,43 +233,4 @@
         freeTemporary.invoke(blob, null);
     }
 
-    //--------------------------------------------------------< inner classes >
-    class OracleBLOBStore extends DbBlobStore {
-
-        public OracleBLOBStore() throws SQLException {
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public synchronized void put(String blobId, InputStream in, long size)
-                throws Exception {
-            PreparedStatement stmt = blobSelectExist;
-            Blob blob = null;
-            try {
-                stmt.setString(1, blobId);
-                stmt.execute();
-                ResultSet rs = stmt.getResultSet();
-                // a BLOB exists if the result has at least one entry
-                boolean exists = rs.next();
-                resetStatement(stmt);
-                closeResultSet(rs);
-
-                stmt = (exists) ? blobUpdate : blobInsert;
-
-                blob = createTemporaryBlob(in);
-                stmt.setBlob(1, blob);
-                stmt.setString(2, blobId);
-                stmt.executeUpdate();
-            } finally {
-                resetStatement(stmt);
-                if (blob != null) {
-                    try {
-                        freeTemporaryBlob(blob);
-                    } catch (Exception e1) {
-                    }
-                }
-            }
-        }
-    }
 }
Index: src/main/java/org/apache/jackrabbit/core/persistence/obj/ObjectPersistenceManager.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/persistence/obj/ObjectPersistenceManager.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/persistence/obj/ObjectPersistenceManager.java	(working copy)
@@ -22,11 +22,8 @@
 import org.apache.jackrabbit.core.fs.FileSystem;
 import org.apache.jackrabbit.core.fs.FileSystemException;
 import org.apache.jackrabbit.core.fs.FileSystemResource;
-import org.apache.jackrabbit.core.fs.local.LocalFileSystem;
 import org.apache.jackrabbit.core.persistence.AbstractPersistenceManager;
 import org.apache.jackrabbit.core.persistence.PMContext;
-import org.apache.jackrabbit.core.persistence.util.BLOBStore;
-import org.apache.jackrabbit.core.persistence.util.FileSystemBLOBStore;
 import org.apache.jackrabbit.core.persistence.util.Serializer;
 import org.apache.jackrabbit.core.state.ItemStateException;
 import org.apache.jackrabbit.core.state.NoSuchItemStateException;
@@ -34,15 +31,11 @@
 import org.apache.jackrabbit.core.state.NodeReferencesId;
 import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.state.PropertyState;
-import org.apache.jackrabbit.core.value.BLOBFileValue;
-import org.apache.jackrabbit.core.value.InternalValue;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.jcr.PropertyType;
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
-import java.io.File;
 import java.io.OutputStream;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
@@ -70,10 +63,6 @@
 
     // file system where the item state is stored
     private FileSystem itemStateFS;
-    // file system where BLOB data is stored
-    private FileSystem blobFS;
-    // BLOBStore that manages BLOB data in the file system
-    private BLOBStore blobStore;
 
     /**
      * Creates a new <code>ObjectPersistenceManager</code> instance.
@@ -142,16 +131,6 @@
         FileSystem wspFS = context.getFileSystem();
         itemStateFS = new BasedFileSystem(wspFS, "/data");
 
-        /**
-         * store BLOB data in local file system in a sub directory
-         * of the workspace home directory
-         */
-        LocalFileSystem blobFS = new LocalFileSystem();
-        blobFS.setRoot(new File(context.getHomeDir(), "blobs"));
-        blobFS.init();
-        this.blobFS = blobFS;
-        blobStore = new FileSystemBLOBStore(blobFS);
-
         initialized = true;
     }
 
@@ -163,19 +142,12 @@
             throw new IllegalStateException("not initialized");
         }
 
-        try {
-            // close BLOB file system
-            blobFS.close();
-            blobFS = null;
-            blobStore = null;
-            /**
-             * there's no need close the item state store because it
-             * is based in the workspace's file system which is
-             * closed by the repository
-             */
-        } finally {
-            initialized = false;
-        }
+        /**
+         * there's no need close the item state store because it
+         * is based in the workspace's file system which is
+         * closed by the repository
+         */
+        initialized = false;
     }
 
     /**
@@ -246,7 +218,7 @@
                     new BufferedInputStream(itemStateFS.getInputStream(propFilePath));
             try {
                 PropertyState state = createNew(id);
-                Serializer.deserialize(state, in, blobStore);
+                Serializer.deserialize(state, in);
                 return state;
             } finally {
                 in.close();
@@ -338,7 +310,7 @@
             BufferedOutputStream out = new BufferedOutputStream(propFile.getOutputStream());
             try {
                 // serialize property state
-                Serializer.serialize(state, out, blobStore);
+                Serializer.serialize(state, out);
             } finally {
                 out.close();
             }
@@ -404,20 +376,6 @@
             throw new IllegalStateException("not initialized");
         }
 
-        // delete binary values (stored as files)
-        InternalValue[] values = state.getValues();
-        if (values != null) {
-            for (int i = 0; i < values.length; i++) {
-                InternalValue val = values[i];
-                if (val != null) {
-                    if (val.getType() == PropertyType.BINARY) {
-                        BLOBFileValue blobVal = (BLOBFileValue) val.internalValue();
-                        // delete blob file and prune empty parent folders
-                        blobVal.delete(true);
-                    }
-                }
-            }
-        }
         // delete property file
         String propFilePath = buildPropFilePath(state.getPropertyId());
         FileSystemResource propFile = new FileSystemResource(itemStateFS, propFilePath);
Index: src/main/java/org/apache/jackrabbit/core/persistence/util/FileSystemBLOBStore.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/persistence/util/FileSystemBLOBStore.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/persistence/util/FileSystemBLOBStore.java	(working copy)
@@ -1,129 +0,0 @@
-/*
- * 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.core.persistence.util;
-
-import org.apache.jackrabbit.core.PropertyId;
-import org.apache.jackrabbit.core.fs.FileSystem;
-import org.apache.jackrabbit.core.fs.FileSystemPathUtil;
-import org.apache.jackrabbit.core.fs.FileSystemResource;
-
-import java.io.BufferedOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * <code>FileSystemBLOBStore</code> is a <code>ResourceBasedBLOBStore</code>
- * implementation that stores BLOB data in a <code>FileSystem</code>.
- */
-public class FileSystemBLOBStore implements ResourceBasedBLOBStore {
-
-    /**
-     * the file system where the BLOBs are stored
-     */
-    private final FileSystem fs;
-
-    /**
-     * Creates a new <code>FileSystemBLOBStore</code> instance.
-     *
-     * @param fs file system for storing the BLOB data
-     */
-    public FileSystemBLOBStore(FileSystem fs) {
-        this.fs = fs;
-    }
-
-    //------------------------------------------------------------< BLOBStore >
-    /**
-     * {@inheritDoc}
-     */
-    public String createId(PropertyId id, int index) {
-        // the blobId is an absolute file system path
-        StringBuffer sb = new StringBuffer();
-        sb.append(FileSystem.SEPARATOR_CHAR);
-        char[] chars = id.getParentId().getUUID().toString().toCharArray();
-        int cnt = 0;
-        for (int i = 0; i < chars.length; i++) {
-            if (chars[i] == '-') {
-                continue;
-            }
-            //if (cnt > 0 && cnt % 4 == 0) {
-            if (cnt == 2 || cnt == 4) {
-                sb.append(FileSystem.SEPARATOR_CHAR);
-            }
-            sb.append(chars[i]);
-            cnt++;
-        }
-        sb.append(FileSystem.SEPARATOR_CHAR);
-        sb.append(FileSystemPathUtil.escapeName(id.getName().toString()));
-        sb.append('.');
-        sb.append(index);
-        sb.append(".bin");
-        return sb.toString();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public InputStream get(String blobId) throws Exception {
-        return getResource(blobId).getInputStream();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void put(String blobId, InputStream in, long size) throws Exception {
-        OutputStream out = null;
-        // the blobId is an absolute file system path
-        FileSystemResource internalBlobFile = new FileSystemResource(fs, blobId);
-        internalBlobFile.makeParentDirs();
-        try {
-            out = new BufferedOutputStream(internalBlobFile.getOutputStream());
-            byte[] buffer = new byte[8192];
-            int read;
-            while ((read = in.read(buffer)) > 0) {
-                out.write(buffer, 0, read);
-            }
-        } finally {
-            if (out != null) {
-                out.close();
-            }
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean remove(String blobId) throws Exception {
-        // the blobId is an absolute file system path
-        FileSystemResource res = new FileSystemResource(fs, blobId);
-        if (!res.exists()) {
-            return false;
-        }
-        // delete resource and prune empty parent folders
-        res.delete(true);
-        return true;
-    }
-
-    //-----------------------------------------------< ResourceBasedBLOBStore >
-    /**
-     * {@inheritDoc}
-     */
-    public FileSystemResource getResource(String blobId)
-            throws Exception {
-        // the blobId is an absolute file system path
-        return new FileSystemResource(fs, blobId);
-    }
-}
Index: src/main/java/org/apache/jackrabbit/core/persistence/util/ResourceBasedBLOBStore.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/persistence/util/ResourceBasedBLOBStore.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/persistence/util/ResourceBasedBLOBStore.java	(working copy)
@@ -1,36 +0,0 @@
-/*
- * 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.core.persistence.util;
-
-import org.apache.jackrabbit.core.PropertyId;
-import org.apache.jackrabbit.core.fs.FileSystemResource;
-
-/**
- * <code>ResourceBasedBLOBStore</code> extends the <code>BLOBStore</code>
- * interface with the method {@link #getResource(String)}
- */
-public interface ResourceBasedBLOBStore extends BLOBStore {
-    /**
-     * Retrieves the BLOB data with the specified id as a permanent resource.
-     *
-     * @param blobId identifier of the BLOB data as returned by
-     *               {@link #createId(PropertyId, int)}
-     * @return a resource representing the BLOB data
-     * @throws Exception if an error occured
-     */
-    FileSystemResource getResource(String blobId) throws Exception;
-}
Index: src/main/java/org/apache/jackrabbit/core/persistence/util/Serializer.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/persistence/util/Serializer.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/persistence/util/Serializer.java	(working copy)
@@ -18,7 +18,6 @@
 
 import org.apache.jackrabbit.core.NodeId;
 import org.apache.jackrabbit.core.PropertyId;
-import org.apache.jackrabbit.core.fs.FileSystemResource;
 import org.apache.jackrabbit.core.nodetype.NodeDefId;
 import org.apache.jackrabbit.core.nodetype.PropDefId;
 import org.apache.jackrabbit.core.state.NodeReferences;
@@ -30,10 +29,14 @@
 import org.apache.jackrabbit.uuid.UUID;
 
 import javax.jcr.PropertyType;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
-import java.io.IOException;
 import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
 import java.io.OutputStream;
 import java.util.Arrays;
 import java.util.Collection;
@@ -167,13 +170,10 @@
      * @param state     <code>state</code> to serialize
      * @param stream    the stream where the <code>state</code> should be
      *                  serialized to
-     * @param blobStore handler for BLOB data
      * @throws Exception if an error occurs during the serialization
-     * @see #deserialize(PropertyState, InputStream,BLOBStore)
+     * @see #deserialize(PropertyState, InputStream)
      */
-    public static void serialize(PropertyState state,
-                                 OutputStream stream,
-                                 BLOBStore blobStore)
+    public static void serialize(PropertyState state, OutputStream stream)
             throws Exception {
         DataOutputStream out = new DataOutputStream(stream);
 
@@ -189,56 +189,11 @@
         InternalValue[] values = state.getValues();
         out.writeInt(values.length); // count
         for (int i = 0; i < values.length; i++) {
-            InternalValue val = values[i];
-            if (state.getType() == PropertyType.BINARY) {
-                // special handling required for binary value:
-                // put binary value in BLOB store
-                BLOBFileValue blobVal = (BLOBFileValue) val.internalValue();
-                InputStream in = blobVal.getStream();
-                String blobId = blobStore.createId(state.getPropertyId(), i);
-                try {
-                    blobStore.put(blobId, in, blobVal.getLength());
-                } finally {
-                    try {
-                        in.close();
-                    } catch (IOException e) {
-                        // ignore
-                    }
-                }
-                // store id of BLOB as property value
-                out.writeUTF(blobId);   // value
-                // replace value instance with value backed by resource
-                // in BLOB store and discard old value instance (e.g. temp file)
-                if (blobStore instanceof ResourceBasedBLOBStore) {
-                    // optimization: if the BLOB store is resource-based
-                    // retrieve the resource directly rather than having
-                    // to read the BLOB from an input stream
-                    FileSystemResource fsRes =
-                            ((ResourceBasedBLOBStore) blobStore).getResource(blobId);
-                    values[i] = InternalValue.create(fsRes);
-                } else {
-                    in = blobStore.get(blobId);
-                    try {
-                        values[i] = InternalValue.create(in, false);
-                    } finally {
-                        try {
-                            in.close();
-                        } catch (IOException e) {
-                            // ignore
-                        }
-                    }
-                }
-                blobVal.discard();
-            } else {
-                /**
-                 * because writeUTF(String) has a size limit of 65k,
-                 * Strings are serialized as <length><byte[]>
-                 */
-                //out.writeUTF(val.toString());   // value
-                byte[] bytes = val.toString().getBytes(ENCODING);
-                out.writeInt(bytes.length); // lenght of byte[]
-                out.write(bytes);   // byte[]
-            }
+            // because writeUTF(String) has a size limit of 65k,
+            // Strings are serialized as <length><byte[]>
+            byte[] bytes = values[i].toString().getBytes(ENCODING);
+            out.writeInt(bytes.length); // length of byte[]
+            out.write(bytes);           // byte[]
         }
     }
 
@@ -250,13 +205,10 @@
      * @param state     <code>state</code> to deserialize
      * @param stream    the stream where the <code>state</code> should be
      *                  deserialized from
-     * @param blobStore handler for BLOB data
      * @throws Exception if an error occurs during the deserialization
-     * @see #serialize(PropertyState, OutputStream, BLOBStore)
+     * @see #serialize(PropertyState, OutputStream)
      */
-    public static void deserialize(PropertyState state,
-                                   InputStream stream,
-                                   BLOBStore blobStore)
+    public static void deserialize(PropertyState state, InputStream stream)
             throws Exception {
         DataInputStream in = new DataInputStream(stream);
 
@@ -276,44 +228,13 @@
         int count = in.readInt();   // count
         InternalValue[] values = new InternalValue[count];
         for (int i = 0; i < count; i++) {
-            InternalValue val;
-            if (type == PropertyType.BINARY) {
-                s = in.readUTF();   // value (i.e. blobId)
-                // special handling required for binary value:
-                // the value stores the id of the BLOB data
-                // in the BLOB store
-                if (blobStore instanceof ResourceBasedBLOBStore) {
-                    // optimization: if the BLOB store is resource-based
-                    // retrieve the resource directly rather than having
-                    // to read the BLOB from an input stream
-                    FileSystemResource fsRes =
-                            ((ResourceBasedBLOBStore) blobStore).getResource(s);
-                    val = InternalValue.create(fsRes);
-                } else {
-                    InputStream is = blobStore.get(s);
-                    try {
-                        val = InternalValue.create(is, false);
-                    } finally {
-                        try {
-                            is.close();
-                        } catch (IOException e) {
-                            // ignore
-                        }
-                    }
-                }
-            } else {
-                /**
-                 * because writeUTF(String) has a size limit of 65k,
-                 * Strings are serialized as <length><byte[]>
-                 */
-                //s = in.readUTF();   // value
-                int len = in.readInt(); // lenght of byte[]
-                byte[] bytes = new byte[len];
-                in.readFully(bytes); // byte[]
-                s = new String(bytes, ENCODING);
-                val = InternalValue.valueOf(s, type);
-            }
-            values[i] = val;
+            // because writeUTF(String) has a size limit of 65k,
+            // Strings are serialized as <length><byte[]>
+            int len = in.readInt(); // length of byte[]
+            byte[] bytes = new byte[len];
+            in.readFully(bytes); // byte[]
+            values[i] =
+                InternalValue.valueOf(new String(bytes, ENCODING), type);
         }
         state.setValues(values);
     }
Index: src/main/java/org/apache/jackrabbit/core/persistence/util/BLOBStore.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/persistence/util/BLOBStore.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/persistence/util/BLOBStore.java	(working copy)
@@ -1,72 +0,0 @@
-/*
- * 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.core.persistence.util;
-
-import org.apache.jackrabbit.core.PropertyId;
-
-import java.io.InputStream;
-
-/**
- * <code>BLOBStore</code> represents an abstract store for binary property
- * values (BLOBs).
- *
- * @see ResourceBasedBLOBStore
- */
-public interface BLOBStore {
-    /**
-     * Creates a unique identifier for the BLOB data associated with the given
-     * property id and value subscript.
-     *
-     * @param id    id of the property associated with the BLOB data
-     * @param index subscript of the value holding the BLOB data
-     * @return a string identifying the BLOB data
-     */
-    String createId(PropertyId id, int index);
-
-    /**
-     * Stores the BLOB data and returns a unique identifier.
-     *
-     * @param blobId identifier of the BLOB data as returned by
-     *               {@link #createId(PropertyId, int)}
-     * @param in     stream containing the BLOB data
-     * @param size   size of the BLOB data
-     * @throws Exception if an error occured
-     */
-    void put(String blobId, InputStream in, long size) throws Exception;
-
-    /**
-     * Retrieves the BLOB data with the specified id as a binary stream.
-     *
-     * @param blobId identifier of the BLOB data as returned by
-     *               {@link #createId(PropertyId, int)}
-     * @return an input stream that delivers the BLOB data
-     * @throws Exception if an error occured
-     */
-    InputStream get(String blobId) throws Exception;
-
-    /**
-     * Removes the BLOB data with the specified id.
-     *
-     * @param blobId identifier of the BLOB data as returned by
-     *               {@link #createId(PropertyId, int)}
-     * @return <code>true</code> if BLOB data with the given id exists and has
-     *         been successfully removed, <code>false</code> if there's no BLOB
-     *         data with the given id.
-     * @throws Exception if an error occured
-     */
-    boolean remove(String blobId) throws Exception;
-}
Index: src/main/java/org/apache/jackrabbit/core/persistence/mem/InMemPersistenceManager.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/persistence/mem/InMemPersistenceManager.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/persistence/mem/InMemPersistenceManager.java	(working copy)
@@ -22,32 +22,25 @@
 import org.apache.jackrabbit.core.fs.FileSystem;
 import org.apache.jackrabbit.core.fs.FileSystemPathUtil;
 import org.apache.jackrabbit.core.fs.FileSystemResource;
-import org.apache.jackrabbit.core.fs.local.LocalFileSystem;
 import org.apache.jackrabbit.core.persistence.AbstractPersistenceManager;
 import org.apache.jackrabbit.core.persistence.PMContext;
-import org.apache.jackrabbit.core.persistence.util.BLOBStore;
 import org.apache.jackrabbit.core.state.ItemStateException;
 import org.apache.jackrabbit.core.state.NoSuchItemStateException;
 import org.apache.jackrabbit.core.state.NodeReferences;
 import org.apache.jackrabbit.core.state.NodeReferencesId;
 import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.state.PropertyState;
-import org.apache.jackrabbit.core.persistence.util.FileSystemBLOBStore;
 import org.apache.jackrabbit.core.persistence.util.Serializer;
-import org.apache.jackrabbit.core.value.BLOBFileValue;
-import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.name.QName;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.jcr.PropertyType;
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
-import java.io.File;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
@@ -86,11 +79,6 @@
     protected static final byte NODE_ENTRY = 0;
     protected static final byte PROP_ENTRY = 1;
 
-    // file system where BLOB data is stored
-    protected FileSystem blobFS;
-    // BLOBStore that manages BLOB data in the file system
-    protected BLOBStore blobStore;
-
     /**
      * file system where the content of the hash maps are read from/written to
      * (if <code>persistent==true</code>)
@@ -298,16 +286,6 @@
 
         wspFS = context.getFileSystem();
 
-        /**
-         * store BLOB data in local file system in a sub directory
-         * of the workspace home directory
-         */
-        LocalFileSystem blobFS = new LocalFileSystem();
-        blobFS.setRoot(new File(context.getHomeDir(), "blobs"));
-        blobFS.init();
-        this.blobFS = blobFS;
-        blobStore = new FileSystemBLOBStore(blobFS);
-
         if (persistent) {
             // deserialize contents of state and refs stores
             loadContents();
@@ -328,27 +306,8 @@
             if (persistent) {
                 // serialize contents of state and refs stores
                 storeContents();
-            } else {
-                // clear out blob store
-                try {
-                    String[] folders = blobFS.listFolders("/");
-                    for (int i = 0; i < folders.length; i++) {
-                        blobFS.deleteFolder(folders[i]);
-                    }
-                    String[] files = blobFS.listFiles("/");
-                    for (int i = 0; i < files.length; i++) {
-                        blobFS.deleteFile(files[i]);
-                    }
-                } catch (Exception e) {
-                    // ignore
-                }
             }
 
-            // close BLOB file system
-            blobFS.close();
-            blobFS = null;
-            blobStore = null;
-
             stateStore.clear();
             stateStore = null;
             refsStore.clear();
@@ -403,7 +362,7 @@
         ByteArrayInputStream in = new ByteArrayInputStream(data);
         try {
             PropertyState state = createNew(id);
-            Serializer.deserialize(state, in, blobStore);
+            Serializer.deserialize(state, in);
             return state;
         } catch (Exception e) {
             String msg = "failed to read property state: " + id;
@@ -449,7 +408,7 @@
             ByteArrayOutputStream out =
                     new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
             // serialize property state
-            Serializer.serialize(state, out, blobStore);
+            Serializer.serialize(state, out);
 
             // store in serialized format in map for better memory efficiency
             stateStore.put(state.getPropertyId(), out.toByteArray());
@@ -482,21 +441,6 @@
             throw new IllegalStateException("not initialized");
         }
 
-        // delete binary values (stored as files)
-        InternalValue[] values = state.getValues();
-        if (values != null) {
-            for (int i = 0; i < values.length; i++) {
-                InternalValue val = values[i];
-                if (val != null) {
-                    if (val.getType() == PropertyType.BINARY) {
-                        BLOBFileValue blobVal = (BLOBFileValue) val.internalValue();
-                        // delete blob file and prune empty parent folders
-                        blobVal.delete(true);
-                    }
-                }
-            }
-        }
-
         // remove property state
         stateStore.remove(state.getPropertyId());
     }
Index: src/main/java/org/apache/jackrabbit/core/SessionImpl.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/SessionImpl.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/SessionImpl.java	(working copy)
@@ -74,7 +74,6 @@
 import javax.jcr.nodetype.ConstraintViolationException;
 import javax.jcr.nodetype.NoSuchNodeTypeException;
 import javax.jcr.observation.EventListener;
-import javax.jcr.observation.EventListenerIterator;
 import javax.jcr.observation.ObservationManager;
 import javax.jcr.version.VersionException;
 import javax.security.auth.Subject;
@@ -248,7 +247,9 @@
         }
         this.subject = subject;
         nsMappings = new LocalNamespaceMappings(rep.getNamespaceRegistry());
-        ntMgr = new NodeTypeManagerImpl(rep.getNodeTypeRegistry(), rep.getNamespaceRegistry(), getNamespaceResolver());
+        ntMgr = new NodeTypeManagerImpl(
+                rep.getNodeTypeRegistry(), rep.getNamespaceRegistry(),
+                getNamespaceResolver(), rep.getDataStore());
         String wspName = wspConfig.getName();
         wsp = createWorkspaceInstance(wspConfig,
                 rep.getWorkspaceStateManager(wspName), rep, this);
Index: src/main/java/org/apache/jackrabbit/core/PropertyImpl.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/PropertyImpl.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/PropertyImpl.java	(working copy)
@@ -268,19 +268,6 @@
         // modify the state of this property
         PropertyState thisState = (PropertyState) getOrCreateTransientItemState();
 
-        // free old values as necessary
-        InternalValue[] oldValues = thisState.getValues();
-        if (oldValues != null) {
-            for (int i = 0; i < oldValues.length; i++) {
-                InternalValue old = oldValues[i];
-                if (old != null && old.getType() == PropertyType.BINARY) {
-                    // make sure temporarily allocated data is discarded
-                    // before overwriting it
-                    ((BLOBFileValue) old.internalValue()).discard();
-                }
-            }
-        }
-
         // set new values
         thisState.setValues(values);
         // set type
@@ -331,7 +318,8 @@
                     InternalValue.create(name).toJCRValue(session.getNamespaceResolver()),
                     reqType,
                     ValueFactoryImpl.getInstance());
-            internalValue = InternalValue.create(targetValue, session.getNamespaceResolver());
+            internalValue = InternalValue.create(
+                    targetValue, rep.getDataStore(), session.getNamespaceResolver());
         } else {
             // no type conversion required
             internalValue = InternalValue.create(name);
@@ -382,7 +370,8 @@
                                 InternalValue.create(name).toJCRValue(session.getNamespaceResolver()),
                                 reqType,
                                 ValueFactoryImpl.getInstance());
-                        internalValue = InternalValue.create(targetValue, session.getNamespaceResolver());
+                        internalValue = InternalValue.create(
+                                targetValue, rep.getDataStore(), session.getNamespaceResolver());
                     } else {
                         // no type conversion required
                         internalValue = InternalValue.create(name);
@@ -673,7 +662,8 @@
             Value targetVal = ValueHelper.convert(
                     new DateValue(date), reqType,
                     ValueFactoryImpl.getInstance());
-            value = InternalValue.create(targetVal, session.getNamespaceResolver());
+            value = InternalValue.create(
+                    targetVal, rep.getDataStore(), session.getNamespaceResolver());
         } else {
             // no type conversion required
             value = InternalValue.create(date);
@@ -707,7 +697,8 @@
             Value targetVal = ValueHelper.convert(
                     new DoubleValue(number), reqType,
                     ValueFactoryImpl.getInstance());
-            value = InternalValue.create(targetVal, session.getNamespaceResolver());
+            value = InternalValue.create(
+                    targetVal, rep.getDataStore(), session.getNamespaceResolver());
         } else {
             // no type conversion required
             value = InternalValue.create(number);
@@ -742,15 +733,14 @@
 
         InternalValue value;
         try {
+            value = InternalValue.create(rep.getDataStore(), stream);
             if (reqType != PropertyType.BINARY) {
                 // type conversion required
                 Value targetVal = ValueHelper.convert(
-                        new BLOBFileValue(stream), reqType,
-                        ValueFactoryImpl.getInstance());
-                value = InternalValue.create(targetVal, session.getNamespaceResolver());
-            } else {
-                // no type conversion required
-                value = InternalValue.create(stream);
+                        value.toJCRValue(session.getNamespaceResolver()),
+                        reqType, ValueFactoryImpl.getInstance());
+                value = InternalValue.create(
+                        targetVal, rep.getDataStore(), session.getNamespaceResolver());
             }
         } catch (IOException ioe) {
             String msg = "failed to spool stream to internal storage";
@@ -791,7 +781,8 @@
             Value targetValue = ValueHelper.convert(
                     string, reqType,
                     ValueFactoryImpl.getInstance());
-            internalValue = InternalValue.create(targetValue, session.getNamespaceResolver());
+            internalValue = InternalValue.create(
+                    targetValue, rep.getDataStore(), session.getNamespaceResolver());
         } else {
             // no type conversion required
             internalValue = InternalValue.create(string);
@@ -831,7 +822,8 @@
                         Value targetValue = ValueHelper.convert(
                                 string, reqType,
                                 ValueFactoryImpl.getInstance());
-                        internalValue = InternalValue.create(targetValue, session.getNamespaceResolver());
+                        internalValue = InternalValue.create(
+                                targetValue, rep.getDataStore(), session.getNamespaceResolver());
                     } else {
                         // no type conversion required
                         internalValue = InternalValue.create(string);
@@ -869,7 +861,7 @@
             Value targetVal = ValueHelper.convert(
                     new BooleanValue(b), reqType,
                     ValueFactoryImpl.getInstance());
-            value = InternalValue.create(targetVal, session.getNamespaceResolver());
+            value = InternalValue.create(targetVal, rep.getDataStore(), session.getNamespaceResolver());
         } else {
             // no type conversion required
             value = InternalValue.create(b);
@@ -945,7 +937,7 @@
             Value targetVal = ValueHelper.convert(
                     new LongValue(number), reqType,
                     ValueFactoryImpl.getInstance());
-            value = InternalValue.create(targetVal, session.getNamespaceResolver());
+            value = InternalValue.create(targetVal, rep.getDataStore(), session.getNamespaceResolver());
         } else {
             // no type conversion required
             value = InternalValue.create(number);
@@ -988,10 +980,10 @@
             Value targetVal = ValueHelper.convert(
                     value, reqType,
                     ValueFactoryImpl.getInstance());
-            internalValue = InternalValue.create(targetVal, session.getNamespaceResolver());
+            internalValue = InternalValue.create(targetVal, rep.getDataStore(), session.getNamespaceResolver());
         } else {
             // no type conversion required
-            internalValue = InternalValue.create(value, session.getNamespaceResolver());
+            internalValue = InternalValue.create(value, rep.getDataStore(), session.getNamespaceResolver());
         }
         internalSetValue(new InternalValue[]{internalValue}, reqType);
     }
@@ -1048,10 +1040,10 @@
                         Value targetVal = ValueHelper.convert(
                                 value, reqType,
                                 ValueFactoryImpl.getInstance());
-                        internalValue = InternalValue.create(targetVal, session.getNamespaceResolver());
+                        internalValue = InternalValue.create(targetVal, rep.getDataStore(), session.getNamespaceResolver());
                     } else {
                         // no type conversion required
-                        internalValue = InternalValue.create(value, session.getNamespaceResolver());
+                        internalValue = InternalValue.create(value, rep.getDataStore(), session.getNamespaceResolver());
                     }
                 }
                 internalValues[i] = internalValue;
Index: src/main/java/org/apache/jackrabbit/core/NodeImpl.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/NodeImpl.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/NodeImpl.java	(working copy)
@@ -4026,11 +4026,13 @@
             Value[] values = prop.getValues();
             InternalValue[] ivalues = new InternalValue[values.length];
             for (int i = 0; i < values.length; i++) {
-                ivalues[i] = InternalValue.create(values[i], session.getNamespaceResolver());
+                ivalues[i] = InternalValue.create(
+                        values[i], rep.getDataStore(), session.getNamespaceResolver());
             }
             internalSetProperty(prop.getQName(), ivalues);
         } else {
-            InternalValue value = InternalValue.create(prop.getValue(), session.getNamespaceResolver());
+            InternalValue value = InternalValue.create(
+                    prop.getValue(), rep.getDataStore(), session.getNamespaceResolver());
             internalSetProperty(prop.getQName(), value);
         }
     }
Index: src/main/java/org/apache/jackrabbit/core/query/lucene/JackrabbitTextExtractor.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/query/lucene/JackrabbitTextExtractor.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/query/lucene/JackrabbitTextExtractor.java	(working copy)
@@ -19,15 +19,11 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.Reader;
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.Set;
 import java.util.StringTokenizer;
 
-import org.apache.jackrabbit.core.query.TextFilter;
 import org.apache.jackrabbit.extractor.CompositeTextExtractor;
 import org.apache.jackrabbit.extractor.DelegatingTextExtractor;
 import org.apache.jackrabbit.extractor.EmptyTextExtractor;
@@ -40,8 +36,8 @@
  * implements the following functionality:
  * <ul>
  *   <li>
- *     Parses the configured {@link TextExtractor} and {@link TextFilter}
- *     class names and instantiates the configured classes.
+ *     Parses the configured {@link TextExtractor} class names and
+ *     instantiates the configured classes.
  *   </li>
  *   <li>
  *     Acts as the delegate extractor for any configured
@@ -53,11 +49,6 @@
  *     are delegated.
  *   </li>
  *   <li>
- *     Creates a {@link TextFilterExtractor} adapter for a configured
- *     {@link TextFilter} instance when it is first used and adds that adapter
- *     to the composite extractor for use in text extraction.
- *   </li>
- *   <li>
  *     Logs a warning and creates a dummy {@link EmptyTextExtractor} instance
  *     for any unsupported content types when first detected. The dummy
  *     extractor is added to the composite extractor to prevent future
@@ -80,7 +71,7 @@
     private final Set types = new HashSet();
 
     /**
-     * Composite extractor used to for all text extration tasks. Contains
+     * Composite extractor used to for all text extraction tasks. Contains
      * all the {@link TextExtractor} instances for directly supported content
      * types, the {@link TextFilterExtractor} adapters for backwards
      * compatibility with configured {@link TextFilter} instances that have
@@ -91,18 +82,11 @@
         new CompositeTextExtractor();
 
     /**
-     * Configured {@link TextFilter} instances. Used for backwards
-     * compatibility with existing configuration files and {@link TextFilter}
-     * implementations.
-     */
-    private final Collection filters = new ArrayList();
-
-    /**
      * Creates a Jackrabbit text extractor containing the configured component
      * classes.
      *
-     * @param classes configured {@link TextExtractor} (and {@link TextFilter})
-     *                class names (space- or comma-separated)
+     * @param classes configured {@link TextExtractor} class names
+     *                (space- or comma-separated)
      */
     public JackrabbitTextExtractor(String classes) {
         logger.debug("JackrabbitTextExtractor({})", classes);
@@ -117,8 +101,6 @@
                 }
                 if (object instanceof TextExtractor) {
                     extractor.addTextExtractor((TextExtractor) object);
-                } else if (object instanceof TextFilter) {
-                    filters.add(object);
                 } else {
                     logger.warn("Unknown text extractor class: {}", name);
                 }
@@ -174,19 +156,6 @@
             throws IOException {
         logger.debug("extractText(stream, {}, {})", type, encoding);
         if (!types.contains(type)) {
-            Iterator iterator = filters.iterator();
-            while (iterator.hasNext()) {
-                TextFilter filter = (TextFilter) iterator.next();
-                if (filter.canFilter(type)) {
-                    types.add(type);
-                    extractor.addTextExtractor(
-                            new TextFilterExtractor(type, filter));
-                    break;
-                }
-            }
-        }
-
-        if (!types.contains(type)) {
             logger.warn("Full text indexing of {} is not supported", type);
             types.add(type);
             extractor.addTextExtractor(new EmptyTextExtractor(type));
Index: src/main/java/org/apache/jackrabbit/core/query/lucene/TextFilterExtractor.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/query/lucene/TextFilterExtractor.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/query/lucene/TextFilterExtractor.java	(working copy)
@@ -1,124 +0,0 @@
-/*
- * 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.core.query.lucene;
-
-import java.io.FilterReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-import java.io.StringReader;
-import java.util.Map;
-
-import javax.jcr.RepositoryException;
-
-import org.apache.jackrabbit.core.PropertyId;
-import org.apache.jackrabbit.core.query.TextFilter;
-import org.apache.jackrabbit.core.state.ItemState;
-import org.apache.jackrabbit.core.state.PropertyState;
-import org.apache.jackrabbit.core.value.BLOBFileValue;
-import org.apache.jackrabbit.core.value.InternalValue;
-import org.apache.jackrabbit.extractor.TextExtractor;
-
-/**
- * Adapter class for achieving backwards compatibility with classes
- * implementing the deprectated {@link TextFilter} interface. This class
- * implements the {@link TextExtractor} interface through calls to an
- * underlying {@link TextFilter} instance.
- */
-public class TextFilterExtractor implements TextExtractor {
-
-    /**
-     * Supported content types.
-     */
-    private final String[] types;
-
-    /**
-     * The adapted text filter.
-     */
-    private final TextFilter filter;
-
-    /**
-     * Creates a text extractor adapter that supports the given content
-     * types using the given text filter.
-     *
-     * @param types supported content types
-     * @param filter text filter to be adapted
-     */
-    public TextFilterExtractor(String[] types, TextFilter filter) {
-        this.types = types;
-        this.filter = filter;
-    }
-
-    /**
-     * Creates a text extractor adapter that supports the given content
-     * type using the given text filter.
-     *
-     * @param type supported content type
-     * @param filter text filter to be adapted
-     */
-    public TextFilterExtractor(String type, TextFilter filter) {
-        this(new String[] { type }, filter);
-    }
-
-    /**
-     * Returns the supported content types.
-     *
-     * @return supported content types
-     */
-    public String[] getContentTypes() {
-        return types;
-    }
-
-    /**
-     * Extracts the text content of the given binary stream by calling the
-     * underlying {@link TextFilter} instance. A dummy {@link PropertyState}
-     * instance is created to comply with the
-     * {@link TextFilter#doFilter(PropertyState, String)} method signature.
-     *
-     * @param stream binary stream
-     * @param type content type
-     * @param encoding character encoding, or <code>null</code>
-     * @return reader reader for the extracted text content
-     * @throws IOException if the adapted call fails
-     */
-    public Reader extractText(InputStream stream, String type, String encoding)
-            throws IOException {
-        final InternalValue value = InternalValue.create(stream);
-        try {
-            PropertyState state = new PropertyState(
-                    (PropertyId) null, ItemState.STATUS_EXISTING, true);
-            state.setValues(new InternalValue[] { value });
-            Map fields = filter.doFilter(state, encoding);
-            Object fulltext = fields.get(FieldNames.FULLTEXT);
-            if (fulltext instanceof Reader) {
-                return new FilterReader((Reader) fulltext) {
-                    public void close() throws IOException {
-                        super.close();
-                        ((BLOBFileValue) value.internalValue()).discard();
-                    }
-                };
-            } else {
-                ((BLOBFileValue) value.internalValue()).discard();
-                return new StringReader("");
-            }
-        } catch (RepositoryException e) {
-            ((BLOBFileValue) value.internalValue()).discard();
-            return new StringReader("");
-        }
-    }
-
-}
Index: src/main/java/org/apache/jackrabbit/core/data/DataStore.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/data/DataStore.java	(revision 0)
+++ src/main/java/org/apache/jackrabbit/core/data/DataStore.java	(revision 0)
@@ -0,0 +1,73 @@
+/*
+ * 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.core.data;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Append-only store for binary streams. A data store consists of a number
+ * of identifiable data records that each contain a distinct binary stream.
+ * New binary streams can be added to the data store, but existing streams
+ * are never removed or modified.
+ * <p>
+ * A data store should be fully thread-safe, i.e. it should be possible to
+ * add and access data records concurrently. Optimally even separate processes
+ * should be able to concurrently access the data store with zero interprocess
+ * synchronization.
+ */
+public interface DataStore {
+
+    /**
+     * Returns the identified data record. The given identifier should be
+     * the identifier of a previously saved data record. Since records are
+     * never removed, there should never be cases where the identified record
+     * is not found. Abnormal cases like that are treated as errors and
+     * handled by throwing an exception.
+     *
+     * @param identifier data identifier
+     * @return identified data record
+     * @throws IOException if the data store could not be accessed,
+     *                     or if the given identifier is invalid
+     */
+    DataRecord getRecord(DataIdentifier identifier) throws IOException;
+
+    /**
+     * Creates a new data record. The given binary stream is consumed and
+     * a binary record containing the consumed stream is created and returned.
+     * If the same stream already exists in another record, then that record
+     * is returned instead of creating a new one.
+     * <p>
+     * The given stream is consumed and <strong>not closed</strong> by this
+     * method. It is the responsibility of the caller to close the stream.
+     * A typical call pattern would be:
+     * <pre>
+     *     InputStream stream = ...;
+     *     try {
+     *         record = store.addRecord(stream);
+     *     } finally {
+     *         stream.close();
+     *     }
+     * </pre>
+     *
+     * @param stream binary stream
+     * @return data record that contains the given stream
+     * @throws IOException if the data store could not be accessed
+     */
+    DataRecord addRecord(InputStream stream) throws IOException;
+
+}

Property changes on: src\main\java\org\apache\jackrabbit\core\data\DataStore.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java	(revision 0)
+++ src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java	(revision 0)
@@ -0,0 +1,200 @@
+/*
+ * 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.core.data;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Random;
+
+/**
+ * Simple file-based data store. Data records are stored as normal files
+ * named using a message digest of the contained binary stream.
+ * <p>
+ * A three level directory structure is used to avoid placing too many
+ * files in a single directory. The chosen structure is designed to scale
+ * up to billions of distinct records.
+ * <p>
+ * This implementation relies on the underlying file system to support
+ * atomic O(1) move operations with {@link File#renameTo(File)}.
+ */
+public class FileDataStore implements DataStore {
+
+    /**
+     * The digest algorithm used to uniquely identify records.
+     */
+    private static final String DIGEST = "SHA-1";
+
+    /**
+     * Name of the directory used for temporary files.
+     */
+    private static final String TMP = "tmp";
+
+    /**
+     * Temporary file counter used to guarantee that concurrent threads
+     * in this JVM do not accidentally use the same temporary file names.
+     * <p>
+     * This variable is static to allow multiple separate data store
+     * instances in the same JVM to access the same data store directory
+     * on disk. The counter is initialized to a random number based on the
+     * time when this class was first loaded to minimize the chance of two
+     * separate JVM processes (or class loaders within the same JVM) using
+     * the same temporary file names. 
+     */
+    private static long counter = new Random().nextLong();
+
+    /**
+     * Returns the next value of the internal temporary file counter.
+     *
+     * @return next counter value
+     */
+    private static synchronized long nextCount() {
+        return counter++;
+    }
+
+    public static final DataStore INSTANCE =
+        new FileDataStore(new File("d:/datastore"));
+
+    /**
+     * The directory that contains all the data record files. The structure
+     * of content within this directory is controlled by this class.
+     */
+    private final File directory;
+
+    /**
+     * Creates a data store based on the given directory.
+     *
+     * @param directory data store directory
+     */
+    public FileDataStore(File directory) {
+        this.directory = directory;
+    }
+
+    /**
+     * Returns the record with the given identifier. Note that this method
+     * performs no sanity checks on the given identifier. It is up to the
+     * caller to ensure that only identifiers of previously created data
+     * records are used.
+     *
+     * @param identifier data identifier
+     * @return identified data record
+     */
+    public DataRecord getRecord(DataIdentifier identifier) {
+        return new FileDataRecord(identifier, getFile(identifier));
+    }
+
+    /**
+     * Creates a new record based on the given input stream. The stream
+     * is first consumed and the contents are saved in a temporary file
+     * and the SHA-1 message digest of the stream is calculated. If a
+     * record with the same SHA-1 digest (and length) is found then it is
+     * returned. Otherwise the temporary file is moved in place to become
+     * the new data record that gets returned.
+     *
+     * @param input binary stream
+     * @return data record that contains the given stream
+     * @throws IOException if the record could not be created
+     */
+    public DataRecord addRecord(InputStream input) throws IOException {
+        File temporary = newTemporaryFile();
+        try {
+            // Copy the stream to the temporary file and calculate the
+            // stream length and the message digest of the stream
+            long length = 0;
+            MessageDigest digest = MessageDigest.getInstance(DIGEST);
+            OutputStream output = new FileOutputStream(temporary);
+            try {
+                byte[] b = new byte[4096];
+                for (int n = input.read(b); n != -1; n = input.read(b)) {
+                    output.write(b, 0, n);
+                    digest.update(b, 0, n);
+                    length += n;
+                }
+            } finally {
+                output.close();
+            }
+
+            // Check if the same record already exists, or
+            // move the temporary file in place if needed
+            DataIdentifier identifier = new DataIdentifier(digest.digest());
+            File file = getFile(identifier);
+            File parent = file.getParentFile();
+            if (!parent.isDirectory()) {
+                parent.mkdirs();
+            }
+            if (!file.exists()) {
+                temporary.renameTo(file);
+            }
+
+            // Sanity checks on the record file. These should never fail,
+            // but better safe than sorry...
+            if (!file.isFile()) {
+                throw new IOException("Not a file: " + file);
+            }
+            if (file.length() != length) {
+                throw new IOException(DIGEST + " collision: " + file);
+            }
+
+            return new FileDataRecord(identifier, file);
+        } catch (NoSuchAlgorithmException e) {
+            throw new IOException(DIGEST + " not available: " + e.getMessage());
+        } finally {
+            temporary.delete();
+        }
+    }
+
+    /**
+     * Returns the identified file. This method implements the pattern
+     * used to avoid problems with too many files in a single directory.
+     * <p>
+     * No sanity checks are performed on the given identifier.
+     *
+     * @param identifier data identifier
+     * @return identified file
+     */
+    private File getFile(DataIdentifier identifier) {
+        String string = identifier.toString();
+        File file = directory;
+        file = new File(file, string.substring(0, 2));
+        file = new File(file, string.substring(2, 4));
+        file = new File(file, string.substring(4, 6));
+        return new File(file, string);
+    }
+
+    /**
+     * Returns a unique temporary file to be used for creating a new
+     * data record. A synchronized counter value and the current time are
+     * used to construct the name of the temporary file in a way that
+     * minimizes the chance of collisions across concurrent threads or
+     * processes.
+     *
+     * @return temporary file
+     */
+    private File newTemporaryFile() {
+        File temporary = new File(directory, TMP);
+        if (!temporary.isDirectory()) {
+            temporary.mkdirs();
+        }
+        String name = TMP + "-" + nextCount() + "-" + System.currentTimeMillis();
+        return new File(temporary, name);
+    }
+
+}

Property changes on: src\main\java\org\apache\jackrabbit\core\data\FileDataStore.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: src/main/java/org/apache/jackrabbit/core/data/DataRecord.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/data/DataRecord.java	(revision 0)
+++ src/main/java/org/apache/jackrabbit/core/data/DataRecord.java	(revision 0)
@@ -0,0 +1,50 @@
+/*
+ * 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.core.data;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Immutable data record that consists of a binary stream.
+ */
+public interface DataRecord {
+
+    /**
+     * Returns the identifier of this record.
+     *
+     * @return data identifier
+     */
+    DataIdentifier getIdentifier();
+
+    /**
+     * Returns the length of the binary stream in this record.
+     *
+     * @return length of the binary stream
+     * @throws IOException if the record could not be accessed
+     */
+    long getLength() throws IOException;
+
+    /**
+     * Returns the the binary stream in this record.
+     *
+     * @return binary stream
+     * @throws IOException if the record could not be accessed
+     */
+    InputStream getStream() throws IOException;
+
+}

Property changes on: src\main\java\org\apache\jackrabbit\core\data\DataRecord.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: src/main/java/org/apache/jackrabbit/core/data/FileDataRecord.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/data/FileDataRecord.java	(revision 0)
+++ src/main/java/org/apache/jackrabbit/core/data/FileDataRecord.java	(revision 0)
@@ -0,0 +1,66 @@
+/*
+ * 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.core.data;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+
+/**
+ * Data record that is based on a normal file.
+ */
+class FileDataRecord extends AbstractDataRecord {
+
+    /**
+     * The file that contains the binary stream.
+     */
+    private final File file;
+
+    /**
+     * Creates a data record based on the given identifier and file.
+     *
+     * @param identifier data identifier
+     * @param file file that contains the binary stream
+     */
+    public FileDataRecord(DataIdentifier identifier, File file) {
+        super(identifier);
+        assert file.isFile();
+        this.file = file;
+    }
+
+    /**
+     * Returns the length of the file.
+     *
+     * @return file length
+     */
+    public long getLength() {
+        return file.length();
+    }
+
+    /**
+     * Returns an input stream for reading the file.
+     *
+     * @return file input stream
+     * @throws IOException if the file could not be opened
+     */
+    public InputStream getStream() throws IOException {
+        return new FileInputStream(file);
+    }
+
+}

Property changes on: src\main\java\org\apache\jackrabbit\core\data\FileDataRecord.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: src/main/java/org/apache/jackrabbit/core/data/DataIdentifier.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/data/DataIdentifier.java	(revision 0)
+++ src/main/java/org/apache/jackrabbit/core/data/DataIdentifier.java	(revision 0)
@@ -0,0 +1,100 @@
+/*
+ * 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.core.data;
+
+import java.io.Serializable;
+
+/**
+ * Opaque data identifier used to identify records in a data store. 
+ * All identifiers must be serializable and implement the standard
+ * object equality and hash code methods.
+ */
+public final class DataIdentifier implements Serializable {
+
+    /**
+     * Serial version UID.
+     */
+    private static final long serialVersionUID = -9197191401131100016L;
+
+    /**
+     * Array of hexadecimal digits.
+     */
+    private static final char[] HEX = "0123456789abcdef".toCharArray();
+
+    /**
+     * Data identifier.
+     */
+    private final String identifier;
+
+    /**
+     * Creates a data identifier from the given string.
+     *
+     * @param identifier data identifier
+     */
+    public DataIdentifier(String identifier) {
+        this.identifier = identifier;
+    }
+
+    /**
+     * Creates a data identifier from the hexadecimal string
+     * representation of the given bytes.
+     *
+     * @param identifier data identifier
+     */
+    public DataIdentifier(byte[] identifier) {
+        char[] buffer = new char[identifier.length * 2];
+        for (int i = 0; i < identifier.length; i++) {
+            buffer[2*i] = HEX[(identifier[i] >> 4) & 0x0f]; 
+            buffer[2*i + 1] = HEX[identifier[i] & 0x0f]; 
+        }
+        this.identifier = new String(buffer);
+    }
+
+    //-------------------------------------------------------------< Object >
+
+    /**
+     * Returns the identifier string.
+     *
+     * @return identifier string
+     */
+    public String toString() {
+        return identifier;
+    }
+
+    /**
+     * Checks if the given object is a data identifier and has the same
+     * string representation as this one.
+     *
+     * @param object other object
+     * @return <code>true</code> if the given object is the same identifier,
+     *         <code>false</code> otherwise
+     */
+    public boolean equals(Object object) {
+        return (object instanceof DataIdentifier)
+            && identifier.equals(object.toString()); 
+    }
+
+    /**
+     * Returns the hash code of the identifier string.
+     *
+     * @return hash code
+     */
+    public int hashCode() {
+        return identifier.hashCode();
+    }
+
+}

Property changes on: src\main\java\org\apache\jackrabbit\core\data\DataIdentifier.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: src/main/java/org/apache/jackrabbit/core/data/AbstractDataRecord.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/data/AbstractDataRecord.java	(revision 0)
+++ src/main/java/org/apache/jackrabbit/core/data/AbstractDataRecord.java	(revision 0)
@@ -0,0 +1,81 @@
+/*
+ * 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.core.data;
+
+/**
+ * Abstract data record base class. This base class contains only
+ * a reference to the data identifier of the record and implements
+ * the standard {@link Object} equality, hash code, and string
+ * representation methods based on the identifier.
+ */
+public abstract class AbstractDataRecord implements DataRecord {
+
+    /**
+     * The binary identifier;
+     */
+    private final DataIdentifier identifier;
+
+    /**
+     * Creates a data record with the given identifier.
+     *
+     * @param identifier data identifier
+     */
+    public AbstractDataRecord(DataIdentifier identifier) {
+        this.identifier = identifier;
+    }
+
+    /**
+     * Returns the data identifier.
+     *
+     * @param data identifier
+     */
+    public DataIdentifier getIdentifier() {
+        return identifier;
+    }
+
+    /**
+     * Returns the string representation of the data identifier.
+     *
+     * @return string representation
+     */
+    public String toString() {
+        return identifier.toString();
+    }
+
+    /**
+     * Checks if the given object is a data record with the same identifier
+     * as this one.
+     *
+     * @param object other object
+     * @return <code>true</code> if the other object is a data record and has
+     *         the same identifier as this one, <code>false</code> otherwise
+     */
+    public boolean equals(Object object) {
+        return (object instanceof DataRecord)
+            && identifier.equals(((DataRecord) object).getIdentifier()); 
+    }
+
+    /**
+     * Returns the hash code of the data identifier.
+     *
+     * @return hash code
+     */
+    public int hashCode() {
+        return identifier.hashCode();
+    }
+
+}

Property changes on: src\main\java\org\apache\jackrabbit\core\data\AbstractDataRecord.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: src/main/java/org/apache/jackrabbit/core/value/InternalValue.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/value/InternalValue.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/value/InternalValue.java	(working copy)
@@ -16,7 +16,8 @@
  */
 package org.apache.jackrabbit.core.value;
 
-import org.apache.jackrabbit.core.fs.FileSystemResource;
+import org.apache.jackrabbit.core.data.DataIdentifier;
+import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.name.MalformedPathException;
 import org.apache.jackrabbit.name.NameException;
 import org.apache.jackrabbit.name.NamespaceResolver;
@@ -41,7 +42,6 @@
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.ValueFormatException;
-import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Calendar;
@@ -79,12 +79,14 @@
     //------------------------------------------------------< factory methods >
     /**
      * @param value
+     * @param store data store
      * @param nsResolver
      * @return
      * @throws ValueFormatException
      * @throws RepositoryException
      */
-    public static InternalValue create(Value value, NamespaceResolver nsResolver)
+    public static InternalValue create(
+            Value value, DataStore store, NamespaceResolver nsResolver)
             throws ValueFormatException, RepositoryException {
         if (value == null) {
             throw new IllegalArgumentException("null value");
@@ -92,23 +94,14 @@
 
         switch (value.getType()) {
             case PropertyType.BINARY:
-                try {
-                    if (value instanceof BLOBFileValue) {
-                        return new InternalValue((BLOBFileValue) value);
-                    } else {
-                        InputStream stream = value.getStream();
-                        try {
-                            return new InternalValue(new BLOBFileValue(stream));
-                        } finally {
-                            try {
-                                stream.close();
-                            } catch (IOException e) {
-                                // ignore
-                            }
-                        }
+                if (value instanceof BLOBFileValue) {
+                    return new InternalValue(((BLOBFileValue) value).getIdentifer());
+                } else {
+                    try {
+                        return InternalValue.create(store, value.getStream());
+                    } catch (IOException e) {
+                        throw new RepositoryException(e);
                     }
-                } catch (IOException ioe) {
-                    throw new ValueFormatException(ioe.getMessage());
                 }
             case PropertyType.BOOLEAN:
                 return value.getBoolean() ? BOOLEAN_TRUE : BOOLEAN_FALSE;
@@ -182,52 +175,16 @@
 
     /**
      * @param value
-     * @return the created value
-     */
-    public static InternalValue create(byte[] value) {
-        return new InternalValue(new BLOBFileValue(value));
-    }
-
-    /**
-     * @param value
      * @return
      * @throws IOException
      */
-    public static InternalValue create(InputStream value) throws IOException {
-        return new InternalValue(new BLOBFileValue(value));
+    public static InternalValue create(
+            DataStore store, InputStream value) throws IOException {
+        return new InternalValue(store.addRecord(value).getIdentifier());
     }
 
     /**
      * @param value
-     * @param temp
-     * @return
-     * @throws IOException
-     */
-    public static InternalValue create(InputStream value, boolean temp) throws IOException {
-        return new InternalValue(new BLOBFileValue(value, temp));
-    }
-
-    /**
-     * @param value
-     * @return
-     * @throws IOException
-     */
-    public static InternalValue create(FileSystemResource value)
-            throws IOException {
-        return new InternalValue(new BLOBFileValue(value));
-    }
-
-    /**
-     * @param value
-     * @return
-     * @throws IOException
-     */
-    public static InternalValue create(File value) throws IOException {
-        return new InternalValue(new BLOBFileValue(value));
-    }
-
-    /**
-     * @param value
      * @return the created value
      */
     public static InternalValue create(QName value) {
@@ -342,27 +299,7 @@
      * @throws RepositoryException
      */
     public InternalValue createCopy() throws RepositoryException {
-        if (type == PropertyType.BINARY) {
-            // return a copy since the wrapped BLOBFileValue instance is mutable
-            try {
-                InputStream stream = ((BLOBFileValue) val).getStream();
-                try {
-                    return new InternalValue(new BLOBFileValue(stream));
-                } finally {
-                    try {
-                        stream.close();
-                    } catch (IOException e) {
-                        // ignore
-                    }
-                }
-            } catch (IOException ioe) {
-                throw new RepositoryException("failed to copy binary value", ioe);
-            }
-        } else {
-            // for all other types it's safe to return 'this' because the
-            // wrapped value is immutable (and therefore this instance as well)
-            return this;
-        }
+        return this;
     }
 
     /**
@@ -397,10 +334,8 @@
                 return new InternalValue(QName.valueOf(s));
             case PropertyType.STRING:
                 return new InternalValue(s);
-
             case PropertyType.BINARY:
-                throw new IllegalArgumentException(
-                        "this method does not support the type PropertyType.BINARY");
+                return new InternalValue(new DataIdentifier(s));
             default:
                 throw new IllegalArgumentException("illegal type");
         }
@@ -472,7 +407,7 @@
         type = PropertyType.BOOLEAN;
     }
 
-    private InternalValue(BLOBFileValue value) {
+    private InternalValue(DataIdentifier value) {
         val = value;
         type = PropertyType.BINARY;
     }
Index: src/main/java/org/apache/jackrabbit/core/value/BLOBFileValue.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/value/BLOBFileValue.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/value/BLOBFileValue.java	(working copy)
@@ -16,30 +16,22 @@
  */
 package org.apache.jackrabbit.core.value;
 
-import org.apache.jackrabbit.core.fs.FileSystemException;
-import org.apache.jackrabbit.core.fs.FileSystemResource;
-import org.apache.jackrabbit.util.ISO8601;
-import org.apache.jackrabbit.util.TransientFileFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.Value;
-import javax.jcr.ValueFormatException;
-import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
-import java.util.Arrays;
 import java.util.Calendar;
 
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFormatException;
+
+import org.apache.jackrabbit.core.data.DataIdentifier;
+import org.apache.jackrabbit.core.data.DataRecord;
+import org.apache.jackrabbit.util.ISO8601;
+
 /**
  * <code>BLOBFileValue</code> represents a binary <code>Value</code> which is
  * backed by a resource or byte[]. Unlike <code>BinaryValue</code> it has no
@@ -53,11 +45,6 @@
 public class BLOBFileValue implements Value {
 
     /**
-     * The default logger
-     */
-    private static Logger log = LoggerFactory.getLogger(BLOBFileValue.class);
-
-    /**
      * the property type
      */
     public static final int TYPE = PropertyType.BINARY;
@@ -68,308 +55,47 @@
     protected static final String DEFAULT_ENCODING = "UTF-8";
 
     /**
-     * empty array
+     * The data record.
      */
-    private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+    private final DataRecord record;
 
     /**
-     * max size for keeping tmp data in memory
-     */
-    private static final int MAX_BUFFER_SIZE = 0x10000;
-
-    /**
-     * underlying file
-     */
-    private final File file;
-
-    /**
-     * flag indicating if this instance represents a <i>temporary</i> value
-     * whose dynamically allocated resources can be explicitly freed on
-     * {@link #discard()}.
-     */
-    private final boolean temp;
-
-    /**
-     * buffer for small-sized data
-     */
-    private byte[] buffer = EMPTY_BYTE_ARRAY;
-
-    /**
-     * underlying file system resource
-     */
-    private final FileSystemResource fsResource;
-
-    /**
-     * converted text
-     */
-    private String text = null;
-
-    /**
-     * Creates a new <code>BLOBFileValue</code> instance from an
-     * <code>InputStream</code>. The contents of the stream is spooled
-     * to a temporary file or to a byte buffer if its size is smaller than
-     * {@link #MAX_BUFFER_SIZE}.
-     * <p/>
-     * The new instance represents a <i>temporary</i> value whose dynamically
-     * allocated resources will be freed explicitly on {@link #discard()}.
+     * Creates a new <code>BLOBFileValue</code> instance that represents the
+     * given data record.
      *
-     * @param in stream to be represented as a <code>BLOBFileValue</code> instance
-     * @throws IOException if an error occurs while reading from the stream or
-     *                     writing to the temporary file
+     * @param record data record
      */
-    public BLOBFileValue(InputStream in) throws IOException {
-        this(in, true);
+    public BLOBFileValue(DataRecord record) {
+        this.record = record;
     }
 
-    /**
-     * Creates a new <code>BLOBFileValue</code> instance from an
-     * <code>InputStream</code>. The contents of the stream is spooled
-     * to a temporary file or to a byte buffer if its size is smaller than
-     * {@link #MAX_BUFFER_SIZE}.
-     * <p/>
-     * The <code>temp</code> parameter governs whether dynamically allocated
-     * resources will be freed explicitly on {@link #discard()}. Note that any
-     * dynamically allocated resources (temp file/buffer) will be freed
-     * implicitly once this instance has been gc'ed.
-     *
-     * @param in stream to be represented as a <code>BLOBFileValue</code> instance
-     * @param temp flag indicating whether this instance represents a
-     *             <i>temporary</i> value whose resources can be explicitly freed
-     *             on {@link #discard()}.
-     * @throws IOException if an error occurs while reading from the stream or
-     *                     writing to the temporary file
-     */
-    public BLOBFileValue(InputStream in, boolean temp) throws IOException {
-        byte[] spoolBuffer = new byte[0x2000];
-        int read;
-        int len = 0;
-        OutputStream out = null;
-        File spoolFile = null;
-        try {
-            while ((read = in.read(spoolBuffer)) > 0) {
-                if (out != null) {
-                    // spool to temp file
-                    out.write(spoolBuffer, 0, read);
-                    len += read;
-                } else if (len + read > MAX_BUFFER_SIZE) {
-                    // threshold for keeping data in memory exceeded;
-                    // create temp file and spool buffer contents
-                    TransientFileFactory fileFactory = TransientFileFactory.getInstance();
-                    spoolFile = fileFactory.createTransientFile("bin", null, null);
-                    out = new FileOutputStream(spoolFile);
-                    out.write(buffer, 0, len);
-                    out.write(spoolBuffer, 0, read);
-                    buffer = null;
-                    len += read;
-                } else {
-                    // reallocate new buffer and spool old buffer contents
-                    byte[] newBuffer = new byte[len + read];
-                    System.arraycopy(buffer, 0, newBuffer, 0, len);
-                    System.arraycopy(spoolBuffer, 0, newBuffer, len, read);
-                    buffer = newBuffer;
-                    len += read;
-                }
-            }
-        } finally {
-            if (out != null) {
-                out.close();
-            }
-        }
-
-        // init vars
-        file = spoolFile;
-        fsResource = null;
-        this.temp = temp;
+    public DataIdentifier getIdentifer() {
+        return record.getIdentifier();
     }
 
     /**
-     * Creates a new <code>BLOBFileValue</code> instance from a
-     * <code>byte[]</code> array.
-     *
-     * @param bytes byte array to be represented as a <code>BLOBFileValue</code>
-     *              instance
-     */
-    public BLOBFileValue(byte[] bytes) {
-        buffer = bytes;
-        file = null;
-        fsResource = null;
-        // this instance is not backed by a temporarily allocated buffer
-        temp = false;
-    }
-
-    /**
-     * Creates a new <code>BLOBFileValue</code> instance from a <code>File</code>.
-     *
-     * @param file file to be represented as a <code>BLOBFileValue</code> instance
-     * @throws IOException if the file can not be read
-     */
-    public BLOBFileValue(File file) throws IOException {
-        String path = file.getCanonicalPath();
-        if (!file.isFile()) {
-            throw new IOException(path + ": the specified file does not exist");
-        }
-        if (!file.canRead()) {
-            throw new IOException(path + ": the specified file can not be read");
-        }
-        this.file = file;
-        // this instance is backed by a 'real' file; set virtual fs resource to null
-        fsResource = null;
-        // this instance is not backed by temporarily allocated resource/buffer
-        temp = false;
-    }
-
-    /**
-     * Creates a new <code>BLOBFileValue</code> instance from a resource in the
-     * virtual file system.
-     *
-     * @param fsResource resource in virtual file system
-     * @throws IOException if the resource can not be read
-     */
-    public BLOBFileValue(FileSystemResource fsResource) throws IOException {
-        try {
-            if (!fsResource.exists()) {
-                throw new IOException(fsResource.getPath()
-                        + ": the specified resource does not exist");
-            }
-        } catch (FileSystemException fse) {
-            throw new IOException(fsResource.getPath()
-                    + ": Error while creating value: " + fse.toString());
-        }
-        // this instance is backed by a resource in the virtual file system
-        this.fsResource = fsResource;
-        // set 'real' file to null
-        file = null;
-        // this instance is not backed by temporarily allocated resource/buffer
-        temp = false;
-    }
-
-    /**
      * Returns the length of this <code>BLOBFileValue</code>.
      *
      * @return The length, in bytes, of this <code>BLOBFileValue</code>,
      *         or -1L if the length can't be determined.
      */
     public long getLength() {
-        if (file != null) {
-            // this instance is backed by a 'real' file
-            if (file.exists()) {
-                return file.length();
-            } else {
-                return -1;
-            }
-        } else if (fsResource != null) {
-            // this instance is backed by a resource in the virtual file system
-            try {
-                return fsResource.length();
-            } catch (FileSystemException fse) {
-                return -1;
-            }
-        } else {
-            // this instance is backed by an in-memory buffer
-            return buffer.length;
+        try {
+            return record.getLength();
+        } catch (IOException e) {
+            return -1;
         }
     }
 
     /**
-     * Frees temporarily allocated resources such as temporary file, buffer, etc.
-     * If this <code>BLOBFileValue</code> is backed by a persistent resource
-     * calling this method will have no effect.
-     *
-     * @see #delete()
-     * @see #delete(boolean)
-     */
-    public void discard() {
-        if (!temp) {
-            // do nothing if this instance is not backed by temporarily
-            // allocated resource/buffer
-            return;
-        }
-        if (file != null) {
-            // this instance is backed by a temp file
-            file.delete();
-        } else if (buffer != null) {
-            // this instance is backed by an in-memory buffer
-            buffer = EMPTY_BYTE_ARRAY;
-        }
-    }
-
-    /**
-     * Deletes the persistent resource backing this <code>BLOBFileValue</code>.
-     * Same as <code>{@link #delete(false)}</code>.
-     * <p/>
-     * If this <code>BLOBFileValue</code> is <i>not</i> backed by a persistent
-     * resource calling this method will have no effect.
-     *
-     * @see #discard()
-     */
-    public void delete() {
-        if (!temp) {
-            delete(false);
-        }
-    }
-
-    /**
-     * Deletes the persistent resource backing this <code>BLOBFileValue</code>.
-     *
-     * @param pruneEmptyParentDirs if <code>true</code>, empty parent directories
-     *                             will automatically be deleted
-     */
-    public void delete(boolean pruneEmptyParentDirs) {
-        if (file != null) {
-            // this instance is backed by a 'real' file
-            file.delete();
-            if (pruneEmptyParentDirs) {
-                // prune empty parent directories
-                File parent = file.getParentFile();
-                while (parent != null && parent.delete()) {
-                    parent = parent.getParentFile();
-                }
-            }
-        } else if (fsResource != null) {
-            // this instance is backed by a resource in the virtual file system
-            try {
-                fsResource.delete(pruneEmptyParentDirs);
-            } catch (FileSystemException fse) {
-                // ignore
-                log.warn("Error while deleting BLOBFileValue: " + fse.getMessage());
-            }
-        } else {
-            // this instance is backed by an in-memory buffer
-            buffer = EMPTY_BYTE_ARRAY;
-        }
-    }
-
-    /**
      * Spools the contents of this <code>BLOBFileValue</code> to the given
      * output stream.
      *
      * @param out output stream
-     * @throws RepositoryException if the input stream for this
-     *                             <code>BLOBFileValue</code> could not be obtained
-     * @throws IOException         if an error occurs while while spooling
+     * @throws IOException if an error occurs while while spooling
      */
-    public void spool(OutputStream out) throws RepositoryException, IOException {
-        InputStream in;
-        if (file != null) {
-            // this instance is backed by a 'real' file
-            try {
-                in = new FileInputStream(file);
-            } catch (FileNotFoundException fnfe) {
-                throw new RepositoryException("file backing binary value not found",
-                        fnfe);
-            }
-        } else if (fsResource != null) {
-            // this instance is backed by a resource in the virtual file system
-            try {
-                in = fsResource.getInputStream();
-            } catch (FileSystemException fse) {
-                throw new RepositoryException(fsResource.getPath()
-                        + ": the specified resource does not exist", fse);
-            }
-        } else {
-            // this instance is backed by an in-memory buffer
-            in = new ByteArrayInputStream(buffer);
-        }
+    public void spool(OutputStream out) throws IOException {
+        InputStream in = record.getStream();
         try {
             byte[] buffer = new byte[0x2000];
             int read;
@@ -377,61 +103,38 @@
                 out.write(buffer, 0, read);
             }
         } finally {
-            try {
-                in.close();
-            } catch (IOException ignore) {
-            }
+            in.close();
         }
     }
 
     //-------------------------------------------< java.lang.Object overrides >
+
     /**
-     * Returns a string representation of this <code>BLOBFileValue</code>
-     * instance. The string representation of a resource backed value is
-     * the path of the underlying resource. If this instance is backed by an
-     * in-memory buffer the generic object string representation of the byte
-     * array will be used instead.
+     * Returns the string identifier of the data record represented by this
+     * <code>BLOBFileValue</code> instance.
      *
-     * @return A string representation of this <code>BLOBFileValue</code> instance.
+     * @return string identifier
      */
     public String toString() {
-        if (file != null) {
-            // this instance is backed by a 'real' file
-            return file.toString();
-        } else if (fsResource != null) {
-            // this instance is backed by a resource in the virtual file system
-            return fsResource.toString();
-        } else {
-            // this instance is backed by an in-memory buffer
-            return buffer.toString();
-        }
+        return record.getIdentifier().toString();
     }
 
     /**
      * {@inheritDoc}
      */
     public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj instanceof BLOBFileValue) {
-            BLOBFileValue other = (BLOBFileValue) obj;
-            return ((file == null ? other.file == null : file.equals(other.file))
-                    && (fsResource == null ? other.fsResource == null : fsResource.equals(other.fsResource))
-                    && Arrays.equals(buffer, other.buffer));
-        }
-        return false;
+        return this == obj
+            || (obj instanceof BLOBFileValue
+                && record.equals(((BLOBFileValue) obj).record));
     }
 
     /**
-     * Returns zero to satisfy the Object equals/hashCode contract.
-     * This class is mutable and not meant to be used as a hash key.
+     * Returns the hash code of the data record.
      *
-     * @return always zero
-     * @see Object#hashCode()
+     * @return hash code of the data record
      */
     public int hashCode() {
-        return 0;
+        return record.hashCode();
     }
 
     //----------------------------------------------------------------< Value >
@@ -445,64 +148,35 @@
     /**
      * {@inheritDoc}
      */
-    public String getString()
-            throws ValueFormatException, IllegalStateException,
-            RepositoryException {
-        if (text == null) {
+    public String getString() throws RepositoryException {
+        try {
             ByteArrayOutputStream out = new ByteArrayOutputStream();
-            try {
-                spool(out);
-                byte[] data = out.toByteArray();
-                text = new String(data, DEFAULT_ENCODING);
-            } catch (UnsupportedEncodingException e) {
-                throw new RepositoryException(DEFAULT_ENCODING
-                        + " not supported on this platform", e);
-            } catch (IOException e) {
-                throw new ValueFormatException("conversion from stream to string failed", e);
-            } finally {
-                try {
-                    out.close();
-                } catch (IOException e) {
-                    // ignore
-                }
-            }
+            spool(out);
+            return new String(out.toByteArray(), DEFAULT_ENCODING);
+        } catch (UnsupportedEncodingException e) {
+            throw new RepositoryException(
+                    DEFAULT_ENCODING + " not supported on this platform", e);
+        } catch (IOException e) {
+            throw new ValueFormatException(
+                    "conversion from stream to string failed", e);
         }
-        return text;
     }
 
     /**
      * {@inheritDoc}
      */
-    public InputStream getStream()
-            throws IllegalStateException, RepositoryException {
-        // always return a 'fresh' stream
-        if (file != null) {
-            // this instance is backed by a 'real' file
-            try {
-                return new FileInputStream(file);
-            } catch (FileNotFoundException fnfe) {
-                throw new RepositoryException("file backing binary value not found",
-                        fnfe);
-            }
-        } else if (fsResource != null) {
-            // this instance is backed by a resource in the virtual file system
-            try {
-                return fsResource.getInputStream();
-            } catch (FileSystemException fse) {
-                throw new RepositoryException(fsResource.getPath()
-                        + ": the specified resource does not exist", fse);
-            }
-        } else {
-            return new ByteArrayInputStream(buffer);
+    public InputStream getStream() throws RepositoryException {
+        try {
+            return record.getStream();
+        } catch (IOException e) {
+            throw new RepositoryException(e);
         }
     }
 
     /**
      * {@inheritDoc}
      */
-    public double getDouble()
-            throws ValueFormatException, IllegalStateException,
-            RepositoryException {
+    public double getDouble() throws RepositoryException {
         try {
             return Double.parseDouble(getString());
         } catch (NumberFormatException e) {
@@ -513,9 +187,7 @@
     /**
      * {@inheritDoc}
      */
-    public Calendar getDate()
-            throws ValueFormatException, IllegalStateException,
-            RepositoryException {
+    public Calendar getDate() throws RepositoryException {
         Calendar cal = ISO8601.parse(getString());
         if (cal != null) {
             return cal;
@@ -527,9 +199,7 @@
     /**
      * {@inheritDoc}
      */
-    public long getLong()
-            throws ValueFormatException, IllegalStateException,
-            RepositoryException {
+    public long getLong() throws RepositoryException {
         try {
             return Long.parseLong(getString());
         } catch (NumberFormatException e) {
@@ -540,9 +210,8 @@
     /**
      * {@inheritDoc}
      */
-    public boolean getBoolean()
-            throws ValueFormatException, IllegalStateException,
-            RepositoryException {
+    public boolean getBoolean() throws RepositoryException {
         return Boolean.valueOf(getString()).booleanValue();
     }
+
 }
Index: src/main/java/org/apache/jackrabbit/core/state/PropertyState.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/state/PropertyState.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/state/PropertyState.java	(working copy)
@@ -300,55 +300,7 @@
         } else {
             values = new InternalValue[count];
             for (int i = 0; i < values.length; i++) {
-                if (type == PropertyType.BINARY) {
-                    // special handling required for binary value
-                    final long length = in.readLong();
-                    final InputStream stream = in;
-                    // create InputStream wrapper of size 'length'
-                    values[i] = InternalValue.create(new InputStream() {
-
-                        private long consumed = 0;
-
-                        public int read() throws IOException {
-                            if (consumed >= length) {
-                                return -1;  // eof
-                            }
-                            int b = stream.read();
-                            consumed++;
-                            return b;
-                        }
-
-                        public int read(byte[] b, int off, int len) throws IOException {
-                            if (consumed >= length) {
-                                return -1;  // eof
-                            }
-                            if ((consumed + len) > length) {
-                                len = (int) (length - consumed);
-                            }
-                            int read = stream.read(b, off, len);
-                            consumed += read;
-                            return read;
-                        }
-
-                        public long skip(long n) throws IOException {
-                            if (consumed >= length && n > 0) {
-                                return -1;  // eof
-                            }
-                            if ((consumed + n) > length) {
-                                n = length - consumed;
-                            }
-                            long skipped = stream.skip(n);
-                            consumed += skipped;
-                            return skipped;
-                        }
-
-                        public void close() {
-                            // nop
-                        }
-                    }, false);
-                } else {
-                    values[i] = InternalValue.valueOf(in.readUTF(), type);
-                }
+                values[i] = InternalValue.valueOf(in.readUTF(), type);
             }
         }
     }
Index: src/main/java/org/apache/jackrabbit/core/state/util/FileSystemBLOBStore.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/state/util/FileSystemBLOBStore.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/state/util/FileSystemBLOBStore.java	(working copy)
@@ -1,31 +0,0 @@
-/*
- * 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.core.state.util;
-
-import org.apache.jackrabbit.core.fs.FileSystem;
-
-/**
- * Legacy class kept for backward compatibility reasons.
- * @deprecated use {@link org.apache.jackrabbit.core.persistence.util.FileSystemBLOBStore}
- *             instead.
- */
-public class FileSystemBLOBStore extends org.apache.jackrabbit.core.persistence.util.FileSystemBLOBStore {
-
-    public FileSystemBLOBStore(FileSystem fs) {
-        super(fs);
-    }
-}
\ No newline at end of file
Index: src/main/java/org/apache/jackrabbit/core/state/util/ResourceBasedBLOBStore.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/state/util/ResourceBasedBLOBStore.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/state/util/ResourceBasedBLOBStore.java	(working copy)
@@ -1,26 +0,0 @@
-/*
- * 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.core.state.util;
-
-/**
- * Legacy interface kept for backward compatibility reasons.
- * @deprecated use {@link org.apache.jackrabbit.core.persistence.util.ResourceBasedBLOBStore}
- *             instead.
- */
-public interface ResourceBasedBLOBStore
-        extends org.apache.jackrabbit.core.persistence.util.ResourceBasedBLOBStore {
-}
\ No newline at end of file
Index: src/main/java/org/apache/jackrabbit/core/state/util/Serializer.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/state/util/Serializer.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/state/util/Serializer.java	(working copy)
@@ -1,90 +0,0 @@
-/*
- * 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.core.state.util;
-
-import org.apache.jackrabbit.core.state.NodeReferences;
-import org.apache.jackrabbit.core.state.NodeState;
-import org.apache.jackrabbit.core.state.PropertyState;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * Legacy class kept for backward compatibility reasons.
- * @deprecated use {@link org.apache.jackrabbit.core.persistence.util.Serializer}
- *             instead.
- */
-public final class Serializer {
-
-    /**
-     * @deprecated use {@link org.apache.jackrabbit.core.persistence.util.Serializer#serialize(NodeState, OutputStream)}
-     */
-    public static void serialize(NodeState state, OutputStream stream)
-            throws Exception {
-        // delegate to replacement
-        org.apache.jackrabbit.core.persistence.util.Serializer.serialize(state, stream);
-    }
-
-    /**
-     * @deprecated use {@link org.apache.jackrabbit.core.persistence.util.Serializer#deserialize(NodeState, InputStream)}
-     */
-    public static void deserialize(NodeState state, InputStream stream)
-            throws Exception {
-        // delegate to replacement
-        org.apache.jackrabbit.core.persistence.util.Serializer.deserialize(state, stream);
-    }
-
-    /**
-     * @deprecated use {@link org.apache.jackrabbit.core.persistence.util.Serializer#serialize(PropertyState, OutputStream, org.apache.jackrabbit.core.persistence.util.BLOBStore)}
-     */
-    public static void serialize(PropertyState state,
-                                 OutputStream stream,
-                                 BLOBStore blobStore)
-            throws Exception {
-        // delegate to replacement
-        org.apache.jackrabbit.core.persistence.util.Serializer.serialize(state, stream, blobStore);
-    }
-
-    /**
-     * @deprecated use {@link org.apache.jackrabbit.core.persistence.util.Serializer#deserialize(PropertyState, InputStream, org.apache.jackrabbit.core.persistence.util.BLOBStore)}
-     */
-    public static void deserialize(PropertyState state,
-                                   InputStream stream,
-                                   BLOBStore blobStore)
-            throws Exception {
-        // delegate to replacement
-        org.apache.jackrabbit.core.persistence.util.Serializer.deserialize(state, stream, blobStore);
-    }
-
-    /**
-     * @deprecated use {@link org.apache.jackrabbit.core.persistence.util.Serializer#serialize(NodeReferences, OutputStream)}
-     */
-    public static void serialize(NodeReferences refs, OutputStream stream)
-            throws Exception {
-        // delegate to replacement
-        org.apache.jackrabbit.core.persistence.util.Serializer.serialize(refs, stream);
-    }
-
-    /**
-     * @deprecated user {@link org.apache.jackrabbit.core.persistence.util.Serializer#deserialize(NodeReferences, InputStream)}
-     */
-    public static void deserialize(NodeReferences refs, InputStream stream)
-            throws Exception {
-        // delegate to replacement
-        org.apache.jackrabbit.core.persistence.util.Serializer.deserialize(refs, stream);
-    }
-}
\ No newline at end of file
Index: src/main/java/org/apache/jackrabbit/core/state/util/BLOBStore.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/state/util/BLOBStore.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/state/util/BLOBStore.java	(working copy)
@@ -1,27 +0,0 @@
-/*
- * 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.core.state.util;
-
-/**
- * Legacy interface kept for backward compatibility reasons.
- * @deprecated use {@link org.apache.jackrabbit.core.persistence.util.BLOBStore}
- *             instead.
- */
-public interface BLOBStore
-        extends org.apache.jackrabbit.core.persistence.util.BLOBStore {
-
-}
\ No newline at end of file
Index: src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java	(working copy)
@@ -35,6 +35,8 @@
 import org.apache.jackrabbit.core.config.RepositoryConfig;
 import org.apache.jackrabbit.core.config.VersioningConfig;
 import org.apache.jackrabbit.core.config.WorkspaceConfig;
+import org.apache.jackrabbit.core.data.DataStore;
+import org.apache.jackrabbit.core.data.FileDataStore;
 import org.apache.jackrabbit.core.fs.BasedFileSystem;
 import org.apache.jackrabbit.core.fs.FileSystem;
 import org.apache.jackrabbit.core.fs.FileSystemException;
@@ -159,6 +161,11 @@
     private final FileSystem metaDataStore;
 
     /**
+     * Data store for binary properties.
+     */
+    private final DataStore dataStore;
+
+    /**
      * the delegating observation dispatcher for all workspaces
      */
     private final DelegatingObservationDispatcher delegatingDispatcher =
@@ -241,6 +248,8 @@
             throw new RepositoryException(msg, fse);
         }
         metaDataStore = new BasedFileSystem(repStore, fsRootPath);
+        dataStore =
+            new FileDataStore(new File(repConfig.getHomeDir(), "datastore"));
 
         // init root node uuid
         rootNodeId = loadRootNodeId(metaDataStore);
@@ -322,6 +331,10 @@
         log.info("Repository started");
     }
 
+    public DataStore getDataStore() {
+        return dataStore;
+    }
+
     /**
      * Get the cache manager of this repository, useful
      * for setting its memory parameters.
@@ -505,7 +518,7 @@
     protected NodeTypeRegistry createNodeTypeRegistry(NamespaceRegistry nsReg,
                                                       FileSystem fs)
             throws RepositoryException {
-        return NodeTypeRegistry.create(nsReg, fs);
+        return NodeTypeRegistry.create(nsReg, fs, dataStore);
     }
 
     /**
Index: src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeManagerImpl.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeManagerImpl.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeManagerImpl.java	(working copy)
@@ -26,6 +26,7 @@
 import org.apache.jackrabbit.util.name.NamespaceMapping;
 import org.apache.jackrabbit.api.JackrabbitNodeTypeManager;
 import org.apache.jackrabbit.core.NamespaceRegistryImpl;
+import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.core.nodetype.compact.CompactNodeTypeDefReader;
 import org.apache.jackrabbit.core.nodetype.compact.ParseException;
 import org.apache.jackrabbit.core.nodetype.xml.NodeTypeReader;
@@ -84,6 +85,8 @@
      */
     private final NamespaceResolver nsResolver;
 
+    private final DataStore store;
+
     /**
      * A cache for <code>NodeType</code> instances created by this
      * <code>NodeTypeManager</code>
@@ -108,14 +111,16 @@
      * @param ntReg      node type registry
      * @param nsReg      namespace registry
      * @param nsResolver namespace resolver
+     * @param store      data store
      */
     public NodeTypeManagerImpl(
             NodeTypeRegistry ntReg, NamespaceRegistryImpl nsReg,
-            NamespaceResolver nsResolver) {
+            NamespaceResolver nsResolver, DataStore store) {
         this.nsResolver = nsResolver;
         this.ntReg = ntReg;
         this.nsReg = nsReg;
         this.ntReg.addListener(this);
+        this.store = store;
 
         // setup caches with soft references to node type
         // & item definition instances
@@ -182,7 +187,7 @@
             if (nt == null) {
                 EffectiveNodeType ent = ntReg.getEffectiveNodeType(name);
                 NodeTypeDef def = ntReg.getNodeTypeDef(name);
-                nt = new NodeTypeImpl(ent, def, this, nsResolver);
+                nt = new NodeTypeImpl(ent, def, this, nsResolver, store);
                 ntCache.put(name, nt);
             }
             return nt;
@@ -222,7 +227,7 @@
             if (contentType.equalsIgnoreCase(TEXT_XML)
                     || contentType.equalsIgnoreCase(APPLICATION_XML)) {
                 try {
-                    NodeTypeReader ntr = new NodeTypeReader(in);
+                    NodeTypeReader ntr = new NodeTypeReader(in, store);
 
                     Properties namespaces = ntr.getNamespaces();
                     if (namespaces != null) {
@@ -243,7 +248,7 @@
                 try {
                     NamespaceMapping mapping = new NamespaceMapping(nsResolver);
                     CompactNodeTypeDefReader reader = new CompactNodeTypeDefReader(
-                            new InputStreamReader(in), "cnd input stream", mapping);
+                            store, new InputStreamReader(in), "cnd input stream", mapping);
 
                     namespaceMap.putAll(mapping.getPrefixToURIMapping());
 
Index: src/main/java/org/apache/jackrabbit/core/nodetype/compact/CompactNodeTypeDefReader.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/nodetype/compact/CompactNodeTypeDefReader.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/nodetype/compact/CompactNodeTypeDefReader.java	(working copy)
@@ -16,6 +16,7 @@
  */
 package org.apache.jackrabbit.core.nodetype.compact;
 
+import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.core.nodetype.InvalidConstraintException;
 import org.apache.jackrabbit.core.nodetype.ItemDef;
 import org.apache.jackrabbit.core.nodetype.NodeDef;
@@ -124,6 +125,8 @@
  */
 public class CompactNodeTypeDefReader {
 
+    private final DataStore store;
+
     /**
      * the list of parsed nodetype defs
      */
@@ -150,8 +153,9 @@
      * @param r
      * @throws ParseException
      */
-    public CompactNodeTypeDefReader(Reader r, String systemId) throws ParseException {
-        this(r, systemId, new NamespaceMapping());
+    public CompactNodeTypeDefReader(
+            DataStore store, Reader r, String systemId) throws ParseException {
+        this(store, r, systemId, new NamespaceMapping());
     }
 
 
@@ -161,8 +165,10 @@
      * @param r
      * @throws ParseException
      */
-    public CompactNodeTypeDefReader(Reader r, String systemId, NamespaceMapping mapping)
+    public CompactNodeTypeDefReader(
+            DataStore store, Reader r, String systemId, NamespaceMapping mapping)
             throws ParseException {
+        this.store = store;
         lexer = new Lexer(r, systemId);
         this.nsMapping = mapping;
         nextToken();
@@ -486,7 +492,7 @@
             try {
                 value = InternalValue.create(ValueHelper.convert(
                         currentToken, pdi.getRequiredType(),
-                        ValueFactoryImpl.getInstance()), nsMapping);
+                        ValueFactoryImpl.getInstance()), store, nsMapping);
             } catch (ValueFormatException e) {
                 lexer.fail("'" + currentToken + "' is not a valid string representation of a value of type " + pdi.getRequiredType());
             } catch (RepositoryException e) {
Index: src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeImpl.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeImpl.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeImpl.java	(working copy)
@@ -16,6 +16,7 @@
  */
 package org.apache.jackrabbit.core.nodetype;
 
+import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.name.NameException;
 import org.apache.jackrabbit.name.NamespaceResolver;
@@ -51,6 +52,8 @@
     // namespace resolver used to translate qualified names to JCR names
     private final NamespaceResolver nsResolver;
 
+    private final DataStore store;
+
     /**
      * Package private constructor
      * <p/>
@@ -62,13 +65,16 @@
      * @param ntd        the definition of this node type
      * @param ntMgr      the node type manager associated with this node type
      * @param nsResolver namespace resolver
+     * @param store      data store
      */
     NodeTypeImpl(EffectiveNodeType ent, NodeTypeDef ntd,
-                 NodeTypeManagerImpl ntMgr, NamespaceResolver nsResolver) {
+                 NodeTypeManagerImpl ntMgr, NamespaceResolver nsResolver,
+                 DataStore store) {
         this.ent = ent;
         this.ntMgr = ntMgr;
         this.nsResolver = nsResolver;
         this.ntd = ntd;
+        this.store = store;
     }
 
     /**
@@ -381,10 +387,12 @@
                 Value targetVal = ValueHelper.convert(
                         value, targetType,
                         ValueFactoryImpl.getInstance());
-                internalValue = InternalValue.create(targetVal, nsResolver);
+                internalValue = InternalValue.create(
+                        targetVal, store, nsResolver);
             } else {
                 // no type conversion required
-                internalValue = InternalValue.create(value, nsResolver);
+                internalValue = InternalValue.create(
+                        value, store, nsResolver);
             }
             EffectiveNodeType.checkSetPropertyValueConstraints(
                     def, new InternalValue[]{internalValue});
@@ -459,10 +467,12 @@
                         Value targetVal = ValueHelper.convert(
                                 values[i], targetType,
                                 ValueFactoryImpl.getInstance());
-                        internalValue = InternalValue.create(targetVal, nsResolver);
+                        internalValue = InternalValue.create(
+                                targetVal, store, nsResolver);
                     } else {
                         // no type conversion required
-                        internalValue = InternalValue.create(values[i], nsResolver);
+                        internalValue = InternalValue.create(
+                                values[i], store, nsResolver);
                     }
                     list.add(internalValue);
                 }
Index: src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java	(working copy)
@@ -20,6 +20,7 @@
 import org.apache.commons.collections.map.ReferenceMap;
 import org.apache.jackrabbit.core.cluster.NodeTypeEventChannel;
 import org.apache.jackrabbit.core.cluster.NodeTypeEventListener;
+import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.core.fs.FileSystem;
 import org.apache.jackrabbit.core.fs.FileSystemException;
 import org.apache.jackrabbit.core.fs.FileSystemResource;
@@ -94,6 +95,8 @@
      */
     private final NamespaceRegistry nsReg;
 
+    private final DataStore dataStore;
+
     /**
      * Listeners (soft references)
      */
@@ -113,9 +116,10 @@
      * @return <code>NodeTypeRegistry</codes> object
      * @throws RepositoryException
      */
-    public static NodeTypeRegistry create(NamespaceRegistry nsReg, FileSystem ntStore)
+    public static NodeTypeRegistry create(
+            NamespaceRegistry nsReg, FileSystem ntStore, DataStore store)
             throws RepositoryException {
-        NodeTypeRegistry ntMgr = new NodeTypeRegistry(nsReg, ntStore);
+        NodeTypeRegistry ntMgr = new NodeTypeRegistry(nsReg, ntStore, store);
         return ntMgr;
     }
 
@@ -704,10 +708,12 @@
      * @param ntStore
      * @throws RepositoryException
      */
-    protected NodeTypeRegistry(NamespaceRegistry nsReg, FileSystem ntStore)
+    protected NodeTypeRegistry(
+            NamespaceRegistry nsReg, FileSystem ntStore, DataStore store)
             throws RepositoryException {
         this.nsReg = nsReg;
         this.ntStore = ntStore;
+        this.dataStore = store;
         customNodeTypesResource =
                 new FileSystemResource(this.ntStore, CUSTOM_NODETYPES_RESOURCE_NAME);
         try {
@@ -784,7 +790,7 @@
         InputStream in = null;
         try {
             in = getClass().getClassLoader().getResourceAsStream(BUILTIN_NODETYPES_RESOURCE_PATH);
-            store.load(in);
+            store.load(in, dataStore);
         } catch (IOException ioe) {
             String error =
                     "internal error: failed to read built-in node type definitions stored in "
@@ -839,7 +845,7 @@
             log.info("no custom node type definitions found");
         } else {
             try {
-                store.load(in);
+                store.load(in, dataStore);
             } catch (IOException ioe) {
                 String error =
                         "internal error: failed to read custom node type definitions stored in "
Index: src/main/java/org/apache/jackrabbit/core/nodetype/xml/NodeTypeReader.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/nodetype/xml/NodeTypeReader.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/nodetype/xml/NodeTypeReader.java	(working copy)
@@ -16,6 +16,7 @@
  */
 package org.apache.jackrabbit.core.nodetype.xml;
 
+import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.core.nodetype.InvalidConstraintException;
 import org.apache.jackrabbit.core.nodetype.InvalidNodeTypeDefException;
 import org.apache.jackrabbit.core.nodetype.ItemDef;
@@ -60,10 +61,10 @@
      * @throws InvalidNodeTypeDefException if the node type definition
      *                                     format is invalid
      */
-    public static NodeTypeDef[] read(InputStream xml)
+    public static NodeTypeDef[] read(InputStream xml, DataStore store)
             throws IOException, InvalidNodeTypeDefException {
         try {
-            NodeTypeReader reader = new NodeTypeReader(xml);
+            NodeTypeReader reader = new NodeTypeReader(xml, store);
             return reader.getNodeTypeDefs();
         } catch (NameException e) {
             throw new InvalidNodeTypeDefException(
@@ -80,16 +81,19 @@
     /** The namespace resolver. */
     private final NamespaceResolver resolver;
 
+    private final DataStore store;
+
     /**
      * Creates a node type definition file reader.
      *
      * @param xml node type definition file
      * @throws IOException if the node type definition file cannot be read
      */
-    public NodeTypeReader(InputStream xml) throws IOException {
+    public NodeTypeReader(InputStream xml, DataStore store) throws IOException {
         walker = new DOMWalker(xml);
         namespaces = walker.getNamespaces();
         resolver = new AdditionalNamespaceResolver(namespaces);
+        this.store = store;
     }
 
     /**
@@ -246,7 +250,8 @@
                 String value = walker.getContent();
                 try {
                     values.add(InternalValue.create(ValueHelper.convert(
-                            value, type, ValueFactoryImpl.getInstance()), resolver));
+                            value, type, ValueFactoryImpl.getInstance()),
+                            store, resolver));
                 } catch (RepositoryException e) {
                     throw new InvalidNodeTypeDefException(
                             "Unable to create default value: " + value, e);
Index: src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeDefStore.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeDefStore.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeDefStore.java	(working copy)
@@ -16,6 +16,7 @@
  */
 package org.apache.jackrabbit.core.nodetype;
 
+import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.core.nodetype.xml.NodeTypeReader;
 import org.apache.jackrabbit.core.nodetype.xml.NodeTypeWriter;
 import org.apache.jackrabbit.name.QName;
@@ -49,10 +50,10 @@
      * @throws IOException
      * @throws InvalidNodeTypeDefException
      */
-    public void load(InputStream in)
+    public void load(InputStream in, DataStore store)
             throws IOException, InvalidNodeTypeDefException,
             RepositoryException {
-        NodeTypeDef[] types = NodeTypeReader.read(in);
+        NodeTypeDef[] types = NodeTypeReader.read(in, store);
         for (int i = 0; i < types.length; i++) {
             add(types[i]);
         }
Index: src/main/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java	(working copy)
@@ -83,12 +83,6 @@
         try {
             if (start) {
                 importer.startNode(node, state.props);
-                // dispose temporary property values
-                for (Iterator iter = state.props.iterator(); iter.hasNext();) {
-                    PropInfo pi = (PropInfo) iter.next();
-                    pi.dispose();
-                }
-
             }
             if (end) {
                 importer.endNode(node);
Index: src/main/java/org/apache/jackrabbit/core/xml/StringValue.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/xml/StringValue.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/xml/StringValue.java	(working copy)
@@ -16,6 +16,7 @@
  */
 package org.apache.jackrabbit.core.xml;
 
+import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.name.NamespaceResolver;
 import org.apache.jackrabbit.util.Base64;
@@ -26,6 +27,8 @@
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.ValueFormatException;
+
+import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 
@@ -51,7 +54,7 @@
 
     //--------------------------------------------------------< TextValue >
 
-    public Value getValue(int type, NamespaceResolver resolver)
+    public Value getValue(int type, DataStore store, NamespaceResolver resolver)
             throws ValueFormatException, RepositoryException {
         if (type == PropertyType.NAME || type == PropertyType.PATH) {
             // NAME and PATH require special treatment because
@@ -62,7 +65,8 @@
             // current namespace context of xml document
             InternalValue ival =
                     InternalValue.create(ValueHelper.convert(
-                            value, type, ValueFactoryImpl.getInstance()), nsContext);
+                            value, type, ValueFactoryImpl.getInstance()),
+                            store, nsContext);
             // convert InternalValue to Value using this
             // session's namespace mappings
             return ival.toJCRValue(resolver);
@@ -74,7 +78,7 @@
         }
     }
 
-    public InternalValue getInternalValue(int targetType)
+    public InternalValue getInternalValue(int targetType, DataStore store)
             throws ValueFormatException, RepositoryException {
         try {
             if (targetType == PropertyType.BINARY) {
@@ -82,12 +86,14 @@
                 // decode using Reader
                 ByteArrayOutputStream baos = new ByteArrayOutputStream();
                 Base64.decode(value, baos);
-                return InternalValue.create(baos.toByteArray());
+                return InternalValue.create(
+                        store, new ByteArrayInputStream(baos.toByteArray()));
             } else {
                 // convert serialized value to InternalValue using
                 // current namespace context of xml document
                 return InternalValue.create(ValueHelper.convert(
-                        value, targetType, ValueFactoryImpl.getInstance()), nsContext);
+                        value, targetType, ValueFactoryImpl.getInstance()),
+                        store, nsContext);
             }
         } catch (IOException e) {
             throw new RepositoryException("Error decoding Base64 content", e);
Index: src/main/java/org/apache/jackrabbit/core/xml/SessionImporter.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/xml/SessionImporter.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/xml/SessionImporter.java	(working copy)
@@ -17,6 +17,7 @@
 package org.apache.jackrabbit.core.xml;
 
 import org.apache.jackrabbit.core.NodeImpl;
+import org.apache.jackrabbit.core.RepositoryImpl;
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.NodeId;
 import org.apache.jackrabbit.core.util.ReferenceChangeTracker;
@@ -259,7 +260,7 @@
         Iterator iter = propInfos.iterator();
         while (iter.hasNext()) {
             PropInfo pi = (PropInfo) iter.next();
-            pi.apply(node, session.getNamespaceResolver(), refTracker);
+            pi.apply(node, ((RepositoryImpl) session.getRepository()).getDataStore(), session.getNamespaceResolver(), refTracker);
         }
 
         parents.push(node);
Index: src/main/java/org/apache/jackrabbit/core/xml/BufferedStringValue.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/xml/BufferedStringValue.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/xml/BufferedStringValue.java	(working copy)
@@ -16,6 +16,7 @@
  */
 package org.apache.jackrabbit.core.xml;
 
+import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.name.NamespaceResolver;
 import org.apache.jackrabbit.util.Base64;
@@ -29,6 +30,8 @@
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.ValueFormatException;
+
+import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
@@ -226,7 +229,7 @@
 
     //--------------------------------------------------------< TextValue >
 
-    public Value getValue(int targetType, NamespaceResolver resolver)
+    public Value getValue(int targetType, DataStore store, NamespaceResolver resolver)
             throws ValueFormatException, RepositoryException {
         try {
             if (targetType == PropertyType.NAME
@@ -239,7 +242,8 @@
                 // current namespace context of xml document
                 InternalValue ival =
                     InternalValue.create(ValueHelper.convert(
-                            retrieve(), targetType, ValueFactoryImpl.getInstance()), nsContext);
+                            retrieve(), targetType, ValueFactoryImpl.getInstance()),
+                            store, nsContext);
                 // convert InternalValue to Value using this
                 // session's namespace mappings
                 return ival.toJCRValue(resolver);
@@ -267,63 +271,28 @@
         }
     }
 
-    public InternalValue getInternalValue(int type)
+    public InternalValue getInternalValue(int type, DataStore store)
             throws ValueFormatException, RepositoryException {
         try {
             if (type == PropertyType.BINARY) {
                 // base64 encoded BINARY type;
                 // decode using Reader
-                if (length() < 0x10000) {
-                    // < 65kb: deserialize BINARY type in memory
-                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                    Base64.decode(retrieve(), baos);
-                    // no need to close ByteArrayOutputStream
-                    //baos.close();
-                    return InternalValue.create(baos.toByteArray());
-                } else {
-                    // >= 65kb: deserialize BINARY type
-                    // using Reader and temporay file
-                    TransientFileFactory fileFactory = TransientFileFactory.getInstance();
-                    File tmpFile = fileFactory.createTransientFile("bin", null, null);
-                    FileOutputStream out = new FileOutputStream(tmpFile);
-                    Reader reader = reader();
-                    try {
-                        Base64.decode(reader, out);
-                    } finally {
-                        reader.close();
-                        out.close();
-                    }
-                    return InternalValue.create(tmpFile);
-                }
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                Base64.decode(retrieve(), baos);
+                // no need to close ByteArrayOutputStream
+                //baos.close();
+                return InternalValue.create(
+                        store, new ByteArrayInputStream(baos.toByteArray()));
             } else {
                 // convert serialized value to InternalValue using
                 // current namespace context of xml document
                 return InternalValue.create(ValueHelper.convert(
-                        retrieve(), type, ValueFactoryImpl.getInstance()), nsContext);
+                        retrieve(), type, ValueFactoryImpl.getInstance()),
+                        store, nsContext);
             }
         } catch (IOException e) {
             throw new RepositoryException("Error accessing property value", e);
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public void dispose() {
-        if (buffer != null) {
-            buffer = null;
-            bufferPos = 0;
-        } else if (tmpFile != null) {
-            try {
-                writer.close();
-                tmpFile.delete();
-                tmpFile = null;
-                writer = null;
-            } catch (IOException e) {
-                log.warn("Problem disposing property value", e);
-            }
-        } else {
-            log.warn("this instance has already been disposed");
-        }
-    }
 }
Index: src/main/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java	(working copy)
@@ -20,6 +20,7 @@
 import org.apache.jackrabbit.core.HierarchyManager;
 import org.apache.jackrabbit.core.NodeId;
 import org.apache.jackrabbit.core.PropertyId;
+import org.apache.jackrabbit.core.RepositoryImpl;
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.WorkspaceImpl;
 import org.apache.jackrabbit.core.nodetype.EffectiveNodeType;
@@ -468,7 +469,8 @@
             Iterator iter = propInfos.iterator();
             while (iter.hasNext()) {
                 PropInfo pi = (PropInfo) iter.next();
-                pi.apply(node, itemOps, ntReg, refTracker);
+                pi.apply(node, itemOps, ntReg, refTracker,
+                        ((RepositoryImpl) session.getRepository()).getDataStore());
             }
 
             // store affected nodes
Index: src/main/java/org/apache/jackrabbit/core/xml/TextValue.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/xml/TextValue.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/xml/TextValue.java	(working copy)
@@ -20,6 +20,7 @@
 import javax.jcr.Value;
 import javax.jcr.ValueFormatException;
 
+import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.name.NamespaceResolver;
 
@@ -29,17 +30,10 @@
  */
 public interface TextValue {
 
-    Value getValue(int type, NamespaceResolver resolver)
+    Value getValue(int type, DataStore store, NamespaceResolver resolver)
         throws ValueFormatException, RepositoryException;
 
-    InternalValue getInternalValue(int type)
+    InternalValue getInternalValue(int type, DataStore store)
         throws ValueFormatException, RepositoryException;
 
-    /**
-     * Dispose this value, i.e. free all bound resources. Once a value has
-     * been disposed, further method invocations will cause an IOException
-     * to be thrown.
-     */
-    void dispose();
-
 }
Index: src/main/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java	(working copy)
@@ -138,7 +138,6 @@
                         // the character data consists of pure whitespace, ignore
                         log.debug("ignoring pure whitespace character data...");
                         // reset handler
-                        textHandler.dispose();
                         textHandler = null;
                         return;
                     }
@@ -159,7 +158,6 @@
                 importer.endNode(node);
 
                 // reset handler
-                textHandler.dispose();
                 textHandler = null;
             }
         } catch (IOException ioe) {
Index: src/main/java/org/apache/jackrabbit/core/xml/PropInfo.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/xml/PropInfo.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/xml/PropInfo.java	(working copy)
@@ -26,6 +26,7 @@
 import org.apache.jackrabbit.core.BatchedItemOperations;
 import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.PropertyId;
+import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.core.nodetype.EffectiveNodeType;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 import org.apache.jackrabbit.core.nodetype.PropDef;
@@ -83,15 +84,6 @@
         this.values = values;
     }
 
-    /**
-     * Disposes all values contained in this property.
-     */
-    public void dispose() {
-        for (int i = 0; i < values.length; i++) {
-            values[i].dispose();
-        }
-    }
-
     private int getTargetType(PropDef def) {
         int target = def.getRequiredType();
         if (target != PropertyType.UNDEFINED) {
@@ -115,7 +107,7 @@
     }
 
     public void apply(
-            NodeImpl node, NamespaceResolver resolver,
+            NodeImpl node, DataStore store, NamespaceResolver resolver,
             ReferenceChangeTracker refTracker) throws RepositoryException {
         // find applicable definition
         PropDef def = getApplicablePropertyDef(node.getEffectiveNodeType());
@@ -129,7 +121,7 @@
         Value[] va = new Value[values.length];
         int targetType = getTargetType(def);
         for (int i = 0; i < values.length; i++) {
-            va[i] = values[i].getValue(targetType, resolver);
+            va[i] = values[i].getValue(targetType, store, resolver);
         }
 
         // multi- or single-valued property?
@@ -161,7 +153,8 @@
 
     public void apply(
             NodeState node, BatchedItemOperations itemOps,
-            NodeTypeRegistry ntReg, ReferenceChangeTracker refTracker)
+            NodeTypeRegistry ntReg, ReferenceChangeTracker refTracker,
+            DataStore store)
             throws RepositoryException {
         PropertyState prop = null;
         PropDef def = null;
@@ -206,7 +199,7 @@
         int targetType = getTargetType(def);
         InternalValue[] iva = new InternalValue[values.length];
         for (int i = 0; i < values.length; i++) {
-            iva[i] = values[i].getInternalValue(targetType);
+            iva[i] = values[i].getInternalValue(targetType, store);
         }
 
         // set values
Index: src/main/java/org/apache/jackrabbit/core/journal/DatabaseJournal.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/journal/DatabaseJournal.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/journal/DatabaseJournal.java	(working copy)
@@ -266,7 +266,8 @@
             selectRevisionsStmt.execute();
 
             return new DatabaseRecordIterator(
-                    selectRevisionsStmt.getResultSet(), getResolver());
+                    selectRevisionsStmt.getResultSet(),
+                    getResolver(), getDataStore());
         } catch (SQLException e) {
             close(true);
 
Index: src/main/java/org/apache/jackrabbit/core/journal/AbstractRecord.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/journal/AbstractRecord.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/journal/AbstractRecord.java	(working copy)
@@ -27,6 +27,7 @@
 import org.apache.jackrabbit.name.MalformedPathException;
 import org.apache.jackrabbit.core.NodeId;
 import org.apache.jackrabbit.core.PropertyId;
+import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
 import org.apache.jackrabbit.core.nodetype.compact.CompactNodeTypeDefWriter;
 import org.apache.jackrabbit.core.nodetype.compact.CompactNodeTypeDefReader;
@@ -65,11 +66,14 @@
      */
     protected final NamespaceResolver resolver;
 
+    private final DataStore store;
+
     /**
      * Create a new instance of this class.
      */
-    public AbstractRecord(NamespaceResolver resolver) {
+    public AbstractRecord(NamespaceResolver resolver, DataStore store) {
         this.resolver = resolver;
+        this.store = store;
     }
 
     /**
@@ -234,7 +238,8 @@
         try {
             StringReader sr = new StringReader(readString());
 
-            CompactNodeTypeDefReader reader = new CompactNodeTypeDefReader(sr, "(internal)");
+            CompactNodeTypeDefReader reader =
+                new CompactNodeTypeDefReader(store, sr, "(internal)");
             List ntds = reader.getNodeTypeDefs();
             if (ntds.size() != 1) {
                 throw new JournalException("Expected one node type definition: got " + ntds.size());
Index: src/main/java/org/apache/jackrabbit/core/journal/AppendRecord.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/journal/AppendRecord.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/journal/AppendRecord.java	(working copy)
@@ -106,7 +106,7 @@
      * @param producerId producer identifier
      */
     public AppendRecord(AbstractJournal journal, String producerId) {
-        super(journal.getResolver());
+        super(journal.getResolver(), journal.getDataStore());
 
         this.journal = journal;
         this.producerId = producerId;
Index: src/main/java/org/apache/jackrabbit/core/journal/FileJournal.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/journal/FileJournal.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/journal/FileJournal.java	(working copy)
@@ -156,7 +156,9 @@
                 }
             });
         }
-        return new FileRecordIterator(logFiles, startRevision, stopRevision, getResolver());
+        return new FileRecordIterator(
+                logFiles, startRevision, stopRevision,
+                getResolver(), getDataStore());
     }
 
     /**
Index: src/main/java/org/apache/jackrabbit/core/journal/ReadRecord.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/journal/ReadRecord.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/journal/ReadRecord.java	(working copy)
@@ -16,6 +16,7 @@
  */
 package org.apache.jackrabbit.core.journal;
 
+import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.name.QName;
 import org.apache.jackrabbit.name.NamespaceResolver;
 
@@ -62,9 +63,9 @@
      */
     public ReadRecord(String journalId, String producerId,
                       long revision, DataInputStream dataIn, int length,
-                      NamespaceResolver resolver) {
+                      NamespaceResolver resolver, DataStore store) {
 
-        super(resolver);
+        super(resolver, store);
 
         this.journalId = journalId;
         this.producerId = producerId;
Index: src/main/java/org/apache/jackrabbit/core/journal/DatabaseRecordIterator.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/journal/DatabaseRecordIterator.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/journal/DatabaseRecordIterator.java	(working copy)
@@ -18,6 +18,7 @@
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.name.NamespaceResolver;
 
 import java.util.NoSuchElementException;
@@ -46,6 +47,8 @@
      */
     private final NamespaceResolver resolver;
 
+    private final DataStore store;
+
     /**
      * Current record.
      */
@@ -64,9 +67,11 @@
     /**
      * Create a new instance of this class.
      */
-    public DatabaseRecordIterator(ResultSet rs, NamespaceResolver resolver) {
+    public DatabaseRecordIterator(
+            ResultSet rs, NamespaceResolver resolver, DataStore store) {
         this.rs = rs;
         this.resolver = resolver;
+        this.store = store;
     }
 
     /**
@@ -131,7 +136,8 @@
             String journalId = rs.getString(2);
             String producerId = rs.getString(3);
             DataInputStream dataIn = new DataInputStream(rs.getBinaryStream(4));
-            record = new ReadRecord(journalId, producerId, revision, dataIn, 0, resolver);
+            record = new ReadRecord(
+                    journalId, producerId, revision, dataIn, 0, resolver, store);
         } else {
             isEOF = true;
         }
Index: src/main/java/org/apache/jackrabbit/core/journal/FileRecordLog.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/journal/FileRecordLog.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/journal/FileRecordLog.java	(working copy)
@@ -18,6 +18,7 @@
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.name.NamespaceResolver;
 
 import java.io.File;
@@ -220,10 +221,12 @@
      * Read the file record at the current seek position.
      *
      * @param resolver namespace resolver
+     * @param store data store
      * @return file record
      * @throws java.io.IOException if an I/O error occurs
      */
-    public ReadRecord read(NamespaceResolver resolver) throws IOException {
+    public ReadRecord read(NamespaceResolver resolver, DataStore store)
+            throws IOException {
         String journalId = in.readUTF();
         String producerId = in.readUTF();
         int length = in.readInt();
@@ -233,7 +236,8 @@
                 4 + length;
 
         long revision = previousRevision + position;
-        return new ReadRecord(journalId, producerId, revision, in, length, resolver);
+        return new ReadRecord(
+                journalId, producerId, revision, in, length, resolver, store);
     }
 
     /**
Index: src/main/java/org/apache/jackrabbit/core/journal/FileRecordIterator.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/journal/FileRecordIterator.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/journal/FileRecordIterator.java	(working copy)
@@ -16,6 +16,7 @@
  */
 package org.apache.jackrabbit.core.journal;
 
+import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.name.NamespaceResolver;
 
 import java.io.File;
@@ -48,6 +49,8 @@
      */
     private NamespaceResolver resolver;
 
+    private DataStore store;
+
     /**
      * Current record log, containing file records.
      */
@@ -66,11 +69,12 @@
      * @param stopRevision stop point (inclusive)
      */
     public FileRecordIterator(File[] logFiles, long startRevision, long stopRevision,
-                              NamespaceResolver resolver) {
+                              NamespaceResolver resolver, DataStore store) {
         this.logFiles = logFiles;
         this.revision = startRevision;
         this.stopRevision = stopRevision;
         this.resolver = resolver;
+        this.store = store;
     }
 
 
@@ -117,7 +121,7 @@
         }
 
         try {
-            record = recordLog.read(resolver);
+            record = recordLog.read(resolver, store);
             revision = record.getRevision();
             return record;
         } catch (IOException e) {
Index: src/main/java/org/apache/jackrabbit/core/journal/AbstractJournal.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/journal/AbstractJournal.java	(revision 544329)
+++ src/main/java/org/apache/jackrabbit/core/journal/AbstractJournal.java	(working copy)
@@ -26,6 +26,7 @@
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.name.NamespaceResolver;
 
 /**
@@ -48,6 +49,8 @@
      */
     private NamespaceResolver resolver;
 
+    private DataStore store;
+
     /**
      * Map of registered consumers.
      */
@@ -320,4 +323,14 @@
     public NamespaceResolver getResolver() {
         return resolver;
     }
+
+    /**
+     * Return the data store.
+     *
+     * @return data store
+     */
+    public DataStore getDataStore() {
+        return store;
+    }
+
 }
\ No newline at end of file
