You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2009/09/08 18:09:45 UTC

svn commit: r812570 [5/24] - in /jackrabbit/sandbox/JCR-1456: ./ jackrabbit-api/ jackrabbit-api/src/main/appended-resources/ jackrabbit-api/src/main/appended-resources/META-INF/ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/ jackrabbi...

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyData.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyData.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyData.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyData.java Tue Sep  8 16:09:28 2009
@@ -17,6 +17,8 @@
 package org.apache.jackrabbit.core;
 
 import javax.jcr.nodetype.PropertyDefinition;
+import javax.jcr.RepositoryException;
+
 import org.apache.jackrabbit.core.state.PropertyState;
 
 /**
@@ -28,10 +30,10 @@
      * Create a new instance of this class.
      *
      * @param state associated property state
-     * @param definition associated property definition
+     * @param itemMgr item manager
      */
-    PropertyData(PropertyState state, PropertyDefinition definition) {
-        super(state, definition);
+    PropertyData(PropertyState state, ItemManager itemMgr) {
+        super(state, itemMgr);
     }
 
     /**
@@ -47,8 +49,9 @@
      * Return the associated property definition.
      *
      * @return property definition
+     * @throws RepositoryException if the definition cannot be retrieved.
      */
-    public PropertyDefinition getPropertyDefinition() {
+    public PropertyDefinition getPropertyDefinition() throws RepositoryException {
         return (PropertyDefinition) getDefinition();
     }
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java Tue Sep  8 16:09:28 2009
@@ -17,6 +17,7 @@
 package org.apache.jackrabbit.core;
 
 import java.io.InputStream;
+import java.io.IOException;
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Calendar;
@@ -49,6 +50,7 @@
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.apache.jackrabbit.spi.commons.value.ValueFormat;
 import org.apache.jackrabbit.value.ValueHelper;
+import org.apache.commons.io.input.AutoCloseInputStream;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -226,12 +228,11 @@
             LockException, ConstraintViolationException,
             RepositoryException {
         NodeImpl parent = (NodeImpl) getParent();
-        PropertyDefinition definition = data.getPropertyDefinition();
         // check multi-value flag
-        if (multipleValues != definition.isMultiple()) {
+        if (multipleValues != isMultiple()) {
             String msg = (multipleValues) ?
                     "Single-valued property can not be set to an array of values:" :
-                    "Multivalued property can not be set to a single value (an array of lenght one is OK): ";
+                    "Multivalued property can not be set to a single value (an array of length one is OK): ";
             throw new ValueFormatException(msg + this);
         }
 
@@ -240,7 +241,7 @@
         session.getValidator().checkModify(this, options, Permission.NONE);
 
         // make sure the parent is checked-out and neither locked nor under retention
-        options = ItemValidator.CHECK_VERSIONING | ItemValidator.CHECK_LOCK |
+        options = ItemValidator.CHECK_CHECKED_OUT | ItemValidator.CHECK_LOCK |
                 ItemValidator.CHECK_HOLD | ItemValidator.CHECK_RETENTION;
         session.getValidator().checkModify(parent, options, Permission.NONE);
     }
@@ -259,14 +260,14 @@
             ((NodeImpl) getParent()).removeChildProperty(((PropertyId) id).getName());
             return;
         }
-        ArrayList list = new ArrayList();
+        ArrayList<InternalValue> list = new ArrayList<InternalValue>();
         // compact array (purge null entries)
-        for (int i = 0; i < values.length; i++) {
-            if (values[i] != null) {
-                list.add(values[i]);
+        for (InternalValue v : values) {
+            if (v != null) {
+                list.add(v);
             }
         }
-        values = (InternalValue[]) list.toArray(new InternalValue[list.size()]);
+        values = list.toArray(new InternalValue[list.size()]);
 
         // modify the state of this property
         PropertyState thisState = (PropertyState) getOrCreateTransientItemState();
@@ -414,7 +415,7 @@
      */
     public InternalValue[] internalGetValues() throws RepositoryException {
         final PropertyDefinition definition = data.getPropertyDefinition();
-        if (definition.isMultiple()) {
+        if (isMultiple()) {
             return getPropertyState().getValues();
         } else {
             throw new ValueFormatException(
@@ -433,7 +434,7 @@
      */
     public InternalValue internalGetValue() throws RepositoryException {
         final PropertyDefinition definition = data.getPropertyDefinition();
-        if (definition.isMultiple()) {
+        if (isMultiple()) {
             throw new ValueFormatException(
                     this + " is a multi-valued property,"
                     + " so it's values can only be retrieved as an array");
@@ -474,7 +475,14 @@
     }
 
     public InputStream getStream() throws RepositoryException {
-        return getValue().getStream();
+        final Binary bin = getValue().getBinary();
+        // make sure binary is disposed after stream had been consumed
+        return new AutoCloseInputStream(bin.getStream()) {
+            public void close() throws IOException {
+                super.close();
+                bin.dispose();
+            }
+        };
     }
 
     public long getLong() throws RepositoryException {
@@ -780,7 +788,7 @@
         // check state of this instance
         sanityCheck();
 
-        return data.getPropertyDefinition().isMultiple();
+        return getPropertyState().isMultiValued();
     }
 
     //-----------------------------------------------------------------< Item >

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java Tue Sep  8 16:09:28 2009
@@ -37,12 +37,12 @@
 import org.apache.jackrabbit.spi.Path;
 
 /**
- * <code>SecurityItemModifier</code>: An abstract helper class to allow classes
- * of the security API residing outside of the core package to modify and remove
- * protected items for security. The protected item definitions are required in
- * order not to have security relevant content being changed through common
- * item operations but forcing the usage of the security API. The latter asserts
- * that implementation specific constraints are not violated.
+ * <code>ProtectedItemModifier</code>: An abstract helper class to allow classes
+ * residing outside of the core package to modify and remove protected items.
+ * The protected item definitions are required in order not to have security
+ * relevant content being changed through common item operations but forcing
+ * the usage of the corresponding APIs, which assert that implementation
+ * specific constraints are not violated.
  */
 public abstract class ProtectedItemModifier {
 
@@ -74,7 +74,7 @@
 
         // check for name collisions
         // TODO: improve. copied from NodeImpl
-        NodeState thisState = (NodeState) parentImpl.getItemState();
+        NodeState thisState = parentImpl.getNodeState();
         ChildNodeEntry cne = thisState.getChildNodeEntry(name, 1);
         if (cne != null) {
             // there's already a child node entry with that name;
@@ -118,6 +118,17 @@
         return parentImpl.internalSetProperty(name, intVs);
     }
 
+    protected Property setProperty(NodeImpl parentImpl, Name name, Value[] values, int type) throws RepositoryException {
+        checkPermission(parentImpl, name, getPermission(false, false));
+        // validation: make sure Node is not locked or checked-in.
+        parentImpl.checkSetProperty();
+        InternalValue[] intVs = new InternalValue[values.length];
+        for (int i = 0; i < values.length; i++) {
+            intVs[i] = InternalValue.create(values[i], parentImpl.session);
+        }
+        return parentImpl.internalSetProperty(name, intVs, type);
+    }
+
     protected void removeItem(ItemImpl itemImpl) throws RepositoryException {
         NodeImpl n;
         if (itemImpl.isNode()) {

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java Tue Sep  8 16:09:28 2009
@@ -31,8 +31,6 @@
 import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 import org.apache.jackrabbit.core.persistence.PersistenceCopier;
-import org.apache.jackrabbit.core.state.ItemStateException;
-import org.apache.jackrabbit.core.version.VersionManagerImpl;
 import org.apache.jackrabbit.spi.Name;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -41,6 +39,14 @@
  * Tool for backing up or migrating the entire contents (workspaces,
  * version histories, namespaces, node types, etc.) of a repository to
  * a new repository. The target repository (if it exists) is overwritten.
+ * <p>
+ * No cluster journal records are written in the target repository. If the
+ * target repository is clustered, it should be the only node in the cluster.
+ * <p>
+ * The target repository needs to be fully reindexed after the copy operation.
+ * The static copy() methods will remove the target search index folders from
+ * their default locations to trigger automatic reindexing when the repository
+ * is next started.
  *
  * @since Apache Jackrabbit 1.6
  */
@@ -53,30 +59,110 @@
         LoggerFactory.getLogger(RepositoryCopier.class);
 
     /**
-     * Source repository configuration
+     * Source repository.
      */
-    private final RepositoryConfig sourceConfig;
+    private final RepositoryImpl source;
 
     /**
-     * Target repository configuration
+     * Target repository.
      */
-    private final RepositoryConfig targetConfig;
+    private final RepositoryImpl target;
 
     /**
-     * Creates a tool for copying the full contents of the source repository.
-     * The given source repository directory is expected to contain the
-     * repository configuration as a <code>repository.xml</code> file.
-     * The target repository directory should not already exist. It will be
-     * automatically created with default repository configuration.
+     * Copies the contents of the repository in the given source directory
+     * to a repository in the given target directory.
      *
      * @param source source repository directory
      * @param target target repository directory
-     * @throws RepositoryException if the repositories can not be accessed
+     * @throws RepositoryException if the copy operation fails
+     * @throws IOException if the target repository can not be initialized
+     */
+    public static void copy(File source, File target)
+            throws RepositoryException, IOException {
+        copy(RepositoryConfig.create(source), RepositoryConfig.install(target));
+    }
+
+    /**
+     * Copies the contents of the repository with the given configuration
+     * to a repository in the given target directory.
+     *
+     * @param source source repository configuration
+     * @param target target repository directory
+     * @throws RepositoryException if the copy operation fails
+     * @throws IOException if the target repository can not be initialized
+     */
+    public static void copy(RepositoryConfig source, File target)
+            throws RepositoryException, IOException {
+        copy(source, RepositoryConfig.install(target));
+    }
+
+    /**
+     * Copies the contents of the source repository with the given
+     * configuration to a target repository with the given configuration.
+     *
+     * @param source source repository configuration
+     * @param target target repository directory
+     * @throws RepositoryException if the copy operation fails
+     */
+    public static void copy(RepositoryConfig source, RepositoryConfig target)
+            throws RepositoryException {
+        RepositoryImpl repository = RepositoryImpl.create(source);
+        try {
+            copy(repository, target);
+        } finally {
+            repository.shutdown();
+        }
+    }
+
+    /**
+     * Copies the contents of the given source repository to a repository in
+     * the given target directory.
+     * <p>
+     * The source repository <strong>must not be modified</strong> while
+     * the copy operation is running to avoid an inconsistent copy.
+     *
+     * @param source source repository directory
+     * @param target target repository directory
+     * @throws RepositoryException if the copy operation fails
      * @throws IOException if the target repository can not be initialized
      */
-    public RepositoryCopier(File source, File target)
+    public static void copy(RepositoryImpl source, File target)
             throws RepositoryException, IOException {
-        this(RepositoryConfig.create(source), RepositoryConfig.install(target));
+        copy(source, RepositoryConfig.install(target));
+    }
+
+    /**
+     * Copies the contents of the given source repository to a target
+     * repository with the given configuration.
+     * <p>
+     * The source repository <strong>must not be modified</strong> while
+     * the copy operation is running to avoid an inconsistent copy.
+     *
+     * @param source source repository directory
+     * @param target target repository directory
+     * @throws RepositoryException if the copy operation fails
+     * @throws IOException if the target repository can not be initialized
+     */
+    public static void copy(RepositoryImpl source, RepositoryConfig target)
+            throws RepositoryException {
+        RepositoryImpl repository = RepositoryImpl.create(target);
+        try {
+            new RepositoryCopier(source, repository).copy();
+        } finally {
+            repository.shutdown();
+        }
+
+        // Remove index directories to force re-indexing on next startup
+        // TODO: There should be a cleaner way to do this
+        File targetDir = new File(target.getHomeDir());
+        File repoDir = new File(targetDir, "repository");
+        FileUtils.deleteQuietly(new File(repoDir, "index"));
+        File[] workspaces = new File(targetDir, "workspaces").listFiles();
+        if (workspaces != null) {
+            for (File workspace : workspaces) {
+                FileUtils.deleteQuietly(new File(workspace, "index"));
+            }
+        }
     }
 
     /**
@@ -84,18 +170,22 @@
      * to the given target repository. Any existing content in the target
      * repository will be overwritten.
      *
-     * @param source source repository configuration
-     * @param target target repository configuration
-     * @throws RepositoryException if the repositories can not be accessed
+     * @param source source repository
+     * @param target target repository
      */
-    public RepositoryCopier(RepositoryConfig source, RepositoryConfig target)
-            throws RepositoryException {
-        sourceConfig = source;
-        targetConfig = target;
+    public RepositoryCopier(RepositoryImpl source, RepositoryImpl target) {
+        this.source = source;
+        this.target = target;
     }
 
     /**
      * Copies the full content from the source to the target repository.
+     * <p>
+     * The source repository <strong>must not be modified</strong> while
+     * the copy operation is running to avoid an inconsistent copy.
+     * <p>
+     * This method leaves the search indexes of the target repository in
+     * an 
      * Note that both the source and the target repository must be closed
      * during the copy operation as this method requires exclusive access
      * to the repositories.
@@ -105,89 +195,65 @@
     public void copy() throws RepositoryException {
         logger.info(
                 "Copying repository content from {} to {}",
-                sourceConfig.getHomeDir(), targetConfig.getHomeDir());
-
-        RepositoryImpl source = RepositoryImpl.create(sourceConfig);
+                source.repConfig.getHomeDir(),
+                target.repConfig.getHomeDir());
         try {
-            RepositoryImpl target = RepositoryImpl.create(targetConfig);
-            try {
-                copyNamespaces(
-                        source.getNamespaceRegistry(),
-                        target.getNamespaceRegistry());
-                copyNodeTypes(
-                        source.getNodeTypeRegistry(),
-                        target.getNodeTypeRegistry());
-                copyVersionStore(
-                        source.getVersionManagerImpl(),
-                        target.getVersionManagerImpl());
-                copyWorkspaces(source, target);
-            } catch (InvalidNodeTypeDefException e) {
-                throw new RepositoryException("Failed to copy node types", e);
-            } catch (ItemStateException e) {
-                throw new RepositoryException("Failed to copy item states", e);
-            } finally {
-                target.shutdown();
-            }
-
-            // Remove index directories to force re-indexing on next startup
-            // TODO: There should be a cleaner way to do this
-            File targetDir = new File(targetConfig.getHomeDir());
-            File repoDir = new File(targetDir, "repository");
-            FileUtils.deleteQuietly(new File(repoDir, "index"));
-            File[] workspaces = new File(targetDir, "workspaces").listFiles();
-            if (workspaces != null) {
-                for (File workspace : workspaces) {
-                    FileUtils.deleteQuietly(new File(workspace, "index"));
-                }
-            }
-        } finally {
-            source.shutdown();
+            copyNamespaces();
+            copyNodeTypes();
+            copyVersionStore();
+            copyWorkspaces();
+        } catch (Exception e) {
+            throw new RepositoryException("Failed to copy content", e);
         }
     }
 
-    private void copyNamespaces(
-            NamespaceRegistry source, NamespaceRegistry target)
-            throws RepositoryException {
-        logger.info("Copying registered namespaces");
+    private void copyNamespaces() throws RepositoryException {
+        NamespaceRegistry sourceRegistry = source.getNamespaceRegistry();
+        NamespaceRegistry targetRegistry = target.getNamespaceRegistry();
 
-        Collection<String> existing = Arrays.asList(target.getURIs());
-        for (String uri : source.getURIs()) {
+        logger.info("Copying registered namespaces");
+        Collection<String> existing = Arrays.asList(targetRegistry.getURIs());
+        for (String uri : sourceRegistry.getURIs()) {
             if (!existing.contains(uri)) {
                 // TODO: what if the prefix is already taken?
-                target.registerNamespace(source.getPrefix(uri), uri);
+                targetRegistry.registerNamespace(
+                        sourceRegistry.getPrefix(uri), uri);
             }
         }
     }
 
-    private void copyNodeTypes(NodeTypeRegistry source, NodeTypeRegistry target)
-            throws RepositoryException, InvalidNodeTypeDefException {
-        logger.info("Copying registered node types");
+    private void copyNodeTypes() throws RepositoryException {
+        NodeTypeRegistry sourceRegistry = source.getNodeTypeRegistry();
+        NodeTypeRegistry targetRegistry = target.getNodeTypeRegistry();
 
+        logger.info("Copying registered node types");
         Collection<Name> existing =
-            Arrays.asList(target.getRegisteredNodeTypes());
+            Arrays.asList(targetRegistry.getRegisteredNodeTypes());
         Collection<NodeTypeDef> register = new ArrayList<NodeTypeDef>();
-        for (Name name : source.getRegisteredNodeTypes()) {
+        for (Name name : sourceRegistry.getRegisteredNodeTypes()) {
             // TODO: what about modified node types?
             if (!existing.contains(name)) {
-                register.add(source.getNodeTypeDef(name));
+                register.add(sourceRegistry.getNodeTypeDef(name));
             }
         }
-        target.registerNodeTypes(register);
+        try {
+            targetRegistry.registerNodeTypes(register);
+        } catch (InvalidNodeTypeDefException e) {
+            throw new RepositoryException("Unable to copy node types", e);
+        }
     }
 
-    private void copyVersionStore(
-            VersionManagerImpl source, VersionManagerImpl target)
-            throws RepositoryException, ItemStateException {
+    private void copyVersionStore() throws RepositoryException {
         logger.info("Copying version histories");
-
         PersistenceCopier copier = new PersistenceCopier(
-                source.getPersistenceManager(),
-                target.getPersistenceManager());
+                source.getVersionManagerImpl().getPersistenceManager(),
+                target.getVersionManagerImpl().getPersistenceManager(),
+                target.getDataStore());
         copier.copy(RepositoryImpl.VERSION_STORAGE_NODE_ID);
+        copier.copy(RepositoryImpl.ACTIVITIES_NODE_ID);
     }
 
-    private void copyWorkspaces(RepositoryImpl source, RepositoryImpl target)
-            throws RepositoryException, ItemStateException {
+    private void copyWorkspaces() throws RepositoryException {
         Collection<String> existing = Arrays.asList(target.getWorkspaceNames());
         for (String name : source.getWorkspaceNames()) {
             logger.info("Copying workspace {}" , name);
@@ -198,7 +264,8 @@
 
             PersistenceCopier copier = new PersistenceCopier(
                     source.getWorkspaceInfo(name).getPersistenceManager(),
-                    target.getWorkspaceInfo(name).getPersistenceManager());
+                    target.getWorkspaceInfo(name).getPersistenceManager(),
+                    target.getDataStore());
             copier.excludeNode(RepositoryImpl.SYSTEM_ROOT_NODE_ID);
             copier.copy(RepositoryImpl.ROOT_NODE_ID);
         }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java Tue Sep  8 16:09:28 2009
@@ -25,13 +25,21 @@
 import java.io.StringReader;
 import java.security.AccessControlContext;
 import java.security.AccessController;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
+import java.util.Iterator;
+import java.util.concurrent.Executors;
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
 
 import javax.jcr.AccessDeniedException;
 import javax.jcr.Credentials;
@@ -42,9 +50,10 @@
 import javax.jcr.Session;
 import javax.jcr.SimpleCredentials;
 import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+import javax.jcr.Repository;
+import javax.jcr.PropertyType;
 import javax.jcr.observation.Event;
-import javax.jcr.observation.EventIterator;
-import javax.jcr.observation.EventListener;
 import javax.jcr.observation.ObservationManager;
 import javax.security.auth.Subject;
 
@@ -97,9 +106,10 @@
 import org.apache.jackrabbit.core.state.SharedItemStateManager;
 import org.apache.jackrabbit.core.util.RepositoryLockMechanism;
 import org.apache.jackrabbit.core.util.db.ConnectionFactory;
-import org.apache.jackrabbit.core.version.VersionManager;
-import org.apache.jackrabbit.core.version.VersionManagerImpl;
+import org.apache.jackrabbit.core.version.InternalVersionManager;
+import org.apache.jackrabbit.core.version.InternalVersionManagerImpl;
 import org.apache.jackrabbit.core.xml.ClonedInputSource;
+import org.apache.jackrabbit.value.ValueFactoryImpl;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
 import org.apache.jackrabbit.spi.commons.namespace.RegistryNamespaceResolver;
@@ -116,7 +126,7 @@
  * A <code>RepositoryImpl</code> ...
  */
 public class RepositoryImpl extends AbstractRepository
-        implements javax.jcr.Repository, JackrabbitRepository, SessionListener, EventListener, WorkspaceListener {
+        implements javax.jcr.Repository, JackrabbitRepository, SessionListener, WorkspaceListener {
 
     private static Logger log = LoggerFactory.getLogger(RepositoryImpl.class);
 
@@ -136,35 +146,35 @@
     public static final NodeId VERSION_STORAGE_NODE_ID = NodeId.valueOf("deadbeef-face-babe-cafe-babecafebabe");
 
     /**
-     * hardcoded id of the "/jcr:system/jcr:versionStorage/jcr:activities" node
+     * hardcoded id of the "/jcr:system/jcr:activities" node
      */
     public static final NodeId ACTIVITIES_NODE_ID = NodeId.valueOf("deadbeef-face-babe-ac71-babecafebabe");
 
     /**
+     * hardcoded id of the "/jcr:system/jcr:configurations" node
+     */
+    public static final NodeId CONFIGURATIONS_NODE_ID = NodeId.valueOf("deadbeef-face-babe-c04f-babecafebabe");
+
+    /**
      * hardcoded id of the "/jcr:system/jcr:nodeTypes" node
      */
     public static final NodeId NODETYPES_NODE_ID = NodeId.valueOf("deadbeef-cafe-cafe-cafe-babecafebabe");
 
     /**
-     * the name of the file system resource containing the properties of the
-     * repository.
+     * the name of the resource containing customized descriptors of the repository.
      */
-    private static final String PROPERTIES_RESOURCE = "rep.properties";
+    private static final String PROPERTIES_RESOURCE = "repository.properties";
 
     /**
-     * the repository properties.
+     * the repository descriptors, maps String keys to Value/Value[] objects
      */
-    private final Properties repProps;
-
-    // names of well-known repository properties
-    public static final String STATS_NODE_COUNT_PROPERTY = "jcr.repository.stats.nodes.count";
-    public static final String STATS_PROP_COUNT_PROPERTY = "jcr.repository.stats.properties.count";
+    private final Map<String, DescriptorValue> repDescriptors = new HashMap<String, DescriptorValue>();
 
     private NodeId rootNodeId;
 
     private final NamespaceRegistryImpl nsReg;
     private final NodeTypeRegistry ntReg;
-    private final VersionManagerImpl vMgr;
+    private final InternalVersionManagerImpl vMgr;
     private final VirtualNodeTypeStateManager virtNTMgr;
 
     /**
@@ -206,13 +216,9 @@
     /**
      * active sessions (weak references)
      */
-    private final ReferenceMap activeSessions =
+    private final Map<SessionImpl, SessionImpl> activeSessions =
             new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.WEAK);
 
-    // misc. statistics
-    private long nodesCount;
-    private long propsCount;
-
     // flag indicating if repository has been shut down
     private boolean disposed;
 
@@ -253,6 +259,11 @@
     private WorkspaceEventChannel createWorkspaceEventChannel;
 
     /**
+     * Scheduled executor service.
+     */
+    protected final ScheduledExecutorService executor;
+
+    /**
      * Protected constructor.
      *
      * @param repConfig the repository configuration.
@@ -261,6 +272,10 @@
      *                             or another error occurs.
      */
     protected RepositoryImpl(RepositoryConfig repConfig) throws RepositoryException {
+        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(
+                Runtime.getRuntime().availableProcessors() * 2,
+                new ThreadPoolExecutor.CallerRunsPolicy());
+        this.executor = executor;
 
         // Acquire a lock on the repository home
         repLock = repConfig.getRepositoryLockMechanism();
@@ -293,10 +308,8 @@
             // init root node uuid
             rootNodeId = loadRootNodeId(metaDataStore);
 
-            // load repository properties
-            repProps = loadRepProps();
-            nodesCount = Long.parseLong(repProps.getProperty(STATS_NODE_COUNT_PROPERTY, "0"));
-            propsCount = Long.parseLong(repProps.getProperty(STATS_PROP_COUNT_PROPERTY, "0"));
+            // initialize repository descriptors
+            initRepositoryDescriptors();
 
             // create registries
             nsReg = createNamespaceRegistry(new BasedFileSystem(repStore, "/namespaces"));
@@ -457,7 +470,7 @@
      * @return the newly created version manager
      * @throws RepositoryException if an error occurs
      */
-    protected VersionManagerImpl createVersionManager(VersioningConfig vConfig,
+    protected InternalVersionManagerImpl createVersionManager(VersioningConfig vConfig,
                                                       DelegatingObservationDispatcher delegatingDispatcher)
             throws RepositoryException {
 
@@ -473,7 +486,7 @@
 
         ISMLocking ismLocking = vConfig.getISMLocking();
 
-        return new VersionManagerImpl(pm, fs, ntReg, delegatingDispatcher,
+        return new InternalVersionManagerImpl(pm, fs, ntReg, delegatingDispatcher,
                 SYSTEM_ROOT_NODE_ID,
                 VERSION_STORAGE_NODE_ID,
                 ACTIVITIES_NODE_ID,
@@ -698,7 +711,7 @@
         return ntReg;
     }
 
-    protected VersionManager getVersionManager() {
+    protected InternalVersionManager getVersionManager() {
         return vMgr;
     }
 
@@ -1113,17 +1126,16 @@
         // (copy sessions to array to avoid ConcurrentModificationException;
         // manually copy entries rather than calling ReferenceMap#toArray() in
         // order to work around  http://issues.apache.org/bugzilla/show_bug.cgi?id=25551)
-        SessionImpl[] sa;
+        List<SessionImpl> sa;
         synchronized (activeSessions) {
-            int cnt = 0;
-            sa = new SessionImpl[activeSessions.size()];
-            for (Iterator<SessionImpl> it = activeSessions.values().iterator(); it.hasNext(); cnt++) {
-                sa[cnt] = it.next();
+            sa = new ArrayList<SessionImpl>(activeSessions.size());
+            for (SessionImpl session : activeSessions.values()) {
+                sa.add(session);
             }
         }
-        for (int i = 0; i < sa.length; i++) {
-            if (sa[i] != null) {
-                sa[i].logout();
+        for (SessionImpl session : sa) {
+            if (session != null) {
+                session.logout();
             }
         }
 
@@ -1147,14 +1159,7 @@
             }
         }
 
-        if (repProps != null) {
-            // persist repository properties
-            try {
-                storeRepProps(repProps);
-            } catch (RepositoryException e) {
-                log.error("failed to persist repository properties", e);
-            }
-        }
+        repDescriptors.clear();
 
         if (dataStore != null) {
             try {
@@ -1180,6 +1185,18 @@
         // wake up threads waiting on this instance's monitor (e.g. workspace janitor)
         notifyAll();
 
+        // Shut down the executor service 
+        executor.shutdown();
+        try {
+            // Wait for all remaining background threads to terminate
+            if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
+                log.warn("Attempting to forcibly shutdown runaway threads");
+                executor.shutdownNow();
+            }
+        } catch (InterruptedException e) {
+            log.warn("Interrupted while waiting for background threads", e);
+        }
+
         // finally release repository lock
         if (repLock != null) {
             try {
@@ -1200,6 +1217,10 @@
         return repConfig;
     }
 
+    InternalVersionManagerImpl getVersionManagerImpl() {
+        return vMgr;
+    }
+
     /**
      * Returns the repository file system.
      * @return repository file system
@@ -1209,104 +1230,154 @@
     }
 
     /**
-     * Sets the default properties of the repository.
-     * <p/>
-     * This method loads the <code>Properties</code> from the
-     * <code>org/apache/jackrabbit/core/repository.properties</code> resource
-     * found in the class path and (re)sets the statistics properties, if not
-     * present.
-     *
-     * @param props the properties object to load
-     *
-     * @throws RepositoryException if the properties can not be loaded
-     */
-    protected void setDefaultRepositoryProperties(Properties props)
-            throws RepositoryException {
-        InputStream in = RepositoryImpl.class.getResourceAsStream("repository.properties");
-        try {
-            props.load(in);
-            in.close();
-
-            // set counts
-            if (!props.containsKey(STATS_NODE_COUNT_PROPERTY)) {
-                props.setProperty(STATS_NODE_COUNT_PROPERTY, Long.toString(nodesCount));
-            }
-            if (!props.containsKey(STATS_PROP_COUNT_PROPERTY)) {
-                props.setProperty(STATS_PROP_COUNT_PROPERTY, Long.toString(propsCount));
-            }
-        } catch (IOException e) {
-            String msg = "Failed to load repository properties: " + e.toString();
-            log.error(msg);
-            throw new RepositoryException(msg, e);
-        }
-    }
-
-    /**
-     * Loads the repository properties by executing the following steps:
+     * Initializes the repository descriptors by executing the following steps:
      * <ul>
-     * <li> if the {@link #PROPERTIES_RESOURCE} exists in the meta data store,
-     * the properties are loaded from that resource.</li>
-     * <li> {@link #setDefaultRepositoryProperties(Properties)} is called
-     * afterwards in order to initialize/update the repository properties
-     * since some default properties might have changed and need updating.</li>
-     * <li> finally {@link #storeRepProps(Properties)} is called in order to
-     * persist the newly generated properties.</li>
+     * <li>Sets standard descriptors</li>
+     * <li>{@link #getCustomRepositoryDescriptors()} is called
+     * afterwards in order to add custom/overwrite standard repository decriptors.</li>
      * </ul>
      *
-     * @return the newly loaded/initialized repository properties
-     *
      * @throws RepositoryException
      */
-    protected Properties loadRepProps() throws RepositoryException {
-        FileSystemResource propFile = new FileSystemResource(metaDataStore, PROPERTIES_RESOURCE);
-        try {
-            Properties props = new Properties();
-            if (propFile.exists()) {
-                InputStream in = propFile.getInputStream();
-                try {
-                    props.load(in);
-                } finally {
-                    in.close();
-                }
-            }
-            // now set the default props
-            setDefaultRepositoryProperties(props);
-
-            // and store
-            storeRepProps(props);
+    protected void initRepositoryDescriptors() throws RepositoryException {
 
-            return props;
-
-        } catch (Exception e) {
-            String msg = "failed to load repository properties";
-            log.debug(msg);
-            throw new RepositoryException(msg, e);
+        ValueFactory valFactory = ValueFactoryImpl.getInstance();
+        Value valTrue = valFactory.createValue(true);
+        Value valFalse = valFactory.createValue(false);
+
+        setDescriptor(Repository.REP_NAME_DESC, "Jackrabbit");
+        setDescriptor(Repository.REP_VENDOR_DESC, "Apache Software Foundation");
+        setDescriptor(Repository.REP_VENDOR_URL_DESC, "http://jackrabbit.apache.org/");
+        setDescriptor(Repository.SPEC_NAME_DESC, "Content Repository API for Java(TM) Technology Specification");
+        setDescriptor(Repository.SPEC_VERSION_DESC, "2.0");
+
+        setDescriptor(Repository.IDENTIFIER_STABILITY, Repository.IDENTIFIER_STABILITY_INDEFINITE_DURATION);
+        setDescriptor(Repository.LEVEL_1_SUPPORTED, valTrue);
+        setDescriptor(Repository.LEVEL_2_SUPPORTED, valTrue);
+        setDescriptor(Repository.WRITE_SUPPORTED, valTrue);
+        setDescriptor(Repository.OPTION_NODE_TYPE_MANAGEMENT_SUPPORTED, valTrue);
+        setDescriptor(Repository.NODE_TYPE_MANAGEMENT_AUTOCREATED_DEFINITIONS_SUPPORTED, valTrue);
+        setDescriptor(Repository.NODE_TYPE_MANAGEMENT_INHERITANCE, Repository.NODE_TYPE_MANAGEMENT_INHERITANCE_MULTIPLE);
+        setDescriptor(Repository.NODE_TYPE_MANAGEMENT_MULTIPLE_BINARY_PROPERTIES_SUPPORTED, valTrue);
+        setDescriptor(Repository.NODE_TYPE_MANAGEMENT_MULTIVALUED_PROPERTIES_SUPPORTED, valTrue);
+        setDescriptor(Repository.NODE_TYPE_MANAGEMENT_ORDERABLE_CHILD_NODES_SUPPORTED, valTrue);
+        setDescriptor(Repository.NODE_TYPE_MANAGEMENT_OVERRIDES_SUPPORTED, valFalse);
+        setDescriptor(Repository.NODE_TYPE_MANAGEMENT_PRIMARY_ITEM_NAME_SUPPORTED, valTrue);
+
+        Value[] types = new Value[] {
+                valFactory.createValue(PropertyType.BINARY),
+                valFactory.createValue(PropertyType.BOOLEAN),
+                valFactory.createValue(PropertyType.DATE),
+                valFactory.createValue(PropertyType.DECIMAL),
+                valFactory.createValue(PropertyType.DOUBLE),
+                valFactory.createValue(PropertyType.LONG),
+                valFactory.createValue(PropertyType.NAME),
+                valFactory.createValue(PropertyType.PATH),
+                valFactory.createValue(PropertyType.REFERENCE),
+                valFactory.createValue(PropertyType.STRING),
+                valFactory.createValue(PropertyType.URI),
+                valFactory.createValue(PropertyType.WEAKREFERENCE),
+                valFactory.createValue(PropertyType.UNDEFINED)
+        };
+        setDescriptor(Repository.NODE_TYPE_MANAGEMENT_PROPERTY_TYPES, types);
+
+        setDescriptor(Repository.NODE_TYPE_MANAGEMENT_RESIDUAL_DEFINITIONS_SUPPORTED, valTrue);
+        setDescriptor(Repository.NODE_TYPE_MANAGEMENT_SAME_NAME_SIBLINGS_SUPPORTED, valTrue);
+        setDescriptor(Repository.NODE_TYPE_MANAGEMENT_VALUE_CONSTRAINTS_SUPPORTED, valTrue);
+        setDescriptor(Repository.NODE_TYPE_MANAGEMENT_UPDATE_IN_USE_SUPORTED, valFalse);
+        setDescriptor(Repository.OPTION_ACCESS_CONTROL_SUPPORTED, valTrue);
+        setDescriptor(Repository.OPTION_JOURNALED_OBSERVATION_SUPPORTED, valTrue);
+        setDescriptor(Repository.OPTION_LIFECYCLE_SUPPORTED, valTrue);
+        setDescriptor(Repository.OPTION_LOCKING_SUPPORTED, valTrue);
+        setDescriptor(Repository.OPTION_OBSERVATION_SUPPORTED, valTrue);
+        setDescriptor(Repository.OPTION_NODE_AND_PROPERTY_WITH_SAME_NAME_SUPPORTED, valTrue);
+        setDescriptor(Repository.OPTION_QUERY_SQL_SUPPORTED, valTrue);
+        setDescriptor(Repository.OPTION_RETENTION_SUPPORTED, valTrue);
+        setDescriptor(Repository.OPTION_SHAREABLE_NODES_SUPPORTED, valTrue);
+        setDescriptor(Repository.OPTION_SIMPLE_VERSIONING_SUPPORTED, valTrue);
+        setDescriptor(Repository.OPTION_TRANSACTIONS_SUPPORTED, valTrue);
+        setDescriptor(Repository.OPTION_UNFILED_CONTENT_SUPPORTED, valFalse);
+        setDescriptor(Repository.OPTION_UPDATE_MIXIN_NODE_TYPES_SUPPORTED, valTrue);
+        setDescriptor(Repository.OPTION_UPDATE_PRIMARY_NODE_TYPE_SUPPORTED, valTrue);
+        setDescriptor(Repository.OPTION_VERSIONING_SUPPORTED, valTrue);
+        setDescriptor(Repository.OPTION_WORKSPACE_MANAGEMENT_SUPPORTED, valTrue);
+        setDescriptor(Repository.OPTION_XML_EXPORT_SUPPORTED, valTrue);
+        setDescriptor(Repository.OPTION_XML_IMPORT_SUPPORTED, valTrue);
+        setDescriptor(Repository.OPTION_ACTIVITIES_SUPPORTED, valTrue);
+        setDescriptor(Repository.OPTION_BASELINES_SUPPORTED, valTrue);
+
+        setDescriptor(Repository.QUERY_FULL_TEXT_SEARCH_SUPPORTED, valTrue);
+        setDescriptor(Repository.QUERY_JOINS, Repository.QUERY_JOINS_INNER_OUTER);
+
+        Value[] languages = new Value[] {
+                valFactory.createValue("javax.jcr.query.JCR-JQOM"),
+                valFactory.createValue("javax.jcr.query.JCR-SQL2")
+        };
+        setDescriptor(Repository.QUERY_LANGUAGES, languages);
+
+        setDescriptor(Repository.QUERY_STORED_QUERIES_SUPPORTED, valTrue);
+        setDescriptor(Repository.QUERY_XPATH_POS_INDEX, valTrue);
+        // Disabled since in default configuration document order is not supported.
+        // See https://issues.apache.org/jira/browse/JCR-1237 for details
+        setDescriptor(Repository.QUERY_XPATH_DOC_ORDER, valFalse);
+
+        // now set customized repository descriptor values (if any exist)
+        Properties props = getCustomRepositoryDescriptors();
+        if (props != null) {
+            for (Iterator it = props.keySet().iterator(); it.hasNext();) {
+                String key = (String) it.next();
+                setDescriptor(key, props.getProperty(key));
+            }
         }
     }
 
     /**
-     * Stores the properties to a persistent resource in the meta filesytem.
+     * Returns a <code>Properties</code> object containing custom repository
+     * descriptors or <code>null</code> if none exist.
+     * <p/>
+     * Overridable to allow subclasses to add custom descriptors or to
+     * override standard descriptor values.
+     * <p/>
+     * Note that the properties entries will be set as single-valued <code>STRING</code>
+     * descriptor values.
+     * <p/>
+     * This method tries to load the <code>Properties</code> from the
+     * <code>org/apache/jackrabbit/core/repository.properties</code> resource
+     * found in the class path.
      *
-     * @throws RepositoryException
+     * @throws RepositoryException if the properties can not be loaded
      */
-    protected void storeRepProps(Properties props) throws RepositoryException {
-        FileSystemResource propFile = new FileSystemResource(metaDataStore, PROPERTIES_RESOURCE);
-        try {
-            propFile.makeParentDirs();
-            OutputStream os = propFile.getOutputStream();
-            try {
-                props.store(os, null);
+    protected Properties getCustomRepositoryDescriptors() throws RepositoryException {
+        InputStream in = RepositoryImpl.class.getResourceAsStream(PROPERTIES_RESOURCE);
+        if (in != null) {
+            try {
+                Properties props = new Properties();
+                props.load(in);
+                return props;
+            } catch (IOException e) {
+                String msg = "Failed to load customized repository properties: " + e.toString();
+                log.error(msg);
+                throw new RepositoryException(msg, e);
             } finally {
-                // make sure stream is closed
-                os.close();
+                IOUtils.closeQuietly(in);
             }
-        } catch (Exception e) {
-            String msg = "failed to persist repository properties";
-            log.debug(msg);
-            throw new RepositoryException(msg, e);
+        } else {
+            return null;
         }
     }
 
+    protected void setDescriptor(String desc, String value) {
+        setDescriptor(desc, ValueFactoryImpl.getInstance().createValue(value));
+    }
+
+    protected void setDescriptor(String desc, Value value) {
+        repDescriptors.put(desc, new DescriptorValue(value));
+    }
+
+    protected void setDescriptor(String desc, Value[] values) {
+        repDescriptors.put(desc, new DescriptorValue(values));
+    }
+
     /**
      * Creates a workspace persistence manager based on the given
      * configuration. The persistence manager is instantiated using
@@ -1424,31 +1495,46 @@
      * {@inheritDoc}
      */
     public String getDescriptor(String key) {
-        return repProps.getProperty(key);
+        Value v = getDescriptorValue(key);
+        try {
+            return (v == null) ? null : v.getString();
+        } catch (RepositoryException e) {
+            log.error("corrupt descriptor value: " + key, e);
+            return null;
+        }
     }
 
     /**
      * {@inheritDoc}
      */
     public String[] getDescriptorKeys() {
-        String[] keys = repProps.keySet().toArray(new String[repProps.keySet().size()]);
+        String[] keys = repDescriptors.keySet().toArray(new String[repDescriptors.keySet().size()]);
         Arrays.sort(keys);
         return keys;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     public Value getDescriptorValue(String key) {
-        throw new UnsupportedOperationException(
-                "not implemented yet - see JCR-2062");
+        DescriptorValue descVal = repDescriptors.get(key);
+        return (descVal != null) ? descVal.getValue() : null;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     public Value[] getDescriptorValues(String key) {
-        throw new UnsupportedOperationException(
-                "not implemented yet - see JCR-2062");
+        DescriptorValue descVal = repDescriptors.get(key);
+        return (descVal != null) ? descVal.getValues() : null;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     public boolean isSingleValueDescriptor(String key) {
-        throw new UnsupportedOperationException(
-                "not implemented yet - see JCR-2062");
+        DescriptorValue descVal = repDescriptors.get(key);
+        return (descVal != null && descVal.getValue() != null);
     }
 
     //------------------------------------------------------< SessionListener >
@@ -1468,41 +1554,6 @@
         }
     }
 
-    //--------------------------------------------------------< EventListener >
-    /**
-     * {@inheritDoc}
-     */
-    public void onEvent(EventIterator events) {
-        // check status of this instance
-        if (disposed) {
-            // ignore, repository instance has been shut down
-            return;
-        }
-
-        synchronized (repProps) {
-            while (events.hasNext()) {
-                Event event = events.nextEvent();
-                long type = event.getType();
-                if ((type & Event.NODE_ADDED) == Event.NODE_ADDED) {
-                    nodesCount++;
-                    repProps.setProperty(STATS_NODE_COUNT_PROPERTY, Long.toString(nodesCount));
-                }
-                if ((type & Event.NODE_REMOVED) == Event.NODE_REMOVED) {
-                    nodesCount--;
-                    repProps.setProperty(STATS_NODE_COUNT_PROPERTY, Long.toString(nodesCount));
-                }
-                if ((type & Event.PROPERTY_ADDED) == Event.PROPERTY_ADDED) {
-                    propsCount++;
-                    repProps.setProperty(STATS_PROP_COUNT_PROPERTY, Long.toString(propsCount));
-                }
-                if ((type & Event.PROPERTY_REMOVED) == Event.PROPERTY_REMOVED) {
-                    propsCount--;
-                    repProps.setProperty(STATS_PROP_COUNT_PROPERTY, Long.toString(propsCount));
-                }
-            }
-        }
-    }
-
     //------------------------------------------< overridable factory methods >
     /**
      * Creates an instance of the {@link SessionImpl} class representing a
@@ -1821,7 +1872,8 @@
                 // lock manager is lazily instantiated in order to avoid
                 // 'chicken & egg' bootstrap problems
                 if (lockMgr == null) {
-                    lockMgr = new LockManagerImpl(getSystemSession(), fs);
+                    lockMgr =
+                        new LockManagerImpl(getSystemSession(), fs, executor);
                     if (clusterNode != null && config.isClustered()) {
                         lockChannel = clusterNode.createLockChannel(getName());
                         lockMgr.setEventChannel(lockChannel);
@@ -2003,12 +2055,6 @@
              * {@link org.apache.jackrabbit.core.state.SharedItemStateManager#createRootNodeState}
              */
 
-            // register the repository as event listener for keeping repository statistics
-            wsp.getObservationManager().addEventListener(RepositoryImpl.this,
-                    Event.NODE_ADDED | Event.NODE_REMOVED
-                    | Event.PROPERTY_ADDED | Event.PROPERTY_REMOVED,
-                    "/", true, null, null, false);
-
             // register SearchManager as event listener
             SearchManager searchMgr = getSearchManager();
             if (searchMgr != null) {
@@ -2268,8 +2314,7 @@
 
                 synchronized (activeSessions) {
                     // remove workspaces with active sessions
-                    for (Iterator it = activeSessions.values().iterator(); it.hasNext();) {
-                        SessionImpl ses = (SessionImpl) it.next();
+                    for (SessionImpl ses : activeSessions.values()) {
                         wspNames.remove(ses.getWorkspace().getName());
                     }
                 }
@@ -2337,8 +2382,28 @@
         }
     }
 
-    VersionManagerImpl getVersionManagerImpl() {
-        return vMgr;
-    }
+    /**
+     * Represents a Repository Descriptor Value (either Value or Value[])
+     */
+    protected final class DescriptorValue {
+
+        private Value val;
+        private Value[] vals;
+
+        protected DescriptorValue(Value val) {
+            this.val = val;
+        }
 
+        protected DescriptorValue(Value[] vals) {
+            this.vals = vals;
+        }
+
+        protected Value getValue() {
+            return val;
+        }
+
+        protected Value[] getValues() {
+            return vals != null ? vals : new Value[] {val};
+        }
+    }
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java Tue Sep  8 16:09:28 2009
@@ -16,48 +16,6 @@
  */
 package org.apache.jackrabbit.core;
 
-import java.io.File;
-import java.io.PrintStream;
-import java.security.AccessControlException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.jcr.AccessDeniedException;
-import javax.jcr.Credentials;
-import javax.jcr.InvalidItemStateException;
-import javax.jcr.Item;
-import javax.jcr.ItemExistsException;
-import javax.jcr.ItemNotFoundException;
-import javax.jcr.LoginException;
-import javax.jcr.NamespaceException;
-import javax.jcr.NoSuchWorkspaceException;
-import javax.jcr.Node;
-import javax.jcr.PathNotFoundException;
-import javax.jcr.Property;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.SimpleCredentials;
-import javax.jcr.UnsupportedRepositoryOperationException;
-import javax.jcr.ValueFactory;
-import javax.jcr.Workspace;
-import javax.jcr.lock.Lock;
-import javax.jcr.lock.LockException;
-import javax.jcr.nodetype.ConstraintViolationException;
-import javax.jcr.nodetype.NoSuchNodeTypeException;
-import javax.jcr.observation.EventListener;
-import javax.jcr.observation.ObservationManager;
-import javax.jcr.retention.RetentionManager;
-import javax.jcr.security.AccessControlManager;
-import javax.jcr.version.VersionException;
-import javax.security.auth.Subject;
-
 import org.apache.commons.collections.IteratorUtils;
 import org.apache.commons.collections.map.ReferenceMap;
 import org.apache.jackrabbit.api.JackrabbitSession;
@@ -89,10 +47,12 @@
 import org.apache.jackrabbit.core.state.SharedItemStateManager;
 import org.apache.jackrabbit.core.util.Dumpable;
 import org.apache.jackrabbit.core.value.ValueFactoryImpl;
-import org.apache.jackrabbit.core.version.VersionManager;
-import org.apache.jackrabbit.core.version.VersionManagerImpl;
+import org.apache.jackrabbit.core.version.InternalVersionManager;
+import org.apache.jackrabbit.core.version.InternalVersionManagerImpl;
 import org.apache.jackrabbit.core.xml.ImportHandler;
 import org.apache.jackrabbit.core.xml.SessionImporter;
+import org.apache.jackrabbit.core.xml.AccessControlImporter;
+import org.apache.jackrabbit.core.xml.ProtectedNodeImporter;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.commons.conversion.DefaultNamePathResolver;
@@ -107,6 +67,48 @@
 import org.xml.sax.ContentHandler;
 import org.xml.sax.InputSource;
 
+import javax.jcr.AccessDeniedException;
+import javax.jcr.Credentials;
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.Item;
+import javax.jcr.ItemExistsException;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.LoginException;
+import javax.jcr.NamespaceException;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Property;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.ValueFactory;
+import javax.jcr.Workspace;
+import javax.jcr.ImportUUIDBehavior;
+import javax.jcr.lock.Lock;
+import javax.jcr.lock.LockException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
+import javax.jcr.observation.EventListener;
+import javax.jcr.observation.ObservationManager;
+import javax.jcr.retention.RetentionManager;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.version.VersionException;
+import javax.security.auth.Subject;
+import java.io.File;
+import java.io.PrintStream;
+import java.security.AccessControlException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 /**
  * A <code>SessionImpl</code> ...
  */
@@ -198,7 +200,12 @@
     /**
      * The version manager for this session
      */
-    protected final VersionManager versionMgr;
+    protected final InternalVersionManager versionMgr;
+
+    /**
+     * node type instance handler
+     */
+    protected final NodeTypeInstanceHandler ntInstanceHandler;
 
     /**
      * Listeners (weak references)
@@ -285,6 +292,7 @@
         itemMgr = createItemManager(itemStateMgr, hierMgr);
         accessMgr = createAccessManager(subject, itemStateMgr.getHierarchyMgr());
         versionMgr = createVersionManager(rep);
+        ntInstanceHandler = new NodeTypeInstanceHandler(userId);
     }
 
     /**
@@ -302,7 +310,7 @@
      * @return session item state manager
      */
     protected SessionItemStateManager createSessionItemStateManager(LocalItemStateManager manager) {
-        return new SessionItemStateManager(
+        return SessionItemStateManager.createInstance(
                 rep.getRootNodeId(), manager, rep.getNodeTypeRegistry());
     }
 
@@ -329,7 +337,7 @@
      */
     protected ItemManager createItemManager(SessionItemStateManager itemStateMgr,
                                             HierarchyManager hierMgr) {
-        return new ItemManager(itemStateMgr, hierMgr, this,
+        return ItemManager.createInstance(itemStateMgr, hierMgr, this,
                 ntMgr.getRootNodeDefinition(), rep.getRootNodeId());
     }
 
@@ -338,7 +346,7 @@
      * the repository version manager.
      * @return version manager
      */
-    protected VersionManager createVersionManager(RepositoryImpl rep)
+    protected InternalVersionManager createVersionManager(RepositoryImpl rep)
             throws RepositoryException {
 
         return rep.getVersionManager();
@@ -476,11 +484,11 @@
     }
 
     /**
-     * Returns the <code>VersionManager</code> associated with this session.
+     * Returns the <code>InternalVersionManager</code> associated with this session.
      *
-     * @return the <code>VersionManager</code> associated with this session
+     * @return the <code>InternalVersionManager</code> associated with this session
      */
-    public VersionManager getVersionManager() {
+    public InternalVersionManager getInternalVersionManager() {
         return versionMgr;
     }
 
@@ -497,6 +505,14 @@
     }
 
     /**
+     * Returns the node type instance handler for this session
+     * @return the node type instance handler.
+     */
+    public NodeTypeInstanceHandler getNodeTypeInstanceHandler() {
+        return ntInstanceHandler;
+    }
+
+    /**
      * Sets the named attribute. If the value is <code>null</code>, then
      * the named attribute is removed.
      *
@@ -643,7 +659,7 @@
      */
     public GarbageCollector createDataStoreGarbageCollector() throws RepositoryException {
         ArrayList<PersistenceManager> pmList = new ArrayList<PersistenceManager>();
-        VersionManagerImpl vm = (VersionManagerImpl) rep.getVersionManager();
+        InternalVersionManagerImpl vm = (InternalVersionManagerImpl) rep.getVersionManager();
         PersistenceManager pm = vm.getPersistenceManager();
         pmList.add(pm);
         String[] wspNames = rep.getWorkspaceNames();
@@ -781,6 +797,10 @@
      * {@inheritDoc}
      */
     public Workspace getWorkspace() {
+        return getWorkspaceImpl();
+    }
+
+    WorkspaceImpl getWorkspaceImpl() {
         return wsp;
     }
 
@@ -1053,7 +1073,7 @@
         // verify for both source and destination parent nodes that
         // - they are checked-out
         // - are not protected neither by node type constraints nor by retention/hold
-        int options = ItemValidator.CHECK_VERSIONING | ItemValidator.CHECK_LOCK |
+        int options = ItemValidator.CHECK_CHECKED_OUT | ItemValidator.CHECK_LOCK |
                 ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD | ItemValidator.CHECK_RETENTION;
         getValidator().checkRemove(srcParentNode, options, Permission.NONE);
         getValidator().checkModify(destParentNode, options, Permission.NONE);
@@ -1098,7 +1118,7 @@
             destParentNode.renameChildNode(srcName.getName(), index, targetId, destName.getName());
         } else {
             // check shareable case
-            if (((NodeState) targetNode.getItemState()).isShareable()) {
+            if (targetNode.getNodeState().isShareable()) {
                 String msg = "Moving a shareable node is not supported.";
                 log.debug(msg);
                 throw new UnsupportedRepositoryOperationException(msg);
@@ -1150,11 +1170,12 @@
 
         // verify that parent node is checked-out, not locked and not protected
         // by either node type constraints nor by some retention or hold.
-        int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_VERSIONING |
+        int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_CHECKED_OUT |
                 ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD | ItemValidator.CHECK_RETENTION;
         getValidator().checkModify(parent, options, Permission.NONE);
 
-        SessionImporter importer = new SessionImporter(parent, this, uuidBehavior);
+        ProtectedNodeImporter pi = new AccessControlImporter(this, this, false, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
+        SessionImporter importer = new SessionImporter(parent, this, uuidBehavior, pi, null);
         return new ImportHandler(importer, this);
     }
 
@@ -1528,13 +1549,69 @@
     }
 
     /**
-     * @see javax.jcr.Session#hasCapability(String, Object, Map)
+     * @see javax.jcr.Session#hasCapability(String, Object, Object[]) 
      * @since JCR 2.0
      */
-    public boolean hasCapability(String methodType, Object target, Map arguments)
+    public boolean hasCapability(String methodName, Object target, Object[] arguments)
             throws RepositoryException {
-        //TODO
-        throw new UnsupportedRepositoryOperationException("Not yet implemented");
+        // value of this method (as currently spec'ed) to jcr api clients
+        // is rather limited...
+
+        // here's therefore a minimal rather than best effort implementation;
+        // returning true is always fine according to the spec...
+        int options = ItemValidator.CHECK_CHECKED_OUT | ItemValidator.CHECK_LOCK |
+                ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD | ItemValidator.CHECK_RETENTION;
+        if (target instanceof Node) {
+            if (methodName.equals("addNode")
+                    || methodName.equals("addMixin")
+                    || methodName.equals("orderBefore")
+                    || methodName.equals("removeMixin")
+                    || methodName.equals("removeShare")
+                    || methodName.equals("removeSharedSet")
+                    || methodName.equals("setPrimaryType")
+                    || methodName.equals("setProperty")
+                    || methodName.equals("update")) {
+                return getValidator().canModify((ItemImpl) target, options, Permission.NONE);
+            } else if (methodName.equals("remove")) {
+                try {
+                    getValidator().checkRemove((ItemImpl) target, options, Permission.NONE);
+                } catch (RepositoryException e) {
+                    return false;
+                }
+            }
+        } else if (target instanceof Property) {
+            if (methodName.equals("setValue")
+                    || methodName.equals("save")) {
+                return getValidator().canModify((ItemImpl) target, options, Permission.NONE);
+            } else if (methodName.equals("remove")) {
+                try {
+                    getValidator().checkRemove((ItemImpl) target, options, Permission.NONE);
+                } catch (RepositoryException e) {
+                    return false;
+                }
+            }
+        } else if (target instanceof Workspace) {
+            if (methodName.equals("clone")
+                    || methodName.equals("copy")
+                    || methodName.equals("createWorkspace")
+                    || methodName.equals("deleteWorkspace")
+                    || methodName.equals("getImportContentHandler")
+                    || methodName.equals("importXML")
+                    || methodName.equals("move")) {
+                // todo minimal, best effort checks (e.g. permissions for write methods etc)
+            }
+        } else if (target instanceof Session) {
+            if (methodName.equals("clone")
+                    || methodName.equals("removeItem")
+                    || methodName.equals("getImportContentHandler")
+                    || methodName.equals("importXML")
+                    || methodName.equals("save")) {
+                // todo minimal, best effort checks (e.g. permissions for write methods etc)
+            }
+        }
+
+        // we're unable to evaluate capability, return true (staying on the safe side)
+        return true;
     }
 
     /**

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java Tue Sep  8 16:09:28 2009
@@ -19,6 +19,7 @@
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
+import java.security.Principal;
 
 import javax.jcr.AccessDeniedException;
 import javax.jcr.PathNotFoundException;
@@ -274,5 +275,19 @@
             // cannot determine the effective policies for the system session.
             return new AccessControlPolicy[0];
         }
+
+        /**
+     * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlManager#hasPrivileges(String, Set, Privilege[])
+     */
+        public boolean hasPrivileges(String absPath, Set<Principal> principals, Privilege[] privileges) throws PathNotFoundException, RepositoryException {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        /**
+         * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlManager#getPrivileges(String, Set)
+         */
+        public Privilege[] getPrivileges(String absPath, Set<Principal> principals) throws PathNotFoundException, RepositoryException {
+            throw new UnsupportedOperationException("not implemented");
+        }
     }
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java Tue Sep  8 16:09:28 2009
@@ -16,18 +16,17 @@
  */
 package org.apache.jackrabbit.core;
 
-import java.util.HashMap;
-
 import javax.jcr.AccessDeniedException;
 import javax.jcr.InvalidItemStateException;
 import javax.jcr.ItemExistsException;
-import javax.jcr.ItemNotFoundException;
 import javax.jcr.NamespaceRegistry;
 import javax.jcr.NoSuchWorkspaceException;
 import javax.jcr.PathNotFoundException;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
 import javax.jcr.lock.LockException;
 import javax.jcr.nodetype.ConstraintViolationException;
 import javax.jcr.nodetype.NodeTypeManager;
@@ -35,7 +34,6 @@
 import javax.jcr.query.QueryManager;
 import javax.jcr.version.Version;
 import javax.jcr.version.VersionException;
-import javax.jcr.version.VersionHistory;
 import javax.jcr.version.VersionManager;
 
 import org.apache.jackrabbit.api.JackrabbitWorkspace;
@@ -52,10 +50,6 @@
 import org.apache.jackrabbit.core.retention.RetentionRegistry;
 import org.apache.jackrabbit.core.state.LocalItemStateManager;
 import org.apache.jackrabbit.core.state.SharedItemStateManager;
-import org.apache.jackrabbit.core.version.DateVersionSelector;
-import org.apache.jackrabbit.core.version.JcrVersionManagerImpl;
-import org.apache.jackrabbit.core.version.VersionImpl;
-import org.apache.jackrabbit.core.version.VersionSelector;
 import org.apache.jackrabbit.core.xml.ImportHandler;
 import org.apache.jackrabbit.core.xml.Importer;
 import org.apache.jackrabbit.core.xml.WorkspaceImporter;
@@ -127,7 +121,7 @@
     /**
      * The API Version manager for this workspace
      */
-    protected JcrVersionManagerImpl versionMgr;
+    protected VersionManagerImpl versionMgr;
 
     /**
      * The internal manager used to evaluate effective retention policies and
@@ -216,7 +210,17 @@
             tmpSession = rep.createSession(session.getSubject(), name);
             WorkspaceImpl newWsp = (WorkspaceImpl) tmpSession.getWorkspace();
 
-            newWsp.clone(srcWorkspace, "/", "/", false);
+            // Workspace#clone(String, String, String, booelan) doesn't
+            // allow to clone to "/"...
+            //newWsp.clone(srcWorkspace, "/", "/", false);
+           Node root = session.getRootNode();
+           for (NodeIterator it = root.getNodes(); it.hasNext(); ) {
+               Node child = it.nextNode();
+               // skip nodes that already exist in newly created workspace
+               if (!tmpSession.nodeExists(child.getPath())) {
+                   newWsp.clone(srcWorkspace, child.getPath(), child.getPath(), false);
+               }
+           }
         } finally {
             if (tmpSession != null) {
                 // we don't need the temporary session anymore, logout
@@ -253,10 +257,13 @@
     /**
      * @see javax.jcr.Workspace#getVersionManager()
      */
-    public VersionManager getVersionManager()
-            throws UnsupportedRepositoryOperationException, RepositoryException {
+    public VersionManager getVersionManager() {
+        return getVersionManagerImpl();
+    }
+
+    VersionManagerImpl getVersionManagerImpl() {
         if (versionMgr == null) {
-            versionMgr = new JcrVersionManagerImpl(session);
+            versionMgr = new VersionManagerImpl(session, stateMgr, hierMgr);
         }
         return versionMgr;
     }
@@ -784,90 +791,14 @@
     /**
      * {@inheritDoc}
      */
+    @Deprecated
     public void restore(Version[] versions, boolean removeExisting)
             throws ItemExistsException, UnsupportedRepositoryOperationException,
             VersionException, LockException, InvalidItemStateException,
             RepositoryException {
-
-        // todo: perform restore operations direct on the node states
-
         // check state of this instance
         sanityCheck();
-
-        // add all versions to map of versions to restore
-        final HashMap<String, VersionImpl> toRestore = new HashMap<String, VersionImpl>();
-        for (Version v : versions) {
-            VersionHistory vh = v.getContainingHistory();
-            // check for collision
-            if (toRestore.containsKey(vh.getUUID())) {
-                throw new VersionException("Unable to restore. Two or more versions have same version history.");
-            }
-            toRestore.put(vh.getUUID(), (VersionImpl) v);
-        }
-
-        // create a version selector to the set of versions
-        VersionSelector vsel = new VersionSelector() {
-            public Version select(VersionHistory versionHistory) throws RepositoryException {
-                // try to select version as specified
-                Version v = toRestore.get(versionHistory.getUUID());
-                if (v == null) {
-                    // select latest one
-                    v = DateVersionSelector.selectByDate(versionHistory, null);
-                }
-                return v;
-            }
-        };
-
-        // check for pending changes
-        if (session.hasPendingChanges()) {
-            String msg = "Unable to restore version. Session has pending changes.";
-            log.debug(msg);
-            throw new InvalidItemStateException(msg);
-        }
-        // TODO: add checks for lock/hold...
-        boolean success = false;
-        try {
-            // now restore all versions that have a node in the ws
-            int numRestored = 0;
-            while (toRestore.size() > 0) {
-                Version[] restored = null;
-                for (VersionImpl v : toRestore.values()) {
-                    try {
-                        NodeImpl node = (NodeImpl) session.getNodeById(v.getInternalFrozenNode().getFrozenId());
-                        restored = node.internalRestore(v, vsel, removeExisting);
-                        // remove restored versions from set
-                        for (Version r : restored) {
-                            toRestore.remove(r.getContainingHistory().getUUID());
-                        }
-                        numRestored += restored.length;
-                        break;
-                    } catch (ItemNotFoundException e) {
-                        // ignore
-                    }
-                }
-                if (restored == null) {
-                    if (numRestored == 0) {
-                        throw new VersionException("Unable to restore. At least one version needs"
-                                + " existing versionable node in workspace.");
-                    } else {
-                        throw new VersionException("Unable to restore. All versions with non"
-                                + " existing versionable nodes need parent.");
-                    }
-                }
-            }
-            session.save();
-            success = true;
-        } finally {
-            if (!success) {
-                // revert session
-                try {
-                    log.debug("reverting changes applied during restore...");
-                    session.refresh(false);
-                } catch (RepositoryException e) {
-                    log.error("Error while reverting changes applied during restore.", e);
-                }
-            }
-        }
+        getVersionManager().restore(versions, removeExisting);
     }
 
     /**

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java Tue Sep  8 16:09:28 2009
@@ -24,9 +24,9 @@
 import org.apache.jackrabbit.core.security.authentication.AuthContext;
 import org.apache.jackrabbit.core.state.SharedItemStateManager;
 import org.apache.jackrabbit.core.state.XAItemStateManager;
-import org.apache.jackrabbit.core.version.VersionManager;
-import org.apache.jackrabbit.core.version.VersionManagerImpl;
-import org.apache.jackrabbit.core.version.XAVersionManager;
+import org.apache.jackrabbit.core.version.InternalVersionManager;
+import org.apache.jackrabbit.core.version.InternalVersionManagerImpl;
+import org.apache.jackrabbit.core.version.InternalXAVersionManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -54,7 +54,8 @@
     /**
      * Global transactions
      */
-    private static final Map txGlobal = Collections.synchronizedMap(new HashMap());
+    private static final Map<Xid, TransactionContext> txGlobal =
+        Collections.synchronizedMap(new HashMap<Xid, TransactionContext>());
 
     /**
      * System property specifying the default Transaction Timeout
@@ -133,7 +134,7 @@
     private void init() throws RepositoryException {
         XAItemStateManager stateMgr = (XAItemStateManager) wsp.getItemStateManager();
         XALockManager lockMgr = (XALockManager) getLockManager();
-        XAVersionManager versionMgr = (XAVersionManager) getVersionManager();
+        InternalXAVersionManager versionMgr = (InternalXAVersionManager) getInternalVersionManager();
 
         /**
          * Create array that contains all resources that participate in this
@@ -169,11 +170,11 @@
     /**
      * {@inheritDoc}
      */
-    protected VersionManager createVersionManager(RepositoryImpl rep)
+    protected InternalVersionManager createVersionManager(RepositoryImpl rep)
             throws RepositoryException {
 
-        VersionManagerImpl vMgr = (VersionManagerImpl) rep.getVersionManager();
-        return new XAVersionManager(vMgr, rep.getNodeTypeRegistry(), this, rep.getItemStateCacheFactory());
+        InternalVersionManagerImpl vMgr = (InternalVersionManagerImpl) rep.getVersionManager();
+        return new InternalXAVersionManager(vMgr, rep.getNodeTypeRegistry(), this, rep.getItemStateCacheFactory());
     }
 
     /**
@@ -386,9 +387,7 @@
      */
     public synchronized void associate(TransactionContext tx) {
         this.tx = tx;
-
-        for (int i = 0; i < txResources.length; i++) {
-            InternalXAResource txResource = txResources[i];
+        for (InternalXAResource txResource : txResources) {
             txResource.associate(tx);
         }
     }
@@ -411,9 +410,9 @@
         super.logout();
         // dispose the caches
         try {
-            ((XAVersionManager) versionMgr).close();
+            ((InternalXAVersionManager) versionMgr).close();
         } catch (Exception e) {
-            log.warn("error while closing XAVersionManager", e);
+            log.warn("error while closing InternalXAVersionManager", e);
         }
     }
 

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ZombieHierarchyManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ZombieHierarchyManager.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ZombieHierarchyManager.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ZombieHierarchyManager.java Tue Sep  8 16:09:28 2009
@@ -16,8 +16,6 @@
  */
 package org.apache.jackrabbit.core;
 
-import java.util.Iterator;
-
 import org.apache.jackrabbit.core.id.ItemId;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.state.ChildNodeEntry;
@@ -102,10 +100,7 @@
                                                          Name name,
                                                          int index) {
         // check removed child node entries first
-        Iterator iter = parent.getRemovedChildNodeEntries().iterator();
-        while (iter.hasNext()) {
-            ChildNodeEntry entry =
-                    (ChildNodeEntry) iter.next();
+        for (ChildNodeEntry entry : parent.getRemovedChildNodeEntries()) {
             if (entry.getName().equals(name)
                     && entry.getIndex() == index) {
                 return entry;
@@ -124,10 +119,7 @@
     protected ChildNodeEntry getChildNodeEntry(NodeState parent,
                                                          NodeId id) {
         // check removed child node entries first
-        Iterator iter = parent.getRemovedChildNodeEntries().iterator();
-        while (iter.hasNext()) {
-            ChildNodeEntry entry =
-                    (ChildNodeEntry) iter.next();
+        for (ChildNodeEntry entry : parent.getRemovedChildNodeEntries()) {
             if (entry.getId().equals(id)) {
                 return entry;
             }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ChangeLogRecord.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ChangeLogRecord.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ChangeLogRecord.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ChangeLogRecord.java Tue Sep  8 16:09:28 2009
@@ -99,7 +99,7 @@
     /**
      * List of <code>EventState</code>s.
      */
-    private List events;
+    private List<EventState> events;
 
     /**
      * The user data.
@@ -114,7 +114,7 @@
     /**
      * Last used session for event sources.
      */
-    private Session lastSession;
+    private ClusterSession lastSession;
 
     /**
      * Create a new instance of this class. Used when serializing.
@@ -126,7 +126,7 @@
      * @param timestamp when the changes for this record were persisted.
      * @param userData the user data associated with these changes.
      */
-    public ChangeLogRecord(ChangeLog changes, List events,
+    public ChangeLogRecord(ChangeLog changes, List<EventState> events,
                            Record record, String workspace,
                            long timestamp, String userData) {
         super(record, workspace);
@@ -149,7 +149,7 @@
 
         this.identifier = identifier;
         this.changes = new ChangeLog();
-        this.events = new ArrayList();
+        this.events = new ArrayList<EventState>();
     }
 
     /**
@@ -276,16 +276,16 @@
         Path.Element childRelPath = record.readPathElement();
         Name ntName = record.readQName();
 
-        Set mixins = new HashSet();
+        Set<Name> mixins = new HashSet<Name>();
         int mixinCount = record.readInt();
         for (int i = 0; i < mixinCount; i++) {
             mixins.add(record.readQName());
         }
         String userId = record.readString();
 
-        Map info = null;
+        Map<String, InternalValue> info = null;
         if (type == Event.NODE_MOVED) {
-            info = new HashMap();
+            info = new HashMap<String, InternalValue>();
             // read info map
             int infoSize = record.readInt();
             for (int i = 0; i < infoSize; i++) {
@@ -325,7 +325,7 @@
      */
     private EventState createEventState(int type, NodeId parentId, Path parentPath,
                                         NodeId childId, Path.Element childRelPath,
-                                        Name ntName, Set mixins, String userId) {
+                                        Name ntName, Set<Name> mixins, String userId) {
         switch (type) {
             case Event.NODE_ADDED:
                 return EventState.childNodeAdded(parentId, parentPath, childId, childRelPath,
@@ -358,7 +358,7 @@
      * @return session
      */
     private Session getOrCreateSession(String userId) {
-        if (lastSession == null || !lastSession.getUserID().equals(userId)) {
+        if (lastSession == null || !lastSession.isUserId(userId)) {
             lastSession = new ClusterSession(userId);
         }
         return lastSession;
@@ -392,9 +392,7 @@
             }
         }
 
-        Iterator iter = events.iterator();
-        while (iter.hasNext()) {
-            EventState event = (EventState) iter.next();
+        for (EventState event : events) {
             writeEventRecord(event);
         }
     }
@@ -466,22 +464,21 @@
         record.writePathElement(event.getChildRelPath());
         record.writeQName(event.getNodeType());
 
-        Set mixins = event.getMixinNames();
+        Set<Name> mixins = event.getMixinNames();
         record.writeInt(mixins.size());
-        Iterator iter = mixins.iterator();
+        Iterator<Name> iter = mixins.iterator();
         while (iter.hasNext()) {
-            record.writeQName((Name) iter.next());
+            record.writeQName(iter.next());
         }
         record.writeString(event.getUserId());
 
         if (event.getType() == Event.NODE_MOVED) {
             // write info map
-            Map info = event.getInfo();
+            Map<String, InternalValue> info = event.getInfo();
             record.writeInt(info.size());
-            for (Iterator it = info.entrySet().iterator(); it.hasNext(); ) {
-                Map.Entry entry = (Map.Entry) it.next();
-                String key = (String) entry.getKey();
-                InternalValue value = (InternalValue) entry.getValue();
+            for (Map.Entry<String, InternalValue> entry : info.entrySet()) {
+                String key = entry.getKey();
+                InternalValue value = entry.getValue();
                 record.writeString(key);
                 if (value == null) {
                     // use undefined for null value
@@ -515,7 +512,7 @@
      *
      * @return events
      */
-    public List getEvents() {
+    public List<EventState> getEvents() {
         return Collections.unmodifiableList(events);
     }