public void processReferences()

in jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImporter.java [371:545]


    public void processReferences() throws RepositoryException {
        if (!initialized) {
            throw new IllegalStateException("Not initialized");
        }

        // assert that user manager is isn't in auto-save mode
        if (userManager.isAutoSave()) {
            userManager.autoSave(false);
        }
        try {
            List<Object> processed = new ArrayList<Object>();
            for (Iterator<Object> it = referenceTracker.getProcessedReferences(); it.hasNext();) {
                Object reference = it.next();
                if (reference instanceof Membership) {
                    Authorizable a = userManager.getAuthorizable(((Membership) reference).groupId);
                    if (a == null || !a.isGroup()) {
                        throw new RepositoryException(((Membership) reference).groupId + " does not represent a valid group.");
                    }

                    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();) {
                        Authorizable dm = declMembers.next();
                        toRemove.put(dm.getID(), dm);
                    }

                    List<Authorizable> toAdd = new ArrayList<Authorizable>();
                    final List<Membership.Member> nonExisting = new ArrayList<Membership.Member>();

                    for (Membership.Member member : ((Membership) reference).members) {
                        NodeId remapped = referenceTracker.getMappedId(member.id);
                        NodeId id = (remapped == null) ? member.id : remapped;

                        Authorizable authorz = null;
                        try {
                            NodeImpl n = ((SessionImpl) session).getNodeById(id);
                            authorz = userManager.getAuthorizable(n);
                        } catch (RepositoryException e) {
                            // no such node or failed to retrieve authorizable
                            // warning is logged below.
                        }
                        if (authorz != null) {
                            if (toRemove.remove(authorz.getID()) == null) {
                                toAdd.add(authorz);
                            } // else: no need to remove from rep:members
                        } else {
                            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(member);
                            }
                        }
                    }

                    // 2. adjust members of the group
                    for (Authorizable m : toRemove.values()) {
                        if (!gr.removeMember(m)) {
                            handleFailure("Failed remove existing member (" + m + ") from " + gr);
                        }
                    }
                    for (Authorizable m : toAdd) {
                        if (!gr.addMember(m)) {
                            handleFailure("Failed add member (" + m + ") to " + gr);
                        }
                    }

                    // 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();

                        if (userManager.hasMemberSplitSize()) {
                            userManager.performProtectedOperation((SessionImpl) session, new SessionWriteOperation<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);
                        }
                    }

                    processed.add(reference);

                } else if (reference instanceof Impersonators) {
                    Authorizable a = userManager.getAuthorizable(((Impersonators) reference).userId);
                    if (a == null || a.isGroup()) {
                        throw new RepositoryException(((Impersonators) reference).userId + " does not represent a valid user.");
                    }

                    Impersonation imp = ((User) a).getImpersonation();

                    // 1. collect principals to add and to remove.
                    Map<String, Principal> toRemove = new HashMap<String, Principal>();
                    for (PrincipalIterator pit = imp.getImpersonators(); pit.hasNext();) {
                        Principal princ = pit.nextPrincipal();
                        toRemove.put(princ.getName(), princ);
                    }

                    List<Principal> toAdd = new ArrayList<Principal>();
                    Value[] vs = ((Impersonators) reference).values;
                    for (Value v : vs) {
                        String princName = v.getString();
                        if (toRemove.remove(princName) == null) {
                            // add it to the list of new impersonators to be added.
                            toAdd.add(new PrincipalImpl(princName));
                        } // else: no need to revoke impersonation for the given principal.
                    }

                    // 2. adjust set of impersonators
                    for (Principal princ : toRemove.values()) {
                        if (!imp.revokeImpersonation(princ)) {
                            handleFailure("Failed to revoke impersonation for " + princ.getName() + " on " + a);
                        }
                    }
                    for (Principal princ : toAdd) {
                        if (!imp.grantImpersonation(princ)) {
                            handleFailure("Failed to grant impersonation for " + princ.getName() + " on " + a);
                        }
                    }
                    // NOTE: no best effort handling so far. (TODO)

                    processed.add(reference);
                }
            }
            // successfully processed this entry of the reference tracker
            // -> remove from the reference tracker.
            referenceTracker.removeReferences(processed);
        } finally {
            // reset the autosave mode of the user manager in order to restore
            // the original state.
            if (resetAutoSave) {
                userManager.autoSave(true);
            }
        }
    }