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 [2/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/RELEASE-NOTES.txt
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/RELEASE-NOTES.txt?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/RELEASE-NOTES.txt (original)
+++ jackrabbit/sandbox/JCR-1456/RELEASE-NOTES.txt Tue Sep  8 16:09:28 2009
@@ -1,4 +1,4 @@
-Release Notes -- Apache Jackrabbit -- Version 2.0-alpha4
+Release Notes -- Apache Jackrabbit -- Version 2.0-alpha10
 
 Introduction
 ------------
@@ -8,10 +8,10 @@
 Request 283 (JSR 283, http://jcp.org/en/jsr/detail?id=283).
 
 The purpose of this alpha release is to allow people to test and review
-the new JCR 2.0 features before they are finalized. Feedback to both the
-Jackrabbit project and the JSR 283 expert group is highly appreciated.
-Note that an alpha release is not expected to be feature-complete or
-otherwise suitable for production use.
+the new Jackrabbit and JCR 2.0 features before they are finalized. Feedback
+to both the Jackrabbit project and the JSR 283 expert group is highly
+appreciated. Note that an alpha release is not expected to be feature-complete
+or otherwise suitable for production use.
 
 Changes in this release
 -----------------------
@@ -20,9 +20,8 @@
 notable changes in this release are:
 
   * Upgrade to JCR 2.0. This Jackrabbit release implements and is based
-    on a pre-release version of the JCR 2.0 API. See below for a status
-    listing of the issues related to JCR 2.0 changes. We expect to achieve
-    full feature-completeness in time for the final Jackrabbit 2.0 release.
+    on a pre-release version of the JCR 2.0 API. All of the features
+    required by the JSR 283 specification have been implemented.
 
   * Upgrade to Java 5. All of Jackrabbit (except the jcr-tests component)
     now requires Java 5 as the base platform. Java 1.4 environments are no
@@ -37,64 +36,13 @@
     separately from the Jackrabbit content repository. See the individual
     components for their most recent releases.
 
+  * Data store feature enabled in the default repository configuration.
+
 For more detailed information about all the changes in this and other
 Jackrabbit releases, please see the Jackrabbit issue tracker at
 
     https://issues.apache.org/jira/browse/JCR
 
-JCR 2.0 feature completeness
-----------------------------
-
-The following 41 top level JCR 2.0 implementation issues are being tracked in
-the Jackrabbit issue tracker. Most of them have already been partially
-implemented, but the issue will only be marked as resolved once no more
-related work is needed.
-
-Open (16 issues)
-  [JCR-1565] JSR 283 lifecycle management
-  [JCR-1588] JSR 283: Access Control
-  [JCR-1590] JSR 283: Locking
-  [JCR-1591] JSR 283: NodeType Management
-  [JCR-1712] JSR 283: JCR Names
-  [JCR-1974] JSR 283: Evaluate Capabilities
-  [JCR-2058] JSR 283: VersionManager and new versioning methods
-  [JCR-2062] JSR 283: Repository Compliance
-  [JCR-2085] test case (TCK) maintenance for JCR 2.0
-  [JCR-2092] make spi query code compatible with JCR 2.0
-  [JCR-2116] JSR 283: Built-In Node Types
-  [JCR-2137] Use type StaticOperand for fullTextSearchExpression
-  [JCR-2140] JSR 283: Baselines
-  [JCR-2198] Text.escapeIllegalJCRChars should be adjusted to match the ...
-  [JCR-2200] Implement Query.getBindVariableNames()
-  [JCR-2201] Implement QueryResult.getSelectorNames()
-
-Resolved (25 issues)
-  [JCR-1564] JSR 283 namespace handling
-  [JCR-1589] JSR 283: Retention & Hold Management
-  [JCR-1592] JSR 283: Activities
-  [JCR-1593] JSR 283: Simple versioning
-  [JCR-1608] JSR 283: Workspace Management
-  [JCR-1609] JSR 283: new Property Types
-  [JCR-1834] JSR 283: Create RepositoryFactory implementation
-  [JCR-1839] JSR 283: Introduce Event.getDate()
-  [JCR-1849] JSR 283: EventJournal
-  [JCR-1904] JSR 283: Event user data
-  [JCR-1947] JSR 283: Node Type Attribute Subtyping Rules
-  [JCR-2028] JSR 283: JCR Path
-  [JCR-2053] JSR 283: Shareable nodes support in query
-  [JCR-2056] JSR 283: Binary interfaces
-  [JCR-2059] JSR 283: Access Property/Node from Session
-  [JCR-2060] JSR 283: Access Nodes and Properties by Array of "NameGlob"
-  [JCR-2061] JSR 283: References and Dereferencing of Property Values
-  [JCR-2074] JSR 283: New Event Types
-  [JCR-2075] JSR 283: Identifier based event filtering
-  [JCR-2076] JSR 283: QOM and SQL2
-  [JCR-2086] JSR 283: Implementation of EventIterator.getDate
-  [JCR-2090] JSR 283: new methods on NodeType
-  [JCR-2091] Searchability settings in PropertyDefinition
-  [JCR-2093] Implement QueryObjectModelFactory.fullTextSearch() in ...
-  [JCR-2117] JSR 283: adopt CND syntax changes
-
 Release Contents
 ----------------
 
@@ -114,8 +62,7 @@
 Repository for Java Technology API (JCR). A content repository is a
 hierarchical content store with support for structured and unstructured
 content, full text search, versioning, transactions, observation, and
-more. Typical applications that use content repositories include content
-management, document management, and records management systems.
+more.
 
 For more information, visit http://jackrabbit.apache.org/
 

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-api/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-api/pom.xml?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-api/pom.xml (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-api/pom.xml Tue Sep  8 16:09:28 2009
@@ -33,7 +33,7 @@
     <relativePath>../jackrabbit-parent/pom.xml</relativePath>
   </parent>
   <artifactId>jackrabbit-api</artifactId>
-  <name>Jackrabbit API</name>
+  <name>Apache Jackrabbit API</name>
   <description>Jacrabbit-specific extensions to the JCR API</description>
   <packaging>bundle</packaging>
 
@@ -61,6 +61,15 @@
           </instructions>
         </configuration>
       </plugin>
+      <plugin>
+        <groupId>org.apache.rat</groupId>
+        <artifactId>apache-rat-plugin</artifactId>
+        <configuration>
+          <excludes>
+            <exclude>.checkstyle</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
     </plugins>
   </build>
 

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlList.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlList.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlList.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlList.java Tue Sep  8 16:09:28 2009
@@ -71,9 +71,9 @@
      * Same as {@link #addEntry(Principal, Privilege[], boolean, Map)} using
      * some implementation specific restrictions.
      *
-     * @param principal
-     * @param privileges
-     * @param isAllow
+     * @param principal the principal to add the entry for
+     * @param privileges the privileges to add
+     * @param isAllow if <code>true</code> if this is a positive (allow) entry
      * @return true if this policy has changed by incorporating the given entry;
      * false otherwise.
      * @throws AccessControlException If any of the given parameter is invalid
@@ -81,7 +81,8 @@
      * @throws RepositoryException If another error occurs.
      * @see AccessControlList#addAccessControlEntry(Principal, Privilege[])
      */
-    boolean addEntry(Principal principal, Privilege[] privileges, boolean isAllow) throws AccessControlException, RepositoryException;
+    boolean addEntry(Principal principal, Privilege[] privileges, boolean isAllow)
+            throws AccessControlException, RepositoryException;
 
     /**
      * Adds an access control entry to this policy consisting of the specified
@@ -95,9 +96,9 @@
      * An <code>AccessControlException</code> is thrown if any of the specified
      * parameters is invalid or if some other access control related exception occurs.
      * 
-     * @param principal
-     * @param privileges
-     * @param isAllow
+     * @param principal the principal to add the entry for
+     * @param privileges the privileges to add
+     * @param isAllow if <code>true</code> if this is a positive (allow) entry
      * @param restrictions A map of additional restrictions used to narrow the
      * effect of the entry to be created. The map must map JCR names to a single
      * {@link javax.jcr.Value} object.
@@ -109,5 +110,6 @@
      * @see AccessControlList#addAccessControlEntry(Principal, Privilege[])
      */
     boolean addEntry(Principal principal, Privilege[] privileges,
-                     boolean isAllow, Map<String, Value> restrictions) throws AccessControlException, RepositoryException;
+                     boolean isAllow, Map<String, Value> restrictions)
+            throws AccessControlException, RepositoryException;
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlManager.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlManager.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlManager.java Tue Sep  8 16:09:28 2009
@@ -19,9 +19,12 @@
 import javax.jcr.AccessDeniedException;
 import javax.jcr.RepositoryException;
 import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.PathNotFoundException;
 import javax.jcr.security.AccessControlException;
 import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.Privilege;
 import java.security.Principal;
+import java.util.Set;
 
 /**
  * <code>JackrabbitAccessControlManager</code> provides extensions to the
@@ -62,4 +65,79 @@
      * @throws RepositoryException
      */
     JackrabbitAccessControlPolicy[] getPolicies(Principal principal) throws AccessDeniedException, AccessControlException, UnsupportedRepositoryOperationException, RepositoryException;
+
+    /**
+     * Returns whether the given set of <code>Principal</code>s has the specified
+     * privileges for absolute path <code>absPath</code>, which must be an
+     * existing node.
+     * <p>
+     * Testing an aggregate privilege is equivalent to testing each non
+     * aggregate privilege among the set returned by calling
+     * <code>Privilege.getAggregatePrivileges()</code> for that privilege.
+     * <p>
+     * The results reported by the this method reflect the net <i>effect</i> of
+     * the currently applied control mechanisms. It does not reflect unsaved
+     * access control policies or unsaved access control entries. Changes to
+     * access control status caused by these mechanisms only take effect on
+     * <code>Session.save()</code> and are only then reflected in the results of
+     * the privilege test methods.
+     * <p>
+     * Since this method allows to view the privileges of principals other
+     * than included in the editing session, this method must throw
+     * <code>AccessDeniedException</code> if the session lacks
+     * <code>READ_ACCESS_CONTROL</code> privilege for the <code>absPath</code>
+     * node.
+     *
+     * @param absPath    an absolute path.
+     * @param principals a set of <code>Principal</code>s for which is the
+     * given privileges are tested.
+     * @param privileges an array of <code>Privilege</code>s.
+     * @return <code>true</code> if the session has the specified privileges;
+     *         <code>false</code> otherwise.
+     * @throws javax.jcr.PathNotFoundException if no node at <code>absPath</code> exists
+     * or the session does not have sufficent access to retrieve a node at that location.
+     * @throws AccessDeniedException if the session lacks
+     * <code>READ_ACCESS_CONTROL</code> privilege for the <code>absPath</code> node.
+     * @throws RepositoryException  if another error occurs.
+     */
+    public boolean hasPrivileges(String absPath, Set<Principal> principals, Privilege[] privileges)
+            throws PathNotFoundException, AccessDeniedException, RepositoryException;
+
+    /**
+     * Returns the privileges the given set of <code>Principal</code>s has for
+     * absolute path <code>absPath</code>, which must be an existing node.
+     * <p>
+     * The returned privileges are those for which {@link #hasPrivileges} would
+     * return <code>true</code>.
+     * <p>
+     * The results reported by the this method reflect the net <i>effect</i> of
+     * the currently applied control mechanisms. It does not reflect unsaved
+     * access control policies or unsaved access control entries. Changes to
+     * access control status caused by these mechanisms only take effect on
+     * <code>Session.save()</code> and are only then reflected in the results of
+     * the privilege test methods.
+     * <p>
+     * Since this method allows to view the privileges of principals other
+     * than included in the editing session, this method must throw
+     * <code>AccessDeniedException</code> if the session lacks
+     * <code>READ_ACCESS_CONTROL</code> privilege for the <code>absPath</code>
+     * node.
+     * <p>
+     * Note that this method does not resolve any group membership, as this is
+     * the job of the user manager. nor does it augment the set with the
+     * "everyone" principal.
+     *
+     * @param absPath an absolute path.
+     * @param principals a set of <code>Principal</code>s for which is the
+     * privileges are retrieved.
+     * @return an array of <code>Privilege</code>s.
+     * @throws PathNotFoundException if no node at <code>absPath</code> exists
+     * or the session does not have sufficient access to retrieve a node at that
+     * location.
+     * @throws AccessDeniedException if the session lacks <code>READ_ACCESS_CONTROL</code>
+     * privilege for the <code>absPath</code> node.
+     * @throws RepositoryException  if another error occurs.
+     */
+    public Privilege[] getPrivileges(String absPath, Set<Principal> principals)
+            throws PathNotFoundException, AccessDeniedException, RepositoryException;
 }
\ No newline at end of file

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/principal/PrincipalManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/principal/PrincipalManager.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/principal/PrincipalManager.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/principal/PrincipalManager.java Tue Sep  8 16:09:28 2009
@@ -80,10 +80,9 @@
      * <code>PrincipalManager</code> has been built for.
      *
      * @param principalName the name of the principal to retrieve
-     * @return return the requested principal.
-     * @throws NoSuchPrincipalException If no principal with the given name exists.
+     * @return return the requested principal or <code>null</code> if not exists
      */
-    Principal getPrincipal(String principalName) throws NoSuchPrincipalException;
+    Principal getPrincipal(String principalName);
 
     /**
      * Gets the principals matching a simple filter expression applied against

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/Authorizable.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/Authorizable.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/Authorizable.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/Authorizable.java Tue Sep  8 16:09:28 2009
@@ -16,12 +16,13 @@
  */
 package org.apache.jackrabbit.api.security.user;
 
-import org.apache.jackrabbit.api.security.principal.PrincipalIterator;
+import java.security.Principal;
+import java.util.Iterator;
 
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
-import java.security.Principal;
-import java.util.Iterator;
+
+import org.apache.jackrabbit.api.security.principal.PrincipalIterator;
 
 /**
  * The Authorizable is the common base interface for {@link User} and
@@ -29,23 +30,23 @@
  * with an <code>Authorizable</code> (see below) and allow to access and
  * modify additional properties such as e.g. full name, e-mail or address.
  * <p/>
- *
+ * <p/>
  * Please note the difference between <code>Authorizable</code> and
  * {@link java.security.Principal Principal}:<br>
  * An <code>Authorizable</code> is repository object that is neither associated
  * with nor depending from a particular <code>Session</code> and thus independant
  * of the login mechanisms creating <code>Session</code>s.<br>
- *
+ * <p/>
  * On the other hand <code>Principal</code>s are representations of user
  * identities. In other words: each <code>Principal</code> within the set
  * associated with the Session's Subject upon login represents an identity for
  * that user. An the set of <code>Principal</code>s may differ between different
  * login mechanisms.<br>
- *
+ * <p/>
  * Consequently an one-to-many relationship exists between Authorizable
  * and Principal (see also {@link #getPrincipal()} and {@link #getPrincipals()}).
- * <p />
- *
+ * <p/>
+ * <p/>
  * The interfaces derived from Authorizable are defined as follows:
  * <ul>
  * <li>{@link User}: defined to be an authorizable that can be authenticated
@@ -57,7 +58,7 @@
  * @see User
  * @see Group
  */
-public interface Authorizable  {
+public interface Authorizable {
 
     /**
      * Return the implementation specific identifer for this
@@ -70,9 +71,9 @@
     String getID() throws RepositoryException;
 
     /**
-	 * @return if the current Authorizable is a {@link Group}
-	 */
-	boolean isGroup();
+     * @return if the current Authorizable is a {@link Group}
+     */
+    boolean isGroup();
 
     /**
      * @return a representation as Principal.
@@ -87,10 +88,8 @@
      * Principal a <code>AuthorizableExistsException</code> is thrown.
      *
      * @param principal
-     * @return true if added, false if this Authorizable already represents
-     * the given Principal.
      * @return AuthorizableExistsException If the given principal is already refered
-     * to by another Authorizable.
+     *         to by another Authorizable.
      * @throws RepositoryException
      */
     boolean addReferee(Principal principal) throws AuthorizableExistsException, RepositoryException;
@@ -106,7 +105,7 @@
 
     /**
      * @return Iterator of all Principal related to this authentication Object
-     * including the main principal, (see {@link #getPrincipal()}).
+     *         including the main principal, (see {@link #getPrincipal()}).
      * @throws RepositoryException
      */
     PrincipalIterator getPrincipals() throws RepositoryException;
@@ -115,14 +114,14 @@
      * @return all {@link Group}s, this Authorizable is declared member of.
      * @throws RepositoryException
      */
-    Iterator declaredMemberOf() throws RepositoryException;
+    Iterator<Group> declaredMemberOf() throws RepositoryException;
 
     /**
      * @return all {@link Group}s, this Authorizable is member of included
-     * indirect group membership.
+     *         indirect group membership.
      * @throws RepositoryException
      */
-    Iterator memberOf() throws RepositoryException;
+    Iterator<Group> memberOf() throws RepositoryException;
 
     /**
      * Removes this <code>Authorizable</code>, if the session has sufficient
@@ -131,7 +130,7 @@
      * a Group itself).
      *
      * @throws RepositoryException If an error occured and the
-     * <code>Authorizable</code> could not be removed.
+     *                             <code>Authorizable</code> could not be removed.
      */
     void remove() throws RepositoryException;
 
@@ -143,17 +142,17 @@
      * @see #getProperty(String)
      * @see #hasProperty(String)
      */
-    Iterator getPropertyNames() throws RepositoryException;
+    Iterator<String> getPropertyNames() throws RepositoryException;
 
     /**
-	 * Tests if a the property with specified name exists.
+     * Tests if a the property with specified name exists.
      *
-	 * @param name
-	 * @return
-	 * @throws RepositoryException
-	 * @see #getProperty(String)
-	 */
-	boolean hasProperty(String name) throws RepositoryException;
+     * @param name
+     * @return
+     * @throws RepositoryException
+     * @see #getProperty(String)
+     */
+    boolean hasProperty(String name) throws RepositoryException;
 
     /**
      * Set an arbitrary property to this <code>Authorizable</code>.
@@ -169,17 +168,17 @@
      *
      * @param name
      * @param value multiple values
-     * @throws RepositoryException  If the specified property could not be set.
+     * @throws RepositoryException If the specified property could not be set.
      */
     void setProperty(String name, Value[] value) throws RepositoryException;
 
-	/**
+    /**
      * Returns the values for the properties with the specified name or
      * <code>null</code>.
      *
      * @param name
      * @return value of the property with the given name or <code>null</code>
-     * if no such property exists.
+     *         if no such property exists.
      * @throws RepositoryException If an error occurs.
      */
     Value[] getProperty(String name) throws RepositoryException;
@@ -189,7 +188,7 @@
      *
      * @param name
      * @return true If the property with the specified name was successfully
-     * removed; false if no such property was present.
+     *         removed; false if no such property was present.
      * @throws RepositoryException If an error occurs.
      */
     boolean removeProperty(String name) throws RepositoryException;

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/Group.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/Group.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/Group.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/Group.java Tue Sep  8 16:09:28 2009
@@ -29,7 +29,7 @@
      * members of this Group.
      * @throws RepositoryException
      */
-    Iterator getDeclaredMembers() throws RepositoryException;
+    Iterator<Authorizable> getDeclaredMembers() throws RepositoryException;
 
     /**
      * @return Iterator of <code>Authorizable</code>s which are members of
@@ -37,7 +37,7 @@
      * that are indirect group members.
      * @throws RepositoryException
      */
-    Iterator getMembers() throws RepositoryException;
+    Iterator<Authorizable> getMembers() throws RepositoryException;
 
     /**
      * @return true if the Authorizable to test is a direct or indirect member

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/UserManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/UserManager.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/UserManager.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/UserManager.java Tue Sep  8 16:09:28 2009
@@ -116,9 +116,7 @@
     User createUser(String userID, String password) throws AuthorizableExistsException, RepositoryException;
 
     /**
-     * Creates an User for the given userID that authenitcates with the given
-     * {@link javax.jcr.Credentials Credentials} and returns the specified
-     * Principal upon {@link User#getPrincipal()}. If the implementation is not
+     * Creates an User for the given parameters. If the implementation is not
      * able to deal with the <code>itermediatePath</code> that parameter should
      * be ignored.
      * Except for the <code>itermediatePath</code>, neither of the specified
@@ -139,26 +137,29 @@
 
     /**
      * Creates a new <code>Group</code> that is based on the given principal.
+     * Note that the group's ID is implementation specific. The implementation
+     * may take the principal name as ID hint but must in any case assert that
+     * it is unique among the IDs known to this manager.
      *
      * @param principal A non-null <code>Principal</code>
      * @return The new <code>Group</code>.
-     * @throws AuthorizableExistsException in case the given groupID is already
-     * in use or another Authorizable with the same principal name exists.
+     * @throws AuthorizableExistsException in case the given principal is already
+     * in use with another Authorizable.
      * @throws RepositoryException If another error occurs.
      */
     Group createGroup(Principal principal) throws AuthorizableExistsException, RepositoryException;
 
     /**
      * Creates a new <code>Group</code> that is based on the given principal
-     * and the specified <code>itermediatePath</code> hint. If the implementation is not
-     * able to deal with the <code>itermediatePath</code> that parameter should
-     * be ignored.
+     * and the specified <code>itermediatePath</code> hint. If the implementation
+     * is not able to deal with the <code>itermediatePath</code> this parameter
+     * should be ignored.
      *
      * @param principal
      * @param intermediatePath
      * @return The new <code>Group</code>.
-     * @throws AuthorizableExistsException in case the given groupID is already
-     * in use or another Authorizable with the same principal name exists.
+     * @throws AuthorizableExistsException in case the given principal is already
+     * in use with another Authorizable.
      * @throws RepositoryException If another error occurs.
      */
     Group createGroup(Principal principal, String intermediatePath) throws AuthorizableExistsException, RepositoryException;

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/pom.xml?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/pom.xml (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/pom.xml Tue Sep  8 16:09:28 2009
@@ -73,7 +73,7 @@
           <includes>
             <include>**/*TestAll.java</include>
           </includes>
-          <argLine>-Xmx128m</argLine>
+          <argLine>-Xmx256m</argLine>
           <systemProperties>
             <property>
               <name>derby.system.durability</name>
@@ -95,7 +95,7 @@
               <name>known.issues</name>
               <value>
                 org.apache.jackrabbit.core.xml.DocumentViewTest#testMultiValue
-                org.apache.jackrabbit.test.api.version.ActivitiesTest#testActivitiesPath
+                org.apache.jackrabbit.core.ConcurrentImportTest  
               </value>
             </property>
           </systemProperties>

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/AbstractNodeData.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/AbstractNodeData.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/AbstractNodeData.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/AbstractNodeData.java Tue Sep  8 16:09:28 2009
@@ -17,6 +17,7 @@
 package org.apache.jackrabbit.core;
 
 import javax.jcr.nodetype.NodeDefinition;
+import javax.jcr.RepositoryException;
 
 import org.apache.jackrabbit.core.id.ItemId;
 import org.apache.jackrabbit.core.id.NodeId;
@@ -34,10 +35,10 @@
      * Create a new instance of this class.
      *
      * @param state node state
-     * @param definition node definition
+     * @param itemMgr item manager
      */
-    protected AbstractNodeData(NodeState state, NodeDefinition definition) {
-        super(state, definition);
+    protected AbstractNodeData(NodeState state, ItemManager itemMgr) {
+        super(state, itemMgr);
 
         if (state.isShareable()) {
             this.primaryParentId = state.getParentId();
@@ -66,8 +67,9 @@
      * Return the associated node defintion.
      *
      * @return node definition
+     * @throws RepositoryException if the definition cannot be retrieved.
      */
-    public NodeDefinition getNodeDefinition() {
+    public NodeDefinition getNodeDefinition() throws RepositoryException {
         return (NodeDefinition) getDefinition();
     }
 

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java Tue Sep  8 16:09:28 2009
@@ -59,7 +59,7 @@
 import org.apache.jackrabbit.core.util.ReferenceChangeTracker;
 import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.core.version.VersionHistoryInfo;
-import org.apache.jackrabbit.core.version.VersionManager;
+import org.apache.jackrabbit.core.version.InternalVersionManager;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException;
@@ -269,7 +269,7 @@
         // 2. check access rights, lock status, node type constraints, etc.
         checkAddNode(destParentState, destName,
                 srcState.getNodeTypeName(), CHECK_ACCESS | CHECK_LOCK
-                | CHECK_VERSIONING | CHECK_CONSTRAINTS | CHECK_HOLD | CHECK_RETENTION);
+                | CHECK_CHECKED_OUT | CHECK_CONSTRAINTS | CHECK_HOLD | CHECK_RETENTION);
 
         // 3. verify that source has mixin mix:shareable
         if (!isShareable(srcState)) {
@@ -401,9 +401,13 @@
 
         // 2. check access rights, lock status, node type constraints, etc.
 
+        // JCR-2269: store target node state in changelog early as a
+        // precautionary measure in order to isolate it from concurrent 
+        // underlying changes while checking preconditions
+        stateMgr.store(destParentState);
         checkAddNode(destParentState, destName.getName(),
                 srcState.getNodeTypeName(), CHECK_ACCESS | CHECK_LOCK
-                | CHECK_VERSIONING | CHECK_CONSTRAINTS | CHECK_HOLD | CHECK_RETENTION);
+                | CHECK_CHECKED_OUT | CHECK_CONSTRAINTS | CHECK_HOLD | CHECK_RETENTION);
         // check read access right on source node using source access manager
         try {
             if (!srcAccessMgr.isGranted(srcPath, Permission.READ)) {
@@ -547,11 +551,11 @@
         // 2. check if target state can be removed from old/added to new parent
 
         checkRemoveNode(target, srcParent.getNodeId(),
-                CHECK_ACCESS | CHECK_LOCK | CHECK_VERSIONING | CHECK_CONSTRAINTS
+                CHECK_ACCESS | CHECK_LOCK | CHECK_CHECKED_OUT | CHECK_CONSTRAINTS
                 | CHECK_HOLD | CHECK_RETENTION);
         checkAddNode(destParent, destName.getName(),
                 target.getNodeTypeName(), CHECK_ACCESS | CHECK_LOCK
-                | CHECK_VERSIONING | CHECK_CONSTRAINTS | CHECK_HOLD | CHECK_RETENTION);
+                | CHECK_CHECKED_OUT | CHECK_CONSTRAINTS | CHECK_HOLD | CHECK_RETENTION);
 
         // 3. do move operation (modify and store affected states)
         boolean renameOnly = srcParent.getNodeId().equals(destParent.getNodeId());
@@ -637,7 +641,7 @@
 
         // 2. check if target state can be removed from parent
         checkRemoveNode(target, parentId,
-                CHECK_ACCESS | CHECK_LOCK | CHECK_VERSIONING
+                CHECK_ACCESS | CHECK_LOCK | CHECK_CHECKED_OUT
                 | CHECK_CONSTRAINTS | CHECK_REFERENCES | CHECK_HOLD | CHECK_RETENTION);
 
         // 3. do remove operation
@@ -661,7 +665,7 @@
      *                     parent node</li>
      *                     <li><code>{@link #CHECK_LOCK}</code>: make sure
      *                     there's no foreign lock on parent node</li>
-     *                     <li><code>{@link #CHECK_VERSIONING}</code>: make sure
+     *                     <li><code>{@link #CHECK_CHECKED_OUT}</code>: make sure
      *                     parent node is checked-out</li>
      *                     <li><code>{@link #CHECK_CONSTRAINTS}</code>:
      *                     make sure no node type constraints would be violated</li>
@@ -693,7 +697,7 @@
 
         // 2. versioning status
 
-        if ((options & CHECK_VERSIONING) == CHECK_VERSIONING) {
+        if ((options & CHECK_CHECKED_OUT) == CHECK_CHECKED_OUT) {
             // make sure parent node is checked-out
             verifyCheckedOut(parentPath);
         }
@@ -789,7 +793,7 @@
      *                    and remove privilege on target node</li>
      *                    <li><code>{@link #CHECK_LOCK}</code>: make sure
      *                    there's no foreign lock on parent node</li>
-     *                    <li><code>{@link #CHECK_VERSIONING}</code>: make sure
+     *                    <li><code>{@link #CHECK_CHECKED_OUT}</code>: make sure
      *                    parent node is checked-out</li>
      *                    <li><code>{@link #CHECK_CONSTRAINTS}</code>:
      *                    make sure no node type constraints would be violated</li>
@@ -827,7 +831,7 @@
      *                    and remove privilege on target node</li>
      *                    <li><code>{@link #CHECK_LOCK}</code>: make sure
      *                    there's no foreign lock on parent node</li>
-     *                    <li><code>{@link #CHECK_VERSIONING}</code>: make sure
+     *                    <li><code>{@link #CHECK_CHECKED_OUT}</code>: make sure
      *                    parent node is checked-out</li>
      *                    <li><code>{@link #CHECK_CONSTRAINTS}</code>:
      *                    make sure no node type constraints would be violated</li>
@@ -867,7 +871,7 @@
 
         // 2. versioning status
 
-        if ((options & CHECK_VERSIONING) == CHECK_VERSIONING) {
+        if ((options & CHECK_CHECKED_OUT) == CHECK_CHECKED_OUT) {
             // make sure parent node is checked-out
             verifyCheckedOut(parentPath);
         }
@@ -1256,8 +1260,8 @@
         prop.setMultiValued(def.isMultiple());
 
         // compute system generated values if necessary
-        InternalValue[] genValues =
-                computeSystemGeneratedPropertyValues(parent, def);
+        InternalValue[] genValues = session.getNodeTypeInstanceHandler()
+                .computeSystemGeneratedPropertyValues(parent, def);
         if (genValues != null) {
             prop.setValues(genValues);
         } else if (def.getDefaultValues() != null) {
@@ -1500,71 +1504,6 @@
     }
 
     //------------------------------------------------------< private methods >
-    /**
-     * Computes the values of well-known system (i.e. protected) properties.
-     * todo: duplicate code in NodeImpl: consolidate and delegate to NodeTypeInstanceHandler
-     *
-     * @param parent
-     * @param def
-     * @return the computed values
-     */
-    private InternalValue[] computeSystemGeneratedPropertyValues(NodeState parent,
-                                                                 PropDef def) {
-        InternalValue[] genValues = null;
-
-        /**
-         * todo: need to come up with some callback mechanism for applying system generated values
-         * (e.g. using a NodeTypeInstanceHandler interface)
-         */
-
-        // compute system generated values
-        Name declaringNT = def.getDeclaringNodeType();
-        Name name = def.getName();
-        // TODO JCR-2116: Built-In Node Types; => adapt to JCR 2.0 built-in node types (mix:created, etc)
-        if (NameConstants.MIX_REFERENCEABLE.equals(declaringNT)) {
-            // mix:referenceable node type
-            if (NameConstants.JCR_UUID.equals(name)) {
-                // jcr:uuid property
-                genValues = new InternalValue[]{InternalValue.create(
-                        parent.getNodeId().toString())};
-            }
-        } else if (NameConstants.NT_BASE.equals(declaringNT)) {
-            // nt:base node type
-            if (NameConstants.JCR_PRIMARYTYPE.equals(name)) {
-                // jcr:primaryType property
-                genValues = new InternalValue[]{InternalValue.create(parent.getNodeTypeName())};
-            } else if (NameConstants.JCR_MIXINTYPES.equals(name)) {
-                // jcr:mixinTypes property
-                Set<Name> mixins = parent.getMixinTypeNames();
-                ArrayList<InternalValue> values = new ArrayList<InternalValue>(mixins.size());
-                for (Name n : mixins) {
-                    values.add(InternalValue.create(n));
-                }
-                genValues = values.toArray(new InternalValue[values.size()]);
-            }
-        } else if (NameConstants.NT_HIERARCHYNODE.equals(declaringNT)
-                || NameConstants.MIX_CREATED.equals(declaringNT)) {
-            // nt:hierarchyNode node type
-            if (NameConstants.JCR_CREATED.equals(name)) {
-                // jcr:created property
-                genValues = new InternalValue[]{InternalValue.create(Calendar.getInstance())};
-            }
-        } else if (NameConstants.NT_RESOURCE.equals(declaringNT)) {
-            // nt:resource node type
-            if (NameConstants.JCR_LASTMODIFIED.equals(name)) {
-                // jcr:lastModified property
-                genValues = new InternalValue[]{InternalValue.create(Calendar.getInstance())};
-            }
-        } else if (NameConstants.NT_VERSION.equals(declaringNT)) {
-            // nt:version node type
-            if (NameConstants.JCR_CREATED.equals(name)) {
-                // jcr:created property
-                genValues = new InternalValue[]{InternalValue.create(Calendar.getInstance())};
-            }
-        }
-
-        return genValues;
-    }
 
     /**
      * Recursively removes the given node state including its properties and
@@ -1602,7 +1541,7 @@
                     checkRemoveNode(nodeState, targetState.getNodeId(),
                             CHECK_ACCESS
                             | CHECK_LOCK
-                            | CHECK_VERSIONING
+                            | CHECK_CHECKED_OUT
                             | CHECK_HOLD
                             | CHECK_RETENTION
                     );
@@ -1732,7 +1671,7 @@
                         checkRemoveNode(existingState,
                                 CHECK_ACCESS
                                 | CHECK_LOCK
-                                | CHECK_VERSIONING
+                                | CHECK_CHECKED_OUT
                                 | CHECK_CONSTRAINTS
                                 | CHECK_HOLD
                                 | CHECK_RETENTION);
@@ -1814,7 +1753,7 @@
                     PropertyState prop = (PropertyState) srcStateMgr.getItemState(propId);
                     copiedFrom = prop.getValues()[0].getNodeId();
                 }
-                VersionManager manager = session.getVersionManager();
+                InternalVersionManager manager = session.getInternalVersionManager();
                 history = manager.getVersionHistory(session, newState, copiedFrom);
             }
             // copy properties

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/CachingHierarchyManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/CachingHierarchyManager.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/CachingHierarchyManager.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/CachingHierarchyManager.java Tue Sep  8 16:09:28 2009
@@ -63,7 +63,7 @@
     /**
      * Mapping of paths to children in the path map
      */
-    private final PathMap pathCache = new PathMap();
+    private final PathMap<LRUEntry> pathCache = new PathMap<LRUEntry>();
 
     /**
      * Mapping of item ids to <code>LRUEntry</code> in the path map
@@ -132,13 +132,13 @@
             pathToNode = path.getAncestor(1);
         }
 
-        PathMap.Element element = map(pathToNode);
+        PathMap.Element<LRUEntry> element = map(pathToNode);
         if (element == null) {
             // not even intermediate match: call base class
             return super.resolvePath(path, typesAllowed);
         }
 
-        LRUEntry entry = (LRUEntry) element.get();
+        LRUEntry entry = element.get();
         if (element.hasPath(path)) {
             // exact match: return answer
             synchronized (cacheMonitor) {
@@ -179,7 +179,7 @@
             throws ItemStateException, RepositoryException {
 
         if (state.isNode()) {
-            PathMap.Element element = get(state.getId());
+            PathMap.Element<LRUEntry> element = get(state.getId());
             if (element != null) {
                 try {
                     Path.Element[] elements = element.getPath().getElements();
@@ -218,7 +218,7 @@
             throws ItemNotFoundException, RepositoryException {
 
         if (id.denotesNode()) {
-            PathMap.Element element = get(id);
+            PathMap.Element<LRUEntry> element = get(id);
             if (element != null) {
                 try {
                     return element.getPath();
@@ -239,7 +239,7 @@
             throws ItemNotFoundException, RepositoryException {
 
         if (id.denotesNode()) {
-            PathMap.Element element = get(id);
+            PathMap.Element<LRUEntry> element = get(id);
             if (element != null) {
                 return element.getName();
             }
@@ -254,7 +254,7 @@
             throws ItemNotFoundException, RepositoryException {
 
         if (id.denotesNode()) {
-            PathMap.Element element = get(id);
+            PathMap.Element<LRUEntry> element = get(id);
             if (element != null) {
                 return element.getDepth();
             }
@@ -269,9 +269,9 @@
             throws ItemNotFoundException, RepositoryException {
 
         if (itemId.denotesNode()) {
-            PathMap.Element element = get(nodeId);
+            PathMap.Element<LRUEntry> element = get(nodeId);
             if (element != null) {
-                PathMap.Element child = get(itemId);
+                PathMap.Element<LRUEntry> child = get(itemId);
                 if (child != null) {
                     return element.isAncestorOf(child);
                 }
@@ -311,10 +311,10 @@
                 // Item not cached, ignore
                 return;
             }
-            for (PathMap.Element element : entry.getElements()) {
-                Iterator iter = element.getChildren();
+            for (PathMap.Element<LRUEntry> element : entry.getElements()) {
+                Iterator<PathMap.Element<LRUEntry>> iter = element.getChildren();
                 while (iter.hasNext()) {
-                    PathMap.Element child = (PathMap.Element) iter.next();
+                    PathMap.Element<LRUEntry> child = iter.next();
                     ChildNodeEntry cne = modified.getChildNodeEntry(
                             child.getName(), child.getNormalizedIndex());
                     if (cne == null) {
@@ -323,7 +323,7 @@
                         continue;
                     }
 
-                    LRUEntry childEntry = (LRUEntry) child.get();
+                    LRUEntry childEntry = child.get();
                     if (childEntry != null && !cne.getId().equals(childEntry.getId())) {
                         // Different child item, remove
                         evict(child, true);
@@ -395,13 +395,14 @@
             if (entry == null) {
                 return;
             }
-            for (PathMap.Element parent : entry.getElements()) {
-                HashMap<Path.Element, PathMap.Element> newChildrenOrder = new HashMap<Path.Element, PathMap.Element>();
+            for (PathMap.Element<LRUEntry> parent : entry.getElements()) {
+                HashMap<Path.Element, PathMap.Element<LRUEntry>> newChildrenOrder =
+                    new HashMap<Path.Element, PathMap.Element<LRUEntry>>();
                 boolean orderChanged = false;
 
-                Iterator iter = parent.getChildren();
+                Iterator<PathMap.Element<LRUEntry>> iter = parent.getChildren();
                 while (iter.hasNext()) {
-                    PathMap.Element child = (PathMap.Element) iter.next();
+                    PathMap.Element<LRUEntry> child = iter.next();
                     LRUEntry childEntry = (LRUEntry) child.get();
                     if (childEntry == null) {
                         /**
@@ -479,7 +480,7 @@
      * @param id node id
      * @return cached element, <code>null</code> if not found
      */
-    private PathMap.Element get(ItemId id) {
+    private PathMap.Element<LRUEntry> get(ItemId id) {
         synchronized (cacheMonitor) {
             LRUEntry entry = (LRUEntry) idCache.get(id);
             if (entry != null) {
@@ -498,11 +499,11 @@
      * @param path path
      * @return cached element, <code>null</code> if not found
      */
-    private PathMap.Element map(Path path) {
+    private PathMap.Element<LRUEntry> map(Path path) {
         synchronized (cacheMonitor) {
-            PathMap.Element element = pathCache.map(path, false);
+            PathMap.Element<LRUEntry> element = pathCache.map(path, false);
             while (element != null) {
-                LRUEntry entry = (LRUEntry) element.get();
+                LRUEntry entry = element.get();
                 if (entry != null) {
                     entry.touch();
                     return element;
@@ -531,7 +532,7 @@
                  */
                 LRUEntry entry = head;
                 while (entry != null) {
-                    PathMap.Element[] elements = entry.getElements();
+                    PathMap.Element<LRUEntry>[] elements = entry.getElements();
                     int childrenCount = 0;
                     for (int i = 0; i < elements.length; i++) {
                         childrenCount += elements[i].getChildrenCount();
@@ -543,7 +544,7 @@
                     entry = entry.getNext();
                 }
             }
-            PathMap.Element element = pathCache.put(path);
+            PathMap.Element<LRUEntry> element = pathCache.put(path);
             if (element.get() != null) {
                 if (!id.equals(((LRUEntry) element.get()).getId())) {
                     log.warn("overwriting PathMap.Element");
@@ -582,7 +583,7 @@
             if (path == null) {
                 return true;
             }
-            PathMap.Element[] elements = entry.getElements();
+            PathMap.Element<LRUEntry>[] elements = entry.getElements();
             for (int i = 0; i < elements.length; i++) {
                 if (elements[i].hasPath(path)) {
                     return true;
@@ -601,7 +602,7 @@
      */
     boolean isCached(Path path) {
         synchronized (cacheMonitor) {
-            PathMap.Element element = pathCache.map(path, true);
+            PathMap.Element<LRUEntry> element = pathCache.map(path, true);
             if (element != null) {
                 return element.get() != null;
             }
@@ -620,7 +621,7 @@
         synchronized (cacheMonitor) {
             LRUEntry entry = (LRUEntry) idCache.get(id);
             if (entry != null) {
-                PathMap.Element[] elements = entry.getElements();
+                PathMap.Element<LRUEntry>[] elements = entry.getElements();
                 for (int i = 0; i < elements.length; i++) {
                     evict(elements[i], shift);
                 }
@@ -636,10 +637,10 @@
      *
      * @param element path map element
      */
-    private void evict(PathMap.Element element, boolean shift) {
+    private void evict(PathMap.Element<LRUEntry> element, boolean shift) {
         // assert: synchronized (cacheMonitor)
-        element.traverse(new PathMap.ElementVisitor() {
-            public void elementVisited(PathMap.Element element) {
+        element.traverse(new PathMap.ElementVisitor<LRUEntry>() {
+            public void elementVisited(PathMap.Element<LRUEntry> element) {
                 LRUEntry entry = (LRUEntry) element.get();
                 if (entry.removeElement(element) == 0) {
                     idCache.remove(entry.getId());
@@ -665,7 +666,7 @@
             throws RepositoryException, ItemStateException {
 
         // assert: synchronized (cacheMonitor)
-        PathMap.Element element = null;
+        PathMap.Element<LRUEntry> element = null;
 
         LRUEntry entry = (LRUEntry) idCache.get(id);
         if (entry != null) {
@@ -678,14 +679,14 @@
                 child = (NodeState) getItemState(id);
             }
             if (child == null || !child.isShareable()) {
-                PathMap.Element[] elements = entry.getElements();
+                PathMap.Element<LRUEntry>[] elements = entry.getElements();
                 element = elements[0];
                 for (int i = 0; i < elements.length; i++) {
                     elements[i].remove();
                 }
             }
         }
-        PathMap.Element parent = pathCache.map(path.getAncestor(1), true);
+        PathMap.Element<LRUEntry> parent = pathCache.map(path.getAncestor(1), true);
         if (parent != null) {
             parent.insert(path.getNameElement());
         }
@@ -710,11 +711,13 @@
             throws RepositoryException, ItemStateException {
 
         // assert: synchronized (cacheMonitor)
-        PathMap.Element parent = pathCache.map(path.getAncestor(1), true);
+        PathMap.Element<LRUEntry> parent =
+            pathCache.map(path.getAncestor(1), true);
         if (parent == null) {
             return;
         }
-        PathMap.Element element = parent.getDescendant(PathFactoryImpl.getInstance().create(
+        PathMap.Element<LRUEntry> element =
+            parent.getDescendant(PathFactoryImpl.getInstance().create(
                 new Path.Element[] { path.getNameElement() }), true);
         if (element != null) {
             // with SNS, this might evict a child that is NOT the one
@@ -749,8 +752,8 @@
      */
     public void dump(final PrintStream ps) {
         synchronized (cacheMonitor) {
-            pathCache.traverse(new PathMap.ElementVisitor() {
-                public void elementVisited(PathMap.Element element) {
+            pathCache.traverse(new PathMap.ElementVisitor<LRUEntry>() {
+                public void elementVisited(PathMap.Element<LRUEntry> element) {
                     StringBuffer line = new StringBuffer();
                     for (int i = 0; i < element.getDepth(); i++) {
                         line.append("--");
@@ -787,9 +790,9 @@
             elementsInCache += entry.getElements().length;
         }
 
-        class PathMapElementCounter implements PathMap.ElementVisitor {
+        class PathMapElementCounter implements PathMap.ElementVisitor<LRUEntry> {
             int count;
-            public void elementVisited(PathMap.Element element) {
+            public void elementVisited(PathMap.Element<LRUEntry> element) {
                 LRUEntry mappedEntry = (LRUEntry) element.get();
                 LRUEntry cachedEntry = (LRUEntry) idCache.get(mappedEntry.getId());
                 if (cachedEntry == null) {
@@ -804,7 +807,7 @@
                         cachedEntry.getId() + ").";
                     throw new IllegalStateException(msg);
                 }
-                PathMap.Element[] elements = cachedEntry.getElements();
+                PathMap.Element<LRUEntry>[] elements = cachedEntry.getElements();
                 for (int i = 0; i < elements.length; i++) {
                     if (elements[i] == element) {
                         count++;
@@ -850,7 +853,7 @@
         /**
          * Elements in path map
          */
-        private PathMap.Element[] elements;
+        private PathMap.Element<LRUEntry>[] elements;
 
         /**
          * Create a new instance of this class
@@ -858,7 +861,7 @@
          * @param id node id
          * @param element the path map element for this entry
          */
-        public LRUEntry(NodeId id, PathMap.Element element) {
+        public LRUEntry(NodeId id, PathMap.Element<LRUEntry> element) {
             this.id = id;
             this.elements = new PathMap.Element[] { element };
 
@@ -909,15 +912,6 @@
         }
 
         /**
-         * Return previous LRU entry
-         *
-         * @return previous LRU entry
-         */
-        public LRUEntry getPrevious() {
-            return previous;
-        }
-
-        /**
          * Return next LRU entry
          *
          * @return next LRU entry
@@ -942,15 +936,16 @@
          *
          * @return element in path map
          */
-        public PathMap.Element[] getElements() {
+        public PathMap.Element<LRUEntry>[] getElements() {
             return elements;
         }
 
         /**
          * Add a mapping to some element.
          */
-        public void addElement(PathMap.Element element) {
-            PathMap.Element[] tmp = new PathMap.Element[elements.length + 1];
+        public void addElement(PathMap.Element<LRUEntry> element) {
+            PathMap.Element<LRUEntry>[] tmp =
+                new PathMap.Element[elements.length + 1];
             System.arraycopy(elements, 0, tmp, 0, elements.length);
             tmp[elements.length] = element;
             elements = tmp;
@@ -961,7 +956,7 @@
          *
          * @return number of mappings left
          */
-        public int removeElement(PathMap.Element element) {
+        public int removeElement(PathMap.Element<LRUEntry> element) {
             boolean found = false;
             for (int i = 0; i < elements.length; i++) {
                 if (found) {
@@ -971,7 +966,8 @@
                 }
             }
             if (found) {
-                PathMap.Element[] tmp = new PathMap.Element[elements.length - 1];
+                PathMap.Element<LRUEntry>[] tmp =
+                    new PathMap.Element[elements.length - 1];
                 System.arraycopy(elements, 0, tmp, 0, tmp.length);
                 elements = tmp;
             }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java Tue Sep  8 16:09:28 2009
@@ -16,54 +16,57 @@
  */
 package org.apache.jackrabbit.core;
 
+import java.security.Principal;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.jcr.AccessDeniedException;
+import javax.jcr.Credentials;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
 import javax.jcr.security.AccessControlException;
+import javax.security.auth.Subject;
+
 import org.apache.jackrabbit.api.security.principal.PrincipalManager;
 import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.api.security.user.Group;
 import org.apache.jackrabbit.api.security.user.UserManager;
 import org.apache.jackrabbit.core.config.AccessManagerConfig;
+import org.apache.jackrabbit.core.config.BeanConfig;
 import org.apache.jackrabbit.core.config.LoginModuleConfig;
 import org.apache.jackrabbit.core.config.SecurityConfig;
+import org.apache.jackrabbit.core.config.SecurityManagerConfig;
 import org.apache.jackrabbit.core.config.WorkspaceConfig;
 import org.apache.jackrabbit.core.config.WorkspaceSecurityConfig;
-import org.apache.jackrabbit.core.config.SecurityManagerConfig;
 import org.apache.jackrabbit.core.security.AMContext;
 import org.apache.jackrabbit.core.security.AccessManager;
+import org.apache.jackrabbit.core.security.DefaultAccessManager;
 import org.apache.jackrabbit.core.security.JackrabbitSecurityManager;
 import org.apache.jackrabbit.core.security.SecurityConstants;
-import org.apache.jackrabbit.core.security.DefaultAccessManager;
 import org.apache.jackrabbit.core.security.authentication.AuthContext;
 import org.apache.jackrabbit.core.security.authentication.AuthContextProvider;
 import org.apache.jackrabbit.core.security.authorization.AccessControlProvider;
 import org.apache.jackrabbit.core.security.authorization.AccessControlProviderFactory;
 import org.apache.jackrabbit.core.security.authorization.AccessControlProviderFactoryImpl;
 import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager;
+import org.apache.jackrabbit.core.security.principal.AdminPrincipal;
 import org.apache.jackrabbit.core.security.principal.DefaultPrincipalProvider;
 import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
 import org.apache.jackrabbit.core.security.principal.PrincipalManagerImpl;
 import org.apache.jackrabbit.core.security.principal.PrincipalProvider;
 import org.apache.jackrabbit.core.security.principal.PrincipalProviderRegistry;
 import org.apache.jackrabbit.core.security.principal.ProviderRegistryImpl;
-import org.apache.jackrabbit.core.security.principal.AdminPrincipal;
+import org.apache.jackrabbit.core.security.principal.FallbackPrincipalProvider;
 import org.apache.jackrabbit.core.security.user.UserManagerImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.jcr.AccessDeniedException;
-import javax.jcr.Credentials;
-import javax.jcr.NoSuchWorkspaceException;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.SimpleCredentials;
-import javax.security.auth.Subject;
-import java.security.Principal;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-
 /**
  * The security manager acts as central managing class for all security related
  * operations on a low-level non-protected level. It manages the
@@ -76,7 +79,6 @@
  */
 public class DefaultSecurityManager implements JackrabbitSecurityManager {
 
-    // TODO: should rather be placed in the core.security package. However protected access to SystemSession required to move here.
     /**
      * the default logger
      */
@@ -183,7 +185,7 @@
 
         Properties[] moduleConfig = authContextProvider.getModuleConfig();
 
-        // retrieve default-ids (admin and anomymous) from login-module-configuration.
+        // retrieve default-ids (admin and anonymous) from login-module-configuration.
         for (Properties props : moduleConfig) {
             if (props.containsKey(LoginModuleConfig.PARAM_ADMIN_ID)) {
                 adminId = props.getProperty(LoginModuleConfig.PARAM_ADMIN_ID);
@@ -210,7 +212,7 @@
         acProviderFactory = new AccessControlProviderFactoryImpl();
         acProviderFactory.init(securitySession);
 
-        // create the evalutor for workspace access
+        // create the workspace access manager
         SecurityManagerConfig smc = config.getSecurityManagerConfig();
         if (smc != null && smc.getWorkspaceAccessConfig() != null) {
             workspaceAccessManager = (WorkspaceAccessManager) smc.getWorkspaceAccessConfig().newInstance();
@@ -221,7 +223,7 @@
         }
         workspaceAccessManager.init(securitySession);
 
-        // initialize principa-provider registry
+        // initialize principal-provider registry
         // 1) create default
         PrincipalProvider defaultPP = new DefaultPrincipalProvider(securitySession, (UserManagerImpl) systemUserManager);
         defaultPP.init(new Properties());
@@ -232,6 +234,15 @@
             principalProviderRegistry.registerProvider(props);
         }
 
+        // add fallback PP if needed. currently disabled.
+        /*
+        if (principalProviderRegistry.getProvider(FallbackPrincipalProvider.class.getName()) == null) {
+            Properties props = new Properties();
+            props.setProperty(LoginModuleConfig.PARAM_PRINCIPAL_PROVIDER_CLASS, FallbackPrincipalProvider.class.getName());
+            principalProviderRegistry.registerProvider(props);
+        }
+        */
+
         // create the principal manager for the security workspace
         systemPrincipalManager = new PrincipalManagerImpl(securitySession, principalProviderRegistry.getProviders());
 
@@ -246,10 +257,18 @@
      * @return user manager
      * @throws RepositoryException if an error occurs
      */
-    protected UserManagerImpl createUserManager(SessionImpl session)
-            throws RepositoryException {
-
-        return new UserManagerImpl(session, adminId);
+    protected UserManagerImpl createUserManager(SessionImpl session) throws RepositoryException {
+        BeanConfig umc = repository.getConfig().getSecurityConfig().getSecurityManagerConfig().getUserManagerConfig();
+        Properties config = null;
+        if (umc != null) {
+            // TODO: deal with other user manager implementations.
+            String clName = umc.getClassName();
+            if (clName != null && !(UserManagerImpl.class.getName().equals(clName) || clName.length() == 0)) {
+                log.warn("Unsupported custom UserManager implementation: '" + clName + "' -> Ignored.");
+            }
+            config = umc.getParameters();
+        }
+        return new UserManagerImpl(session, adminId, config);
     }
 
     /**
@@ -271,9 +290,8 @@
     public void close() {
         checkInitialized();
         synchronized (acProviders) {
-            Iterator<AccessControlProvider> itr = acProviders.values().iterator();
-            while (itr.hasNext()) {
-                itr.next().close();
+            for (AccessControlProvider accessControlProvider : acProviders.values()) {
+                accessControlProvider.close();
             }
             acProviders.clear();
         }
@@ -382,8 +400,7 @@
             // no SimpleCredentials: retrieve authorizables corresponding to
             // a non-group principal. the first one present is used to determine
             // the userID.
-            for (Iterator<Principal> it = subject.getPrincipals().iterator(); it.hasNext();) {
-                Principal p = (Principal) it.next();
+            for (Principal p : subject.getPrincipals()) {
                 if (!(p instanceof Group)) {
                     Authorizable authorz = systemUserManager.getAuthorizable(p);
                     if (authorz != null && !authorz.isGroup()) {
@@ -514,7 +531,7 @@
         /**
          * {@inheritDoc}
          */
-        public boolean grants(Set principals, String workspaceName) throws RepositoryException {
+        public boolean grants(Set<Principal> principals, String workspaceName) throws RepositoryException {
             AccessControlProvider prov = getAccessControlProvider(workspaceName);
             return prov.canAccessRoot(principals);
         }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemData.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemData.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemData.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemData.java Tue Sep  8 16:09:28 2009
@@ -17,10 +17,13 @@
 package org.apache.jackrabbit.core;
 
 import javax.jcr.nodetype.ItemDefinition;
+import javax.jcr.RepositoryException;
 
 import org.apache.jackrabbit.core.id.ItemId;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.state.ItemState;
+import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.state.PropertyState;
 
 /**
  * Data object referenced by different <code>ItemImpl</code> instances that
@@ -40,16 +43,19 @@
     /** Status */
     private int status;
 
+    /** The item manager */
+    private ItemManager itemMgr;
+
     /**
      * Create a new instance of this class.
      *
      * @param state item state
-     * @param definition item definition
+     * @param itemMgr item manager
      */
-    protected ItemData(ItemState state, ItemDefinition definition) {
+    protected ItemData(ItemState state, ItemManager itemMgr) {
         this.id = state.getId();
         this.state = state;
-        this.definition = definition;
+        this.itemMgr = itemMgr;
         this.status = ItemImpl.STATUS_NORMAL;
     }
 
@@ -85,8 +91,16 @@
      * Return the associated item definition.
      *
      * @return item definition
+     * @throws RepositoryException if the definition cannot be retrieved.
      */
-    public ItemDefinition getDefinition() {
+    public ItemDefinition getDefinition() throws RepositoryException {
+        if (definition == null && itemMgr != null) {
+            if (isNode()) {
+                definition = itemMgr.getDefinition((NodeState) state);
+            } else {
+                definition = itemMgr.getDefinition((PropertyState) state);
+            }
+        }
         return definition;
     }
 

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java Tue Sep  8 16:09:28 2009
@@ -18,8 +18,10 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.Map;
 import java.util.Set;
 
 import javax.jcr.AccessDeniedException;
@@ -43,7 +45,6 @@
 import javax.jcr.nodetype.NodeType;
 import javax.jcr.version.VersionException;
 
-import org.apache.commons.collections.iterators.IteratorChain;
 import org.apache.jackrabbit.core.id.ItemId;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.nodetype.EffectiveNodeType;
@@ -65,7 +66,7 @@
 import org.apache.jackrabbit.core.state.StaleItemStateException;
 import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.core.version.VersionHistoryInfo;
-import org.apache.jackrabbit.core.version.VersionManager;
+import org.apache.jackrabbit.core.version.InternalVersionManager;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
@@ -342,35 +343,34 @@
         return removed;
     }
 
-    private void validateTransientItems(Iterator<ItemState> dirtyIter, Iterator<ItemState> removedIter)
+    /**
+     * the following validations/checks are performed on transient items:
+     *
+     * for every transient item:
+     * - if it is 'modified' or 'new' check the corresponding write permission.
+     * - if it is 'removed' check the REMOVE permission
+     *
+     * for every transient node:
+     * - if it is 'new' check that its node type satisfies the
+     *   'required node type' constraint specified in its definition
+     * - check if 'mandatory' child items exist
+     *
+     * for every transient property:
+     * - check if the property value satisfies the value constraints
+     *   specified in the property's definition
+     *
+     * note that the protected flag is checked in Node.addNode/Node.remove
+     * (for adding/removing child entries of a node), in
+     * Node.addMixin/removeMixin/setPrimaryType (for type changes on nodes)
+     * and in Property.setValue (for properties to be modified).
+     */
+    private void validateTransientItems(Iterable<ItemState> dirty, Iterable<ItemState> removed)
             throws AccessDeniedException, ConstraintViolationException,
             RepositoryException {
-        /**
-         * the following validations/checks are performed on transient items:
-         *
-         * for every transient item:
-         * - if it is 'modified' or 'new' check the corresponding write permission.
-         * - if it is 'removed' check the REMOVE permission
-         *
-         * for every transient node:
-         * - if it is 'new' check that its node type satisfies the
-         *   'required node type' constraint specified in its definition
-         * - check if 'mandatory' child items exist
-         *
-         * for every transient property:
-         * - check if the property value satisfies the value constraints
-         *   specified in the property's definition
-         *
-         * note that the protected flag is checked in Node.addNode/Node.remove
-         * (for adding/removing child entries of a node), in
-         * Node.addMixin/removeMixin/setPrimaryType (for type changes on nodes)
-         * and in Property.setValue (for properties to be modified).
-         */
         AccessManager accessMgr = session.getAccessManager();
         NodeTypeManagerImpl ntMgr = session.getNodeTypeManager();
         // walk through list of dirty transient items and validate each
-        while (dirtyIter.hasNext()) {
-            ItemState itemState = dirtyIter.next();
+        for (ItemState itemState : dirty) {
             ItemDefinition def;
             if (itemState.isNode()) {
                 def = ntMgr.getNodeDefinition(((NodeState) itemState).getDefinitionId());
@@ -578,8 +578,7 @@
         }
 
         // walk through list of removed transient items and check REMOVE permission
-        while (removedIter.hasNext()) {
-            ItemState itemState = removedIter.next();
+        for (ItemState itemState : removed) {
             ItemDefinition def;
             if (itemState.isNode()) {
                 def = ntMgr.getNodeDefinition(((NodeState) itemState).getDefinitionId());
@@ -600,14 +599,12 @@
         }
     }
 
-    private void removeTransientItems(Iterator<ItemState> iter) {
-
-        /**
-         * walk through list of transient items marked 'removed' and
-         * definitively remove each one
-         */
-        while (iter.hasNext()) {
-            ItemState transientState = iter.next();
+    /**
+     * walk through list of transient items marked 'removed' and
+     * definitively remove each one
+     */
+    private void removeTransientItems(Iterable<ItemState> states) {
+        for (ItemState transientState : states) {
             ItemState persistentState = transientState.getOverlayedState();
             /**
              * remove persistent state
@@ -619,22 +616,22 @@
         }
     }
 
-    private void persistTransientItems(Iterator<ItemState> iter)
+    /**
+     * walk through list of transient items and persist each one
+     */
+    private void persistTransientItems(Iterable<ItemState> states)
             throws RepositoryException {
-
-        // walk through list of transient items and persist each one
-        while (iter.hasNext()) {
-            ItemState state = iter.next();
-            ItemImpl item = itemMgr.getItem(state.getId());
+        for (ItemState state : states) {
             // persist state of transient item
-            item.makePersistent();
+            itemMgr.getItem(state.getId()).makePersistent();
         }
     }
 
-    private void restoreTransientItems(Iterator<ItemState> iter) {
-        // walk through list of transient states and re-apply transient changes
-        while (iter.hasNext()) {
-            ItemState itemState = iter.next();
+    /**
+     * walk through list of transient states and re-apply transient changes
+     */
+    private void restoreTransientItems(Iterable<ItemState> items) {
+        for (ItemState itemState : items) {
             ItemId id = itemState.getId();
             ItemImpl item;
 
@@ -687,9 +684,8 @@
      * has been removed, throw.</li>
      * </ul>
      */
-    private void processShareableNodes(Iterator<ItemState> iter) throws RepositoryException {
-        while (iter.hasNext()) {
-            ItemState is = iter.next();
+    private void processShareableNodes(Iterable<ItemState> states) throws RepositoryException {
+        for (ItemState is : states) {
             if (is.isNode()) {
                 NodeState ns = (NodeState) is;
                 boolean wasShareable = false;
@@ -721,22 +717,21 @@
      * <p/>
      * Called by {@link #save()}.
      *
-     * @param iter
+     * @param states
      * @return true if this call generated new transient state; otherwise false
      * @throws RepositoryException
      */
-    private boolean initVersionHistories(Iterator<ItemState> iter) throws RepositoryException {
+    private boolean initVersionHistories(Iterable<ItemState> states) throws RepositoryException {
         // walk through list of transient items and search for new versionable nodes
         boolean createdTransientState = false;
-        while (iter.hasNext()) {
-            ItemState itemState = iter.next();
+        for (ItemState itemState : states) {
             if (itemState.isNode()) {
                 NodeState nodeState = (NodeState) itemState;
                 EffectiveNodeType nt = getEffectiveNodeType(nodeState);
                 if (nt.includesNodeType(NameConstants.MIX_VERSIONABLE)) {
                     if (!nodeState.hasPropertyName(NameConstants.JCR_VERSIONHISTORY)) {
                         NodeImpl node = (NodeImpl) itemMgr.getItem(itemState.getId());
-                        VersionManager vMgr = session.getVersionManager();
+                        InternalVersionManager vMgr = session.getInternalVersionManager();
                         /**
                          * check if there's already a version history for that
                          * node; this would e.g. be the case if a versionable
@@ -767,7 +762,7 @@
                     // we need to check the version manager for an existing
                     // version history, since simple versioning does not
                     // expose it's reference in a property
-                    VersionManager vMgr = session.getVersionManager();
+                    InternalVersionManager vMgr = session.getInternalVersionManager();
                     vMgr.getVersionHistory(session, nodeState, null);
 
                     // create isCheckedOutProperty if not already exists
@@ -846,7 +841,7 @@
             session.getValidator().checkRemove(this, options, Permission.NONE);
 
             // parent node: make sure it is checked-out and not protected nor locked.
-            options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_VERSIONING |
+            options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_CHECKED_OUT |
                     ItemValidator.CHECK_CONSTRAINTS;
             session.getValidator().checkModify(parentNode, options, Permission.NONE);
         }
@@ -958,15 +953,15 @@
              */
             Collection<ItemState> removed = getRemovedStates();
 
-            /**
-             * build set of item id's which are within the scope of
-             * (i.e. affected by) this save operation
-             */
-            Set<ItemId> affectedIds = new HashSet<ItemId>(dirty.size() + removed.size());
-            for (Iterator<ItemState> it =
-                    new IteratorChain(dirty.iterator(), removed.iterator());
-                 it.hasNext();) {
-                affectedIds.add(it.next().getId());
+            // All affected item states. They keys are used to look up whether
+            // an item is affected, and the values are iterated through below
+            Map<ItemId, ItemState> affected =
+                new HashMap<ItemId, ItemState>(dirty.size() + removed.size());
+            for (ItemState state : dirty) {
+                affected.put(state.getId(), state);
+            }
+            for (ItemState state : removed) {
+                affected.put(state.getId(), state);
             }
 
             /**
@@ -976,10 +971,7 @@
              * (e.g. moving a node requires that the target node including both
              * old and new parents are saved)
              */
-            for (Iterator<ItemState> it =
-                    new IteratorChain(dirty.iterator(), removed.iterator());
-                 it.hasNext();) {
-                ItemState transientState = it.next();
+            for (ItemState transientState : affected.values()) {
                 if (transientState.isNode()) {
                     NodeState nodeState = (NodeState) transientState;
                     Set<NodeId> dependentIDs = new HashSet<NodeId>();
@@ -1006,16 +998,12 @@
                                 } else {
                                     // parent id hasn't changed, check whether
                                     // the node has been renamed (JCR-1034)
-                                    if (!affectedIds.contains(newParentId)
+                                    if (!affected.containsKey(newParentId)
                                             && stateMgr.hasTransientItemState(newParentId)) {
                                         try {
                                             NodeState parent = (NodeState) stateMgr.getTransientItemState(newParentId);
                                             // check parent's renamed child node entries
-                                            for (Iterator<ChildNodeEntry> cneIt =
-                                                    parent.getRenamedChildNodeEntries().iterator();
-                                                 cneIt.hasNext();) {
-                                                ChildNodeEntry cne =
-                                                        cneIt.next();
+                                            for (ChildNodeEntry cne : parent.getRenamedChildNodeEntries()) {
                                                 if (cne.getId().equals(nodeState.getId())) {
                                                     // node has been renamed,
                                                     // add parent to dependencies
@@ -1033,26 +1021,18 @@
                     }
 
                     // removed child node entries
-                    for (Iterator<ChildNodeEntry> cneIt =
-                            nodeState.getRemovedChildNodeEntries().iterator();
-                         cneIt.hasNext();) {
-                        ChildNodeEntry cne = cneIt.next();
+                    for (ChildNodeEntry cne : nodeState.getRemovedChildNodeEntries()) {
                         dependentIDs.add(cne.getId());
                     }
                     // added child node entries
-                    for (Iterator<ChildNodeEntry> cneIt =
-                            nodeState.getAddedChildNodeEntries().iterator();
-                         cneIt.hasNext();) {
-                        ChildNodeEntry cne = cneIt.next();
+                    for (ChildNodeEntry cne : nodeState.getAddedChildNodeEntries()) {
                         dependentIDs.add(cne.getId());
                     }
 
                     // now walk through dependencies and check whether they
                     // are within the scope of this save operation
-                    Iterator<NodeId> depIt = dependentIDs.iterator();
-                    while (depIt.hasNext()) {
-                        NodeId id = depIt.next();
-                        if (!affectedIds.contains(id)) {
+                    for (NodeId id : dependentIDs) {
+                        if (!affected.containsKey(id)) {
                             // JCR-1359 workaround: check whether unresolved
                             // dependencies originate from 'this' session;
                             // otherwise ignore them
@@ -1069,11 +1049,9 @@
                 }
             }
 
-            /**
-             * validate access and node type constraints
-             * (this will also validate child removals)
-             */
-            validateTransientItems(dirty.iterator(), removed.iterator());
+            // validate access and node type constraints
+            // (this will also validate child removals)
+            validateTransientItems(dirty, removed);
 
             // start the update operation
             try {
@@ -1089,20 +1067,20 @@
             try {
 
                 // process transient items marked as 'removed'
-                removeTransientItems(removed.iterator());
+                removeTransientItems(removed);
 
                 // process transient items that have change in mixins
-                processShareableNodes(dirty.iterator());
+                processShareableNodes(dirty);
 
                 // initialize version histories for new nodes (might generate new transient state)
-                if (initVersionHistories(dirty.iterator())) {
+                if (initVersionHistories(dirty)) {
                     // re-build the list of transient states because the previous call
                     // generated new transient state
                     dirty = getTransientStates();
                 }
 
                 // process 'new' or 'modified' transient states
-                persistTransientItems(dirty.iterator());
+                persistTransientItems(dirty);
 
                 // dispose the transient states marked 'new' or 'modified'
                 // at this point item state data is pushed down one level,
@@ -1111,8 +1089,7 @@
                 // transient item states must be removed now. otherwise
                 // the session item state provider will return an orphaned
                 // item state which is not referenced by any node instance.
-                for (Iterator<ItemState> it = dirty.iterator(); it.hasNext();) {
-                    ItemState transientState = it.next();
+                for (ItemState transientState : dirty) {
                     // dispose the transient state, it is no longer used
                     stateMgr.disposeTransientItemState(transientState);
                 }
@@ -1136,7 +1113,7 @@
                     // applied by persistTransientItems() and we need to
                     // restore transient state, i.e. undo the effect of
                     // persistTransientItems()
-                    restoreTransientItems(dirty.iterator());
+                    restoreTransientItems(dirty);
                 }
             }
 
@@ -1145,8 +1122,7 @@
             // item states in attic are removed after store, because
             // the observation mechanism needs to build paths of removed
             // items in store().
-            for (Iterator<ItemState> it = removed.iterator(); it.hasNext();) {
-                ItemState transientState = it.next();
+            for (ItemState transientState : removed) {
                 // dispose the transient state, it is no longer used
                 stateMgr.disposeTransientItemStateInAttic(transientState);
             }
@@ -1236,19 +1212,17 @@
         }
 
         // process list of 'new', 'modified' or 'stale' transient states
-        Iterator<ItemState> iter = list.iterator();
-        while (iter.hasNext()) {
-            transientState = iter.next();
+        for (ItemState state : list) {
             // dispose the transient state, it is no longer used;
             // this will indirectly (through stateDiscarded listener method)
             // either restore or permanently invalidate the wrapping Item instances
-            stateMgr.disposeTransientItemState(transientState);
+            stateMgr.disposeTransientItemState(state);
         }
 
         if (isNode()) {
             // discard all transient descendants in the attic (i.e. those marked
             // as 'removed'); this will resurrect the removed items
-            iter = stateMgr.getDescendantTransientItemStatesInAttic((NodeId) id);
+            Iterator<ItemState> iter = stateMgr.getDescendantTransientItemStatesInAttic((NodeId) id);
             while (iter.hasNext()) {
                 transientState = iter.next();
                 // dispose the transient state; this will indirectly (through