jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ju...@apache.org
Subject svn commit: r792142 [13/35] - in /jackrabbit/sandbox/JCR-1456: ./ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/ jackrabbit-core/ jackrabbit-core/src/main/java/org/apache/jackrab...
Date Wed, 08 Jul 2009 13:57:46 GMT
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInDataStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInDataStore.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInDataStore.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInDataStore.java Wed Jul  8 13:57:13 2009
@@ -30,7 +30,7 @@
 /**
  * Represents binary data which is stored in the data store.
  */
-public class BLOBInDataStore extends BLOBFileValue {
+class BLOBInDataStore extends BLOBFileValue {
 
     private final DataStore store;
     private final DataIdentifier identifier;
@@ -53,22 +53,19 @@
         this.identifier = identifier;
     }
 
-    public void delete(boolean pruneEmptyParentDirs) {
+    void delete(boolean pruneEmptyParentDirs) {
         // do nothing
     }
 
-    public void discard() {
+    void discard() {
         // do nothing
     }
-    
-    public DataIdentifier getDataIdentifier() {
+
+    DataIdentifier getDataIdentifier() {
         return identifier;
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isImmutable() {
+    boolean isImmutable() {
         return true;
     }
 
@@ -91,11 +88,11 @@
         return 0;
     }
 
-    public long getLength() {
+    public long getSize() {
         try {
             return getDataRecord().getLength();
         } catch (DataStoreException e) {
-            log.warn("getLength for " + identifier + " failed", e);
+            log.warn("getSize for " + identifier + " failed", e);
             return -1;
         }
     }
@@ -113,7 +110,7 @@
         DataIdentifier identifier = new DataIdentifier(id);
         return new BLOBInDataStore(store, identifier);
     }
-    
+
     static BLOBInDataStore getInstance(DataStore store, DataIdentifier identifier) {
         return new BLOBInDataStore(store, identifier);
     }
@@ -138,8 +135,4 @@
         return store.getRecord(identifier);
     }
 
-    public boolean isSmall() {
-        return false;
-    }
-
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInMemory.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInMemory.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInMemory.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInMemory.java Wed Jul  8 13:57:13 2009
@@ -29,7 +29,7 @@
 /**
  * Represents binary data which is backed by a byte[] (in memory).
  */
-public class BLOBInMemory extends BLOBFileValue {
+class BLOBInMemory extends BLOBFileValue {
 
     /**
      * Logger instance for this class
@@ -117,49 +117,31 @@
         return BLOBInMemory.getInstance(data);
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public void delete(boolean pruneEmptyParentDirs) {
+    void delete(boolean pruneEmptyParentDirs) {
         // do nothing
         // this object could still be referenced
         // the data will be garbage collected
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public void discard() {
+    void discard() {
         // do nothing
         // this object could still be referenced
         // the data will be garbage collected
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isImmutable() {
+    boolean isImmutable() {
         return true;
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public long getLength() {
+    public long getSize() {
         return data.length;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     public InputStream getStream() {
         return new ByteArrayInputStream(data);
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public String getString() throws RepositoryException {
+    String getString() throws RepositoryException {
         try {
             return new String(data, "UTF-8");
         } catch (UnsupportedEncodingException e) {
@@ -167,9 +149,6 @@
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
     public String toString() {
         StringBuilder buff = new StringBuilder(PREFIX.length() + 2 * data.length);
         buff.append(PREFIX);
@@ -182,9 +161,6 @@
         return buff.toString();
     }
 
-    /**
-     * {@inheritDoc}
-     */
     public boolean equals(Object obj) {
         if (this == obj) {
             return true;
@@ -207,8 +183,4 @@
         return 0;
     }
 
-    public boolean isSmall() {
-        return true;
-    }
-
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInResource.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInResource.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInResource.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInResource.java Wed Jul  8 13:57:13 2009
@@ -29,7 +29,7 @@
 /**
  * Represents binary data which is stored in a file system resource.
  */
-public class BLOBInResource extends BLOBFileValue {
+class BLOBInResource extends BLOBFileValue {
 
     /**
      * The default logger
@@ -82,10 +82,7 @@
         return new BLOBInResource(fsResource);
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public void delete(boolean pruneEmptyParentDirs) {
+    void delete(boolean pruneEmptyParentDirs) {
         try {
             fsResource.delete(pruneEmptyParentDirs);
         } catch (FileSystemException fse) {
@@ -95,31 +92,19 @@
 
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public void discard() {
+    void discard() {
         // this instance is not backed by temporarily allocated resource/buffer
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isImmutable() {
+    boolean isImmutable() {
         // delete will modify the state.
         return false;
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public long getLength() {
+    public long getSize() {
         return length;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     public InputStream getStream() throws RepositoryException {
         try {
             return fsResource.getInputStream();
@@ -129,16 +114,10 @@
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
     public String toString() {
         return PREFIX +  fsResource.toString();
     }
 
-    /**
-     * {@inheritDoc}
-     */
     public boolean equals(Object obj) {
         if (this == obj) {
             return true;
@@ -161,11 +140,4 @@
         return 0;
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isSmall() {
-        return false;
-    }
-
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInTempFile.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInTempFile.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInTempFile.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInTempFile.java Wed Jul  8 13:57:13 2009
@@ -26,13 +26,14 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.io.RandomAccessFile;
 
 import javax.jcr.RepositoryException;
 
 /**
  * Represents binary data which is stored in a temporary file.
  */
-public class BLOBInTempFile extends BLOBFileValue {
+class BLOBInTempFile extends BLOBFileValue {
 
     /**
      * the prefix of the string representation of this value
@@ -104,42 +105,27 @@
         return new BLOBInTempFile(file, temp);
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public void delete(boolean pruneEmptyParentDirs) {
+    void delete(boolean pruneEmptyParentDirs) {
         file.delete();
         length = -1;
         file = null;
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public void discard() {
+    void discard() {
         if (temp) {
             delete(true);
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isImmutable() {
+    boolean isImmutable() {
         // discard and delete can modify the state.
         return false;
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public long getLength() {
+    public long getSize() {
         return length;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     public InputStream getStream() throws IllegalStateException, RepositoryException {
         try {
             return new LazyFileInputStream(file);
@@ -148,16 +134,10 @@
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
     public String toString() {
         return PREFIX + file.toString();
     }
 
-    /**
-     * {@inheritDoc}
-     */
     public boolean equals(Object obj) {
         if (this == obj) {
             return true;
@@ -180,11 +160,13 @@
         return 0;
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isSmall() {
-        return false;
+    public int read(byte[] b, long position) throws IOException, RepositoryException {
+        RandomAccessFile raf = new RandomAccessFile(file, "r");
+        try {
+            raf.seek(position);
+            return raf.read(b);
+        } finally {
+            raf.close();
+        }
     }
-
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BinaryValueImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BinaryValueImpl.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BinaryValueImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BinaryValueImpl.java Wed Jul  8 13:57:13 2009
@@ -24,40 +24,28 @@
 /**
  * Represents a binary value that is backed by a blob file value.
  */
-public class BinaryValueImpl extends BinaryValue implements JackrabbitValue {
-    
+class BinaryValueImpl extends BinaryValue implements JackrabbitValue {
+
     private final BLOBFileValue blob;
 
     /**
      * Construct a new object from the given blob.
-     * 
+     *
      * @param blob the blob
      */
     BinaryValueImpl(BLOBFileValue blob) throws RepositoryException {
-        super(blob.getStream());
+        super(blob);
         this.blob = blob;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     public String getContentIdentity() {
         DataIdentifier id = blob.getDataIdentifier();
         return id == null ? null : id.toString();
     }
 
     /**
-     * Get the wrapped blob file value
-     * 
-     * @return the blob file value
-     */
-    BLOBFileValue getBlob() {
-        return blob;
-    }
-    
-    /**
      * Get the data identifier if one is available.
-     * 
+     *
      * @return the data identifier or null
      */
     DataIdentifier getDataIdentifier() {

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValue.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValue.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValue.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValue.java Wed Jul  8 13:57:13 2009
@@ -16,43 +16,39 @@
  */
 package org.apache.jackrabbit.core.value;
 
-import org.apache.commons.io.IOUtils;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.SequenceInputStream;
+import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Calendar;
+
+import javax.jcr.Binary;
+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.DataStore;
+import org.apache.jackrabbit.core.data.DataStoreException;
 import org.apache.jackrabbit.core.fs.FileSystemResource;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.QValue;
 import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException;
 import org.apache.jackrabbit.spi.commons.conversion.NameException;
 import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
-import org.apache.jackrabbit.spi.Path;
-import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.spi.QValue;
-import org.apache.jackrabbit.util.ISO8601;
-import org.apache.jackrabbit.uuid.UUID;
-import org.apache.jackrabbit.value.StringValue;
-import org.apache.jackrabbit.value.URIValue;
-import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
 import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
-import org.apache.jackrabbit.spi.commons.value.ValueFactoryQImpl;
+import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
 import org.apache.jackrabbit.spi.commons.value.AbstractQValue;
+import org.apache.jackrabbit.spi.commons.value.AbstractQValueFactory;
 import org.apache.jackrabbit.spi.commons.value.QValueValue;
-
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.Value;
-import javax.jcr.ValueFormatException;
-import javax.jcr.Session;
-import javax.jcr.ValueFactory;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.SequenceInputStream;
-import java.io.UnsupportedEncodingException;
-import java.util.Calendar;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.math.BigDecimal;
+import org.apache.jackrabbit.util.ISO8601;
+import org.apache.jackrabbit.uuid.UUID;
 
 /**
  * <code>InternalValue</code> represents the internal format of a property value.
@@ -84,12 +80,6 @@
     private static final InternalValue BOOLEAN_FALSE = new InternalValue(false);
 
     /**
-     * If set to 'true', the data store is used when configured in repository.xml
-     */
-    public static final boolean USE_DATA_STORE =
-        Boolean.valueOf(System.getProperty("org.jackrabbit.useDataStore", "true")).booleanValue();
-
-    /**
      * Temporary binary values smaller or equal this size are kept in memory
      */
     private static final int MIN_BLOB_FILE_SIZE = 1024;
@@ -102,6 +92,8 @@
      * @param value the JCR value
      * @param resolver
      * @return the created internal value
+     * @throws RepositoryException
+     * @throws ValueFormatException
      */
     public static InternalValue create(Value value, NamePathResolver resolver)
             throws ValueFormatException, RepositoryException {
@@ -116,41 +108,32 @@
      * @param resolver
      * @param store the data store
      * @return the created internal value
+     * @throws RepositoryException
+     * @throws ValueFormatException
      */
     public static InternalValue create(Value value, NamePathResolver resolver, DataStore store)
             throws ValueFormatException, RepositoryException {
         switch (value.getType()) {
             case PropertyType.BINARY:
                 InternalValue result;
-                if (USE_DATA_STORE) {
-                    BLOBFileValue blob = null;
-                    if (value instanceof BinaryValueImpl) {
-                        BinaryValueImpl bin = (BinaryValueImpl) value;
-                        DataIdentifier identifier = bin.getDataIdentifier();
-                        if (identifier != null) {
-                            // access the record to ensure it is not garbage collected
-                            if (store.getRecordIfStored(identifier) != null) {
-                                // it exists - so we don't need to stream it again
-                                // but we need to create a new object because the original
-                                // one might be in a different data store (repository)
-                                blob = BLOBInDataStore.getInstance(store, identifier);
-                            }
+                BLOBFileValue blob = null;
+                if (value instanceof BinaryValueImpl) {
+                    BinaryValueImpl bin = (BinaryValueImpl) value;
+                    DataIdentifier identifier = bin.getDataIdentifier();
+                    if (identifier != null) {
+                        // access the record to ensure it is not garbage collected
+                        if (store.getRecordIfStored(identifier) != null) {
+                            // it exists - so we don't need to stream it again
+                            // but we need to create a new object because the original
+                            // one might be in a different data store (repository)
+                            blob = BLOBInDataStore.getInstance(store, identifier);
                         }
                     }
-                    if (blob == null) {
-                        blob = getBLOBFileValue(store, value.getStream(), true);
-                    }
-                    result = new InternalValue(blob);
-                } else if (value instanceof BLOBFileValue) {
-                    result = new InternalValue((BLOBFileValue) value);
-                } else {
-                    InputStream stream = value.getStream();
-                    try {
-                        result = createTemporary(stream);
-                    } finally {
-                        IOUtils.closeQuietly(stream);
-                    }
                 }
+                if (blob == null) {
+                    blob = getBLOBFileValue(store, value.getBinary().getStream(), true);
+                }
+                result = new InternalValue(blob);
                 return result;
             case PropertyType.BOOLEAN:
                 return create(value.getBoolean());
@@ -209,6 +192,54 @@
         }
     }
 
+    public static InternalValue create(QValue value)
+            throws RepositoryException {
+        switch (value.getType()) {
+            case PropertyType.BINARY:
+                try {
+                    return create(value.getString().getBytes(AbstractQValueFactory.DEFAULT_ENCODING));
+                } catch (UnsupportedEncodingException e) {
+                    throw new InternalError(AbstractQValueFactory.DEFAULT_ENCODING + " not supported");
+                }
+            case PropertyType.BOOLEAN:
+                return new InternalValue(value.getBoolean());
+            case PropertyType.DATE:
+                return new InternalValue(value.getCalendar());
+            case PropertyType.DOUBLE:
+                return new InternalValue(value.getDouble());
+            case PropertyType.DECIMAL:
+                return new InternalValue(value.getDecimal());
+            case PropertyType.LONG:
+                return new InternalValue(value.getLong());
+            case PropertyType.REFERENCE:
+                return create(new UUID(value.getString()));
+            case PropertyType.WEAKREFERENCE:
+                return create(new UUID(value.getString()), true);
+            case PropertyType.URI:
+                return new InternalValue(value.getURI());
+            case PropertyType.NAME:
+                return new InternalValue(value.getName());
+            case PropertyType.PATH:
+                return new InternalValue(value.getPath());
+            case PropertyType.STRING:
+                return new InternalValue(value.getString());
+            default:
+                throw new IllegalArgumentException("illegal value");
+        }
+    }
+
+    static InternalValue getInternalValue(DataIdentifier identifier, DataStore store) throws DataStoreException {
+        // access the record to ensure it is not garbage collected
+        if (store.getRecordIfStored(identifier) != null) {
+            // it exists - so we don't need to stream it again
+            // but we need to create a new object because the original
+            // one might be in a different data store (repository)
+            BLOBFileValue blob = BLOBInDataStore.getInstance(store, identifier);
+            return new InternalValue(blob);
+        }
+        return null;
+    }
+
     /**
      * @param value
      * @return the created value
@@ -253,7 +284,7 @@
      * @param value
      * @return the created value
      */
-    public static InternalValue create(URI value) {
+    static InternalValue create(URI value) {
         return new InternalValue(value);
     }
 
@@ -270,10 +301,7 @@
      * @return the created value
      */
     public static InternalValue create(byte[] value) {
-        if (USE_DATA_STORE) {
-            return new InternalValue(BLOBInMemory.getInstance(value));
-        }
-        return new InternalValue(new BLOBValue(value));
+        return new InternalValue(BLOBInMemory.getInstance(value));
     }
 
     /**
@@ -281,52 +309,32 @@
      *
      * @param value the stream
      * @return the internal value
+     * @throws RepositoryException
      */
     public static InternalValue createTemporary(InputStream value) throws RepositoryException {
-        if (USE_DATA_STORE) {
-            return new InternalValue(getBLOBFileValue(null, value, true));
-        }
-        try {
-            return new InternalValue(new BLOBValue(value, true));
-        } catch (IOException e) {
-            throw new RepositoryException("Error creating temporary file", e);
-        }
+        return new InternalValue(getBLOBFileValue(null, value, true));
     }
 
     /**
-     * Create an internal value that is backed by a temporary file
-     * (if data store usage is disabled or the store is null)
-     * or in the data store if it is not null and enabled.
+     * Create an internal value that is stored in the data store (if enabled).
      *
-     * @param value the stream
-     * @param store the data store or null to use a temporary file
+     * @param value the input stream
+     * @param store
      * @return the internal value
+     * @throws RepositoryException
      */
-    public static InternalValue createTemporary(InputStream value, DataStore store) throws RepositoryException {
-        if (USE_DATA_STORE) {
-            return new InternalValue(getBLOBFileValue(store, value, true));
-        }
-        try {
-            return new InternalValue(new BLOBValue(value, true));
-        } catch (IOException e) {
-            throw new RepositoryException("Error creating temporary file", e);
-        }
+    static InternalValue create(InputStream value, DataStore store) throws RepositoryException {
+        return new InternalValue(getBLOBFileValue(store, value, false));
     }
 
     /**
      * @param value
      * @return
      * @throws IOException
+     * @throws RepositoryException
      */
     public static InternalValue create(InputStream value) throws RepositoryException {
-        if (USE_DATA_STORE) {
-            return new InternalValue(getBLOBFileValue(null, value, false));
-        }
-        try {
-            return new InternalValue(new BLOBValue(value, false));
-        } catch (IOException e) {
-            throw new RepositoryException("Error creating file", e);
-        }
+        return new InternalValue(getBLOBFileValue(null, value, false));
     }
 
     /**
@@ -335,20 +343,7 @@
      * @throws IOException
      */
     public static InternalValue create(FileSystemResource value) throws IOException {
-        if (USE_DATA_STORE) {
-            return new InternalValue(BLOBInResource.getInstance(value));
-        }
-        return new InternalValue(new BLOBValue(value));
-    }
-
-    /**
-     * @param value
-     * @return
-     * @throws IOException
-     */
-    public static InternalValue create(File value) throws IOException {
-        assert !USE_DATA_STORE;
-        return new InternalValue(new BLOBValue(value));
+        return new InternalValue(BLOBInResource.getInstance(value));
     }
 
     /**
@@ -359,7 +354,6 @@
      * @return the value
      */
     public static InternalValue create(DataStore store, String id) {
-        assert USE_DATA_STORE && store != null;
         return new InternalValue(getBLOBFileValue(store, id));
     }
 
@@ -384,18 +378,6 @@
     }
 
     /**
-     * @param values
-     * @return the created value
-     */
-    public static InternalValue[] create(String[] values) {
-        InternalValue[] ret = new InternalValue[values.length];
-        for (int i = 0; i < values.length; i++) {
-            ret[i] = new InternalValue(values[i]);
-        }
-        return ret;
-    }
-
-    /**
      * @param value
      * @return the created value
      */
@@ -421,78 +403,17 @@
     }
 
     //----------------------------------------------------< conversions, etc. >
-    /**
-     * @param resolver
-     * @return
-     * @throws RepositoryException
-     * @deprecated
-     */
-    public Value toJCRValue(NamePathResolver resolver)
-            throws RepositoryException {
-        ValueFactory vf;
-        if (resolver instanceof Session) {
-            vf = ((Session) resolver).getValueFactory();
-        } else {
-            vf = new ValueFactoryImpl(resolver);
-        }
-
-        if (vf instanceof ValueFactoryQImpl) {
-            return ((ValueFactoryQImpl) vf).createValue(this);
-        } else {
-            switch (type) {
-                case PropertyType.BINARY:
-                    return vf.createValue(((BLOBFileValue) val).getStream());
-                case PropertyType.BOOLEAN:
-                    return vf.createValue(((Boolean) val).booleanValue());
-                case PropertyType.DATE:
-                    return vf.createValue((Calendar) val);
-                case PropertyType.DOUBLE:
-                    return vf.createValue(((Double) val).doubleValue());
-                case PropertyType.LONG:
-                    return vf.createValue(((Long) val).longValue());
-                case PropertyType.DECIMAL:
-                    return vf.createValue((BigDecimal) val);
-                case PropertyType.REFERENCE:
-                    return vf.createValue(val.toString(), PropertyType.REFERENCE);
-                case PropertyType.WEAKREFERENCE:
-                    return vf.createValue(val.toString(), PropertyType.WEAKREFERENCE);
-                case PropertyType.URI:
-                    return new URIValue((URI) val);
-                case PropertyType.PATH:
-                    return vf.createValue(resolver.getJCRPath((Path) val), PropertyType.PATH);
-                case PropertyType.NAME:
-                    return vf.createValue(resolver.getJCRName((Name) val), PropertyType.NAME);
-                case PropertyType.STRING:
-                    return new StringValue((String) val);
-                default:
-                    throw new RepositoryException("illegal internal value type");
-            }
-        }
-    }
-
-    /**
-     * @deprecated
-     * @return the internal object
-     */
-    public Object internalValue() {
-        return val;
-    }
 
-    public BLOBFileValue getBLOBFileValue() {
+    BLOBFileValue getBLOBFileValue() {
         assert val != null && type == PropertyType.BINARY;
         return (BLOBFileValue) val;
     }
 
     public UUID getUUID() {
-        assert val != null && type == PropertyType.REFERENCE;
+        assert val != null && (type == PropertyType.REFERENCE || type == PropertyType.WEAKREFERENCE);
         return (UUID) val;
     }
 
-    public Name getQName() {
-        assert val != null && type == PropertyType.NAME;
-        return (Name) val;
-    }
-
     public Calendar getDate() {
         assert val != null && type == PropertyType.DATE;
         return (Calendar) val;
@@ -512,10 +433,8 @@
             return this;
         }
         BLOBFileValue v = (BLOBFileValue) val;
-        if (USE_DATA_STORE) {
-            if (v.isImmutable()) {
-                return this;
-            }
+        if (v.isImmutable()) {
+            return this;
         }
         // return a copy since the wrapped BLOBFileValue instance is mutable
         InputStream stream = v.getStream();
@@ -547,7 +466,7 @@
     public static InternalValue valueOf(String s, int type) {
         switch (type) {
             case PropertyType.BOOLEAN:
-                return create(Boolean.valueOf(s).booleanValue());
+                return create(Boolean.valueOf(s));
             case PropertyType.DATE:
                 return create(ISO8601.parse(s));
             case PropertyType.DOUBLE:
@@ -602,11 +521,11 @@
     }
 
     private InternalValue(long value) {
-        super(Long.valueOf(value));
+        super(value);
     }
 
     private InternalValue(double value) {
-        super(Double.valueOf(value));
+        super(value);
     }
 
     private InternalValue(Calendar value) {
@@ -614,15 +533,15 @@
     }
 
     private InternalValue(boolean value) {
-        super(Boolean.valueOf(value));
+        super(value);
     }
 
     private InternalValue(URI value) {
-        super(value, PropertyType.URI);
+        super(value);
     }
 
     private InternalValue(BigDecimal value) {
-        super(value, PropertyType.DECIMAL);
+        super(value);
     }
 
     private InternalValue(BLOBFileValue value) {
@@ -633,10 +552,6 @@
         super(value);
     }
 
-    private InternalValue(UUID value) {
-        super(value, PropertyType.REFERENCE);
-    }
-
     private InternalValue(UUID value, boolean weak) {
         super(value, weak ? PropertyType.WEAKREFERENCE : PropertyType.REFERENCE);
     }
@@ -649,6 +564,7 @@
      * @param in the input stream
      * @param temporary if the file should be deleted when discard is called (ignored if a data store is used)
      * @return the value
+     * @throws RepositoryException
      */
     private static BLOBFileValue getBLOBFileValue(DataStore store, InputStream in, boolean temporary) throws RepositoryException {
         int maxMemorySize;
@@ -705,22 +621,16 @@
      * @param dataStore the data store
      * @throws RepositoryException
      */
-    public void store(DataStore dataStore) throws RepositoryException, IOException {
-        assert USE_DATA_STORE;
+    public void store(DataStore dataStore) throws RepositoryException {
         assert dataStore != null;
         assert type == PropertyType.BINARY;
         BLOBFileValue v = (BLOBFileValue) val;
         if (v instanceof BLOBInDataStore) {
             // already in the data store, OK
             return;
-        } else if (v instanceof BLOBInMemory) {
-            if (v.getLength() < dataStore.getMinRecordLength()) {
-                // in memory and does not make sense to store, OK
-                return;
-            }
         }
-        // store the temp file to the data store, or (theoretically) load it in memory
-        val = getBLOBFileValue(dataStore, v.getStream(), false);
+        // store it in the data store
+        val = BLOBInDataStore.getInstance(dataStore, getStream());
     }
 
     //-------------------------------------------------------------< QValue >---
@@ -729,7 +639,7 @@
      */
     public long getLength() throws RepositoryException {
         if (PropertyType.BINARY == type) {
-            return ((BLOBFileValue) val).getLength();
+            return ((BLOBFileValue) val).getSize();
         } else {
             return super.getLength();
         }
@@ -763,4 +673,45 @@
             }
         }
     }
+
+    /**
+     * @see org.apache.jackrabbit.spi.QValue#getBinary()
+     */
+    public Binary getBinary() throws RepositoryException {
+        if (type == PropertyType.BINARY) {
+            return (BLOBFileValue) val;
+        } else {
+            try {
+                // convert via string
+                byte[] data = getString().getBytes(InternalValueFactory.DEFAULT_ENCODING);
+                return BLOBInMemory.getInstance(data);
+            } catch (UnsupportedEncodingException e) {
+                throw new RepositoryException(InternalValueFactory.DEFAULT_ENCODING + " is not supported encoding on this platform", e);
+            }
+        }
+    }
+
+    /**
+     * @see org.apache.jackrabbit.spi.QValue#discard()
+     */
+    public void discard() {
+        if (type == PropertyType.BINARY) {
+            BLOBFileValue bfv = (BLOBFileValue) val;
+            bfv.discard();
+        } else {
+            super.discard();
+        }
+    }
+
+    /**
+     * Delete persistent binary objects. This method does not delete objects in
+     * the data store.
+     */
+    public void deleteBinaryResource() {
+        if (type == PropertyType.BINARY) {
+            BLOBFileValue bfv = (BLOBFileValue) val;
+            bfv.delete(true);
+        }
+    }
+
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValueFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValueFactory.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValueFactory.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValueFactory.java Wed Jul  8 13:57:13 2009
@@ -16,6 +16,7 @@
  */
 package org.apache.jackrabbit.core.value;
 
+import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.QValue;
@@ -50,9 +51,12 @@
      */
     private static final Logger log = LoggerFactory.getLogger(InternalValueFactory.class);
 
-    private static final QValueFactory INSTANCE = new InternalValueFactory();
+    private static final QValueFactory INSTANCE = new InternalValueFactory(null);
 
-    private InternalValueFactory() {
+    private final DataStore store;
+
+    InternalValueFactory(DataStore store) {
+        this.store = store;
     }
 
     public static QValueFactory getInstance() {
@@ -133,20 +137,24 @@
         return InternalValue.create(value);
     }
 
+    public QValue create(URI value) throws RepositoryException {
+        return InternalValue.create(value);
+    }
+
+    public QValue create(BigDecimal value) throws RepositoryException {
+        return InternalValue.create(value);
+    }
+
     public QValue create(byte[] value) throws RepositoryException {
         return InternalValue.create(value);
     }
 
     public QValue create(InputStream value) throws RepositoryException, IOException {
-        return InternalValue.create(value);
+        return InternalValue.create(value, store);
     }
 
     public QValue create(File value) throws RepositoryException, IOException {
-        if (InternalValue.USE_DATA_STORE) {
-            InputStream in = new FileInputStream(value);
-            return InternalValue.createTemporary(in);
-        } else {
-            return InternalValue.create(value);
-        }
+        InputStream in = new FileInputStream(value);
+        return InternalValue.createTemporary(in);
     }
 }
\ No newline at end of file

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/ValueFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/ValueFactoryImpl.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/ValueFactoryImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/ValueFactoryImpl.java Wed Jul  8 13:57:13 2009
@@ -16,12 +16,15 @@
  */
 package org.apache.jackrabbit.core.value;
 
+import org.apache.jackrabbit.core.data.DataIdentifier;
+import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
 import org.apache.jackrabbit.spi.commons.value.ValueFactoryQImpl;
 import org.apache.jackrabbit.spi.QValue;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.jcr.Binary;
 import javax.jcr.Value;
 import javax.jcr.PropertyType;
 import javax.jcr.ValueFormatException;
@@ -39,6 +42,8 @@
      */
     private static final Logger log = LoggerFactory.getLogger(ValueFactoryImpl.class);
 
+    private final DataStore store;
+
     /**
      * Constructs a new <code>ValueFactoryQImpl</code> based
      * on an existing SPI <code>QValueFactory</code> and a
@@ -46,8 +51,9 @@
      *
      * @param resolver wrapped <code>NamePathResolver</code>
      */
-    public ValueFactoryImpl(NamePathResolver resolver) {
-        super(InternalValueFactory.getInstance(), resolver);
+    public ValueFactoryImpl(NamePathResolver resolver, DataStore store) {
+        super(new InternalValueFactory(store), resolver);
+        this.store = store;
     }
 
     public Value createValue(QValue qvalue) {
@@ -56,12 +62,30 @@
                 return new BinaryValueImpl(((InternalValue) qvalue).getBLOBFileValue());
             } catch (RepositoryException e) {
                 // should not get here
-                log.error(e.getMessage());
+                log.error(e.getMessage(), e);
             }
         }
         return super.createValue(qvalue);
     }
 
+    public Value createValue(Binary binary) {
+        try {
+            if (binary instanceof BLOBInDataStore) {
+                DataIdentifier identifier = ((BLOBInDataStore) binary).getDataIdentifier();
+                InternalValue value = InternalValue.getInternalValue(identifier, store);
+                if (value != null) {
+                    // if the value is already in this data store
+                    return new BinaryValueImpl(value.getBLOBFileValue());
+                }
+            }
+            return createValue(binary.getStream());
+        } catch (RepositoryException e) {
+            log.error(e.getMessage(), e);
+            // ignore - the super method may be smarter
+        }
+        return super.createValue(binary);
+    }
+
     public Value createValue(InputStream value) {
         try {
             InternalValue qvalue = (InternalValue) getQValueFactory().create(value);
@@ -76,7 +100,7 @@
     public Value createValue(String value, int type) throws ValueFormatException {
         if (PropertyType.BINARY == type) {
             try {
-                InternalValue qvalue = (InternalValue) getQValueFactory().create(value, type);                
+                InternalValue qvalue = (InternalValue) getQValueFactory().create(value, type);
                 return new BinaryValueImpl(qvalue.getBLOBFileValue());
             } catch (RepositoryException e) {
                 throw new ValueFormatException(e);

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/AbstractVersionManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/AbstractVersionManager.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/AbstractVersionManager.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/AbstractVersionManager.java Wed Jul  8 13:57:13 2009
@@ -16,32 +16,36 @@
  */
 package org.apache.jackrabbit.core.version;
 
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.ReferentialIntegrityException;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+import javax.jcr.version.VersionException;
+
 import org.apache.jackrabbit.core.NodeId;
 import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 import org.apache.jackrabbit.core.state.DefaultISMLocking;
+import org.apache.jackrabbit.core.state.ISMLocking.ReadLock;
+import org.apache.jackrabbit.core.state.ISMLocking.WriteLock;
 import org.apache.jackrabbit.core.state.ItemStateException;
 import org.apache.jackrabbit.core.state.LocalItemStateManager;
+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.ISMLocking.ReadLock;
-import org.apache.jackrabbit.core.state.ISMLocking.WriteLock;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
+import org.apache.jackrabbit.uuid.UUID;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.Value;
-import javax.jcr.ItemNotFoundException;
-import javax.jcr.version.VersionException;
-
 /**
  * Base implementation of the {@link VersionManager} interface.
  * <p/>
- * All read operations must aquire the read lock before reading, all write
- * operations must aquire the write lock.
+ * All read operations must acquire the read lock before reading, all write
+ * operations must acquire the write lock.
  */
 abstract class AbstractVersionManager implements VersionManager {
 
@@ -66,6 +70,11 @@
     protected NodeStateEx historyRoot;
 
     /**
+     * Persistent root node of the activities.
+     */
+    protected NodeStateEx activitiesRoot;
+
+    /**
      * the lock on this version manager
      */
     private final DefaultISMLocking rwLock = new DefaultISMLocking();
@@ -91,6 +100,18 @@
     /**
      * {@inheritDoc}
      */
+    public InternalActivity getActivity(NodeId id) throws RepositoryException {
+        // lock handling via getItem()
+        InternalActivity v = (InternalActivity) getItem(id);
+        if (v == null) {
+            log.warn("Versioning item not found: " + id);
+        }
+        return v;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
     public InternalVersionHistory getVersionHistory(NodeId id)
             throws RepositoryException {
         // lock handling via getItem()
@@ -107,7 +128,7 @@
             String uuid = id.getUUID().toString();
             Name name = getName(uuid);
 
-            NodeStateEx parent = getParentNode(uuid, false);
+            NodeStateEx parent = getParentNode(historyRoot, uuid, null);
             if (parent != null && parent.hasNode(name)) {
                 NodeStateEx history = parent.getNode(name, 1);
                 return getVersionHistory(history.getNodeId());
@@ -137,6 +158,7 @@
 
     /**
      * Acquires the write lock on this version manager.
+     * @return returns the write lock
      */
     protected WriteLock acquireWriteLock() {
         while (true) {
@@ -150,6 +172,7 @@
 
     /**
      * acquires the read lock on this version manager.
+     * @return returns the read lock
      */
     protected ReadLock acquireReadLock() {
         while (true) {
@@ -246,7 +269,8 @@
     /**
      * {@inheritDoc}
      */
-    public VersionHistoryInfo getVersionHistory(Session session, NodeState node)
+    public VersionHistoryInfo getVersionHistory(Session session, NodeState node,
+                                                NodeId copiedFrom)
             throws RepositoryException {
         VersionHistoryInfo info = null;
 
@@ -255,7 +279,7 @@
             String uuid = node.getNodeId().getUUID().toString();
             Name name = getName(uuid);
 
-            NodeStateEx parent = getParentNode(uuid, false);
+            NodeStateEx parent = getParentNode(historyRoot, uuid, null);
             if (parent != null && parent.hasNode(name)) {
                 NodeStateEx history = parent.getNode(name, 1);
                 Name root = NameConstants.JCR_ROOTVERSION;
@@ -268,7 +292,7 @@
         }
 
         if (info == null) {
-            info = createVersionHistory(session, node);
+            info = createVersionHistory(session, node, copiedFrom);
         }
 
         return info;
@@ -279,19 +303,22 @@
      * a new 'mix:versionable' node or when adding the 'mix:versionable' mixin
      * to a node.
      *
-     * @param session
-     * @param node NodeState
+     * @param session repository session
+     * @param node versionable node state
+     * @param copiedFrom node id for the jcr:copiedFrom property
      * @return identifier of the new version history node
-     * @throws RepositoryException
-     * @see #getVersionHistory(Session, NodeState)
+     * @throws RepositoryException if an error occurrs
+     * @see #getVersionHistory(Session, NodeState, NodeId)
      */
-    protected abstract VersionHistoryInfo createVersionHistory(
-            Session session, NodeState node) throws RepositoryException;
+    protected abstract VersionHistoryInfo createVersionHistory(Session session,
+                                                               NodeState node,
+                                                               NodeId copiedFrom)
+            throws RepositoryException;
 
     /**
      * Returns the item with the given persistent id. Subclass responsibility.
      * <p/>
-     * Please note, that the overridden method must aquire the readlock before
+     * Please note, that the overridden method must acquire the readlock before
      * reading the state manager.
      *
      * @param id the id of the item
@@ -312,34 +339,48 @@
 
     /**
      * Checks if there are item references (from outside the version storage)
-     * that reference the given version item. Subclass responsiblity.
+     * that reference the given node. Subclass responsibility.
      * <p/>
-     * Please note, that the overridden method must aquire the readlock before
+     * Please note, that the overridden method must acquire the readlock before
      * reading the state manager.
      *
-     * @param item version item
+     * @param id the id of the node
      * @return <code>true</code> if there are item references from outside the
      *         version storage; <code>false</code> otherwise.
      * @throws RepositoryException if an error occurs while reading from the
      *                             repository.
      */
-    protected abstract boolean hasItemReferences(InternalVersionItem item)
+    protected abstract boolean hasItemReferences(NodeId id)
+            throws RepositoryException;
+
+    /**
+     * Returns the node with the given persistent id. Subclass responsibility.
+     * <p/>
+     * Please note, that the overridden method must acquire the readlock before
+     * reading the state manager.
+     *
+     * @param id the id of the node
+     * @throws RepositoryException if an error occurs while reading from the
+     *                             repository.
+     */
+    protected abstract NodeStateEx getNodeStateEx(NodeId id)
             throws RepositoryException;
 
     /**
      * Creates a new Version History.
      *
      * @param node the node for which the version history is to be initialized
+     * @param copiedFrom node id for the jcr:copiedFrom parameter
      * @return the identifiers of the newly created version history and root version
-     * @throws javax.jcr.RepositoryException
+     * @throws RepositoryException if an error occurs
      */
-    NodeStateEx createVersionHistory(NodeState node)
+    NodeStateEx internalCreateVersionHistory(NodeState node, NodeId copiedFrom)
             throws RepositoryException {
         WriteOperation operation = startWriteOperation();
         try {
             // create deep path
             String uuid = node.getNodeId().getUUID().toString();
-            NodeStateEx parent = getParentNode(uuid, true);
+            NodeStateEx parent = getParentNode(historyRoot, uuid, NameConstants.REP_VERSIONSTORAGE);
             Name name = getName(uuid);
             if (parent.hasNode(name)) {
                 // already exists
@@ -348,7 +389,7 @@
 
             // create new history node in the persistent state
             NodeStateEx history =
-                InternalVersionHistoryImpl.create(this, parent, name, node);
+                InternalVersionHistoryImpl.create(this, parent, name, node, copiedFrom);
 
             // end update
             operation.save();
@@ -365,11 +406,89 @@
     }
 
     /**
+     * Creates a new activity.
+     *
+     * @param title title of the new activity
+     * @return the id of the newly created activity
+     * @throws RepositoryException if an error occurs
+     */
+    NodeStateEx internalCreateActivity(String title)
+            throws RepositoryException {
+        WriteOperation operation = startWriteOperation();
+        try {
+            // create deep path
+            NodeId activityId = new NodeId(UUID.randomUUID());
+            NodeStateEx parent = getParentNode(activitiesRoot, activityId.toString(), NameConstants.REP_ACTIVITIES);
+            Name name = getName(activityId.toString());
+
+            // create new activity node in the persistent state
+            NodeStateEx pNode = InternalActivityImpl.create(parent, name, activityId, title);
+
+            // end update
+            operation.save();
+
+            log.debug("Created new activity " + activityId
+                    + " with title " + title + ".");
+            return pNode;
+        } catch (ItemStateException e) {
+            throw new RepositoryException(e);
+        } finally {
+            operation.close();
+        }
+    }
+
+    /**
+     * Removes the specified activity
+     *
+     * @param activity the acitvity to remove
+     * @throws javax.jcr.RepositoryException if any other error occurs.
+     */
+    protected void internalRemoveActivity(InternalActivityImpl activity)
+            throws RepositoryException {
+        WriteOperation operation = startWriteOperation();
+        try {
+            // check if the activity has any references in the workspaces
+            NodeId nodeId = activity.getId();
+            NodeReferencesId refId = new NodeReferencesId(nodeId);
+            if (stateMgr.hasNodeReferences(refId)) {
+                NodeReferences refs = stateMgr.getNodeReferences(refId);
+                if (refs.hasReferences()) {
+                    throw new ReferentialIntegrityException("Unable to delete activity. still referenced.");
+                }
+            }
+            // TODO:
+            // check if the activity is used in anywhere in the version storage
+            // and reject removal
+
+            // remove activity and possible empty parent directories
+            NodeStateEx act = getNodeStateEx(nodeId);
+            NodeId parentId = act.getParentId();
+            Name name = act.getName();
+            while (parentId != null) {
+                NodeStateEx parent = getNodeStateEx(parentId);
+                parent.removeNode(name);
+                parent.store();
+                if (parent.getChildNodes().length == 0 && !parentId.equals(activitiesRoot.getNodeId())) {
+                    name = parent.getName();
+                    parentId = parent.getParentId();
+                } else {
+                    parentId = null;
+                }
+            }
+            operation.save();
+        } catch (ItemStateException e) {
+            log.error("Error while storing: " + e.toString());
+        } finally {
+            operation.close();
+        }
+    }
+
+    /**
      * Utility method that returns the given string as a name in the default
      * namespace.
      *
      * @param name string name
-     * @return qualified name
+     * @return A <code>Name</code> object.
      */
     private Name getName(String name) {
         return NameFactoryImpl.getInstance().create(Name.NS_DEFAULT_URI, name);
@@ -378,24 +497,26 @@
     /**
      * Utility method that returns the parent node under which the version
      * history of the identified versionable node is or will be stored. If
-     * the create flag is set, then the returned parent node and any ancestor
-     * nodes are automatically created if they do not already exist. Otherwise
+     * the <code>interNT</code> is not <code>null</code> then the returned
+     * parent node and any ancestor nodes are automatically created if they do
+     * not already exist. Otherwise
      * <code>null</code> is returned if the parent node does not exist.
      *
+     * @param parent the parent node
      * @param uuid UUID of a versionable node
-     * @param create whether to create missing nodes
+     * @param interNT intermediate nodetype.
      * @return parent node of the version history, or <code>null</code>
      * @throws RepositoryException if an error occurs
      */
-    private NodeStateEx getParentNode(String uuid, boolean create)
+    private NodeStateEx getParentNode(NodeStateEx parent, String uuid, Name interNT)
             throws RepositoryException {
-        NodeStateEx n = historyRoot;
+        NodeStateEx n = parent;
         for (int i = 0; i < 3; i++) {
             Name name = getName(uuid.substring(i * 2, i * 2 + 2));
             if (n.hasNode(name)) {
                 n = n.getNode(name, 1);
-            } else if (create) {
-                n.addNode(name, NameConstants.REP_VERSIONSTORAGE, null, false);
+            } else if (interNT != null) {
+                n.addNode(name, interNT, null, false);
                 n.store();
                 n = n.getNode(name, 1);
             } else {
@@ -415,13 +536,21 @@
      * @throws javax.jcr.RepositoryException if an error occurs
      * @see javax.jcr.Node#checkin()
      */
-    protected InternalVersion checkin(InternalVersionHistoryImpl history,
+    protected InternalVersion internalCheckin(InternalVersionHistoryImpl history,
                                       NodeImpl node, boolean simple)
             throws RepositoryException {
         WriteOperation operation = startWriteOperation();
         try {
             String versionName = calculateCheckinVersionName(history, node, simple);
             InternalVersionImpl v = history.checkin(NameFactoryImpl.getInstance().create("", versionName), node);
+
+            // check for jcr:activity
+            if (node.hasProperty(NameConstants.JCR_ACTIVITY)) {
+                NodeId actId = new NodeId(node.getProperty(NameConstants.JCR_ACTIVITY).internalGetValue().getUUID());
+                InternalActivityImpl act = (InternalActivityImpl) getItem(actId);
+                act.addVersion(v);
+            }
+
             operation.save();
             return v;
         } catch (ItemStateException e) {
@@ -484,8 +613,8 @@
         } else {
             // 1. search a predecessor, suitable for generating the new name
             Value[] values = node.getProperty(NameConstants.JCR_PREDECESSORS).getValues();
-            for (int i = 0; i < values.length; i++) {
-                InternalVersion pred = history.getVersion(NodeId.valueOf(values[i].getString()));
+            for (Value value: values) {
+                InternalVersion pred = history.getVersion(NodeId.valueOf(value.getString()));
                 if (best == null
                         || pred.getName().getLocalName().length() < best.getName().getLocalName().length()) {
                     best = pred;
@@ -518,7 +647,7 @@
      *  not have a version with <code>name</code>.
      * @throws javax.jcr.RepositoryException if any other error occurs.
      */
-    protected void removeVersion(InternalVersionHistoryImpl history, Name name)
+    protected void internalRemoveVersion(InternalVersionHistoryImpl history, Name name)
             throws VersionException, RepositoryException {
         WriteOperation operation = startWriteOperation();
         try {
@@ -577,7 +706,7 @@
      * Invoked by the internal version item itself, when it's underlying
      * persistence state was discarded.
      *
-     * @param item
+     * @param item item that was discarded
      */
     protected void itemDiscarded(InternalVersionItem item) {
     }
@@ -609,6 +738,8 @@
                     return ((InternalVersionHistory) parent).getVersion(id);
                 } else if (ntName.equals(NameConstants.NT_VERSIONHISTORY)) {
                     return new InternalVersionHistoryImpl(this, pNode);
+                } else if (ntName.equals(NameConstants.NT_ACTIVITY)) {
+                    return new InternalActivityImpl(this, pNode);
                 } else {
                     return null;
                 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalFrozenNodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalFrozenNodeImpl.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalFrozenNodeImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalFrozenNodeImpl.java Wed Jul  8 13:57:13 2009
@@ -123,7 +123,7 @@
                 }
             } else if (prop.getName().equals(NameConstants.JCR_FROZENPRIMARYTYPE)) {
                 // special property
-                frozenPrimaryType = node.getPropertyValue(NameConstants.JCR_FROZENPRIMARYTYPE).getQName();
+                frozenPrimaryType = node.getPropertyValue(NameConstants.JCR_FROZENPRIMARYTYPE).getName();
             } else if (prop.getName().equals(NameConstants.JCR_FROZENMIXINTYPES)) {
                 // special property
                 InternalValue[] values = node.getPropertyValues(NameConstants.JCR_FROZENMIXINTYPES);
@@ -132,7 +132,7 @@
                 } else {
                     frozenMixinTypes = new Name[values.length];
                     for (int j = 0; j < values.length; j++) {
-                        frozenMixinTypes[j] = values[j].getQName();
+                        frozenMixinTypes[j] = values[j].getName();
                     }
                 }
             } else if (prop.getName().equals(NameConstants.JCR_PRIMARYTYPE)) {

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionHistoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionHistoryImpl.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionHistoryImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionHistoryImpl.java Wed Jul  8 13:57:13 2009
@@ -39,6 +39,7 @@
 import java.util.Iterator;
 import java.util.Set;
 import java.util.LinkedHashMap;
+import java.util.Map;
 
 /**
  * Implements a <code>InternalVersionHistory</code>
@@ -61,7 +62,7 @@
      * key = version label (String)
      * value = version name
      */
-    private HashMap labelCache = new HashMap();
+    private Map<Name, Name> labelCache = new HashMap<Name, Name>();
 
     /**
      * the root version of this history
@@ -73,19 +74,19 @@
      * key = version name
      * value = version id (NodeId)
      */
-    private LinkedHashMap/*<Name, NodeId>*/ nameCache = new LinkedHashMap/*<Name, NodeId>*/();
+    private Map<Name, NodeId> nameCache = new LinkedHashMap<Name, NodeId>();
 
     /**
      * the hashmap of all versions
      * key = version id (NodeId)
      * value = version
      */
-    private HashMap/*<NodeId, InternalVersion>*/ versionCache = new HashMap/*<NodeId, InternalVersion>*/();
+    private Map<NodeId, InternalVersion> versionCache = new HashMap<NodeId, InternalVersion>();
 
     /**
      * Temporary version cache, used on a refresh.
      */
-    private HashMap/*<NodeId, InternalVersion>*/ tempVersionCache = new HashMap/*<NodeId, InternalVersion>*/();
+    private Map<NodeId, InternalVersion> tempVersionCache = new HashMap<NodeId, InternalVersion>();
 
     /**
      * the node that holds the label nodes
@@ -136,8 +137,7 @@
         // init label cache
         try {
             PropertyState[] labels = labelNode.getProperties();
-            for (int i = 0; i < labels.length; i++) {
-                PropertyState pState = labels[i];
+            for (PropertyState pState : labels) {
                 if (pState.getType() == PropertyType.REFERENCE) {
                     Name labelName = pState.getName();
                     UUID ref = pState.getValues()[0].getUUID();
@@ -159,8 +159,7 @@
         // get version entries
         ChildNodeEntry[] children = (ChildNodeEntry[])
             node.getState().getChildNodeEntries().toArray();
-        for (int i = 0; i < children.length; i++) {
-            ChildNodeEntry child = children[i];
+        for (ChildNodeEntry child : children) {
             if (child.getName().equals(NameConstants.JCR_VERSIONLABELS)) {
                 continue;
             }
@@ -169,9 +168,7 @@
 
         // fix legacy
         if (rootVersion.getSuccessors().length == 0) {
-            Iterator iter = nameCache.keySet().iterator();
-            while (iter.hasNext()) {
-                Name versionName = (Name) iter.next();
+            for (Name versionName : nameCache.keySet()) {
                 InternalVersionImpl v = createVersionInstance(versionName);
                 v.legacyResolveSuccessors();
             }
@@ -188,9 +185,8 @@
         init();
 
         // invalidate all versions that are not referenced any more
-        Iterator iter = tempVersionCache.values().iterator();
-        while (iter.hasNext()) {
-            InternalVersionImpl v = (InternalVersionImpl) iter.next();
+        for (Object o : tempVersionCache.values()) {
+            InternalVersionImpl v = (InternalVersionImpl) o;
             v.invalidate();
         }
         tempVersionCache.clear();
@@ -210,10 +206,8 @@
             vMgr.versionCreated(v);
 
             // add labels
-            Iterator iter = labelCache.keySet().iterator();
-            while (iter.hasNext()) {
-                Name labelName = (Name) iter.next();
-                Name versionName = (Name) labelCache.get(labelName);
+            for (Name labelName: labelCache.keySet()) {
+                Name versionName = labelCache.get(labelName);
                 if (v.getName().equals(versionName)) {
                     v.internalAddLabel(labelName);
                 }
@@ -265,12 +259,12 @@
      * {@inheritDoc}
      */
     public InternalVersion getVersion(Name versionName) throws VersionException {
-        NodeId versionId = (NodeId) nameCache.get(versionName);
+        NodeId versionId = nameCache.get(versionName);
         if (versionId == null) {
             throw new VersionException("Version " + versionName + " does not exist.");
         }
 
-        InternalVersion v = (InternalVersion) versionCache.get(versionId);
+        InternalVersion v = versionCache.get(versionId);
         if (v == null) {
             v = createVersionInstance(versionName);
         }
@@ -288,11 +282,9 @@
      * {@inheritDoc}
      */
     public InternalVersion getVersion(NodeId id) {
-        InternalVersion v = (InternalVersion) versionCache.get(id);
+        InternalVersion v = versionCache.get(id);
         if (v == null) {
-            Iterator iter = nameCache.keySet().iterator();
-            while (iter.hasNext()) {
-                Name versionName = (Name) iter.next();
+            for (Name versionName : nameCache.keySet()) {
                 if (nameCache.get(versionName).equals(id)) {
                     v = createVersionInstance(versionName);
                     break;
@@ -306,13 +298,13 @@
      * {@inheritDoc}
      */
     public InternalVersion getVersionByLabel(Name label) {
-        Name versionName = (Name) labelCache.get(label);
+        Name versionName = labelCache.get(label);
         if (versionName == null) {
             return null;
         }
 
-        NodeId id = (NodeId) nameCache.get(versionName);
-        InternalVersion v = (InternalVersion) versionCache.get(id);
+        NodeId id = nameCache.get(versionName);
+        InternalVersion v = versionCache.get(id);
         if (v == null) {
             v = createVersionInstance(versionName);
         }
@@ -323,7 +315,7 @@
      * {@inheritDoc}
      */
     public Name[] getVersionNames() {
-        return (Name[]) nameCache.keySet().toArray(new Name[nameCache.size()]);
+        return nameCache.keySet().toArray(new Name[nameCache.size()]);
     }
     
     /**
@@ -344,7 +336,7 @@
      * {@inheritDoc}
      */
     public Name[] getVersionLabels() {
-        return (Name[]) labelCache.keySet().toArray(new Name[labelCache.size()]);
+        return labelCache.keySet().toArray(new Name[labelCache.size()]);
     }
 
     /**
@@ -375,19 +367,25 @@
             throw new VersionException(msg);
         }
         // check if any references (from outside the version storage) exist on this version
-        if (vMgr.hasItemReferences(v)) {
+        if (vMgr.hasItemReferences(v.getId())) {
             throw new ReferentialIntegrityException("Unable to remove version. At least once referenced.");
         }
 
         // unregister from labels
         Name[] labels = v.internalGetLabels();
-        for (int i = 0; i < labels.length; i++) {
-            v.internalRemoveLabel(labels[i]);
-            labelNode.removeProperty(labels[i]);
+        for (Name label : labels) {
+            v.internalRemoveLabel(label);
+            labelNode.removeProperty(label);
         }
         // detach from the version graph
         v.internalDetach();
 
+        // check if referenced by an activity
+        InternalActivityImpl activity = v.getActivity();
+        if (activity != null) {
+            activity.removeVersion(v);
+        }
+
         // remove from persistence state
         node.removeNode(v.getName());
 
@@ -396,12 +394,29 @@
         nameCache.remove(versionName);
         vMgr.versionDestroyed(v);
 
-        // store changes
-        node.store();
+        // Check if this was the last version in addition to the root version
+        if (!vMgr.hasItemReferences(node.getNodeId())) {
+            log.debug("Current version history has no references");
+            NodeStateEx[] childNodes = node.getChildNodes();
+
+            // Check if there is only root version and version labels nodes
+            if (childNodes.length == 2) {
+                log.debug("Removing orphan version history as it contains only two children");
+                NodeStateEx parentNode = vMgr.getNodeStateEx(node.getParentId());
+                // Remove version history node
+                parentNode.removeNode(node.getName());
+                // store changes for this node and his children
+                parentNode.store();
+            }
+        } else {
+            log.debug("Current version history has at least one reference");
+            // store changes
+            node.store();
+        }
 
         // now also remove from labelCache
-        for (int i = 0; i < labels.length; i++) {
-            labelCache.remove(labels[i]);
+        for (Name label : labels) {
+            labelCache.remove(label);
         }
     }
 
@@ -426,7 +441,7 @@
         if (versionName != null && version == null) {
             throw new VersionException("Version " + versionName + " does not exist in this version history.");
         }
-        Name prevName = (Name) labelCache.get(label);
+        Name prevName = labelCache.get(label);
         InternalVersionImpl prev = null;
         if (prevName == null) {
             if (version == null) {
@@ -509,6 +524,12 @@
         NodeId versionId = new NodeId(UUID.randomUUID());
         NodeStateEx vNode = node.addNode(name, NameConstants.NT_VERSION, versionId, true);
 
+        // check for jcr:activity
+        if (src.hasProperty(NameConstants.JCR_ACTIVITY)) {
+            InternalValue act = src.getProperty(NameConstants.JCR_ACTIVITY).internalGetValue();
+            vNode.setPropertyValue(NameConstants.JCR_ACTIVITY, act);
+        }
+
         // initialize 'created', 'predecessors' and 'successors'
         vNode.setPropertyValue(NameConstants.JCR_CREATED, InternalValue.create(getCurrentTime()));
         vNode.setPropertyValues(NameConstants.JCR_PREDECESSORS, PropertyType.REFERENCE, predecessors);
@@ -541,12 +562,13 @@
      * @param parent parent node
      * @param name history name
      * @param nodeState node state
+     * @param copiedFrom the id of the base version
      * @return new node state
      * @throws RepositoryException if an error occurs
      */
     static NodeStateEx create(
             AbstractVersionManager vMgr, NodeStateEx parent, Name name,
-            NodeState nodeState) throws RepositoryException {
+            NodeState nodeState, NodeId copiedFrom) throws RepositoryException {
 
         // create history node
         NodeId historyId = new NodeId(UUID.randomUUID());
@@ -559,6 +581,11 @@
         // create label node
         pNode.addNode(NameConstants.JCR_VERSIONLABELS, NameConstants.NT_VERSIONLABELS, null, false);
 
+        // initialize the 'jcr:copiedFrom' property
+        if (copiedFrom != null) {
+            pNode.setPropertyValue(NameConstants.JCR_COPIEDFROM, InternalValue.create(copiedFrom.getUUID(), true));
+        }
+        
         // create root version
         NodeId versionId = new NodeId(UUID.randomUUID());
         NodeStateEx vNode = pNode.addNode(NameConstants.JCR_ROOTVERSION, NameConstants.NT_VERSION, versionId, true);

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionImpl.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionImpl.java Wed Jul  8 13:57:13 2009
@@ -25,11 +25,11 @@
 
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.HashSet;
 import java.util.List;
+import java.util.ArrayList;
 
 /**
  * Implements a <code>InternalVersion</code>
@@ -45,7 +45,7 @@
     /**
      * the set of version labes of this history (values == String)
      */
-    private HashSet labelCache = null;
+    private HashSet<Name> labelCache = null;
 
     /**
      * specifies if this is the root version
@@ -208,8 +208,7 @@
      */
     public boolean isMoreRecent(InternalVersion v) {
         InternalVersion[] preds = getPredecessors();
-        for (int i = 0; i < preds.length; i++) {
-            InternalVersion pred = preds[i];
+        for (InternalVersion pred : preds) {
             if (pred.equals(v) || pred.isMoreRecent(v)) {
                 return true;
             }
@@ -281,14 +280,14 @@
     void internalDetach() throws RepositoryException {
         // detach this from all successors
         InternalVersion[] succ = getSuccessors();
-        for (int i = 0; i < succ.length; i++) {
-            ((InternalVersionImpl) succ[i]).internalDetachPredecessor(this, true);
+        for (InternalVersion aSucc : succ) {
+            ((InternalVersionImpl) aSucc).internalDetachPredecessor(this, true);
         }
 
         // detach cached successors from predecessors
         InternalVersion[] preds = getPredecessors();
-        for (int i = 0; i < preds.length; i++) {
-            ((InternalVersionImpl) preds[i]).internalDetachSuccessor(this, true);
+        for (InternalVersion pred : preds) {
+            ((InternalVersionImpl) pred).internalDetachSuccessor(this, true);
         }
 
         // clear properties
@@ -303,8 +302,8 @@
      */
     void internalAttach() throws RepositoryException {
         InternalVersion[] preds = getPredecessors();
-        for (int i = 0; i < preds.length; i++) {
-            ((InternalVersionImpl) preds[i]).internalAddSuccessor(this, true);
+        for (InternalVersion pred : preds) {
+            ((InternalVersionImpl) pred).internalAddSuccessor(this, true);
         }
     }
 
@@ -317,7 +316,7 @@
      */
     private void internalAddSuccessor(InternalVersionImpl succ, boolean store)
             throws RepositoryException {
-        List l = new ArrayList(Arrays.asList(getSuccessors()));
+        List<InternalVersion> l = new ArrayList<InternalVersion>(Arrays.asList(getSuccessors()));
         if (!l.contains(succ)) {
             l.add(succ);
             storeXCessors(l, NameConstants.JCR_SUCCESSORS, store);
@@ -337,7 +336,7 @@
     private void internalDetachPredecessor(InternalVersionImpl v, boolean store)
             throws RepositoryException {
         // remove 'v' from predecessor list
-        List l = new ArrayList(Arrays.asList(getPredecessors()));
+        List<InternalVersion> l = new ArrayList<InternalVersion>(Arrays.asList(getPredecessors()));
         l.remove(v);
 
         // attach V's predecessors
@@ -358,7 +357,7 @@
     private void internalDetachSuccessor(InternalVersionImpl v, boolean store)
             throws RepositoryException {
         // remove 'v' from successors list
-        List l = new ArrayList(Arrays.asList(getSuccessors()));
+        List<InternalVersion> l = new ArrayList<InternalVersion>(Arrays.asList(getSuccessors()));
         l.remove(v);
 
         // attach V's successors
@@ -374,7 +373,7 @@
      */
     boolean internalAddLabel(Name label) {
         if (labelCache == null) {
-            labelCache = new HashSet();
+            labelCache = new HashSet<Name>();
         }
         return labelCache.add(label);
     }
@@ -408,7 +407,7 @@
         if (labelCache == null) {
             return new Name[0];
         } else {
-            return (Name[]) labelCache.toArray(new Name[labelCache.size()]);
+            return labelCache.toArray(new Name[labelCache.size()]);
         }
     }
 
@@ -427,8 +426,8 @@
     void legacyResolveSuccessors() throws RepositoryException {
         InternalValue[] values = node.getPropertyValues(NameConstants.JCR_PREDECESSORS);
         if (values != null) {
-            for (int i = 0; i < values.length; i++) {
-                NodeId vId = new NodeId(values[i].getUUID());
+            for (InternalValue value : values) {
+                NodeId vId = new NodeId(value.getUUID());
                 InternalVersionImpl v = (InternalVersionImpl) versionHistory.getVersion(vId);
                 v.internalAddSuccessor(this, false);
             }
@@ -455,4 +454,18 @@
     public int hashCode() {
         return getId().hashCode();
     }
+
+    /**
+     * Returns the activity of this version or <code>null</code> if not defined
+     * @return the activity or <code>null</code>
+     * @throws RepositoryException if an error occurs
+     */
+    public InternalActivityImpl getActivity() throws RepositoryException {
+        if (node.hasProperty(NameConstants.JCR_ACTIVITY)) {
+            NodeId actId = new NodeId(node.getPropertyValue(NameConstants.JCR_ACTIVITY).getUUID());
+            return (InternalActivityImpl) vMgr.getItem(actId);
+        } else {
+            return null;
+        }
+    }
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/JcrVersionManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/JcrVersionManagerImpl.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/JcrVersionManagerImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/JcrVersionManagerImpl.java Wed Jul  8 13:57:13 2009
@@ -16,15 +16,25 @@
  */
 package org.apache.jackrabbit.core.version;
 
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.ItemNotFoundException;
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
 import javax.jcr.RepositoryException;
 import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionHistory;
 
+import org.apache.jackrabbit.core.ItemId;
+import org.apache.jackrabbit.core.LazyItemIterator;
+import org.apache.jackrabbit.core.NodeId;
 import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.SessionImpl;
-import javax.jcr.version.Version;
-import javax.jcr.version.VersionHistory;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.slf4j.LoggerFactory;
 import org.slf4j.Logger;
 
@@ -47,6 +57,12 @@
     private final SessionImpl session;
 
     /**
+     * the node id of the current activity
+     */
+    private NodeId currentActivity;
+
+
+    /**
      * Creates a new version manager for the given session
      * @param session workspace sesion
      */
@@ -58,7 +74,7 @@
      * {@inheritDoc}
      */
     public Version checkin(String absPath) throws RepositoryException {
-        return (Version) session.getNode(absPath).checkin();
+        return session.getNode(absPath).checkin();
     }
 
     /**
@@ -75,7 +91,7 @@
         // this is not quite correct, since the entire checkpoint operation
         // should be atomic
         Node node = session.getNode(absPath);
-        Version v = (Version) node.checkin();
+        Version v = node.checkin();
         node.checkout();
         return v;
     }
@@ -92,7 +108,7 @@
      */
     public VersionHistory getVersionHistory(String absPath)
             throws RepositoryException {
-        return (VersionHistory) session.getNode(absPath).getVersionHistory();
+        return session.getNode(absPath).getVersionHistory();
     }
 
     /**
@@ -100,7 +116,7 @@
      */
     public Version getBaseVersion(String absPath)
             throws RepositoryException {
-        return (Version) session.getNode(absPath).getBaseVersion();
+        return session.getNode(absPath).getBaseVersion();
     }
 
     /**
@@ -193,34 +209,142 @@
      * {@inheritDoc}
      */
     public Node setActivity(Node activity) throws RepositoryException {
-        throw new UnsupportedRepositoryOperationException("comming soon...");
+        Node oldActivity = getActivity();
+        if (activity == null) {
+            currentActivity = null;
+        } else {
+            NodeImpl actNode = (NodeImpl) activity;
+            if (!actNode.isNodeType(NameConstants.NT_ACTIVITY)) {
+                throw new UnsupportedRepositoryOperationException("Given node is not an activity.");
+            }
+            currentActivity = actNode.getNodeId();
+        }
+        return oldActivity;
     }
 
     /**
      * {@inheritDoc}
      */
     public Node getActivity() throws RepositoryException {
-        throw new UnsupportedRepositoryOperationException("comming soon...");
+        if (currentActivity == null) {
+            return null;
+        } else {
+            return session.getNodeById(currentActivity);
+        }
     }
 
     /**
      * {@inheritDoc}
      */
     public Node createActivity(String title) throws RepositoryException {
-        throw new UnsupportedRepositoryOperationException("comming soon...");
+        NodeId id = session.getVersionManager().createActivity(session, title);
+        return session.getNodeById(id);
     }
 
     /**
      * {@inheritDoc}
      */
-    public Node removeActivity(String title) throws RepositoryException {
-        throw new UnsupportedRepositoryOperationException("comming soon...");
+    public void removeActivity(Node node) throws RepositoryException {
+        NodeImpl actNode = (NodeImpl) node;
+        if (!actNode.isNodeType(NameConstants.NT_ACTIVITY)) {
+            throw new UnsupportedRepositoryOperationException("Given node is not an activity.");
+        }
+        NodeId actId = actNode.getNodeId();
+        session.getVersionManager().removeActivity(session, actId);
+        if (actId.equals(currentActivity)) {
+            currentActivity = null;
+        }
     }
 
     /**
      * {@inheritDoc}
      */
     public NodeIterator merge(Node activityNode) throws RepositoryException {
-        throw new UnsupportedRepositoryOperationException("comming soon...");
+        NodeImpl actNode = (NodeImpl) activityNode;
+        if (!actNode.isNodeType(NameConstants.NT_ACTIVITY)) {
+            throw new UnsupportedRepositoryOperationException("Given node is not an activity.");
+        }
+        InternalActivity activity = session.getVersionManager().getActivity(actNode.getNodeId());
+        if (activity == null) {
+            throw new UnsupportedRepositoryOperationException("Given activity not found.");
+        }
+        boolean success = false;
+        try {
+            NodeIterator ret = internalMerge(activity);
+            session.save();
+            success = true;
+            return ret;
+        } finally {
+            if (!success) {
+                // revert session
+                try {
+                    log.debug("reverting changes applied during merge...");
+                    session.refresh(false);
+                } catch (RepositoryException e) {
+                    log.error("Error while reverting changes applied merge restore.", e);
+                }
+            }
+        }
+    }
+
+    /**
+     * Internally does the merge without saving the changes.
+     * @param activity internal activity
+     * @throws RepositoryException if an error occurs
+     * @return a node iterator of all failed nodes
+     */
+    private NodeIterator internalMerge(InternalActivity activity)
+            throws RepositoryException {
+        List<ItemId> failedIds = new ArrayList<ItemId>();
+        Map<NodeId, InternalVersion> changeSet = activity.getChangeSet();
+        ChangeSetVersionSelector vsel = new ChangeSetVersionSelector(changeSet);
+        Iterator<NodeId> iter = changeSet.keySet().iterator();
+        while (iter.hasNext()) {
+            InternalVersion v = changeSet.remove(iter.next());
+            NodeId nodeId = new NodeId(v.getVersionHistory().getVersionableUUID());
+            try {
+                NodeImpl node = session.getNodeById(nodeId);
+                InternalVersion base = ((VersionImpl) node.getBaseVersion()).getInternalVersion();
+                VersionImpl version = (VersionImpl) session.getNodeById(v.getId());
+                // if base version is newer than version, add to failed list
+                // but merge it anyways
+                if (base.isMoreRecent(version.getInternalVersion())) {
+                    failedIds.add(node.getNodeId());
+                    // should we add it to the jcr:mergeFailed property ?
+                } else {
+                    Version[] vs = node.internalRestore(version, vsel, true);
+                    for (Version restored: vs) {
+                        changeSet.remove(((VersionImpl) restored).getNodeId());
+                    }
+                }
+            } catch (ItemNotFoundException e) {
+                // ignore nodes not present in this workspace (not best practice)
+            }
+
+            // reset iterator
+            iter = changeSet.keySet().iterator();
+        }
+        return new LazyItemIterator(session.getItemManager(), failedIds);
+    }
+
+    /**
+     * Internal version selector that selects the version in the changeset.
+     */
+    private class ChangeSetVersionSelector implements VersionSelector {
+
+        private final Map<NodeId, InternalVersion> changeSet;
+
+        private ChangeSetVersionSelector(Map<NodeId, InternalVersion> changeSet) {
+            this.changeSet = changeSet;
+        }
+
+        public Version select(VersionHistory vh) throws RepositoryException {
+            InternalVersion v = changeSet.get(((VersionHistoryImpl) vh).getNodeId());
+            if (v != null) {
+                return (Version) session.getNodeById(v.getId());
+            } else {
+                return null;
+            }
+        }
     }
 }
\ No newline at end of file

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/NodeStateEx.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/NodeStateEx.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/NodeStateEx.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/NodeStateEx.java Wed Jul  8 13:57:13 2009
@@ -40,6 +40,7 @@
 import java.util.Set;
 
 import javax.jcr.RepositoryException;
+import javax.jcr.PropertyType;
 import javax.jcr.nodetype.ConstraintViolationException;
 import javax.jcr.nodetype.NoSuchNodeTypeException;
 
@@ -436,6 +437,19 @@
     }
 
     /**
+     * Sets the given mixin types
+     * @param mixinTypeNames the mixin type names
+     * @throws RepositoryException if an error occurs
+     */
+    public void setMixins(Set<Name> mixinTypeNames) throws RepositoryException {
+        nodeState.setMixinTypeNames(mixinTypeNames);
+        // update jcr:mixinTypes property
+        setPropertyValues(NameConstants.JCR_MIXINTYPES, PropertyType.NAME,
+                InternalValue.create(
+                        mixinTypeNames.toArray(new Name[mixinTypeNames.size()]))
+        );
+    }
+    /**
      * creates a new child node
      *
      * @param name



Mime
View raw message