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 [16/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/ jackrabb...

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SessionImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SessionImporter.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SessionImporter.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SessionImporter.java Tue Sep  8 16:09:28 2009
@@ -16,16 +16,9 @@
  */
 package org.apache.jackrabbit.core.xml;
 
-import org.apache.jackrabbit.core.id.NodeId;
-import org.apache.jackrabbit.core.NodeImpl;
-import org.apache.jackrabbit.core.SessionImpl;
-import org.apache.jackrabbit.core.security.authorization.Permission;
-import org.apache.jackrabbit.core.util.ReferenceChangeTracker;
-import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.spi.commons.name.NameConstants;
-import org.apache.jackrabbit.uuid.UUID;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Stack;
 
 import javax.jcr.AccessDeniedException;
 import javax.jcr.ImportUUIDBehavior;
@@ -35,11 +28,20 @@
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
+import javax.jcr.ValueFormatException;
 import javax.jcr.nodetype.ConstraintViolationException;
 import javax.jcr.nodetype.NodeDefinition;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Stack;
+
+import org.apache.jackrabbit.core.NodeImpl;
+import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.id.NodeId;
+import org.apache.jackrabbit.core.nodetype.PropDef;
+import org.apache.jackrabbit.core.security.authorization.Permission;
+import org.apache.jackrabbit.core.util.ReferenceChangeTracker;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * <code>SessionImporter</code> ...
@@ -52,7 +54,7 @@
     private final NodeImpl importTargetNode;
     private final int uuidBehavior;
 
-    private Stack parents;
+    private Stack<NodeImpl> parents;
 
     /**
      * helper object that keeps track of remapped uuid's and imported reference
@@ -61,26 +63,76 @@
     private final ReferenceChangeTracker refTracker;
 
     /**
+     * Importer for protected nodes.
+     */
+    private final ProtectedNodeImporter pnImporter;
+
+    /**
+     * Importer for protected properties.
+     */
+    private final ProtectedPropertyImporter ppImporter;
+
+    /**
      * Creates a new <code>SessionImporter</code> instance.
      *
-     * @param importTargetNode
-     * @param session
+     * @param importTargetNode the target node
+     * @param session          session
      * @param uuidBehavior     any of the constants declared by
      *                         {@link javax.jcr.ImportUUIDBehavior}
      */
     public SessionImporter(NodeImpl importTargetNode,
                            SessionImpl session,
                            int uuidBehavior) {
+        this(importTargetNode, session, uuidBehavior, null, null);
+    }
+
+    /**
+     * Creates a new <code>SessionImporter</code> instance.
+     *
+     * @param importTargetNode the target node
+     * @param session session
+     * @param uuidBehavior the uuid behaviro
+     * @param pnImporter importer for protected nodes
+     * @param ppImporter importer for protected properties
+     */
+    public SessionImporter(NodeImpl importTargetNode, SessionImpl session,
+                           int uuidBehavior,
+                           ProtectedNodeImporter pnImporter,
+                           ProtectedPropertyImporter ppImporter) {
         this.importTargetNode = importTargetNode;
         this.session = session;
         this.uuidBehavior = uuidBehavior;
 
+        this.ppImporter = ppImporter == null
+                ? new DefaultProtectedPropertyImporter(session, session, false)
+                : ppImporter;
+        this.pnImporter = pnImporter == null
+                ? new DefaultProtectedNodeImporter(session, session, false, uuidBehavior)
+                : pnImporter;
         refTracker = new ReferenceChangeTracker();
 
-        parents = new Stack();
+        parents = new Stack<NodeImpl>();
         parents.push(importTargetNode);
     }
 
+    /**
+     * make sure the editing session is allowed create nodes with a
+     * specified node type (and ev. mixins),<br>
+     * NOTE: this check is not executed in a single place as the parent
+     * may change in case of
+     * {@link javax.jcr.ImportUUIDBehavior#IMPORT_UUID_COLLISION_REPLACE_EXISTING IMPORT_UUID_COLLISION_REPLACE_EXISTING}.
+     *  
+     * @param parent parent node
+     * @param nodeName the name
+     * @throws RepositoryException if an error occurs
+     */
+    protected void checkPermission(NodeImpl parent, Name nodeName)
+            throws RepositoryException {
+        if (!session.getAccessManager().isGranted(session.getQPath(parent.getPath()), nodeName, Permission.NODE_TYPE_MNGMT)) {
+            throw new AccessDeniedException("Insufficient permission.");
+        }
+    }
+
     protected NodeImpl createNode(NodeImpl parent,
                                   Name nodeName,
                                   Name nodeTypeName,
@@ -93,13 +145,47 @@
         node = parent.addNode(nodeName, nodeTypeName, id);
         // add mixins
         if (mixinNames != null) {
-            for (int i = 0; i < mixinNames.length; i++) {
-                node.addMixin(mixinNames[i]);
+            for (Name mixinName : mixinNames) {
+                node.addMixin(mixinName);
             }
         }
         return node;
     }
 
+
+    protected void createProperty(NodeImpl node, PropInfo pInfo, PropDef def) throws RepositoryException {
+        // convert serialized values to Value objects
+        Value[] va = pInfo.getValues(pInfo.getTargetType(def), session);
+
+        // multi- or single-valued property?
+        Name name = pInfo.getName();
+        int type = pInfo.getType();
+        if (va.length == 1 && !def.isMultiple()) {
+            Exception e = null;
+            try {
+                // set single-value
+                node.setProperty(name, va[0]);
+            } catch (ValueFormatException vfe) {
+                e = vfe;
+            } catch (ConstraintViolationException cve) {
+                e = cve;
+            }
+            if (e != null) {
+                // setting single-value failed, try setting value array
+                // as a last resort (in case there are ambiguous property
+                // definitions)
+                node.setProperty(name, va, type);
+            }
+        } else {
+            // can only be multi-valued (n == 0 || n > 1)
+            node.setProperty(name, va, type);
+        }
+        if (type == PropertyType.REFERENCE || type == PropertyType.WEAKREFERENCE) {
+            // store reference for later resolution
+            refTracker.processedReference(node.getProperty(name));
+        }
+    }
+
     protected NodeImpl resolveUUIDConflict(NodeImpl parent,
                                            NodeImpl conflicting,
                                            NodeInfo nodeInfo)
@@ -107,6 +193,7 @@
         NodeImpl node;
         if (uuidBehavior == ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW) {
             // create new with new uuid
+            checkPermission(parent, nodeInfo.getName());
             node = createNode(parent, nodeInfo.getName(),
                     nodeInfo.getNodeTypeName(), nodeInfo.getMixinNames(), null);
             // remember uuid mapping
@@ -132,6 +219,7 @@
             // remove conflicting
             conflicting.remove();
             // create new with given uuid
+            checkPermission(parent, nodeInfo.getName());
             node = createNode(parent, nodeInfo.getName(),
                     nodeInfo.getNodeTypeName(), nodeInfo.getMixinNames(),
                     nodeInfo.getId());
@@ -145,6 +233,7 @@
             parent = (NodeImpl) conflicting.getParent();
 
             // replace child node
+            checkPermission(parent, nodeInfo.getName());
             node = parent.replaceChildNode(nodeInfo.getId(), nodeInfo.getName(),
                     nodeInfo.getNodeTypeName(), nodeInfo.getMixinNames());
         } else {
@@ -166,9 +255,9 @@
     /**
      * {@inheritDoc}
      */
-    public void startNode(NodeInfo nodeInfo, List propInfos)
+    public void startNode(NodeInfo nodeInfo, List<PropInfo> propInfos)
             throws RepositoryException {
-        NodeImpl parent = (NodeImpl) parents.peek();
+        NodeImpl parent = parents.peek();
 
         // process node
 
@@ -179,16 +268,28 @@
         Name[] mixins = nodeInfo.getMixinNames();
 
         if (parent == null) {
+            log.debug("Skipping node: " + nodeName);
             // parent node was skipped, skip this child node too
             parents.push(null); // push null onto stack for skipped node
-            log.debug("Skipping node: " + nodeName);
+            // notify the p-i-importer
+            pnImporter.startChildInfo(nodeInfo, propInfos);
             return;
         }
 
-        // make sure the editing session is allowed create nodes with a
-        // specified node type (and ev. mixins)
-        if (!session.getAccessManager().isGranted(session.getQPath(parent.getPath()), nodeName, Permission.NODE_TYPE_MNGMT)) {
-            throw new AccessDeniedException("Insufficient permission.");
+        if (parent.getDefinition().isProtected()) {
+            // skip protected node
+            parents.push(null);
+            log.debug("Skipping protected node: " + nodeName);
+
+            // Notify the ProtectedNodeImporter about the start of a item
+            // tree that is protected by this parent. If it potentially is
+            // able to deal with it, notify it about the child node.
+            if (pnImporter.start(parent)) {
+                log.debug("Protected node -> delegated to ProtectedPropertyImporter");
+                pnImporter.startChildInfo(nodeInfo, propInfos);
+            } /* else: p-i-Importer isn't able to deal with the protected tree.
+                 skip the tree below the protected parent */
+            return;
         }
 
         if (parent.hasNode(nodeName)) {
@@ -199,9 +300,21 @@
                 // existing doesn't allow same-name siblings,
                 // check for potential conflicts
                 if (def.isProtected() && existing.isNodeType(ntName)) {
-                    // skip protected node
-                    parents.push(null); // push null onto stack for skipped node
+                    /*
+                     use the existing node as parent for the possible subsequent
+                     import of a protected tree, that the protected node importer
+                     may or may not be able to deal with.
+                     -> upon the next 'startNode' the check for the parent being
+                        protected will notify the protected node importer.
+                     -> if the importer is able to deal with that node it needs
+                        to care of the complete subtree until it is notified
+                        during the 'endNode' call.
+                     -> if the import can't deal with that node or if that node
+                        is the a leaf in the tree to be imported 'end' will
+                        not have an effect on the importer, that was never started.
+                    */
                     log.debug("Skipping protected node: " + existing);
+                    parents.push(existing);
                     return;
                 }
                 if (def.isAutoCreated() && existing.isNodeType(ntName)) {
@@ -225,6 +338,7 @@
             // create node
             if (id == null) {
                 // no potential uuid conflict, always add new node
+                checkPermission(parent, nodeName);
                 node = createNode(parent, nodeName, ntName, mixins, null);
             } else {
                 // potential uuid conflict
@@ -240,11 +354,12 @@
                     if (node == null) {
                         // no new node has been created, so skip this node
                         parents.push(null); // push null onto stack for skipped node
-                        log.debug("skipping existing node " + nodeInfo.getName());
+                        log.debug("Skipping existing node " + nodeInfo.getName());
                         return;
                     }
                 } else {
                     // create new with given uuid
+                    checkPermission(parent, nodeName);
                     node = createNode(parent, nodeName, ntName, mixins, id);
                 }
             }
@@ -252,20 +367,39 @@
 
         // process properties
 
-        Iterator iter = propInfos.iterator();
-        while (iter.hasNext()) {
-            PropInfo pi = (PropInfo) iter.next();
-            pi.apply(node, session, refTracker);
+        for (PropInfo pi : propInfos) {
+            // find applicable definition
+            PropDef def = pi.getApplicablePropertyDef(node.getEffectiveNodeType());
+            if (def.isProtected()) {
+                // skip protected property
+                log.debug("Skipping protected property " + pi.getName());
+
+                // notify the ProtectedPropertyImporter.
+                if (ppImporter.handlePropInfo(node, pi, def)) {
+                    // TODO: deal with reference props within the imported tree?                    
+                    log.debug("Protected property -> delegated to ProtectedPropertyImporter");
+                } // else: p-i-Importer isn't able to deal with this property
+            } else {
+                // regular property -> create the property
+                createProperty(node, pi, def);
+            }
         }
 
         parents.push(node);
     }
 
+
     /**
      * {@inheritDoc}
      */
     public void endNode(NodeInfo nodeInfo) throws RepositoryException {
-        parents.pop();
+        NodeImpl parent = parents.pop();
+        if (parent == null) {
+            pnImporter.endChildInfo();
+        } else if (parent.getDefinition().isProtected()) {
+            pnImporter.end(parent);
+            // TODO: deal with reference props within the imported tree?
+        }
     }
 
     /**
@@ -284,7 +418,7 @@
                     && prop.getType() != PropertyType.WEAKREFERENCE) {
                 continue;
             }
-            if (prop.getDefinition().isMultiple()) {
+            if (prop.isMultiple()) {
                 Value[] values = prop.getValues();
                 Value[] newVals = new Value[values.length];
                 for (int i = 0; i < values.length; i++) {

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java Tue Sep  8 16:09:28 2009
@@ -16,26 +16,29 @@
  */
 package org.apache.jackrabbit.core.xml;
 
-import org.apache.jackrabbit.spi.commons.conversion.NameException;
-import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
-import org.apache.jackrabbit.spi.commons.name.NameConstants;
-import org.apache.jackrabbit.core.id.NodeId;
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
 
 import javax.jcr.InvalidSerializedDataException;
+import javax.jcr.NamespaceException;
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
-import javax.jcr.NamespaceException;
 import javax.jcr.ValueFactory;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Stack;
+
+import org.apache.jackrabbit.core.id.NodeId;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.commons.conversion.NameException;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
 
 /**
  * <code>SysViewImportHandler</code>  ...
  */
+@SuppressWarnings({"ThrowableInstanceNeverThrown"})
 class SysViewImportHandler extends TargetImportHandler {
 
     /**
@@ -59,7 +62,8 @@
     /**
      * Constructs a new <code>SysViewImportHandler</code>.
      *
-     * @param importer
+     * @param importer the underlying importer
+     * @param valueFactory the value factory
      */
     SysViewImportHandler(Importer importer, ValueFactory valueFactory) {
         super(importer, valueFactory);
@@ -114,14 +118,14 @@
 
             // node name (value of sv:name attribute)
             String svName = getAttribute(atts, NameConstants.SV_NAME);
-            if (name == null) {
+            if (svName == null) {
                 throw new SAXException(new InvalidSerializedDataException(
                         "missing mandatory sv:name attribute of element sv:node"));
             }
 
             if (!stack.isEmpty()) {
                 // process current node first
-                ImportState current = (ImportState) stack.peek();
+                ImportState current = stack.peek();
                 // need to start current node
                 if (!current.started) {
                     processNode(current, true, false);
@@ -223,7 +227,7 @@
             throws SAXException {
         Name name = NameFactoryImpl.getInstance().create(namespaceURI, localName);
         // check element name
-        ImportState state = (ImportState) stack.peek();
+        ImportState state = stack.peek();
         if (name.equals(NameConstants.SV_NODE)) {
             // sv:node element
             if (!state.started) {
@@ -242,7 +246,7 @@
             // check if all system properties (jcr:primaryType, jcr:uuid etc.)
             // have been collected and create node as necessary
             if (currentPropName.equals(NameConstants.JCR_PRIMARYTYPE)) {
-                BufferedStringValue val = (BufferedStringValue) currentPropValues.get(0);
+                BufferedStringValue val = currentPropValues.get(0);
                 String s = null;
                 try {
                     s = val.retrieve();
@@ -258,9 +262,7 @@
                 if (state.mixinNames == null) {
                     state.mixinNames = new ArrayList<Name>(currentPropValues.size());
                 }
-                for (int i = 0; i < currentPropValues.size(); i++) {
-                    BufferedStringValue val =
-                            (BufferedStringValue) currentPropValues.get(i);
+                for (BufferedStringValue val : currentPropValues) {
                     String s = null;
                     try {
                         s = val.retrieve();
@@ -275,7 +277,7 @@
                     }
                 }
             } else if (currentPropName.equals(NameConstants.JCR_UUID)) {
-                BufferedStringValue val = (BufferedStringValue) currentPropValues.get(0);
+                BufferedStringValue val = currentPropValues.get(0);
                 try {
                     state.uuid = val.retrieve();
                 } catch (IOException ioe) {
@@ -283,9 +285,9 @@
                 }
             } else {
                 PropInfo prop = new PropInfo(
-                        currentPropName, currentPropType,
-                        (TextValue[]) currentPropValues.toArray(
-                                new TextValue[currentPropValues.size()]));
+                        currentPropName,
+                        currentPropType,
+                        currentPropValues.toArray(new TextValue[currentPropValues.size()]));
                 state.props.add(prop);
             }
             // reset temp fields
@@ -316,7 +318,7 @@
         /**
          * list of mixin types of current node
          */
-        ArrayList<Name> mixinNames;
+        List<Name> mixinNames;
         /**
          * uuid of current node
          */
@@ -325,7 +327,7 @@
         /**
          * list of PropInfo instances representing properties of current node
          */
-        ArrayList<PropInfo> props = new ArrayList<PropInfo>();
+        List<PropInfo> props = new ArrayList<PropInfo>();
 
         /**
          * flag indicating whether startNode() has been called for current node

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java Tue Sep  8 16:09:28 2009
@@ -16,22 +16,38 @@
  */
 package org.apache.jackrabbit.core.xml;
 
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Stack;
+
+import javax.jcr.ImportUUIDBehavior;
+import javax.jcr.ItemExistsException;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.lock.LockException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.version.VersionException;
+
 import org.apache.jackrabbit.core.BatchedItemOperations;
 import org.apache.jackrabbit.core.HierarchyManager;
-import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.WorkspaceImpl;
+import org.apache.jackrabbit.core.id.NodeId;
+import org.apache.jackrabbit.core.id.PropertyId;
 import org.apache.jackrabbit.core.nodetype.EffectiveNodeType;
 import org.apache.jackrabbit.core.nodetype.NodeDef;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 import org.apache.jackrabbit.core.nodetype.PropDef;
+import org.apache.jackrabbit.core.state.ChildNodeEntry;
 import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.state.PropertyState;
-import org.apache.jackrabbit.core.state.ChildNodeEntry;
 import org.apache.jackrabbit.core.util.ReferenceChangeTracker;
 import org.apache.jackrabbit.core.value.InternalValue;
+import org.apache.jackrabbit.core.version.InternalVersionManager;
 import org.apache.jackrabbit.core.version.VersionHistoryInfo;
-import org.apache.jackrabbit.core.version.VersionManager;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException;
@@ -39,20 +55,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.jcr.ImportUUIDBehavior;
-import javax.jcr.ItemExistsException;
-import javax.jcr.ItemNotFoundException;
-import javax.jcr.PathNotFoundException;
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.lock.LockException;
-import javax.jcr.nodetype.ConstraintViolationException;
-import javax.jcr.version.VersionException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Stack;
-
 /**
  * <code>WorkspaceImporter</code> ...
  */
@@ -63,7 +65,7 @@
     private final NodeState importTarget;
     private final WorkspaceImpl wsp;
     private final SessionImpl session;
-    private final VersionManager versionManager;
+    private final InternalVersionManager versionManager;
     private final NodeTypeRegistry ntReg;
     private final HierarchyManager hierMgr;
     private final BatchedItemOperations itemOps;
@@ -83,8 +85,8 @@
      * Creates a new <code>WorkspaceImporter</code> instance.
      *
      * @param parentPath   target path where to add the imported subtree
-     * @param wsp
-     * @param ntReg
+     * @param wsp the workspace to operate on
+     * @param ntReg the node type registry
      * @param uuidBehavior flag that governs how incoming UUIDs are handled
      * @throws PathNotFoundException        if no node exists at
      *                                      <code>parentPath</code> or if the
@@ -107,7 +109,7 @@
             VersionException, LockException, RepositoryException {
         this.wsp = wsp;
         this.session = (SessionImpl) wsp.getSession();
-        this.versionManager = session.getVersionManager();
+        this.versionManager = session.getInternalVersionManager();
         this.ntReg = ntReg;
         this.uuidBehavior = uuidBehavior;
 
@@ -129,11 +131,11 @@
     }
 
     /**
-     * @param parent
-     * @param conflicting
-     * @param nodeInfo
-     * @return
-     * @throws RepositoryException
+     * @param parent parent node state
+     * @param conflicting conflicting node state
+     * @param nodeInfo the node info
+     * @return the resolved node state
+     * @throws RepositoryException if an error occurs
      */
     protected NodeState resolveUUIDConflict(NodeState parent,
                                             NodeState conflicting,
@@ -190,7 +192,7 @@
             itemOps.checkRemoveNode(conflicting,
                     BatchedItemOperations.CHECK_ACCESS
                     | BatchedItemOperations.CHECK_LOCK
-                    | BatchedItemOperations.CHECK_VERSIONING
+                    | BatchedItemOperations.CHECK_CHECKED_OUT
                     | BatchedItemOperations.CHECK_CONSTRAINTS
                     | BatchedItemOperations.CHECK_HOLD
                     | BatchedItemOperations.CHECK_RETENTION);
@@ -231,7 +233,7 @@
             itemOps.checkRemoveNode(conflicting,
                     BatchedItemOperations.CHECK_ACCESS
                     | BatchedItemOperations.CHECK_LOCK
-                    | BatchedItemOperations.CHECK_VERSIONING
+                    | BatchedItemOperations.CHECK_CHECKED_OUT
                     | BatchedItemOperations.CHECK_CONSTRAINTS
                     | BatchedItemOperations.CHECK_HOLD
                     | BatchedItemOperations.CHECK_RETENTION);
@@ -253,7 +255,7 @@
                     nodeInfo.getNodeTypeName(),
                     BatchedItemOperations.CHECK_ACCESS
                     | BatchedItemOperations.CHECK_LOCK
-                    | BatchedItemOperations.CHECK_VERSIONING
+                    | BatchedItemOperations.CHECK_CHECKED_OUT
                     | BatchedItemOperations.CHECK_CONSTRAINTS
                     | BatchedItemOperations.CHECK_HOLD
                     | BatchedItemOperations.CHECK_RETENTION);
@@ -291,8 +293,8 @@
      * Post-process imported node (initialize properties with special
      * semantics etc.)
      *
-     * @param node
-     * @throws RepositoryException
+     * @param node the node state
+     * @throws RepositoryException if an error occurs
      */
     protected void postProcessNode(NodeState node) throws RepositoryException {
         /**
@@ -344,6 +346,73 @@
         }
     }
 
+    protected void processProperty(NodeState node, PropInfo pInfo) throws RepositoryException {
+        PropertyState prop;
+        PropDef def;
+
+        Name name = pInfo.getName();
+        int type = pInfo.getType();
+
+        if (node.hasPropertyName(name)) {
+            // a property with that name already exists...
+            PropertyId idExisting = new PropertyId(node.getNodeId(), name);
+            prop = (PropertyState) itemOps.getItemState(idExisting);
+            def = ntReg.getPropDef(prop.getDefinitionId());
+            if (def.isProtected()) {
+                // skip protected property
+                log.debug("skipping protected property "
+                        + itemOps.safeGetJCRPath(idExisting));
+                return;
+            }
+            if (!def.isAutoCreated()
+                    || (prop.getType() != type && type != PropertyType.UNDEFINED)
+                    || def.isMultiple() != prop.isMultiValued()) {
+                throw new ItemExistsException(itemOps.safeGetJCRPath(prop.getPropertyId()));
+            }
+        } else {
+            // there's no property with that name,
+            // find applicable definition
+            def = pInfo.getApplicablePropertyDef(itemOps.getEffectiveNodeType(node));
+            if (def.isProtected()) {
+                // skip protected property
+                log.debug("skipping protected property " + name);
+                return;
+            }
+
+            // create new property
+            prop = itemOps.createPropertyState(node, name, type, def);
+        }
+
+        // check multi-valued characteristic
+        TextValue[] values = pInfo.getTextValues();
+        if (values.length != 1 && !def.isMultiple()) {
+            throw new ConstraintViolationException(itemOps.safeGetJCRPath(prop.getPropertyId())
+                    + " is not multi-valued");
+        }
+
+        // convert serialized values to InternalValue objects
+        int targetType = pInfo.getTargetType(def);
+        InternalValue[] iva = new InternalValue[values.length];
+        for (int i = 0; i < values.length; i++) {
+            iva[i] = values[i].getInternalValue(targetType);
+        }
+
+        // set values
+        prop.setValues(iva);
+
+        // make sure property is valid according to its definition
+        itemOps.validate(prop);
+
+        if (prop.getType() == PropertyType.REFERENCE
+                || prop.getType() == PropertyType.WEAKREFERENCE) {
+            // store reference for later resolution
+            refTracker.processedReference(prop);
+        }
+
+        // store property
+        itemOps.store(prop);
+    }
+    
     /**
      * Adds the the given property to a node unless the property already
      * exists.
@@ -400,7 +469,7 @@
             // check sanity of workspace/session first
             wsp.sanityCheck();
 
-            parent = (NodeState) parents.peek();
+            parent = parents.peek();
 
             // process node
 
@@ -515,8 +584,8 @@
             }
 
             // process properties
-            for (PropInfo pi : propInfos) {
-                pi.apply(node, itemOps, ntReg, refTracker);
+            for (PropInfo propInfo : propInfos) {
+                processProperty(node, propInfo);
             }
 
             // store affected nodes
@@ -544,7 +613,7 @@
             // the import has been aborted, get outta here...
             return;
         }
-        NodeState node = (NodeState) parents.pop();
+        NodeState node = parents.pop();
         if (node == null) {
             // node was skipped, nothing to do here
             return;

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/resources-filtered/org/apache/jackrabbit/core/repository.properties
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/resources-filtered/org/apache/jackrabbit/core/repository.properties?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/resources-filtered/org/apache/jackrabbit/core/repository.properties (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/resources-filtered/org/apache/jackrabbit/core/repository.properties Tue Sep  8 16:09:28 2009
@@ -35,57 +35,3 @@
 
 # The descriptor for the version of this repository implementation.
 jcr.repository.version = ${pom.version}
-
-################################################################################
-# Repository features and support information
-#
-
-# The presence of this key indicates that this implementation supports
-# all level 1 features. This key will always be present.
-level.1.supported = true
-
-# The presence of this key indicates that this implementation supports all level 2 features.
-level.2.supported = true
-
-# The presence of this key indicates that this implementation supports transactions.
-option.transactions.supported = true
-
-# The presence of this key indicates that this implementation supports versioning.
-option.versioning.supported = true
-
-# The presence of this key indicates that this implementation supports simple versioning.
-option.simple.versioning.supported = true
-
-# The presence of this key indicates that this implementation supports activities.
-option.activities.supported = true
-
-# The presence of this key indicates that this implementation supports observation.
-option.observation.supported = true
-
-# The presence of this key indicates that this implementation supports locking.
-option.locking.supported = true
-
-# The presence of this key indicates that this implementation supports the SQL query language.
-option.query.sql.supported = true
-
-# The presence of this key indicates that this implementation supports access control.
-option.access.control.supported = true
-
-# The presence of this key indicates that this implementation supports node type management.
-option.node.type.management.supported = true
-
-# The presence of this key indicates that this implementation supports retention.
-option.retention.supported = true
-
-# The presence of this key indicates that this implementation supports shareable nodes.
-option.shareable.nodes.supported = true
-
-# The presence of this key indicates that the index position notation for same-name siblings is supported within XPath queries.
-query.xpath.pos.index = true
-
-# The presence of this key indicates that XPath queries return results in document order.
-query.xpath.doc.order = false
-# Disabled since in default configuration document order is not supported.
-# See https://issues.apache.org/jira/browse/JCR-1237 for details
-
-

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/JackrabbitRepositoryStub.properties
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/JackrabbitRepositoryStub.properties?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/JackrabbitRepositoryStub.properties (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/JackrabbitRepositoryStub.properties Tue Sep  8 16:09:28 2009
@@ -24,6 +24,7 @@
 # global test configuration
 javax.jcr.tck.testroot=/testroot
 javax.jcr.tck.nodetype=nt:unstructured
+javax.jcr.tck.nodetypenochildren=nt:address
 javax.jcr.tck.nodename1=node1
 javax.jcr.tck.nodename2=node2
 javax.jcr.tck.nodename3=node3
@@ -154,7 +155,7 @@
 # nodetype that does not allow same name siblings
 javax.jcr.tck.SessionTest.testMoveItemExistsException.nodetype2=nt:folder
 # valid node type that can be added as child of nodetype2
-javax.jcr.tck.SessionTest.testMoveItemExistsException.nodetype3=nt:hierarchyNode
+javax.jcr.tck.SessionTest.testMoveItemExistsException.nodetype3=nt:folder
 
 # Test class: SessionTest
 # Test method: testSaveContstraintViolationException
@@ -185,7 +186,7 @@
 # nodetype that has a mandatory child node definition
 javax.jcr.tck.NodeTest.testRemoveMandatoryNode.nodetype2=nt:file
 # nodetype of the  mandatory child
-javax.jcr.tck.NodeTest.testRemoveMandatoryNode.nodetype3=nt:base
+javax.jcr.tck.NodeTest.testRemoveMandatoryNode.nodetype3=nt:unstructured
 # name of the mandatory node
 javax.jcr.tck.NodeTest.testRemoveMandatoryNode.nodename3=jcr:content
 
@@ -219,7 +220,7 @@
 # nodetype that does not allow ordering of child nodes
 javax.jcr.tck.NodeOrderableChildNodesTest.testOrderBeforeUnsupportedRepositoryOperationException.nodetype2=nt:folder
 # valid node type that can be added as child of nodetype 2
-javax.jcr.tck.NodeOrderableChildNodesTest.testOrderBeforeUnsupportedRepositoryOperationException.nodetype3=nt:hierarchyNode
+javax.jcr.tck.NodeOrderableChildNodesTest.testOrderBeforeUnsupportedRepositoryOperationException.nodetype3=nt:folder
 
 # Test class: SetPropertyNodeTest
 # nodetype which is referenceable
@@ -515,3 +516,8 @@
 # JAVAX.JCR.RETENTION CONFIGURATION
 # ==============================================================================
 javax.jcr.tck.retentionpolicyholder=/testconf/retentionTest
+
+# ==============================================================================
+# LIFECYCLE MANAGEMENT CONFIGURATION
+# ==============================================================================
+javax.jcr.tck.lifecycleNode=/testdata/lifecycle/node

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.cnd
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.cnd?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.cnd (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.cnd Tue Sep  8 16:09:28 2009
@@ -31,7 +31,7 @@
  * @since 1.0
  */
 [nt:base]
-  // abstract (currently causes test-case failures, see JCR-2159)
+  abstract
   - jcr:primaryType (NAME) mandatory autocreated protected COMPUTE
   - jcr:mixinTypes (NAME) protected multiple COMPUTE
 
@@ -44,7 +44,7 @@
  * @since 1.0
  */
 [nt:hierarchyNode] > mix:created
-  // abstract (currently causes test-case failures, see JCR-2159)
+  abstract
 
 /**
  * Nodes of this node type may be used to represent files. This node type inherits
@@ -114,14 +114,16 @@
  * controlled by the repository, which should set them appropriately upon the
  * initial persist of a node with this mixin type. In cases where this mixin is
  * added to an already existing node the semantics of these properties are
- * implementation specific.
+ * implementation specific. Note that jackrabbit initializes the properties to
+ * the current date and user in this case.
+ *
  *
  * @since 2.0
  */
 [mix:created]
   mixin
   - jcr:created (DATE) autocreated protected
-  - jcr:createdBy (STRING) protected
+  - jcr:createdBy (STRING) autocreated protected
 
 /**
  * This mixin node type can be used to provide standardized modification
@@ -134,13 +136,16 @@
  *  constitutes a significant modification will depend on the semantics of the various
  *  parts of a node's subgraph and is implementation-dependent"
  *
+ * Jackrabbit initializes the properties to the current date and user in the
+ * case they are newly created.
+ *
  * Note that the protected attributes suggested by JSR283 are omitted in this variant.
  * @since 2.0
  */
 [mix:lastModified]
   mixin
-  - jcr:lastModified (DATE)
-  - jcr:lastModifiedBy (STRING)
+  - jcr:lastModified (DATE) autocreated
+  - jcr:lastModifiedBy (STRING) autocreated
 
 /**
  * This mixin node type can be used to provide a standardized property that
@@ -237,8 +242,7 @@
  */
 [mix:etag]
   mixin
-  // currently has a default value because auto-creation not handled see JCR-2116
-  - jcr:etag (STRING) = '' protected autocreated
+  - jcr:etag (STRING) protected autocreated
 
 //------------------------------------------------------------------------------
 // U N S T R U C T U R E D   C O N T E N T
@@ -269,7 +273,7 @@
  * and does not necessarily imply the use of the UUID syntax, or global uniqueness.
  * The identifier of a referenceable node must be a referenceable identifier.
  * Referenceable identifiers must fulfill a number of constraints beyond the
- * minimum required of standard identifiers (see ยค3.8.3 Referenceable Identifiers).
+ * minimum required of standard identifiers (see 3.8.3 Referenceable Identifiers).
  * A reference property is a property that holds the referenceable identifier of a
  * referenceable node and therefore serves as a pointer to that node. The two types
  * of reference properties, REFERENCE and WEAKREFERENCE differ in that the former
@@ -319,14 +323,14 @@
  */
 [mix:versionable] > mix:simpleVersionable, mix:referenceable
   mixin
-  - jcr:versionHistory (REFERENCE) mandatory protected < 'nt:versionHistory'
+  - jcr:versionHistory (REFERENCE) mandatory protected IGNORE < 'nt:versionHistory'
   - jcr:baseVersion (REFERENCE) mandatory protected IGNORE < 'nt:version'
-  - jcr:predecessors (REFERENCE) mandatory protected multiple < 'nt:version'
+  - jcr:predecessors (REFERENCE) mandatory protected multiple IGNORE < 'nt:version'
   - jcr:mergeFailed (REFERENCE) protected multiple ABORT < 'nt:version'
     /** @since 2.0 */
   - jcr:activity (REFERENCE) protected < 'nt:activity'
     /** @since 2.0 */
-  - jcr:configuration (REFERENCE) protected < 'nt:configuration'
+  - jcr:configuration (REFERENCE) protected IGNORE < 'nt:configuration'
 
 /**
  * @since 1.0
@@ -486,9 +490,6 @@
 // J A C K R A B B I T   I N T E R N A L S
 //------------------------------------------------------------------------------
 
-[rep:nodeTypes]
-  + * (nt:nodeType) = nt:nodeType protected ABORT
-
 [rep:root] > nt:unstructured
   + jcr:system (rep:system) = rep:system mandatory IGNORE
 
@@ -496,26 +497,54 @@
   orderable
   + jcr:versionStorage (rep:versionStorage) = rep:versionStorage mandatory protected ABORT
   + jcr:nodeTypes (rep:nodeTypes) = rep:nodeTypes mandatory protected ABORT
-  + * (nt:base) = nt:unstructured sns IGNORE
+  // @since 2.0
+  + jcr:activities (rep:Activities) = rep:Activities mandatory protected ABORT
+  // @since 2.0
+  + jcr:configurations (rep:Configurations) = rep:Configurations protected ABORT
+  + * (nt:base) = nt:base IGNORE
 
-// implementation note: currently we keep the activities below the version storage
-// because of the complexity of adding new virtual item state providers.
-// the future goal is to keep them as siblings, of course.
 
+/**
+ * Node Types (virtual) storage
+ */
+[rep:nodeTypes]
+  + * (nt:nodeType) = nt:nodeType protected ABORT
+
+/**
+ * Version storage
+ */
 [rep:versionStorage]
-  + * (nt:versionHistory) = nt:versionHistory protected sns ABORT
-  + * (rep:versionStorage) = rep:versionStorage protected sns ABORT
-  + * (rep:activities) = rep:activities protected sns ABORT
-
-[rep:activities]
-  + * (nt:activity) = nt:activity protected sns ABORT
-  + * (rep:activities) = rep:activities protected sns ABORT
-
-// implementation note: because node references are not maintained within the
-// version storage, we store a bidirectional relationship between activities and
- // the respective versions
+  + * (nt:versionHistory) = nt:versionHistory protected ABORT
+  + * (rep:versionStorage) = rep:versionStorage protected ABORT
+
+/**
+ * Activities storage
+ * @since 2.0
+ */
+[rep:Activities]
+  + * (nt:activity) = nt:activity protected ABORT
+  + * (rep:Activities) = rep:Activities protected ABORT
+
+/**
+ * the intermediate nodes for the configurations storage.
+ * Note: since the versionable node points to the configuration and vice versa,
+ * a configuration could never be removed because no such API exists. therefore
+ * the child node definitions are not protected.
+ * @since 2.0
+ */
+[rep:Configurations]
+  + * (nt:configuration) = nt:configuration ABORT
+  + * (rep:Configurations) = rep:Configurations ABORT
+
+/**
+ * mixin that provides a multi value property for referencing versions.
+ * This is used for recording the baseline versions in the nt:configuration
+ * node, and to setup a bidirectional relationship between activities and
+ * the respective versions
+ * @since 2.0
+ */
 [rep:VersionReference] mix
-  - rep:versions (reference) protected multiple abort
+  - rep:versions (REFERENCE) protected multiple
   
 // -----------------------------------------------------------------------------
 // J A C K R A B B I T  S E C U R I T Y

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/repository.xml
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/repository.xml?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/repository.xml (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/repository.xml Tue Sep  8 16:09:28 2009
@@ -32,6 +32,11 @@
     </FileSystem>
 
     <!--
+        data store configuration
+    -->
+    <DataStore class="org.apache.jackrabbit.core.data.FileDataStore"/>
+
+    <!--
         security configuration
     -->
     <Security appName="Jackrabbit">
@@ -98,7 +103,6 @@
         -->
         <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
             <param name="path" value="${wsp.home}/index"/>
-            <param name="extractorPoolSize" value="2"/>
             <param name="supportHighlighting" value="true"/>
         </SearchIndex>
     </Workspace>
@@ -133,7 +137,6 @@
     -->
     <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
         <param name="path" value="${rep.home}/repository/index"/>
-        <param name="extractorPoolSize" value="2"/>
         <param name="supportHighlighting" value="true"/>
     </SearchIndex>
 </Repository>

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/principal/PrincipalManagerTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/principal/PrincipalManagerTest.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/principal/PrincipalManagerTest.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/principal/PrincipalManagerTest.java Tue Sep  8 16:09:28 2009
@@ -50,8 +50,8 @@
 
     private static Principal[] getPrincipals(Session session) {
         // TODO: get rid of SessionImpl dependency
-        Set princ = ((SessionImpl) session).getSubject().getPrincipals();
-        return (Principal[]) princ.toArray(new Principal[princ.size()]);
+        Set<Principal> princ = ((SessionImpl) session).getSubject().getPrincipals();
+        return princ.toArray(new Principal[princ.size()]);
     }
 
     private static boolean isGroup(Principal p) {
@@ -66,9 +66,9 @@
 
     public void testSuperUserIsEveryOne() {
         Principal[] pcpls = getPrincipals(superuser);
-        for (int i = 0; i < pcpls.length; i++) {
-            if (!(pcpls[i].equals(everyone))) {
-                assertTrue(everyone.isMember(pcpls[i]));
+        for (Principal pcpl : pcpls) {
+            if (!(pcpl.equals(everyone))) {
+                assertTrue(everyone.isMember(pcpl));
             }
         }
     }
@@ -77,9 +77,9 @@
         Session s = getHelper().getReadOnlySession();
         try {
             Principal[] pcpls = getPrincipals(s);
-            for (int i = 0; i < pcpls.length; i++) {
-                if (!(pcpls[i].equals(everyone))) {
-                    assertTrue(everyone.isMember(pcpls[i]));
+            for (Principal pcpl : pcpls) {
+                if (!(pcpl.equals(everyone))) {
+                    assertTrue(everyone.isMember(pcpl));
                 }
             }
         } finally {
@@ -91,31 +91,31 @@
         assertTrue(principalMgr.hasPrincipal(everyone.getName()));
 
         Principal[] pcpls = getPrincipals(superuser);
-        for (int i = 0; i < pcpls.length; i++) {
-            assertTrue(principalMgr.hasPrincipal(pcpls[i].getName()));
+        for (Principal pcpl : pcpls) {
+            assertTrue(principalMgr.hasPrincipal(pcpl.getName()));
         }
     }
 
-    public void testGetPrincipal() throws NoSuchPrincipalException {
+    public void testGetPrincipal() {
         Principal p = principalMgr.getPrincipal(everyone.getName());
         assertEquals(everyone, p);
 
         Principal[] pcpls = getPrincipals(superuser);
-        for (int i = 0; i < pcpls.length; i++) {
-            Principal pp = principalMgr.getPrincipal(pcpls[i].getName());
-            assertEquals("PrincipalManager.getPrincipal returned Principal with different Name", pcpls[i].getName(), pp.getName());
+        for (Principal pcpl : pcpls) {
+            Principal pp = principalMgr.getPrincipal(pcpl.getName());
+            assertEquals("PrincipalManager.getPrincipal returned Principal with different Name", pcpl.getName(), pp.getName());
         }
     }
 
-    public void testGetPrincipalGetName() throws NoSuchPrincipalException {
+    public void testGetPrincipalGetName() {
         Principal[] pcpls = getPrincipals(superuser);
-        for (int i = 0; i < pcpls.length; i++) {
-            Principal pp = principalMgr.getPrincipal(pcpls[i].getName());
-            assertEquals("PrincipalManager.getPrincipal returned Principal with different Name", pcpls[i].getName(), pp.getName());
+        for (Principal pcpl : pcpls) {
+            Principal pp = principalMgr.getPrincipal(pcpl.getName());
+            assertEquals("PrincipalManager.getPrincipal returned Principal with different Name", pcpl.getName(), pp.getName());
         }
     }
 
-    public void testGetPrincipals() throws NoSuchPrincipalException {
+    public void testGetPrincipals() {
         PrincipalIterator it = principalMgr.getPrincipals(PrincipalManager.SEARCH_TYPE_NOT_GROUP);
         while (it.hasNext()) {
             Principal p = it.nextPrincipal();
@@ -123,7 +123,7 @@
         }
     }
 
-    public void testGetGroupPrincipals() throws NoSuchPrincipalException {
+    public void testGetGroupPrincipals() {
         PrincipalIterator it = principalMgr.getPrincipals(PrincipalManager.SEARCH_TYPE_GROUP);
         while (it.hasNext()) {
             Principal p = it.nextPrincipal();
@@ -131,7 +131,7 @@
         }
     }
 
-    public void testGetAllPrincipals() throws NoSuchPrincipalException {
+    public void testGetAllPrincipals() {
         PrincipalIterator it = principalMgr.getPrincipals(PrincipalManager.SEARCH_TYPE_ALL);
         while (it.hasNext()) {
             Principal p = it.nextPrincipal();
@@ -154,7 +154,7 @@
         }
     }
 
-    public void testGroupMembership() throws NoSuchPrincipalException {
+    public void testGroupMembership() {
         testMembership(PrincipalManager.SEARCH_TYPE_NOT_GROUP);
         testMembership(PrincipalManager.SEARCH_TYPE_GROUP);
         testMembership(PrincipalManager.SEARCH_TYPE_ALL);
@@ -217,54 +217,54 @@
 
     public void testFindPrincipal() {
         Principal[] pcpls = getPrincipals(superuser);
-        for (int i = 0; i < pcpls.length; i++) {
-            if (pcpls[i].equals(everyone)) {
+        for (Principal pcpl : pcpls) {
+            if (pcpl.equals(everyone)) {
                 continue;
             }
-            Iterator it = principalMgr.findPrincipals(pcpls[i].getName());
+            Iterator it = principalMgr.findPrincipals(pcpl.getName());
             // search must find at least a single principal
-            assertTrue("findPrincipals does not find principal with filter "+pcpls[i].getName(), it.hasNext());
+            assertTrue("findPrincipals does not find principal with filter " + pcpl.getName(), it.hasNext());
         }
     }
 
     public void testFindPrincipalByType() {
         Principal[] pcpls = getPrincipals(superuser);
-        for (int i = 0; i < pcpls.length; i++) {
-            if (pcpls[i].equals(everyone)) {
+        for (Principal pcpl : pcpls) {
+            if (pcpl.equals(everyone)) {
                 // special case covered by another test
                 continue;
             }
 
-            if (isGroup(pcpls[i])) {
-                Iterator it = principalMgr.findPrincipals(pcpls[i].getName(),
+            if (isGroup(pcpl)) {
+                Iterator it = principalMgr.findPrincipals(pcpl.getName(),
                         PrincipalManager.SEARCH_TYPE_GROUP);
                 // search must find at least a single matching group principal
-                assertTrue("findPrincipals does not find principal with filter "+pcpls[i].getName(), it.hasNext());
+                assertTrue("findPrincipals does not find principal with filter " + pcpl.getName(), it.hasNext());
             } else {
-                Iterator it = principalMgr.findPrincipals(pcpls[i].getName(),
+                Iterator it = principalMgr.findPrincipals(pcpl.getName(),
                         PrincipalManager.SEARCH_TYPE_NOT_GROUP);
                 // search must find at least a single matching non-group principal
-                assertTrue("findPrincipals does not find principal with filter "+pcpls[i].getName(), it.hasNext());
+                assertTrue("findPrincipals does not find principal with filter " + pcpl.getName(), it.hasNext());
             }
         }
     }
 
     public void testFindPrincipalByTypeAll() {
         Principal[] pcpls = getPrincipals(superuser);
-        for (int i = 0; i < pcpls.length; i++) {
-            if (pcpls[i].equals(everyone)) {
+        for (Principal pcpl : pcpls) {
+            if (pcpl.equals(everyone)) {
                 // special case covered by another test
                 continue;
             }
 
-            PrincipalIterator it = principalMgr.findPrincipals(pcpls[i].getName(), PrincipalManager.SEARCH_TYPE_ALL);
-            PrincipalIterator it2 = principalMgr.findPrincipals(pcpls[i].getName());
+            PrincipalIterator it = principalMgr.findPrincipals(pcpl.getName(), PrincipalManager.SEARCH_TYPE_ALL);
+            PrincipalIterator it2 = principalMgr.findPrincipals(pcpl.getName());
 
             // both search must reveal the same result and size
             assertTrue(it.getSize() == it2.getSize());
 
-            Set s1 = new HashSet();
-            Set s2 = new HashSet();
+            Set<Principal> s1 = new HashSet<Principal>();
+            Set<Principal> s2 = new HashSet<Principal>();
             while (it.hasNext() && it2.hasNext()) {
                 s1.add(it.nextPrincipal());
                 s2.add(it2.nextPrincipal());

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/AbstractUserTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/AbstractUserTest.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/AbstractUserTest.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/AbstractUserTest.java Tue Sep  8 16:09:28 2009
@@ -23,7 +23,6 @@
 import org.apache.jackrabbit.test.AbstractJCRTest;
 import org.apache.jackrabbit.test.NotExecutableException;
 import org.apache.jackrabbit.util.Text;
-import org.apache.jackrabbit.uuid.UUID;
 
 import javax.jcr.Credentials;
 import javax.jcr.RepositoryException;
@@ -37,6 +36,7 @@
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.UUID;
 
 /**
  * <code>AbstractUserTest</code>...

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/GroupTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/GroupTest.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/GroupTest.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/GroupTest.java Tue Sep  8 16:09:28 2009
@@ -16,22 +16,19 @@
  */
 package org.apache.jackrabbit.api.security.user;
 
-import org.apache.jackrabbit.test.NotExecutableException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.jcr.RepositoryException;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.test.NotExecutableException;
+
 /**
  * <code>GroupTest</code>...
  */
 public class GroupTest extends AbstractUserTest {
 
-    private static Logger log = LoggerFactory.getLogger(GroupTest.class);
-
     private static void assertTrueIsMember(Iterator members, Authorizable auth) throws RepositoryException {
         boolean contained = false;
         while (members.hasNext() && !contained) {
@@ -127,9 +124,9 @@
 
     public void testGetMembersContainsDeclaredMembers() throws NotExecutableException, RepositoryException {
         Group gr = getTestGroup(superuser);
-        List l = new ArrayList();
-        for (Iterator it = gr.getMembers(); it.hasNext();) {
-            l.add(((Authorizable) it.next()).getID());
+        List<String> l = new ArrayList<String>();
+        for (Iterator<Authorizable> it = gr.getMembers(); it.hasNext();) {
+            l.add(it.next().getID());
         }
         for (Iterator it = gr.getDeclaredMembers(); it.hasNext();) {
             assertTrue("All declared members must also be part of the Iterator " +
@@ -158,6 +155,48 @@
         }
     }
 
+    public void testAddRemoveMember() throws NotExecutableException, RepositoryException {
+        User auth = getTestUser(superuser);
+        Group newGroup1 = null;
+        Group newGroup2 = null;
+        try {
+            newGroup1 = userMgr.createGroup(getTestPrincipal());
+            newGroup2 = userMgr.createGroup(getTestPrincipal());
+
+            assertFalse(newGroup1.isMember(auth));
+            assertFalse(newGroup1.removeMember(auth));
+            assertFalse(newGroup2.isMember(auth));
+            assertFalse(newGroup2.removeMember(auth));
+
+            assertTrue(newGroup1.addMember(auth));
+            assertTrue(newGroup1.isMember(auth));
+            assertTrue(newGroup1.isMember(userMgr.getAuthorizable(auth.getID())));
+
+            assertTrue(newGroup2.addMember(auth));
+            assertTrue(newGroup2.isMember(auth));
+            assertTrue(newGroup2.isMember(userMgr.getAuthorizable(auth.getID())));
+
+            assertTrue(newGroup1.removeMember(auth));
+            assertTrue(newGroup2.removeMember(auth));
+
+            assertTrue(newGroup1.addMember(auth));
+            assertTrue(newGroup1.isMember(auth));
+            assertTrue(newGroup1.isMember(userMgr.getAuthorizable(auth.getID())));
+            assertTrue(newGroup1.removeMember(auth));
+
+
+        } finally {
+            if (newGroup1 != null) {
+                newGroup1.removeMember(auth);
+                newGroup1.remove();
+            }
+            if (newGroup2 != null) {
+                newGroup2.removeMember(auth);
+                newGroup2.remove();
+            }
+        }
+    }
+
     public void testAddMemberTwice() throws NotExecutableException, RepositoryException {
         User auth = getTestUser(superuser);
         Group newGroup = null;
@@ -282,8 +321,8 @@
      * Removing a GroupImpl must be possible even if there are still existing
      * members present.
      *
-     * @throws RepositoryException
-     * @throws NotExecutableException
+     * @throws RepositoryException if an error occurs
+     * @throws NotExecutableException if not executable
      */
     public void testRemoveGroupIfMemberExist() throws RepositoryException, NotExecutableException {
         User auth = getTestUser(superuser);

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/AbstractConcurrencyTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/AbstractConcurrencyTest.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/AbstractConcurrencyTest.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/AbstractConcurrencyTest.java Tue Sep  8 16:09:28 2009
@@ -107,11 +107,12 @@
     private void executeAll(Executor[] executors, long timeout) throws RepositoryException {
         Thread[] threads = new Thread[executors.length];
         for (int i = 0; i < executors.length; i++) {
-            threads[i] = new Thread(executors[i]);
+            threads[i] = new Thread(executors[i], "Executor " + i);
         }
         for (int i = 0; i < threads.length; i++) {
             threads[i].start();
         }
+
         boolean stacksDumped = false;
         for (int i = 0; i < threads.length; i++) {
             try {

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentReadWriteTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentReadWriteTest.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentReadWriteTest.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentReadWriteTest.java Tue Sep  8 16:09:28 2009
@@ -64,7 +64,7 @@
                                 try {
                                     for (PropertyIterator it = n.getProperties(); it.hasNext(); ) {
                                         Property p = it.nextProperty();
-                                        if (p.getDefinition().isMultiple()) {
+                                        if (p.isMultiple()) {
                                             p.getValues();
                                         } else {
                                             p.getValue();

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/NodeImplTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/NodeImplTest.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/NodeImplTest.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/NodeImplTest.java Tue Sep  8 16:09:28 2009
@@ -22,9 +22,11 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.jcr.ItemExistsException;
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
+import javax.jcr.nodetype.NodeType;
 import javax.jcr.security.AccessControlManager;
 import javax.jcr.security.AccessControlPolicy;
 import javax.jcr.security.AccessControlPolicyIterator;
@@ -99,7 +101,7 @@
      * @throws RepositoryException
      * @throws NotExecutableException
      */
-    public void testInternalIsCheckedOut() throws RepositoryException, NotExecutableException {
+    public void testIsCheckedOut() throws RepositoryException, NotExecutableException {
         Node n = testRootNode.addNode(nodeName1);
         NodeImpl testNode = (NodeImpl) n.addNode(nodeName2);
         testRootNode.save();
@@ -111,13 +113,13 @@
         Session readOnly = getHelper().getReadOnlySession();
         try {
             NodeImpl tn = (NodeImpl) readOnly.getItem(testNode.getPath());
-            assertTrue(tn.internalIsCheckedOut());
+            assertTrue(tn.isCheckedOut());
 
             n.addMixin(mixVersionable);
             testRootNode.save();
             n.checkin();
 
-            assertFalse(tn.internalIsCheckedOut());
+            assertFalse(tn.isCheckedOut());
         } finally {
             readOnly.logout();
             // reset the denied read-access
@@ -125,4 +127,30 @@
             changeReadPermission(principal, n, true);
         }
     }
-}
\ No newline at end of file
+
+    public void testAddNodeUuid() throws RepositoryException, NotExecutableException {
+        String uuid = "f81d4fae-7dec-11d0-a765-00a0c91e6bf6";
+        Node n = testRootNode.addNode(nodeName1);
+        Node testNode = ((NodeImpl) n).addNodeWithUuid(nodeName2, uuid);
+        testNode.addMixin(NodeType.MIX_REFERENCEABLE);
+        testRootNode.getSession().save();
+        assertEquals(
+                "Node identifier should be: " + uuid,
+                uuid, testNode.getIdentifier());
+    }
+
+    public void testAddNodeUuidCollision() throws RepositoryException, NotExecutableException {
+        String uuid = "f81d4fae-7dec-11d0-a765-00a0c91e6bf6";
+        Node n = testRootNode.addNode(nodeName1);
+        Node testNode1 = ((NodeImpl) n).addNodeWithUuid(nodeName2, uuid);
+        testNode1.addMixin(NodeType.MIX_REFERENCEABLE);
+        testRootNode.getSession().save();
+
+        try {
+            ((NodeImpl) n).addNodeWithUuid(nodeName2, uuid);
+            fail("UUID collision not detected by addNodeWithUuid");
+        } catch (ItemExistsException e) {
+        }
+    }
+
+}

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ShareableNodeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ShareableNodeTest.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ShareableNodeTest.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ShareableNodeTest.java Tue Sep  8 16:09:28 2009
@@ -18,6 +18,9 @@
 
 import javax.jcr.Node;
 import javax.jcr.Workspace;
+import javax.jcr.NodeIterator;
+import javax.jcr.query.QueryManager;
+import javax.jcr.query.Query;
 import javax.jcr.observation.Event;
 import javax.jcr.observation.EventIterator;
 import javax.jcr.observation.ObservationManager;
@@ -119,4 +122,32 @@
         superuser.getWorkspace().getObservationManager().removeEventListener(el);
         assertEquals(1, el.getEventCount());
     }
+
+    /**
+     * Verify that a shared node is removed when the ancestor is removed.
+     * See also JCR-2257.
+     */
+    public void testRemoveAncestorOfSharedNode() throws Exception {
+        Node a1 = testRootNode.addNode("a1");
+        Node a2 = a1.addNode("a2");
+        Node b1 = a1.addNode("b1");
+        ensureMixinType(b1, mixShareable);
+        testRootNode.save();
+        //now we have a shareable node N with path a1/b1
+
+        Workspace workspace = testRootNode.getSession().getWorkspace();
+        String path = a2.getPath() + "/b2";
+        workspace.clone(workspace.getName(), b1.getPath(), path, false);
+        testRootNode.save();
+        //now we have another shareable node N' in the same shared set as N with path a1/a2/b2
+
+        a2.remove();
+        testRootNode.save();
+
+        // assert b2 is removed from index
+        QueryManager qm = superuser.getWorkspace().getQueryManager();
+        String stmt = testPath + "//b2";
+        NodeIterator it = qm.createQuery(stmt, Query.XPATH).execute().getNodes();
+        assertFalse(it.hasNext());
+    }
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestAll.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestAll.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestAll.java Tue Sep  8 16:09:28 2009
@@ -46,6 +46,8 @@
         suite.addTestSuite(ReferencesTest.class);
 
         // test related to NodeStateMerger
+        // temporarily disabled see JCR-2272 and JCR-2295
+        // suite.addTestSuite(ConcurrentImportTest.class);
         suite.addTestSuite(ConcurrentAddRemoveMoveTest.class);
         suite.addTestSuite(ConcurrentAddRemovePropertyTest.class);
         suite.addTestSuite(ConcurrentMixinModificationTest.class);

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cluster/ClusterRecordTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cluster/ClusterRecordTest.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cluster/ClusterRecordTest.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cluster/ClusterRecordTest.java Tue Sep  8 16:09:28 2009
@@ -34,7 +34,6 @@
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
 import org.apache.jackrabbit.test.JUnitTest;
-import org.apache.jackrabbit.uuid.UUID;
 
 /**
  * Test cases for cluster record production and consumption. Verifies that
@@ -118,6 +117,25 @@
     }
 
     /**
+     * Test producing and consuming an update with a null userId
+     */
+    public void testUpdateOperationWithNullUserId() throws Exception {
+        UpdateEvent update = factory.createUpdateOperationWithNullUserId();
+
+        UpdateEventChannel channel = master.createUpdateChannel(DEFAULT_WORKSPACE);
+        channel.updateCreated(update);
+        channel.updatePrepared(update);
+        channel.updateCommitted(update, null);
+
+        SimpleEventListener listener = new SimpleEventListener();
+        slave.createUpdateChannel(DEFAULT_WORKSPACE).setListener(listener);
+        slave.sync();
+
+        assertEquals(1, listener.getClusterEvents().size());
+        assertEquals(listener.getClusterEvents().get(0), update);
+    }
+
+    /**
      * Test producing and consuming a lock operation.
      * @throws Exception
      */

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cluster/UpdateEventFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cluster/UpdateEventFactory.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cluster/UpdateEventFactory.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cluster/UpdateEventFactory.java Tue Sep  8 16:09:28 2009
@@ -37,7 +37,6 @@
 import org.apache.jackrabbit.spi.PathFactory;
 import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
 import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
-import org.apache.jackrabbit.uuid.UUID;
 
 /**
  * Simplistic factory that produces update events, consisting of node identifiers,
@@ -111,10 +110,39 @@
         changes.deleted(n3);
 
         List events = new ArrayList();
-        events.add(createEventState(n1, Event.NODE_ADDED, "{}n1"));
-        events.add(createEventState(p1, n1, Event.PROPERTY_ADDED));
-        events.add(createEventState(p2, n2, Event.PROPERTY_REMOVED));
-        events.add(createEventState(n3, Event.NODE_REMOVED, "{}n3"));
+        events.add(createEventState(n1, Event.NODE_ADDED, "{}n1", session));
+        events.add(createEventState(p1, n1, Event.PROPERTY_ADDED, session));
+        events.add(createEventState(p2, n2, Event.PROPERTY_REMOVED, session));
+        events.add(createEventState(n3, Event.NODE_REMOVED, "{}n3", session));
+
+        return new UpdateEvent(changes, events, System.currentTimeMillis(), "user-data");
+    }
+
+    /**
+     * Create an update operation.
+     *
+     * @return update operation
+     */
+    public UpdateEvent createUpdateOperationWithNullUserId() {
+        NodeState n1 = createNodeState();
+        NodeState n2 = createNodeState();
+        NodeState n3 = createNodeState();
+        PropertyState p1 = createPropertyState(n1.getNodeId(), "{}a");
+        PropertyState p2 = createPropertyState(n2.getNodeId(), "{}b");
+
+        ChangeLog changes = new ChangeLog();
+        changes.added(n1);
+        changes.added(p1);
+        changes.deleted(p2);
+        changes.modified(n2);
+        changes.deleted(n3);
+
+        Session s = new ClusterSession(null);
+        List events = new ArrayList();
+        events.add(createEventState(n1, Event.NODE_ADDED, "{}n1", s));
+        events.add(createEventState(p1, n1, Event.PROPERTY_ADDED, s));
+        events.add(createEventState(p2, n2, Event.PROPERTY_REMOVED, s));
+        events.add(createEventState(n3, Event.NODE_REMOVED, "{}n3", s));
 
         return new UpdateEvent(changes, events, System.currentTimeMillis(), "user-data");
     }
@@ -154,9 +182,11 @@
      * @param n node state
      * @param type <code>Event.NODE_ADDED</code> or <code>Event.NODE_REMOVED</code>
      * @param name node name
+     * @param session the session that produced the event.
      * @return event state
      */
-    protected EventState createEventState(NodeState n, int type, String name) {
+    protected EventState createEventState(NodeState n, int type, String name,
+                                          Session session) {
         Path.Element relPath = pathFactory.createElement(nameFactory.create(name));
 
         switch (type) {
@@ -180,9 +210,11 @@
      * @param p property state
      * @param parent parent node state
      * @param type <code>Event.NODE_ADDED</code> or <code>Event.NODE_REMOVED</code>
+     * @param session the session that produces the event.
      * @return event state
      */
-    protected EventState createEventState(PropertyState p, NodeState parent, int type) {
+    protected EventState createEventState(PropertyState p, NodeState parent, int type,
+                                          Session session) {
         Path.Element relPath = pathFactory.createElement(p.getName());
 
         switch (type) {

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/config/SecurityConfigTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/config/SecurityConfigTest.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/config/SecurityConfigTest.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/config/SecurityConfigTest.java Tue Sep  8 16:09:28 2009
@@ -18,6 +18,7 @@
 
 import org.apache.jackrabbit.core.DefaultSecurityManager;
 import org.apache.jackrabbit.core.security.DefaultAccessManager;
+import org.apache.jackrabbit.core.security.user.UserManagerImpl;
 import org.apache.jackrabbit.core.security.authentication.DefaultLoginModule;
 import org.apache.jackrabbit.core.security.simple.SimpleAccessManager;
 import org.apache.jackrabbit.core.security.simple.SimpleSecurityManager;
@@ -88,6 +89,8 @@
         assertNull(smc.getWorkspaceAccessConfig());
         assertEquals("security", smc.getWorkspaceName());
 
+        assertNull(smc.getUserManagerConfig());
+
         AccessManagerConfig amc = config.getAccessManagerConfig();
         assertNotNull(amc);
         assertTrue(amc.newInstance() instanceof DefaultAccessManager);
@@ -102,6 +105,24 @@
         assertEquals("org.apache.jackrabbit.TestPrincipalProvider", options.getProperty("principalProvider"));
     }
 
+    public void testConfig3() throws ConfigurationException {
+        Element xml = parseXML(new InputSource(new StringReader(CONFIG_3)), true);
+        SecurityConfig config = parser.parseSecurityConfig(xml);
+
+        SecurityManagerConfig smc = config.getSecurityManagerConfig();
+
+        assertNotNull(smc.getUserManagerConfig());
+        BeanConfig umc = smc.getUserManagerConfig();
+
+        Properties params = umc.getParameters();
+        assertNotNull(params);
+
+        assertFalse(params.containsKey(UserManagerImpl.PARAM_COMPATIBILE_JR16));
+        assertTrue(Boolean.parseBoolean(params.getProperty(UserManagerImpl.PARAM_AUTO_EXPAND_TREE)));
+        assertEquals(4, Integer.parseInt(params.getProperty(UserManagerImpl.PARAM_DEFAULT_DEPTH)));
+        assertEquals(2000, Long.parseLong(params.getProperty(UserManagerImpl.PARAM_AUTO_EXPAND_SIZE)));
+    }
+
     public void testInvalidConfig() {
         List invalid = new ArrayList();
         invalid.add(new InputSource(new StringReader(INVALID_CONFIG_1)));
@@ -160,6 +181,24 @@
             "        </LoginModule>\n" +
             "    </Security>";
 
+    private static final String CONFIG_3 =
+            "    <Security appName=\"Jackrabbit\">" +
+            "        <SecurityManager class=\"org.apache.jackrabbit.core.DefaultSecurityManager\" workspaceName=\"security\">" +
+            "           <UserManager class=\"\">" +
+            "           <param name=\"defaultDepth\" value=\"4\"/>" +
+            "           <param name=\"autoExpandTree\" value=\"true\"/>" +
+            "           <param name=\"autoExpandSize\" value=\"2000\"/>" +
+            "           </UserManager>" +
+            "        </SecurityManager>" +
+            "        <AccessManager class=\"org.apache.jackrabbit.core.security.DefaultAccessManager\">" +
+            "        </AccessManager>" +
+            "        <LoginModule class=\"org.apache.jackrabbit.core.security.authentication.DefaultLoginModule\">" +
+            "           <param name=\"anonymousId\" value=\"anonymous\"/>" +
+            "           <param name=\"adminId\" value=\"admin\"/>" +
+            "           <param name=\"principalProvider\" value=\"org.apache.jackrabbit.TestPrincipalProvider\"/>" +
+            "        </LoginModule>\n" +
+            "    </Security>";
+
     private static final String INVALID_CONFIG_1 =
             "    <Security appName=\"Jackrabbit\">" +
             "        <SecurityManager class=\"org.apache.jackrabbit.core.security.simple.SimpleSecurityManager\"></SecurityManager>" +

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GCConcurrentTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GCConcurrentTest.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GCConcurrentTest.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GCConcurrentTest.java Tue Sep  8 16:09:28 2009
@@ -17,6 +17,7 @@
 package org.apache.jackrabbit.core.data;
 
 import org.apache.jackrabbit.core.RepositoryImpl;
+import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.test.AbstractJCRTest;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -40,6 +41,35 @@
     /** logger instance */
     private static final Logger LOG = LoggerFactory.getLogger(GCConcurrentTest.class);
 
+    public void testConcurrentDelete() throws Exception {
+        Node root = testRootNode;
+        Session session = root.getSession();
+        RepositoryImpl rep = (RepositoryImpl) session.getRepository();
+        if (rep.getDataStore() == null) {
+            LOG.info("testGC skipped. Data store is not used.");
+            return;
+        }
+        final String testNodeName = "testConcurrentDelete";
+        node(root, testNodeName);
+        session.save();
+        GarbageCollector gc = ((SessionImpl) session).createDataStoreGarbageCollector();
+        gc.setPersistenceManagerScan(false);
+        gc.setScanEventListener(new ScanEventListener() {
+            public void beforeScanning(Node n) throws RepositoryException {
+                if (n.getName().equals(testNodeName)) {
+                    n.remove();
+                    n.getSession().save();
+                }
+            }
+            public void afterScanning(Node n) throws RepositoryException {
+            }
+            public void done() {
+            }
+        });
+        gc.scan();
+        gc.stopScan();
+    }
+
     public void testGC() throws Exception {
         Node root = testRootNode;
         Session session = root.getSession();

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GarbageCollectorTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GarbageCollectorTest.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GarbageCollectorTest.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GarbageCollectorTest.java Tue Sep  8 16:09:28 2009
@@ -41,6 +41,50 @@
     /** logger instance */
     private static final Logger LOG = LoggerFactory.getLogger(GarbageCollectorTest.class);
 
+    public void testCloseSessionWhileRunningGc() throws Exception {
+        final Session session = getHelper().getReadWriteSession();
+        RepositoryImpl rep = (RepositoryImpl) session.getRepository();
+        if (rep.getDataStore() == null) {
+            LOG.info("testConcurrentClose skipped. Data store is not used.");
+            return;
+        }
+        final GarbageCollector gc = ((SessionImpl) session).createDataStoreGarbageCollector();
+        final Exception[] ex = new Exception[1];
+        gc.setScanEventListener(new ScanEventListener() {
+            boolean closed;
+
+            public void afterScanning(Node n) throws RepositoryException {
+                closeTest();
+            }
+
+            public void beforeScanning(Node n) throws RepositoryException {
+                closeTest();
+            }
+
+            public void done() {
+            }
+
+            private void closeTest() throws RepositoryException {
+                if (closed) {
+                    ex[0] = new Exception("Scanning after the session is closed");
+                }
+                closed = true;
+                session.logout();
+            }
+
+        });
+        try {
+            gc.scan();
+            fail("Exception 'session has been closed' expected");
+        } catch (RepositoryException e) {
+            LOG.debug("Expected exception caught: " + e.getMessage());
+        }
+        if (ex[0] != null) {
+            throw ex[0];
+        }
+        gc.close();
+    }
+
     public void testConcurrentGC() throws Exception {
         Node root = testRootNode;
         Session session = root.getSession();

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/PersistenceManagerIteratorTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/PersistenceManagerIteratorTest.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/PersistenceManagerIteratorTest.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/PersistenceManagerIteratorTest.java Tue Sep  8 16:09:28 2009
@@ -23,7 +23,6 @@
 import org.apache.jackrabbit.core.persistence.PersistenceManager;
 import org.apache.jackrabbit.core.persistence.bundle.AbstractBundlePersistenceManager;
 import org.apache.jackrabbit.test.AbstractJCRTest;
-import org.apache.jackrabbit.uuid.UUID;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;