You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by th...@apache.org on 2007/08/29 10:48:22 UTC

svn commit: r570702 - in /jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core: query/lucene/TextFilterExtractor.java value/BLOBFileValue.java value/BLOBValue.java value/InternalValue.java

Author: thomasm
Date: Wed Aug 29 01:48:20 2007
New Revision: 570702

URL: http://svn.apache.org/viewvc?rev=570702&view=rev
Log:
JCR-926: renamed BLOBFileValue to BLOBValue, new abstract class BLOBFileValue

Added:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBValue.java   (with props)
Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/TextFilterExtractor.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBFileValue.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValue.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/TextFilterExtractor.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/TextFilterExtractor.java?rev=570702&r1=570701&r2=570702&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/TextFilterExtractor.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/TextFilterExtractor.java Wed Aug 29 01:48:20 2007
@@ -29,7 +29,6 @@
 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;
 

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBFileValue.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBFileValue.java?rev=570702&r1=570701&r2=570702&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBFileValue.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBFileValue.java Wed Aug 29 01:48:20 2007
@@ -16,243 +16,49 @@
  */
 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.TransientFileFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.ByteArrayInputStream;
-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.util.Arrays;
 
 import javax.jcr.RepositoryException;
 
 /**
- * <code>BLOBFileValue</code> represents a binary <code>Value</code> which is
- * backed by a resource or byte[]. Unlike <code>BinaryValue</code> it has no
- * state, i.e. the <code>getStream()</code> method always returns a fresh
+ * Represents binary data which is backed by a resource or byte[]. 
+ * Unlike <code>BinaryValue</code> it has no state, i.e. 
+ * the <code>getStream()</code> method always returns a fresh
  * <code>InputStream</code> instance.
  * <p/>
  * <b>Important Note:</b><p/>
- * This is class is for Jackrabbit-internal use only. Applications should
+ * This interface is for Jackrabbit-internal use only. Applications should
  * use <code>javax.jcr.ValueFactory</code> to create binary values.
  */
-public class BLOBFileValue {
-
-    /**
-     * The default logger
-     */
-    private static Logger log = LoggerFactory.getLogger(BLOBFileValue.class);
-
-    /**
-     * empty array
-     */
-    private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
-
-    /**
-     * 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;
-
-    /**
-     * 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
-     */
-    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;
-    }
-
-    /**
-     * 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
-     */
-    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
-     */
-    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;
-    }
+public abstract class BLOBFileValue {
 
     /**
-     * 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
+     * Returns an InputStream representation of this value.
+     * 
+     * @return An InputStream representation of this value.
      */
-    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;
-    }
+    abstract public InputStream getStream() throws IllegalStateException, RepositoryException;
 
     /**
      * 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.
+     * @throws IOException 
      */
-    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;
-        }
-    }
+    abstract public long getLength();
 
     /**
      * 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;
-        }
-    }
+    abstract public void discard();
 
     /**
      * Deletes the persistent resource backing this <code>BLOBFileValue</code>.
@@ -260,32 +66,19 @@
      * @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;
-        }
-    }
+    abstract public void delete(boolean pruneEmptyParentDirs);
 
     /**
+     * {@inheritDoc}
+     */
+    abstract public boolean equals(Object obj);
+    
+    /**
+     * {@inheritDoc}
+     */
+    abstract public String toString();
+    
+    /*
      * Spools the contents of this <code>BLOBFileValue</code> to the given
      * output stream.
      *
@@ -295,27 +88,7 @@
      * @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);
-        }
+        InputStream in = getStream();
         try {
             byte[] buffer = new byte[0x2000];
             int read;
@@ -330,81 +103,15 @@
         }
     }
 
-    //-------------------------------------------< 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.
-     *
-     * @return A string representation of this <code>BLOBFileValue</code> instance.
-     */
-    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();
-        }
-    }
-
-    /**
-     * {@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;
-    }
-
     /**
      * Returns zero to satisfy the Object equals/hashCode contract.
-     * This class is mutable and not meant to be used as a hash key.
+     * This class is not meant to be used as a hash key.
      *
      * @return always zero
      * @see Object#hashCode()
      */
     public int hashCode() {
         return 0;
-    }
-
-    /**
-     * {@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);
-        }
     }
 
 }

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBValue.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBValue.java?rev=570702&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBValue.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBValue.java Wed Aug 29 01:48:20 2007
@@ -0,0 +1,362 @@
+/*
+ * 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.value;
+
+import org.apache.jackrabbit.core.fs.FileSystemException;
+import org.apache.jackrabbit.core.fs.FileSystemResource;
+import org.apache.jackrabbit.util.TransientFileFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.ByteArrayInputStream;
+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.util.Arrays;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * This class represents a binary value which is
+ * backed by a resource or byte[]. Unlike <code>BinaryValue</code> it has no
+ * state, i.e. the <code>getStream()</code> method always returns a fresh
+ * <code>InputStream</code> instance.
+ * <p/>
+ */
+public class BLOBValue extends BLOBFileValue {
+
+    /**
+     * The default logger
+     */
+    private static Logger log = LoggerFactory.getLogger(BLOBValue.class);
+
+    /**
+     * empty array
+     */
+    private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+
+    /**
+     * 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;
+
+    /**
+     * 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
+     */
+    BLOBValue(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;
+    }
+
+    /**
+     * 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
+     */
+    BLOBValue(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
+     */
+    BLOBValue(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
+     */
+    BLOBValue(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;
+        }
+    }
+
+    /**
+     * 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(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>.
+     *
+     * @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;
+        }
+    }
+
+    //-------------------------------------------< 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.
+     *
+     * @return A string representation of this <code>BLOBFileValue</code> instance.
+     */
+    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();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof BLOBValue) {
+            BLOBValue other = (BLOBValue) 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;
+    }
+
+    /**
+     * Returns zero to satisfy the Object equals/hashCode contract.
+     * This class is mutable and not meant to be used as a hash key.
+     *
+     * @return always zero
+     * @see Object#hashCode()
+     */
+    public int hashCode() {
+        return 0;
+    }
+
+    /**
+     * {@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);
+        }
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBValue.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValue.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValue.java?rev=570702&r1=570701&r2=570702&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValue.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValue.java Wed Aug 29 01:48:20 2007
@@ -203,7 +203,7 @@
      * @return the created value
      */
     public static InternalValue create(byte[] value) {
-        return new InternalValue(new BLOBFileValue(value));
+        return new InternalValue(new BLOBValue(value));
     }
 
     /**
@@ -212,7 +212,7 @@
      * @throws IOException
      */
     public static InternalValue createTemporary(InputStream value) throws IOException {
-        return new InternalValue(new BLOBFileValue(value, true));
+        return new InternalValue(new BLOBValue(value, true));
     }    
 
     /**
@@ -222,7 +222,7 @@
      * @throws IOException
      */
     public static InternalValue create(InputStream value) throws IOException {
-        return new InternalValue(new BLOBFileValue(value, false));
+        return new InternalValue(new BLOBValue(value, false));
     }
 
     /**
@@ -232,7 +232,7 @@
      */
     public static InternalValue create(FileSystemResource value)
             throws IOException {
-        return new InternalValue(new BLOBFileValue(value));
+        return new InternalValue(new BLOBValue(value));
     }
 
     /**
@@ -241,7 +241,7 @@
      * @throws IOException
      */
     public static InternalValue create(File value) throws IOException {
-        return new InternalValue(new BLOBFileValue(value));
+        return new InternalValue(new BLOBValue(value));
     }
 
     /**