jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mdue...@apache.org
Subject svn commit: r987181 - in /jackrabbit/trunk/jackrabbit-core/src: main/java/org/apache/jackrabbit/core/config/ main/java/org/apache/jackrabbit/core/security/user/ main/java/org/apache/jackrabbit/core/xml/ test/java/org/apache/jackrabbit/core/config/ test...
Date Thu, 19 Aug 2010 15:04:39 GMT
Author: mduerig
Date: Thu Aug 19 15:04:38 2010
New Revision: 987181

URL: http://svn.apache.org/viewvc?rev=987181&view=rev
Log:
JCR-2710 Add support for large number of users in a group
UserImporter copes with node structure for group membership now

Added:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/DefaultProtectedItemImporter.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/ProtectedItemImporter.java   (with props)
Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/ImportConfig.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/GroupImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImporter.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/DefaultProtectedNodeImporter.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/DefaultProtectedPropertyImporter.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/ProtectedNodeImporter.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/ProtectedPropertyImporter.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SessionImporter.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/config/WorkspaceConfigTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserImporterTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/xml/AccessControlImporterTest.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/ImportConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/ImportConfig.java?rev=987181&r1=987180&r2=987181&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/ImportConfig.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/ImportConfig.java Thu Aug 19 15:04:38 2010
@@ -16,14 +16,13 @@
  */
 package org.apache.jackrabbit.core.config;
 
+import org.apache.jackrabbit.core.xml.ProtectedItemImporter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.apache.jackrabbit.core.xml.ProtectedNodeImporter;
-import org.apache.jackrabbit.core.xml.ProtectedPropertyImporter;
 
-import java.util.List;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
 
 /**
  * <code>XmlImportConfig</code>...
@@ -35,42 +34,26 @@ public class ImportConfig {
      */
     private static final Logger log = LoggerFactory.getLogger(ImportConfig.class);
 
-    private final List<BeanConfig> protectedNodeImporters;
-    private final List<BeanConfig> protectedPropertyImporters;
+    private final List<BeanConfig> protectedItemImporters;
 
     public ImportConfig() {
-        protectedNodeImporters = Collections.emptyList();
-        protectedPropertyImporters = Collections.emptyList();
+        protectedItemImporters = Collections.emptyList();
     }
 
-    public ImportConfig(List<BeanConfig> protectedNodeImporters, List<BeanConfig> protectedPropertyImporters) {
-        this.protectedNodeImporters = protectedNodeImporters;
-        this.protectedPropertyImporters = protectedPropertyImporters;
+    public ImportConfig(List<BeanConfig> protectedItemImporters) {
+        this.protectedItemImporters = protectedItemImporters;
     }
 
-    public List<ProtectedNodeImporter> getProtectedNodeImporters() {
-        List<ProtectedNodeImporter> pnis =
-            new ArrayList<ProtectedNodeImporter>();
-        for (BeanConfig bc : protectedNodeImporters) {
+    public List<? extends ProtectedItemImporter> getProtectedItemImporters() {
+        List<ProtectedItemImporter> piis = new ArrayList();
+        for (BeanConfig bc : protectedItemImporters) {
             try {
-                pnis.add(bc.newInstance(ProtectedNodeImporter.class));
+                piis.add(bc.newInstance(ProtectedItemImporter.class));
             } catch (ConfigurationException e) {
                 log.warn(e.getMessage());
             }
         }
-        return pnis;
+        return piis;
     }
 
-    public List<ProtectedPropertyImporter> getProtectedPropertyImporters() {
-        List<ProtectedPropertyImporter> ppis =
-            new ArrayList<ProtectedPropertyImporter>();
-        for (BeanConfig bc : protectedPropertyImporters) {
-            try {
-                ppis.add(bc.newInstance(ProtectedPropertyImporter.class));
-            } catch (ConfigurationException e) {
-                log.warn(e.getMessage());
-            }
-        }
-        return ppis;
-    }
 }
\ No newline at end of file

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java?rev=987181&r1=987180&r2=987181&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java Thu Aug 19 15:04:38 2010
@@ -207,6 +207,7 @@ public class RepositoryConfigurationPars
      * Name of the optional XmlImport config entry inside the workspace configuration.
      */
     private static final String IMPORT_ELEMENT = "Import";
+    private static final String IMPORT_PII_ELEMENT = "ProtectedItemImporter";
     private static final String IMPORT_PNI_ELEMENT = "ProtectedNodeImporter";
     private static final String IMPORT_PPI_ELEMENT = "ProtectedPropertyImporter";
 
@@ -692,29 +693,24 @@ public class RepositoryConfigurationPars
      * @throws ConfigurationException
      */
     public ImportConfig parseImportConfig(Element parent) throws ConfigurationException {
-        List<BeanConfig> protectedNodeImporters = new ArrayList<BeanConfig>();
-        List<BeanConfig> protectedPropertyImporters = new ArrayList<BeanConfig>();
-
+        List<BeanConfig> protectedItemImporters = new ArrayList<BeanConfig>();
         Element element = getElement(parent, IMPORT_ELEMENT, false);
         if (element != null) {
             NodeList children = element.getChildNodes();
             for (int i = 0; i < children.getLength(); i++) {
                 Node child = children.item(i);
                 if (child.getNodeType() == Node.ELEMENT_NODE) {
-                    if (IMPORT_PNI_ELEMENT.equals(child.getNodeName())) {
-                        String className = getAttribute((Element) child, CLASS_ATTRIBUTE);
-                        BeanConfig bc = new BeanConfig(className, parseParameters((Element) child));
-                        bc.setValidate(false);
-                        protectedNodeImporters.add(bc);
-                    } else if (IMPORT_PPI_ELEMENT.equals(child.getNodeName())) {
+                    if (IMPORT_PNI_ELEMENT.equals(child.getNodeName()) ||
+                            IMPORT_PPI_ELEMENT.equals(child.getNodeName()) ||
+                            IMPORT_PII_ELEMENT.equals(child.getNodeName())) {
                         String className = getAttribute((Element) child, CLASS_ATTRIBUTE);
                         BeanConfig bc = new BeanConfig(className, parseParameters((Element) child));
                         bc.setValidate(false);
-                        protectedPropertyImporters.add(bc);
+                        protectedItemImporters.add(bc);
                     } // else: some other entry -> ignore.
                 }
             }
-            return new ImportConfig(protectedNodeImporters, protectedPropertyImporters);
+            return new ImportConfig(protectedItemImporters);
         }
         return null;
     }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/GroupImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/GroupImpl.java?rev=987181&r1=987180&r2=987181&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/GroupImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/GroupImpl.java Thu Aug 19 15:04:38 2010
@@ -170,11 +170,7 @@ class GroupImpl extends AuthorizableImpl
                 msp = new PropertyBasedMembershipProvider(node);
             }
         } else {
-            if (node.hasProperty(P_MEMBERS) || !node.hasNode(N_MEMBERS)) {
-                msp = new PropertyBasedMembershipProvider(node);
-            } else {
-                msp = new NodeBasedMembershipProvider(node);
-            }
+            msp = new PropertyBasedMembershipProvider(node);
         }
 
         if (node.hasProperty(P_MEMBERS) && node.hasNode(N_MEMBERS)) {
@@ -221,7 +217,7 @@ class GroupImpl extends AuthorizableImpl
         return false;
     }
 
-    private PropertySequence getPropertySequence(Node nMembers) throws RepositoryException {
+    static PropertySequence getPropertySequence(Node nMembers, UserManagerImpl userManager) throws RepositoryException {
         Comparator<String> order = Rank.comparableComparator();
         int maxChildren = userManager.getGroupMembershipSplitSize();
         int minChildren = maxChildren / 2;
@@ -460,7 +456,7 @@ class GroupImpl extends AuthorizableImpl
                             : node.addNode(N_MEMBERS, NT_REP_MEMBERS, null));
 
                     try {
-                        PropertySequence properties = getPropertySequence(nMembers);
+                        PropertySequence properties = getPropertySequence(nMembers, userManager);
                         String propName = Text.escapeIllegalJcrChars(authorizable.getID());
                         if (properties.hasItem(propName)) {
                             log.debug("Authorizable {} is already member of {}", authorizable, this);
@@ -498,7 +494,7 @@ class GroupImpl extends AuthorizableImpl
                 public Boolean perform(SessionContext context) throws RepositoryException {
                     NodeImpl nMembers = node.getNode(N_MEMBERS);
                     try {
-                        PropertySequence properties = getPropertySequence(nMembers);
+                        PropertySequence properties = getPropertySequence(nMembers, userManager);
                         String propName = Text.escapeIllegalJcrChars(authorizable.getID());
                         if (properties.hasItem(propName)) {
                             properties.removeProperty(propName);
@@ -529,7 +525,7 @@ class GroupImpl extends AuthorizableImpl
 
             Collection<Authorizable> members = new HashSet<Authorizable>();
             if (node.hasNode(N_MEMBERS)) {
-                for (Property member : getPropertySequence(node.getNode(N_MEMBERS))) {
+                for (Property member : getPropertySequence(node.getNode(N_MEMBERS), userManager)) {
                     collectMembers(member.getValue(), members, includeIndirect, type);
                 }
             }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImporter.java?rev=987181&r1=987180&r2=987181&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImporter.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImporter.java Thu Aug 19 15:04:38 2010
@@ -23,14 +23,20 @@ import org.apache.jackrabbit.api.securit
 import org.apache.jackrabbit.api.security.user.Impersonation;
 import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.commons.flat.PropertySequence;
 import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
 import org.apache.jackrabbit.core.security.user.UserImporter.ImportBehavior;
+import org.apache.jackrabbit.core.session.SessionContext;
+import org.apache.jackrabbit.core.session.SessionOperation;
+import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.util.ReferenceChangeTracker;
-import org.apache.jackrabbit.core.xml.DefaultProtectedPropertyImporter;
+import org.apache.jackrabbit.core.xml.NodeInfo;
 import org.apache.jackrabbit.core.xml.PropInfo;
+import org.apache.jackrabbit.core.xml.ProtectedNodeImporter;
+import org.apache.jackrabbit.core.xml.ProtectedPropertyImporter;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.QPropertyDefinition;
 import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
@@ -48,6 +54,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
@@ -111,15 +118,22 @@ import java.util.Map;
  * to find the authorizable with the given principal (reason: query will only
  * find persisted content).
  */
-public class UserImporter extends DefaultProtectedPropertyImporter {
+public class UserImporter implements ProtectedPropertyImporter, ProtectedNodeImporter {
 
-    /**
-     * logger instance
-     */
     private static final Logger log = LoggerFactory.getLogger(UserImporter.class);
 
     public static final String PARAM_IMPORT_BEHAVIOR = "importBehavior";
 
+    private JackrabbitSession session;
+
+    private NamePathResolver resolver;
+
+    private boolean isWorkspaceImport;
+
+    private int uuidBehavior;
+
+    private ReferenceChangeTracker referenceTracker;
+
     private UserPerWorkspaceUserManager userManager;
 
     private boolean initialized = false;
@@ -128,47 +142,52 @@ public class UserImporter extends Defaul
 
     private int importBehavior = ImportBehavior.IGNORE;
 
-    @Override
     public boolean init(JackrabbitSession session, NamePathResolver resolver,
                         boolean isWorkspaceImport,
                         int uuidBehavior, ReferenceChangeTracker referenceTracker) {
-        if (super.init(session, resolver, isWorkspaceImport, uuidBehavior, referenceTracker)) {
-            if (initialized) {
-                throw new IllegalStateException("Already initialized");
-            }
-            if (uuidBehavior == ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW) {
-                log.debug("ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW isn't supported when importing users or groups.");
-                return false;
-            }
-            if (isWorkspaceImport) {
-                log.debug("Only Session-Import is supported when importing users or groups.");
-                return false;
-            }
-            try {
-                UserManager uMgr = session.getUserManager();
-                if (uMgr instanceof UserPerWorkspaceUserManager) {
-                    // make sure the user managers autosave flag can be changed to false.
-                    if (uMgr.isAutoSave()) {
-                        uMgr.autoSave(false);
-                        resetAutoSave = true;
-                        log.debug("Changed autosave behavior of UserManager to 'false'.");
-                    }
-                    userManager = (UserPerWorkspaceUserManager) uMgr;
-                    initialized = true;
-                } else {
-                    // either wrong implementation or one that implicitly calls save.
-                    log.debug("Failed to initialize UserImporter: UserManager isn't instance of UserPerWorkspaceUserManager or does implicit save call.");
-                }
-            } catch (RepositoryException e) {
-                // failed to access user manager or to set the autosave behavior
-                // -> return false (not initialized) as importer can't operate.
-                log.error("Failed to initialize UserImporter: ", e);
+
+        this.session = session;
+        this.resolver = resolver;
+        this.isWorkspaceImport = isWorkspaceImport;
+        this.uuidBehavior = uuidBehavior;
+        this.referenceTracker = referenceTracker;
+
+        if (initialized) {
+            throw new IllegalStateException("Already initialized");
+        }
+        if (uuidBehavior == ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW) {
+            log.debug("ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW isn't supported when importing users or groups.");
+            return false;
+        }
+        if (isWorkspaceImport) {
+            log.debug("Only Session-Import is supported when importing users or groups.");
+            return false;
+        }
+        try {
+            UserManager uMgr = session.getUserManager();
+            if (uMgr instanceof UserPerWorkspaceUserManager) {
+                // make sure the user managers autosave flag can be changed to false.
+                if (uMgr.isAutoSave()) {
+                    uMgr.autoSave(false);
+                    resetAutoSave = true;
+                    log.debug("Changed autosave behavior of UserManager to 'false'.");
+                }
+                userManager = (UserPerWorkspaceUserManager) uMgr;
+                initialized = true;
+            } else {
+                // either wrong implementation or one that implicitly calls save.
+                log.debug("Failed to initialize UserImporter: UserManager isn't instance of UserPerWorkspaceUserManager or does implicit save call.");
             }
+        } catch (RepositoryException e) {
+            // failed to access user manager or to set the autosave behavior
+            // -> return false (not initialized) as importer can't operate.
+            log.error("Failed to initialize UserImporter: ", e);
         }
         return initialized;
     }
 
-    @Override
+    // -----------------------------------------------------< ProtectedPropertyImporter >---
+
     public boolean handlePropInfo(NodeImpl parent, PropInfo protectedPropInfo, QPropertyDefinition def) throws RepositoryException {
         if (!initialized) {
             throw new IllegalStateException("Not initialized");
@@ -281,11 +300,11 @@ public class UserImporter extends Defaul
                 // are to be imported later on -> postpone processing to the end.
                 // see -> processRefeferences
                 Value[] vs = protectedPropInfo.getValues(PropertyType.WEAKREFERENCE, resolver);
-                NodeId[] ids = new NodeId[vs.length];
+                Membership membership = new Membership(a.getID());
                 for (int i = 0; i < vs.length; i++) {
-                    ids[i] = new NodeId(vs[i].getString());
+                    membership.addMember(new NodeId(vs[i].getString()));
                 }
-                referenceTracker.processedReference(new Membership(a.getID(), ids));
+                referenceTracker.processedReference(membership);
                 return true;
 
             } // else: cannot handle -> return false
@@ -300,7 +319,10 @@ public class UserImporter extends Defaul
         }
     }
 
-    @Override
+    public boolean handlePropInfo(NodeState parent, PropInfo protectedPropInfo, QPropertyDefinition def) throws RepositoryException {
+        return false;
+    }
+
     public void processReferences() throws RepositoryException {
         if (!initialized) {
             throw new IllegalStateException("Not initialized");
@@ -320,7 +342,7 @@ public class UserImporter extends Defaul
                         throw new RepositoryException(((Membership) reference).groupId + " does not represent a valid group.");
                     }
 
-                    Group gr = (Group) a;
+                    final Group gr = (Group) a;
                     // 1. collect members to add and to remove.
                     Map<String, Authorizable> toRemove = new HashMap<String, Authorizable>();
                     for (Iterator<Authorizable> declMembers = gr.getDeclaredMembers(); declMembers.hasNext();) {
@@ -329,12 +351,11 @@ public class UserImporter extends Defaul
                     }
 
                     List<Authorizable> toAdd = new ArrayList<Authorizable>();
-                    List<Value> nonExisting = new ArrayList<Value>();
-
-                    for (NodeId originalId : ((Membership) reference).ids) {
+                    final List<Membership.Member> nonExisting = new ArrayList<Membership.Member>();
 
-                        NodeId remapped = referenceTracker.getMappedId(originalId);
-                        NodeId id = (remapped == null) ? originalId : remapped;
+                    for (Membership.Member member : ((Membership) reference).members) {
+                        NodeId remapped = referenceTracker.getMappedId(member.id);
+                        NodeId id = (remapped == null) ? member.id : remapped;
 
                         Authorizable authorz = null;
                         try {
@@ -352,7 +373,7 @@ public class UserImporter extends Defaul
                             handleFailure("New member of " + gr + ": No such authorizable (NodeID = " + id + ")");
                             if (importBehavior == ImportBehavior.BESTEFFORT) {
                                 log.info("ImportBehavior.BESTEFFORT: Remember non-existing member for processing.");
-                                nonExisting.add(session.getValueFactory().createValue(id.toString(), PropertyType.WEAKREFERENCE));
+                                nonExisting.add(member);
                             }
                         }
                     }
@@ -372,23 +393,55 @@ public class UserImporter extends Defaul
                     // handling non-existing members in case of best-effort
                     if (!nonExisting.isEmpty()) {
                         log.info("ImportBehavior.BESTEFFORT: Found " + nonExisting.size() + " entries of rep:members pointing to non-existing authorizables. Adding to rep:members.");
+                        final NodeImpl groupNode = ((AuthorizableImpl) gr).getNode();
 
-                        NodeImpl groupNode = ((AuthorizableImpl) gr).getNode();
-                        // build list of valid members set before ....
-                        List<Value> memberValues = new ArrayList<Value>();
-                        if (groupNode.hasProperty(UserConstants.P_MEMBERS)) {
-                            Value[] vls = groupNode.getProperty(UserConstants.P_MEMBERS).getValues();
-                            memberValues.addAll(Arrays.asList(vls));
+                        if (userManager.getGroupMembershipSplitSize() > 0) {
+                            userManager.performProtectedOperation((SessionImpl) session, new SessionOperation<Object>() {
+                                public Boolean perform(SessionContext context) throws RepositoryException {
+                                    NodeImpl nMembers = (groupNode.hasNode(UserConstants.N_MEMBERS)
+                                            ? groupNode.getNode(UserConstants.N_MEMBERS)
+                                            : groupNode.addNode(UserConstants.N_MEMBERS, UserConstants.NT_REP_MEMBERS, null));
+
+                                    // Create N_MEMBERS node structure for holding member references
+                                    for (Membership.Member member : nonExisting) {
+                                        PropertySequence properties = GroupImpl.getPropertySequence(nMembers, userManager);
+                                        String propName = member.name;
+                                        if (propName == null) {
+                                            log.debug("Ignoring unnamed user with id {}", member.id);
+                                            continue;
+                                        }
+                                        if (properties.hasItem(propName)) {
+                                            log.debug("Overwriting authorizable {} which is already member of {}.", propName, gr);
+                                            properties.removeProperty(propName);
+                                        }
+                                        Value newMember = session.getValueFactory().createValue(member.id.toString(), PropertyType.WEAKREFERENCE);
+                                        properties.addProperty(propName, newMember);
+                                    }
+                                    return null;
+                                }
+                            });
+                        } else {
+                            // Create P_MEMBERS for holding member references
+                            // build list of valid members set before ....
+                            List<Value> memberValues = new ArrayList<Value>();
+                            if (groupNode.hasProperty(UserConstants.P_MEMBERS)) {
+                                Value[] vls = groupNode.getProperty(UserConstants.P_MEMBERS).getValues();
+                                memberValues.addAll(Arrays.asList(vls));
+                            }
+
+                            // ... and the non-Existing ones.
+                            for (Membership.Member member : nonExisting) {
+                                memberValues.add(session.getValueFactory().createValue(member.id.toString(), PropertyType.WEAKREFERENCE));
+                            }
+
+                            // and use implementation specific method to set the
+                            // value of rep:members properties which was not possible
+                            // through the API
+                            userManager.setProtectedProperty(groupNode,
+                                    UserConstants.P_MEMBERS,
+                                    memberValues.toArray(new Value[memberValues.size()]),
+                                    PropertyType.WEAKREFERENCE);
                         }
-                        // ... and the non-Existing ones.
-                        memberValues.addAll(nonExisting);
-                        // and use implementation specific method to set the
-                        // value of rep:members properties which was not possible
-                        // through the API
-                        userManager.setProtectedProperty(groupNode,
-                                UserConstants.P_MEMBERS,
-                                memberValues.toArray(new Value[memberValues.size()]),
-                                PropertyType.WEAKREFERENCE);
                     }
 
                     processed.add(reference);
@@ -461,6 +514,66 @@ public class UserImporter extends Defaul
         }
     }
 
+    // -----------------------------------------------------< ProtectedNodeImporter >---
+
+    private Membership currentMembership;
+
+    public boolean start(NodeImpl protectedParent) throws RepositoryException {
+        String repMembers = resolver.getJCRName(UserConstants.NT_REP_MEMBERS);
+        if (repMembers.equals(protectedParent.getPrimaryNodeType().getName())) {
+            NodeImpl groupNode = protectedParent;
+            while(groupNode.getDepth() != 0 &&
+                  repMembers.equals(groupNode.getPrimaryNodeType().getName())) {
+
+                groupNode = (NodeImpl) groupNode.getParent();
+            }
+            Authorizable auth = userManager.getAuthorizable(groupNode);
+            if (auth == null) {
+                log.debug("Cannot handle protected node " + protectedParent + ". It nor one of its parents represent a valid Authorizable.");
+                return false;
+            }
+            else {
+                currentMembership = new Membership(auth.getID());
+                return true;
+            }
+        }
+        else {
+            return false;
+        }
+    }
+
+    public boolean start(NodeState protectedParent) {
+        return false;
+    }
+
+    public void startChildInfo(NodeInfo childInfo, List<PropInfo> propInfos) throws RepositoryException {
+        assert (currentMembership != null);
+
+        if (UserConstants.NT_REP_MEMBERS.equals(childInfo.getNodeTypeName())) {
+            for (PropInfo prop : propInfos) {
+                Value[] vs = prop.getValues(PropertyType.WEAKREFERENCE, resolver);
+                for (int i = 0; i < vs.length; i++) {
+                    String name = resolver.getJCRName(prop.getName());
+                    NodeId id = new NodeId(vs[i].getString());
+                    currentMembership.addMember(name, id);
+                }
+            }
+        }
+        else {
+            log.warn("{} is not of type {}", childInfo.getName(), UserConstants.NT_REP_MEMBERS);
+        }
+    }
+
+    public void endChildInfo() throws RepositoryException {
+    }
+
+    public void end(NodeImpl protectedParent) throws RepositoryException {
+        referenceTracker.processedReference(currentMembership);
+        currentMembership = null;
+    }
+
+    public void end(NodeState protectedParent) {
+    }
 
     //---------------------------------------------------------< BeanConfig >---
     /**
@@ -487,13 +600,31 @@ public class UserImporter extends Defaul
      * @see ImportBehavior For additional configuration options.
      */
     private final class Membership {
-
         private final String groupId;
-        private final NodeId[] ids;
+        private final List<Member> members = new LinkedList<Member>();
 
-        private Membership(String groupId, NodeId[] ids) {
+        public Membership(String groupId) {
             this.groupId = groupId;
-            this.ids = ids;
+        }
+
+        public void addMember(String name, NodeId id) {
+            members.add(new Member(name, id));
+        }
+
+        public void addMember(NodeId id) {
+            addMember(null, id);
+        }
+
+        // If only Java had tuples...
+        public class Member {
+            private final String name;
+            private final NodeId id;
+
+            public Member(String name, NodeId id) {
+                super();
+                this.name = name;
+                this.id = id;
+            }
         }
     }
 

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/DefaultProtectedItemImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/DefaultProtectedItemImporter.java?rev=987181&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/DefaultProtectedItemImporter.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/DefaultProtectedItemImporter.java Thu Aug 19 15:04:38 2010
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.xml;
+
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.core.NodeImpl;
+import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.util.ReferenceChangeTracker;
+import org.apache.jackrabbit.spi.QPropertyDefinition;
+import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
+
+import javax.jcr.RepositoryException;
+import java.util.List;
+
+/**
+ * <code>DefaultProtectedItemImporter</code>...
+ */
+public class DefaultProtectedItemImporter implements ProtectedPropertyImporter, ProtectedNodeImporter {
+
+    protected JackrabbitSession session;
+    protected NamePathResolver resolver;
+    protected boolean isWorkspaceImport;
+    protected int uuidBehavior;
+    protected ReferenceChangeTracker referenceTracker;
+
+    public DefaultProtectedItemImporter() {
+    }
+
+    //----------------------------------------------< ProtectedItemImporter >---
+    /**
+     * @see ProtectedItemImporter#init(org.apache.jackrabbit.api.JackrabbitSession, org.apache.jackrabbit.spi.commons.conversion.NamePathResolver, boolean, int, org.apache.jackrabbit.core.util.ReferenceChangeTracker)
+     */
+    public boolean init(JackrabbitSession session, NamePathResolver resolver, boolean isWorkspaceImport, int uuidBehavior, ReferenceChangeTracker referenceTracker) {
+        this.session = session;
+        this.resolver = resolver;
+        this.isWorkspaceImport = isWorkspaceImport;
+        this.uuidBehavior = uuidBehavior;
+        this.referenceTracker = referenceTracker;
+        return true;
+    }
+
+    //----------------------------------------------< ProtectedNodeImporter >---
+    /**
+     * Always returns <code>false</code>.
+     *
+     * @see ProtectedNodeImporter#start(org.apache.jackrabbit.core.NodeImpl)
+     */
+    public boolean start(NodeImpl protectedParent) throws RepositoryException {
+        return false;
+    }
+
+    /**
+     * Always returns <code>false</code>.
+     *
+     * @see ProtectedNodeImporter#start(org.apache.jackrabbit.core.state.NodeState)
+     */
+    public boolean start(NodeState protectedParent) throws RepositoryException {
+        return false;
+    }
+
+    /**
+     * Does nothing.
+     *
+     * @see ProtectedNodeImporter#end(NodeImpl)
+     */
+    public void end(NodeImpl protectedParent) throws RepositoryException {
+    }
+
+    /**
+     * Does nothing.
+     *
+     * @see ProtectedNodeImporter#end(NodeState)
+     */
+    public void end(NodeState protectedParent) throws RepositoryException {
+    }
+
+    /**
+     * Does nothing.
+     *
+     * @see ProtectedNodeImporter#startChildInfo(NodeInfo, java.util.List)
+     */
+    public void startChildInfo(NodeInfo childInfo, List<PropInfo> propInfos) throws RepositoryException {
+    }
+
+    /**
+     * Does nothing.
+     *
+     * @see ProtectedNodeImporter#endChildInfo()
+     */
+    public void endChildInfo() throws RepositoryException {
+    }
+
+
+
+    //------------------------------------------< ProtectedPropertyImporter >---
+    /**
+     * Always returns <code>false</code>.
+     *
+     * @see ProtectedPropertyImporter#handlePropInfo(org.apache.jackrabbit.core.NodeImpl, PropInfo, org.apache.jackrabbit.spi.QPropertyDefinition)
+     */
+    public boolean handlePropInfo(NodeImpl parent, PropInfo protectedPropInfo, QPropertyDefinition def) throws RepositoryException {
+        return false;
+    }
+
+    /**
+     * Always returns <code>false</code>.
+     *
+     * @see ProtectedPropertyImporter#handlePropInfo(org.apache.jackrabbit.core.state.NodeState, PropInfo, QPropertyDefinition)
+     */
+    public boolean handlePropInfo(NodeState parent, PropInfo protectedPropInfo, QPropertyDefinition def) throws RepositoryException {
+        return false;
+    }
+
+    /**
+     * Always returns <code>false</code>.
+     *
+     * @see ProtectedPropertyImporter#processReferences()
+     */
+    public void processReferences() throws RepositoryException {
+    }
+}
\ No newline at end of file

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

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/DefaultProtectedItemImporter.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/DefaultProtectedNodeImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/DefaultProtectedNodeImporter.java?rev=987181&r1=987180&r2=987181&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/DefaultProtectedNodeImporter.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/DefaultProtectedNodeImporter.java Thu Aug 19 15:04:38 2010
@@ -16,94 +16,12 @@
  */
 package org.apache.jackrabbit.core.xml;
 
-import java.util.List;
-
-import javax.jcr.RepositoryException;
-
-import org.apache.jackrabbit.core.NodeImpl;
-import org.apache.jackrabbit.core.util.ReferenceChangeTracker;
-import org.apache.jackrabbit.core.state.NodeState;
-import org.apache.jackrabbit.api.JackrabbitSession;
-import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
-
 /**
  * Default implementation that isn't able to handle any protected nodes.
  */
-public class DefaultProtectedNodeImporter implements ProtectedNodeImporter {
-
-    protected JackrabbitSession session;
-    protected NamePathResolver resolver;
-    protected boolean isWorkspaceImport;
-    protected int uuidBehavior;
-    protected ReferenceChangeTracker referenceTracker;
+public class DefaultProtectedNodeImporter extends DefaultProtectedItemImporter {
 
     public DefaultProtectedNodeImporter() {
-    }
-
-    public boolean init(JackrabbitSession session, NamePathResolver resolver, boolean isWorkspaceImport, int uuidBehavior, ReferenceChangeTracker referenceTracker) {
-        this.session = session;
-        this.resolver = resolver;
-        this.isWorkspaceImport = isWorkspaceImport;
-        this.uuidBehavior = uuidBehavior;
-        this.referenceTracker = referenceTracker;
-        return true;
-    }
-
-    /**
-     * Always returns <code>false</code>.
-     *
-     * @see ProtectedNodeImporter#start(org.apache.jackrabbit.core.NodeImpl)
-     */
-    public boolean start(NodeImpl protectedParent) throws RepositoryException {
-        return false;
-    }
-
-    /**
-     * Always returns <code>false</code>.
-     *
-     * @see ProtectedNodeImporter#start(org.apache.jackrabbit.core.state.NodeState)
-     */
-    public boolean start(NodeState protectedParent) throws RepositoryException {
-        return false;
-    }
-
-    /**
-     * Does nothing.
-     *
-     * @see ProtectedNodeImporter#end(NodeImpl)
-     */
-    public void end(NodeImpl protectedParent) throws RepositoryException {
-    }
-
-    /**
-     * Does nothing.
-     *
-     * @see ProtectedNodeImporter#end(NodeState)
-     */
-    public void end(NodeState protectedParent) throws RepositoryException {
-    }
-
-    /**
-     * Does nothing.
-     *
-     * @see ProtectedNodeImporter#startChildInfo(NodeInfo, List)
-     */
-    public void startChildInfo(NodeInfo childInfo, List<PropInfo> propInfos) throws RepositoryException {
-    }
-
-    /**
-     * Does nothing.
-     *
-     * @see ProtectedNodeImporter#endChildInfo()
-     */
-    public void endChildInfo() throws RepositoryException {
-    }
-
-    /**
-     * Does nothing.
-     *
-     * @see ProtectedNodeImporter#processReferences()
-     */
-    public void processReferences() throws RepositoryException {
+        super();
     }
 }
\ No newline at end of file

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/DefaultProtectedPropertyImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/DefaultProtectedPropertyImporter.java?rev=987181&r1=987180&r2=987181&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/DefaultProtectedPropertyImporter.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/DefaultProtectedPropertyImporter.java Thu Aug 19 15:04:38 2010
@@ -16,19 +16,14 @@
  */
 package org.apache.jackrabbit.core.xml;
 
-import javax.jcr.RepositoryException;
-
-import org.apache.jackrabbit.core.NodeImpl;
-import org.apache.jackrabbit.core.util.ReferenceChangeTracker;
-import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.core.util.ReferenceChangeTracker;
 import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
-import org.apache.jackrabbit.spi.QPropertyDefinition;
 
 /**
  * Default implementation that isn't able to handle any protected properties.
  */
-public class DefaultProtectedPropertyImporter implements ProtectedPropertyImporter {
+public class DefaultProtectedPropertyImporter extends DefaultProtectedItemImporter {
 
     protected JackrabbitSession session;
 
@@ -41,42 +36,6 @@ public class DefaultProtectedPropertyImp
     protected ReferenceChangeTracker referenceTracker;
 
     public DefaultProtectedPropertyImporter() {
-    }
-
-    public boolean init(JackrabbitSession session, NamePathResolver resolver,
-                        boolean isWorkspaceImport,
-                        int uuidBehavior, ReferenceChangeTracker referenceTracker) {
-        this.session = session;
-        this.resolver = resolver;
-        this.isWorkspaceImport = isWorkspaceImport;
-        this.uuidBehavior = uuidBehavior;
-        this.referenceTracker = referenceTracker;
-        return true;
-    }
-
-    /**
-     * Always returns <code>false</code>.
-     *
-     * @see ProtectedPropertyImporter#handlePropInfo(org.apache.jackrabbit.core.NodeImpl, PropInfo, QPropertyDefinition)
-     */
-    public boolean handlePropInfo(NodeImpl parent, PropInfo protectedPropInfo, QPropertyDefinition def) throws RepositoryException {
-        return false;
-    }
-
-    /**
-     * Always returns <code>false</code>.
-     *
-     * @see ProtectedPropertyImporter#handlePropInfo(org.apache.jackrabbit.core.state.NodeState, PropInfo, QPropertyDefinition)
-     */
-    public boolean handlePropInfo(NodeState parent, PropInfo protectedPropInfo, QPropertyDefinition def) throws RepositoryException {
-        return false;
-    }
-
-    /**
-     * Always returns <code>false</code>.
-     *
-     * @see ProtectedPropertyImporter#processReferences()
-     */
-    public void processReferences() throws RepositoryException {
+        super();
     }
 }
\ No newline at end of file

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/ProtectedItemImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/ProtectedItemImporter.java?rev=987181&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/ProtectedItemImporter.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/ProtectedItemImporter.java Thu Aug 19 15:04:38 2010
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.xml;
+
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.core.util.ReferenceChangeTracker;
+import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * <code>ProtectedItemImporter</code>...
+ */
+public interface ProtectedItemImporter {
+
+    /**
+     *
+     * @param session
+     * @param resolver
+     * @param isWorkspaceImport
+     * @param uuidBehavior
+     * @param referenceTracker
+     * @return
+     */
+    boolean init(JackrabbitSession session, NamePathResolver resolver,
+                 boolean isWorkspaceImport, int uuidBehavior,
+                 ReferenceChangeTracker referenceTracker);
+        
+    /**
+     * Post processing protected reference properties underneath a protected
+     * or non-protected parent node. If the parent is protected it has been
+     * handled by this importer already. This method is called
+     * from {@link org.apache.jackrabbit.core.xml.Importer#end()}.
+     *
+     * @throws javax.jcr.RepositoryException If an error occurs.
+     */
+    void processReferences() throws RepositoryException;
+}
\ No newline at end of file

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

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/ProtectedItemImporter.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/ProtectedNodeImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/ProtectedNodeImporter.java?rev=987181&r1=987180&r2=987181&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/ProtectedNodeImporter.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/ProtectedNodeImporter.java Thu Aug 19 15:04:38 2010
@@ -17,10 +17,7 @@
 package org.apache.jackrabbit.core.xml;
 
 import org.apache.jackrabbit.core.NodeImpl;
-import org.apache.jackrabbit.core.util.ReferenceChangeTracker;
 import org.apache.jackrabbit.core.state.NodeState;
-import org.apache.jackrabbit.api.JackrabbitSession;
-import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
 
 import javax.jcr.RepositoryException;
 import javax.jcr.nodetype.ConstraintViolationException;
@@ -37,20 +34,8 @@ import java.util.List;
  * parent until {@link #end(NodeImpl)} is called. The latter resets this importer
  * and makes it available for another protected import.
  */
-public interface ProtectedNodeImporter {
+public interface ProtectedNodeImporter extends ProtectedItemImporter {
 
-    /**
-     * 
-     * @param session
-     * @param resolver
-     * @param isWorkspaceImport
-     * @param uuidBehavior
-     * @param referenceTracker
-     * @return
-     */
-    boolean init(JackrabbitSession session, NamePathResolver resolver,
-                 boolean isWorkspaceImport, int uuidBehavior,
-                 ReferenceChangeTracker referenceTracker);
 
     /**
      * Notifies this importer about the existence of a protected node that
@@ -161,15 +146,5 @@ public interface ProtectedNodeImporter {
      * is called before all required child information has been imported.
      * @throws RepositoryException If another error occurs.
      */
-    void endChildInfo() throws RepositoryException;
-
-    /**
-     * Post processing protected reference properties underneath a parent
-     * node that has been handled by this importer.
-     * This method is called
-     * from {@link org.apache.jackrabbit.core.xml.Importer#end()}.
-     * 
-     * @throws RepositoryException If an error occurs.
-     */
-    void processReferences() throws RepositoryException;
+    void endChildInfo() throws RepositoryException;    
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/ProtectedPropertyImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/ProtectedPropertyImporter.java?rev=987181&r1=987180&r2=987181&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/ProtectedPropertyImporter.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/ProtectedPropertyImporter.java Thu Aug 19 15:04:38 2010
@@ -32,19 +32,7 @@ import org.apache.jackrabbit.api.Jackrab
  * @see ProtectedNodeImporter for an abstract class used to import protected
  * nodes and the subtree below them.
  */
-public interface ProtectedPropertyImporter {
-
-    /**
-     * 
-     * @param session
-     * @param resolver
-     * @param isWorkspaceImport
-     * @param uuidBehavior
-     *@param referenceTracker  @return
-     */
-    boolean init(JackrabbitSession session, NamePathResolver resolver,
-                 boolean isWorkspaceImport, int uuidBehavior,
-                 ReferenceChangeTracker referenceTracker);
+public interface ProtectedPropertyImporter extends ProtectedItemImporter {
 
     /**
      * Handles a single protected property.
@@ -76,13 +64,4 @@ public interface ProtectedPropertyImport
                            QPropertyDefinition def)
             throws RepositoryException;
 
-
-    /**
-     * Post processing protected reference properties. This method is called
-     * from {@link org.apache.jackrabbit.core.xml.Importer#end()}.
-     *
-     * @throws RepositoryException If an error occurs.
-     */
-    void processReferences() throws RepositoryException;
-
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SessionImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SessionImporter.java?rev=987181&r1=987180&r2=987181&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SessionImporter.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SessionImporter.java Thu Aug 19 15:04:38 2010
@@ -64,11 +64,7 @@ public class SessionImporter implements 
      */
     private final ReferenceChangeTracker refTracker;
 
-    private final List<ProtectedNodeImporter> pnImporters = new ArrayList();
-    /**
-     * Available importers for protected properties.
-     */
-    private final List<ProtectedPropertyImporter> ppImporters = new ArrayList();
+    private final List<ProtectedItemImporter> pItemImporters = new ArrayList();
 
     /**
      * Currently active importer for protected nodes.
@@ -110,31 +106,19 @@ public class SessionImporter implements 
         parents.push(importTargetNode);
 
         if (config != null) {
-            List<ProtectedNodeImporter> ln = config.getProtectedNodeImporters();
-            for (ProtectedNodeImporter pni : ln) {
-                if (pni.init(session, session, false, uuidBehavior, refTracker)) {
-                    pnImporters.add(pni);
-                }
-            }
-            List<ProtectedPropertyImporter> lp = config.getProtectedPropertyImporters();
-            for (ProtectedPropertyImporter ppi : lp) {
-                if (ppi.init(session, session, false, uuidBehavior, refTracker)) {
-                    ppImporters.add(ppi);
+            List<ProtectedItemImporter> iList = (List<ProtectedItemImporter>) config.getProtectedItemImporters();
+            for (ProtectedItemImporter importer : iList) {
+                if (importer.init(session, session, false, uuidBehavior, refTracker)) {
+                    pItemImporters.add(importer);
                 }
             }
         }
 
         // missing config -> initialize defaults.
-        if (pnImporters.isEmpty()) {
-            ProtectedNodeImporter def = new DefaultProtectedNodeImporter();
-            if (def.init(session, session, false, uuidBehavior, refTracker)) {
-                pnImporters.add(def);
-            }
-        }
-        if (ppImporters.isEmpty()) {
-            DefaultProtectedPropertyImporter def = new DefaultProtectedPropertyImporter();
+        if (pItemImporters.isEmpty()) {
+            ProtectedItemImporter def = new DefaultProtectedItemImporter();
             if (def.init(session, session, false, uuidBehavior, refTracker)) {
-                ppImporters.add(def);
+                pItemImporters.add(def);
             }
         }
     }
@@ -307,18 +291,27 @@ public class SessionImporter implements 
             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.
-            for (ProtectedNodeImporter pni : pnImporters) {
-                if (pni.start(parent)) {
-                    log.debug("Protected node -> delegated to ProtectedNodeImporter");
-                    pnImporter = pni;
-                    pnImporter.startChildInfo(nodeInfo, propInfos);
-                    break;
-                } /* else: p-i-Importer isn't able to deal with the protected tree.
+            if (pnImporter != null) {
+                // pnImporter was already started (current nodeInfo is a sibling)
+                // notify it about this child node.
+                pnImporter.startChildInfo(nodeInfo, propInfos);
+            } else {
+                // no importer defined yet:
+                // test if there is a ProtectedNodeImporter among the configured
+                // importers that can handle this.
+                // if there is one, 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.
+                for (ProtectedItemImporter pni : pItemImporters) {
+                    if (pni instanceof ProtectedNodeImporter && ((ProtectedNodeImporter) pni).start(parent)) {
+                        log.debug("Protected node -> delegated to ProtectedNodeImporter");
+                        pnImporter = (ProtectedNodeImporter) pni;
+                        pnImporter.startChildInfo(nodeInfo, propInfos);
+                        break;
+                    } /* else: p-i-Importer isn't able to deal with the protected tree.
                      try next. and if none can handle the passed parent the
                      tree below will be skipped */
+                }
             }
             return;
         }
@@ -406,8 +399,8 @@ public class SessionImporter implements 
                 log.debug("Skipping protected property " + pi.getName());
 
                 // notify the ProtectedPropertyImporter.
-                for (ProtectedPropertyImporter ppi : ppImporters) {
-                    if (ppi.handlePropInfo(node, pi, def)) {
+                for (ProtectedItemImporter ppi : pItemImporters) {
+                    if (ppi instanceof ProtectedPropertyImporter && ((ProtectedPropertyImporter) ppi).handlePropInfo(node, pi, def)) {
                         log.debug("Protected property -> delegated to ProtectedPropertyImporter");
                         break;
                     } /* else: p-i-Importer isn't able to deal with this property.
@@ -453,12 +446,9 @@ public class SessionImporter implements 
          */
         // 1. let protected property/node importers handle protected ref-properties
         //    and (protected) properties underneath a protected parent node.
-        for (ProtectedPropertyImporter ppi : ppImporters) {
+        for (ProtectedItemImporter ppi : pItemImporters) {
             ppi.processReferences();
         }
-        for (ProtectedNodeImporter pni : pnImporters) {
-            pni.processReferences();
-        }
 
         // 2. regular non-protected properties.
         Iterator<Object> iter = refTracker.getProcessedReferences();

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java?rev=987181&r1=987180&r2=987181&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java Thu Aug 19 15:04:38 2010
@@ -16,21 +16,6 @@
  */
 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.SessionImpl;
@@ -56,6 +41,21 @@ import org.apache.jackrabbit.spi.commons
 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> ...
  */
@@ -73,7 +73,7 @@ public class WorkspaceImporter implement
     private final int uuidBehavior;
 
     private boolean aborted;
-    private Stack<NodeState> parents;
+    private final Stack<NodeState> parents;
 
     /**
      * helper object that keeps track of remapped uuid's and imported reference
@@ -160,18 +160,11 @@ public class WorkspaceImporter implement
         // for the time being log an exception if an importer is configured that
         // is expected to work with workspace import. see JCR-2521
         if (config != null) {
-            List<ProtectedNodeImporter> ln = config.getProtectedNodeImporters();
-            for (ProtectedNodeImporter pni : ln) {
-                if (pni.init(session, session, true, uuidBehavior, refTracker)) {
-                    log.warn("Protected node importer configured is not supported by workspace import.");
-                    //throw new UnsupportedOperationException("Workspace-Import of protected nodes: Not yet implement. ");
-                }
-            }
-            List<ProtectedPropertyImporter> lp = config.getProtectedPropertyImporters();
-            for (ProtectedPropertyImporter ppi : lp) {
+            List<? extends ProtectedItemImporter> pi = config.getProtectedItemImporters();
+            for (ProtectedItemImporter ppi : pi) {
                 if (ppi.init(session, session, true, uuidBehavior, refTracker)) {
-                    log.warn("Protected property importer configured is not supported by workspace import.");
-                    //throw new UnsupportedOperationException("Workspace-Import of protected properties: Not yet implement. ");
+                    log.warn("Protected item importer configured is not supported by workspace import.");
+                    //throw new UnsupportedOperationException("Workspace-Import of protected nodes: Not yet implement. ");
                 }
             }
         }
@@ -372,7 +365,7 @@ public class WorkspaceImporter implement
             conditionalAddProperty(
                     node, NameConstants.JCR_ISCHECKEDOUT,
                     PropertyType.BOOLEAN, false, InternalValue.create(true));
-            
+
             // set extra properties only for full versionable nodes
             if (ent.includesNodeType(NameConstants.MIX_VERSIONABLE)) {
                 // jcr:versionHistory
@@ -459,7 +452,7 @@ public class WorkspaceImporter implement
         // store property
         itemOps.store(prop);
     }
-    
+
     /**
      * Adds the the given property to a node unless the property already
      * exists.

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/config/WorkspaceConfigTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/config/WorkspaceConfigTest.java?rev=987181&r1=987180&r2=987181&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/config/WorkspaceConfigTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/config/WorkspaceConfigTest.java Thu Aug 19 15:04:38 2010
@@ -16,12 +16,9 @@
  */
 package org.apache.jackrabbit.core.config;
 
-import junit.framework.TestCase;
 import org.apache.jackrabbit.core.security.authorization.AccessControlProvider;
 import org.apache.jackrabbit.core.security.user.UserImporter;
-import org.apache.jackrabbit.core.xml.AccessControlImporter;
-import org.apache.jackrabbit.core.xml.ProtectedNodeImporter;
-import org.apache.jackrabbit.core.xml.ProtectedPropertyImporter;
+import org.apache.jackrabbit.core.xml.ProtectedItemImporter;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.xml.sax.InputSource;
@@ -31,12 +28,15 @@ import org.xml.sax.SAXParseException;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.StringReader;
 import java.util.List;
 import java.util.Properties;
 
+import junit.framework.TestCase;
+
 /**
  * Test cases for workspace configuration handling.
  */
@@ -87,49 +87,35 @@ public class WorkspaceConfigTest extends
         Element xml = parseXML(new InputSource(new StringReader(XML_1)), true);
         ImportConfig config = parser.parseImportConfig(xml);
 
-        List<ProtectedNodeImporter> ln = config.getProtectedNodeImporters();
-        assertEquals(1, ln.size());
-        assertTrue(ln.get(0) instanceof AccessControlImporter);
-
-        List<ProtectedPropertyImporter> lp = config.getProtectedPropertyImporters();
-        assertEquals(1, lp.size());
-        assertTrue(lp.get(0) instanceof UserImporter);
+        List<? extends ProtectedItemImporter> ln = config.getProtectedItemImporters();
+        assertEquals(2, ln.size());
 
         // XML_2 ---------------------------------------------------------------
         xml = parseXML(new InputSource(new StringReader(XML_2)), true);
         config = parser.parseImportConfig(xml);
 
-        ln = config.getProtectedNodeImporters();
+        ln = config.getProtectedItemImporters();
         assertTrue(ln.isEmpty());
 
-        lp = config.getProtectedPropertyImporters();
-        assertTrue(lp.isEmpty());
-
         // XML_3 ---------------------------------------------------------------
         xml = parseXML(new InputSource(new StringReader(XML_3)), true);
         config = parser.parseImportConfig(xml);
 
-        ln = config.getProtectedNodeImporters();
-        assertEquals(2, ln.size());
-
-        lp = config.getProtectedPropertyImporters();
-        assertEquals(2, lp.size());
+        ln = config.getProtectedItemImporters();
+        assertEquals(4, ln.size());
 
         // XML_4 ---------------------------------------------------------------
         xml = parseXML(new InputSource(new StringReader(XML_4)), true);
         config = parser.parseImportConfig(xml);
 
-        ln = config.getProtectedNodeImporters();
-        assertEquals(1, ln.size());
-
-        lp = config.getProtectedPropertyImporters();
-        assertEquals(1, lp.size());
+        ln = config.getProtectedItemImporters();
+        assertEquals(2, ln.size());
 
         // XML_5 ---------------------------------------------------------------
         xml = parseXML(new InputSource(new StringReader(XML_5)), true);
         config = parser.parseImportConfig(xml);
 
-        lp = config.getProtectedPropertyImporters();
+        List<? extends ProtectedItemImporter> lp = config.getProtectedItemImporters();
         assertEquals(1, lp.size());
         assertTrue(lp.get(0) instanceof UserImporter);
         assertEquals(UserImporter.ImportBehavior.NAME_BESTEFFORT, ((UserImporter)lp.get(0)).getImportBehavior());

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserImporterTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserImporterTest.java?rev=987181&r1=987180&r2=987181&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserImporterTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserImporterTest.java Thu Aug 19 15:04:38 2010
@@ -34,7 +34,7 @@ import org.apache.jackrabbit.core.securi
 import org.apache.jackrabbit.core.security.user.UserImporter.ImportBehavior;
 import org.apache.jackrabbit.core.util.ReferenceChangeTracker;
 import org.apache.jackrabbit.core.xml.ImportHandler;
-import org.apache.jackrabbit.core.xml.ProtectedPropertyImporter;
+import org.apache.jackrabbit.core.xml.ProtectedNodeImporter;
 import org.apache.jackrabbit.core.xml.SessionImporter;
 import org.apache.jackrabbit.test.AbstractJCRTest;
 import org.apache.jackrabbit.test.NotExecutableException;
@@ -52,6 +52,7 @@ import javax.jcr.ItemNotFoundException;
 import javax.jcr.LoginException;
 import javax.jcr.NamespaceException;
 import javax.jcr.Node;
+import javax.jcr.NodeIterator;
 import javax.jcr.PathNotFoundException;
 import javax.jcr.Property;
 import javax.jcr.PropertyType;
@@ -80,6 +81,7 @@ import java.security.Principal;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.UUID;
 
@@ -159,7 +161,7 @@ public class UserImporterTest extends Ab
         super.tearDown();
     }
 
-    private static ProtectedPropertyImporter createImporter() {
+    private static UserImporter createImporter() {
         return new UserImporter();
     }
 
@@ -178,10 +180,10 @@ public class UserImporterTest extends Ab
     }
 
     public void testInitTwice() {
-        ProtectedPropertyImporter ppi = createImporter();
-        assertTrue(ppi.init(sImpl, sImpl, false, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW, new ReferenceChangeTracker()));
+        UserImporter userImporter = createImporter();
+        assertTrue(userImporter.init(sImpl, sImpl, false, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW, new ReferenceChangeTracker()));
         try {
-            ppi.init(sImpl, sImpl, false, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW, new ReferenceChangeTracker());
+            userImporter.init(sImpl, sImpl, false, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW, new ReferenceChangeTracker());
             fail("calling init twice must fail");
         } catch (IllegalStateException e) {
             // success
@@ -836,6 +838,10 @@ public class UserImporterTest extends Ab
     }
 
     public void testImportNonExistingMemberBestEffort() throws IOException, RepositoryException, SAXException, NotExecutableException {
+        if (umgr.getGroupMembershipSplitSize() > 0) {
+            throw new NotExecutableException();
+        }
+
         Node n = testRootNode.addNode(nodeName1, ntUnstructured);
         n.addMixin(mixReferenceable);
 
@@ -886,7 +892,7 @@ public class UserImporterTest extends Ab
 
         String g1Id = "0120a4f9-196a-3f9e-b9f5-23f31f914da7";
         String nonExistingId = "b2f5ff47-4366-31b6-a533-d8dc3614845d"; // groupId of 'g' group.
-        if (umgr.getAuthorizable("g") != null) {
+        if (umgr.getAuthorizable("g") != null || umgr.getGroupMembershipSplitSize() > 0) {
             throw new NotExecutableException();
         }
 
@@ -1206,6 +1212,120 @@ public class UserImporterTest extends Ab
         }
     }
 
+    public void testImportGroupMembersFromNodes() throws RepositoryException, IOException, SAXException {
+        String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><sv:node sv:name=\"s\" xmlns:mix=\"http://www.jcp.org/jcr/mix/1.0\" xmlns:sling=\"http://sling.apache.org/jcr/sling/1.0\" xmlns:nt=\"http://www.jcp.org/jcr/nt/1.0\" xmlns:fn_old=\"http://www.w3.org/2004/10/xpath-functions\" xmlns:fn=\"http://www.w3.org/2005/xpath-functions\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:jcr=\"http://www.jcp.org/jcr/1.0\" xmlns:sv=\"http://www.jcp.org/jcr/sv/1.0\" xmlns:rep=\"internal\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:AuthorizableFolder</sv:value></sv:property><sv:property sv:name=\"jcr:created\" sv:type=\"Date\"><sv:value>2010-08-17T18:22:20.086+02:00</sv:value></sv:property><sv:property sv:name=\"jcr:createdBy\" sv:type=\"String\"><sv:value>admin</sv:value></sv:property><sv:node sv:name=\"sh\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:AuthorizableFolder</sv:value></sv:property><sv:property sv:name=\"jcr
 :created\" sv:type=\"Date\"><sv:value>2010-08-17T18:22:20.086+02:00</sv:value></sv:property><sv:property sv:name=\"jcr:createdBy\" sv:type=\"String\"><sv:value>admin</sv:value></sv:property><sv:node sv:name=\"shrimps\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Group</sv:value></sv:property><sv:property sv:name=\"jcr:uuid\" sv:type=\"String\"><sv:value>08429aec-6f09-30db-8c83-1a2a57fc760c</sv:value></sv:property><sv:property sv:name=\"jcr:created\" sv:type=\"Date\">" +
+                     "<sv:value>2010-08-17T18:22:20.086+02:00</sv:value></sv:property><sv:property sv:name=\"jcr:createdBy\" sv:type=\"String\"><sv:value>admin</sv:value></sv:property><sv:property sv:name=\"rep:principalName\" sv:type=\"String\"><sv:value>shrimps</sv:value></sv:property><sv:node sv:name=\"rep:members\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Members</sv:value></sv:property><sv:node sv:name=\"adi\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Members</sv:value></sv:property><sv:node sv:name=\"adi\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Members</sv:value></sv:property><sv:property sv:name=\"adi\" sv:type=\"WeakReference\"><sv:value>c46335eb-267e-3e1c-9e5b-017acb4cd799</sv:value></sv:property><sv:property sv:name=\"admin\" sv:type=\"WeakReference\"><sv:value>21232f29-7a57-35a7-8389-4a0e4a801fc3</sv:value></sv:property></sv:node><sv:node sv:name=\"angi\"><sv:property sv:
 name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Members</sv:value></sv:property><sv:property sv:name=\"angi\" sv:type=\"WeakReference\"><sv:value>a468b64f-b1df-377c-b325-20d97aaa1ad9</sv:value></sv:property><sv:property sv:name=\"anonymous\" sv:type=\"WeakReference\"><sv:value>294de355-7d9d-30b3-92d8-a1e6aab028cf</sv:value></sv:property><sv:property sv:name=\"cati\" sv:type=\"WeakReference\"><sv:value>f08910b6-41c8-3cb9-a648-1dddd14b132d</sv:value></sv:property></sv:node></sv:node><sv:n" +
+                     "ode sv:name=\"debbi\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Members</sv:value></sv:property><sv:node sv:name=\"debbi\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Members</sv:value></sv:property><sv:property sv:name=\"debbi\" sv:type=\"WeakReference\"><sv:value>d53bedf9-ebb8-3117-a8b8-162d32b4bee2</sv:value></sv:property><sv:property sv:name=\"eddi\" sv:type=\"WeakReference\"><sv:value>1795fa1a-3d20-3a64-996e-eaaeb520a01e</sv:value></sv:property><sv:property sv:name=\"gabi\" sv:type=\"WeakReference\"><sv:value>a0d499c7-5105-3663-8611-a32779a57104</sv:value></sv:property><sv:property sv:name=\"hansi\" sv:type=\"WeakReference\"><sv:value>9ea4d671-8ed1-399a-8401-59487a14d00a</sv:value></sv:property></sv:node><sv:node sv:name=\"hari\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Members</sv:value></sv:property><sv:property sv:name=\"hari\" sv:type=\"WeakReference\"><sv:
 value>a9bcf1e4-d7b9-3a22-a297-5c812d938889</sv:value></sv:property><sv:property sv:name=\"lisi\" sv:type=\"WeakReference\"><sv:value>dc3a8f16-70d6-3bea-a9b7-b65048a0ac40</sv:value></sv:property></sv:node><sv:node sv:name=\"luzi\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Members</sv:value></sv:property><sv:property sv:name=\"luzi\" sv:type=\"WeakReference\"><sv:value>9ec299fd-3461-3f1a-9749-92a76f2516eb</sv:value></sv:property><sv:property sv:name=\"pipi\" sv:type=" +
+                     "\"WeakReference\"><sv:value>16d5d24f-5b09-3199-9bd4-e5f57bf11237</sv:value></sv:property><sv:property sv:name=\"susi\" sv:type=\"WeakReference\"><sv:value>536931d8-0dec-318c-b3db-9612bdd004d4</sv:value></sv:property></sv:node></sv:node></sv:node></sv:node></sv:node></sv:node>";
+
+        List<String> createdUsers = new LinkedList<String>();
+        NodeImpl groupsNode = (NodeImpl) sImpl.getNode(umgr.getGroupsPath());
+        try {
+            String[] users = {"angi", "adi", "hansi", "lisi", "luzi", "susi", "pipi", "hari", "gabi", "eddi",
+                              "debbi", "cati", "admin", "anonymous"};
+
+            for (String user : users) {
+                if (umgr.getAuthorizable(user) == null) {
+                    umgr.createUser(user, user);
+                    createdUsers.add(user);
+                }
+            }
+            if (!umgr.isAutoSave()) {
+                sImpl.save();
+            }
+
+            doImport(groupsNode, xml);
+            if (!umgr.isAutoSave()) {
+                sImpl.save();
+            }
+
+            Authorizable aShrimps = umgr.getAuthorizable("shrimps");
+            assertNotNull(aShrimps);
+            assertTrue(aShrimps.isGroup());
+
+            Group gShrimps = (Group) aShrimps;
+            for (String user : users) {
+                assertTrue(user + " should be member of " + gShrimps, gShrimps.isMember(umgr.getAuthorizable(user)));
+            }
+
+
+        } finally {
+            sImpl.refresh(false);
+            for (String user : createdUsers) {
+                Authorizable a = umgr.getAuthorizable(user);
+                if (a != null && !a.isGroup()) {
+                    a.remove();
+                }
+            }
+            if (!umgr.isAutoSave()) {
+                sImpl.save();
+            }
+            for (NodeIterator it = groupsNode.getNodes(); it.hasNext(); ) {
+                it.nextNode().remove();
+            }
+            if (!umgr.isAutoSave()) {
+                sImpl.save();
+            }
+        }
+    }
+
+    public void testImportGroupMembersFromNodesBestEffort() throws RepositoryException, IOException, SAXException {
+        String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><sv:node sv:name=\"s\" xmlns:mix=\"http://www.jcp.org/jcr/mix/1.0\" xmlns:sling=\"http://sling.apache.org/jcr/sling/1.0\" xmlns:nt=\"http://www.jcp.org/jcr/nt/1.0\" xmlns:fn_old=\"http://www.w3.org/2004/10/xpath-functions\" xmlns:fn=\"http://www.w3.org/2005/xpath-functions\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:jcr=\"http://www.jcp.org/jcr/1.0\" xmlns:sv=\"http://www.jcp.org/jcr/sv/1.0\" xmlns:rep=\"internal\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:AuthorizableFolder</sv:value></sv:property><sv:property sv:name=\"jcr:created\" sv:type=\"Date\"><sv:value>2010-08-17T18:22:20.086+02:00</sv:value></sv:property><sv:property sv:name=\"jcr:createdBy\" sv:type=\"String\"><sv:value>admin</sv:value></sv:property><sv:node sv:name=\"sh\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:AuthorizableFolder</sv:value></sv:property><sv:property sv:name=\"jcr
 :created\" sv:type=\"Date\"><sv:value>2010-08-17T18:22:20.086+02:00</sv:value></sv:property><sv:property sv:name=\"jcr:createdBy\" sv:type=\"String\"><sv:value>admin</sv:value></sv:property><sv:node sv:name=\"shrimps\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Group</sv:value></sv:property><sv:property sv:name=\"jcr:uuid\" sv:type=\"String\"><sv:value>08429aec-6f09-30db-8c83-1a2a57fc760c</sv:value></sv:property><sv:property sv:name=\"jcr:created\" sv:type=\"Date\">" +
+                     "<sv:value>2010-08-17T18:22:20.086+02:00</sv:value></sv:property><sv:property sv:name=\"jcr:createdBy\" sv:type=\"String\"><sv:value>admin</sv:value></sv:property><sv:property sv:name=\"rep:principalName\" sv:type=\"String\"><sv:value>shrimps</sv:value></sv:property><sv:node sv:name=\"rep:members\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Members</sv:value></sv:property><sv:node sv:name=\"adi\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Members</sv:value></sv:property><sv:node sv:name=\"adi\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Members</sv:value></sv:property><sv:property sv:name=\"adi\" sv:type=\"WeakReference\"><sv:value>c46335eb-267e-3e1c-9e5b-017acb4cd799</sv:value></sv:property><sv:property sv:name=\"admin\" sv:type=\"WeakReference\"><sv:value>21232f29-7a57-35a7-8389-4a0e4a801fc3</sv:value></sv:property></sv:node><sv:node sv:name=\"angi\"><sv:property sv:
 name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Members</sv:value></sv:property><sv:property sv:name=\"angi\" sv:type=\"WeakReference\"><sv:value>a468b64f-b1df-377c-b325-20d97aaa1ad9</sv:value></sv:property><sv:property sv:name=\"anonymous\" sv:type=\"WeakReference\"><sv:value>294de355-7d9d-30b3-92d8-a1e6aab028cf</sv:value></sv:property><sv:property sv:name=\"cati\" sv:type=\"WeakReference\"><sv:value>f08910b6-41c8-3cb9-a648-1dddd14b132d</sv:value></sv:property></sv:node></sv:node><sv:n" +
+                     "ode sv:name=\"debbi\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Members</sv:value></sv:property><sv:node sv:name=\"debbi\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Members</sv:value></sv:property><sv:property sv:name=\"debbi\" sv:type=\"WeakReference\"><sv:value>d53bedf9-ebb8-3117-a8b8-162d32b4bee2</sv:value></sv:property><sv:property sv:name=\"eddi\" sv:type=\"WeakReference\"><sv:value>1795fa1a-3d20-3a64-996e-eaaeb520a01e</sv:value></sv:property><sv:property sv:name=\"gabi\" sv:type=\"WeakReference\"><sv:value>a0d499c7-5105-3663-8611-a32779a57104</sv:value></sv:property><sv:property sv:name=\"hansi\" sv:type=\"WeakReference\"><sv:value>9ea4d671-8ed1-399a-8401-59487a14d00a</sv:value></sv:property></sv:node><sv:node sv:name=\"hari\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Members</sv:value></sv:property><sv:property sv:name=\"hari\" sv:type=\"WeakReference\"><sv:
 value>a9bcf1e4-d7b9-3a22-a297-5c812d938889</sv:value></sv:property><sv:property sv:name=\"lisi\" sv:type=\"WeakReference\"><sv:value>dc3a8f16-70d6-3bea-a9b7-b65048a0ac40</sv:value></sv:property></sv:node><sv:node sv:name=\"luzi\"><sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:Members</sv:value></sv:property><sv:property sv:name=\"luzi\" sv:type=\"WeakReference\"><sv:value>9ec299fd-3461-3f1a-9749-92a76f2516eb</sv:value></sv:property><sv:property sv:name=\"pipi\" sv:type=" +
+                     "\"WeakReference\"><sv:value>16d5d24f-5b09-3199-9bd4-e5f57bf11237</sv:value></sv:property><sv:property sv:name=\"susi\" sv:type=\"WeakReference\"><sv:value>536931d8-0dec-318c-b3db-9612bdd004d4</sv:value></sv:property></sv:node></sv:node></sv:node></sv:node></sv:node></sv:node>";
+
+        List<String> createdUsers = new LinkedList<String>();
+        NodeImpl groupsNode = (NodeImpl) sImpl.getNode(umgr.getGroupsPath());
+        try {
+            String[] users = {"angi", "adi", "hansi", "lisi", "luzi", "susi", "pipi", "hari", "gabi", "eddi",
+                              "debbi", "cati", "admin", "anonymous"};
+
+            doImport(groupsNode, xml, UserImporter.ImportBehavior.BESTEFFORT);
+            if (!umgr.isAutoSave()) {
+                sImpl.save();
+            }
+
+            for (String user : users) {
+                if (umgr.getAuthorizable(user) == null) {
+                    umgr.createUser(user, user);
+                    createdUsers.add(user);
+                }
+            }
+            if (!umgr.isAutoSave()) {
+                sImpl.save();
+            }
+
+            Authorizable aShrimps = umgr.getAuthorizable("shrimps");
+            assertNotNull(aShrimps);
+            assertTrue(aShrimps.isGroup());
+
+            Group gShrimps = (Group) aShrimps;
+            for (String user : users) {
+                assertTrue(user + " should be member of " + gShrimps, gShrimps.isMember(umgr.getAuthorizable(user)));
+            }
+
+
+        } finally {
+            sImpl.refresh(false);
+            for (String user : createdUsers) {
+                Authorizable a = umgr.getAuthorizable(user);
+                if (a != null && !a.isGroup()) {
+                    a.remove();
+                }
+            }
+            if (!umgr.isAutoSave()) {
+                sImpl.save();
+            }
+            for (NodeIterator it = groupsNode.getNodes(); it.hasNext(); ) {
+                it.nextNode().remove();
+            }
+            if (!umgr.isAutoSave()) {
+                sImpl.save();
+            }
+        }
+    }
+
     private void doImport(NodeImpl target, String xml) throws IOException, SAXException, RepositoryException {
         InputStream in = new ByteArrayInputStream(xml.getBytes("UTF-8"));
         SessionImporter importer = new SessionImporter(target, sImpl,
@@ -1238,22 +1358,23 @@ public class UserImporterTest extends Ab
     //--------------------------------------------------------------------------
     private final class PseudoConfig extends ImportConfig {
 
-        private final ProtectedPropertyImporter ppi;
+        private final UserImporter userImporter;
 
         private PseudoConfig() {
-            this.ppi = createImporter();
+            this.userImporter = createImporter();
         }
 
         private PseudoConfig(int importBehavior) {
-            this.ppi = createImporter();
-            ((UserImporter) ppi).setImportBehavior(
+            this.userImporter = createImporter();
+            (userImporter).setImportBehavior(
                     ImportBehavior.nameFromValue(importBehavior));
         }
 
         @Override
-        public List<ProtectedPropertyImporter> getProtectedPropertyImporters() {
-            return Collections.singletonList(ppi);
+        public List<? extends ProtectedNodeImporter> getProtectedItemImporters() {
+            return Collections.singletonList(userImporter);
         }
+
     }
 
     private final class DummySession implements JackrabbitSession {

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/xml/AccessControlImporterTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/xml/AccessControlImporterTest.java?rev=987181&r1=987180&r2=987181&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/xml/AccessControlImporterTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/xml/AccessControlImporterTest.java Thu Aug 19 15:04:38 2010
@@ -19,16 +19,16 @@ package org.apache.jackrabbit.core.xml;
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlEntry;
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
-import org.apache.jackrabbit.api.security.user.UserManager;
 import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.api.security.user.UserManager;
 import org.apache.jackrabbit.commons.xml.ParsingContentHandler;
 import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.config.ImportConfig;
+import org.apache.jackrabbit.core.security.SecurityConstants;
 import org.apache.jackrabbit.core.security.authorization.AccessControlConstants;
 import org.apache.jackrabbit.core.security.principal.EveryonePrincipal;
 import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
-import org.apache.jackrabbit.core.security.SecurityConstants;
 import org.apache.jackrabbit.test.AbstractJCRTest;
 import org.apache.jackrabbit.test.NotExecutableException;
 import org.xml.sax.SAXException;
@@ -38,16 +38,17 @@ import javax.jcr.Node;
 import javax.jcr.NodeIterator;
 import javax.jcr.nodetype.ConstraintViolationException;
 import javax.jcr.security.AccessControlEntry;
+import javax.jcr.security.AccessControlList;
 import javax.jcr.security.AccessControlManager;
 import javax.jcr.security.AccessControlPolicy;
-import javax.jcr.security.Privilege;
 import javax.jcr.security.AccessControlPolicyIterator;
-import javax.jcr.security.AccessControlList;
+import javax.jcr.security.Privilege;
+
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.util.Arrays;
-import java.util.List;
 import java.util.Collections;
+import java.util.List;
 
 /**
  * <code>AccessControlImporterTest</code>: Testing import of resource based
@@ -279,7 +280,7 @@ public class AccessControlImporterTest e
             new ParsingContentHandler(ih).parse(in);
 
             assertTrue(target.hasNode("test"));
-            String path = target.getNode("test").getPath();    
+            String path = target.getNode("test").getPath();
 
             AccessControlManager acMgr = sImpl.getAccessControlManager();
             AccessControlPolicy[] policies = acMgr.getPolicies(path);
@@ -296,7 +297,7 @@ public class AccessControlImporterTest e
             assertEquals(acMgr.privilegeFromName(Privilege.JCR_WRITE), entry.getPrivileges()[0]);
 
             if(entry instanceof JackrabbitAccessControlEntry) {
-                assertTrue(((JackrabbitAccessControlEntry) entry).isAllow());                
+                assertTrue(((JackrabbitAccessControlEntry) entry).isAllow());
             }
 
         } finally {
@@ -596,7 +597,7 @@ public class AccessControlImporterTest e
     /**
      * With the default importer that isn't able to deal with ACEs the
      * policy will be created but any ACEs will be ignored.
-     * 
+     *
      * @throws Exception
      */
     public void testImportWithDefaultImporter() throws Exception {
@@ -635,7 +636,7 @@ public class AccessControlImporterTest e
         }
 
         @Override
-        public List<ProtectedNodeImporter> getProtectedNodeImporters() {
+        public List<? extends ProtectedNodeImporter> getProtectedItemImporters() {
             return Collections.singletonList(aci);
         }
     }



Mime
View raw message