You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by tr...@apache.org on 2015/09/30 20:34:46 UTC

svn commit: r1706119 [2/2] - in /jackrabbit/oak/branches/1.0: oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/ oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/ex...

Modified: jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java?rev=1706119&r1=1706118&r2=1706119&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java (original)
+++ jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java Wed Sep 30 18:34:45 2015
@@ -16,26 +16,11 @@
  */
 package org.apache.jackrabbit.oak.spi.security.authentication.external.impl;
 
-import java.io.ByteArrayInputStream;
-import java.math.BigDecimal;
-import java.security.Principal;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
-import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.jcr.Binary;
 import javax.jcr.RepositoryException;
-import javax.jcr.Value;
 import javax.jcr.ValueFactory;
 
 import org.apache.felix.scr.annotations.Activate;
@@ -43,23 +28,16 @@ import org.apache.felix.scr.annotations.
 import org.apache.felix.scr.annotations.ConfigurationPolicy;
 import org.apache.felix.scr.annotations.Service;
 import org.apache.jackrabbit.api.security.user.Authorizable;
-import org.apache.jackrabbit.api.security.user.Group;
-import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.api.security.user.UserManager;
 import org.apache.jackrabbit.commons.iterator.AbstractLazyIterator;
 import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
-import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalGroup;
-import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentity;
-import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityException;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProvider;
-import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityRef;
-import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalUser;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncContext;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncException;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncHandler;
-import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncResult;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncedIdentity;
-import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.basic.DefaultSyncConfig;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.basic.DefaultSyncContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -67,7 +45,7 @@ import org.slf4j.LoggerFactory;
  * {@code DefaultSyncHandler} implements an sync handler that synchronizes users and groups from an external identity
  * provider with the repository users.
  * <p/>
- * Please refer to {@link DefaultSyncConfig} for configuration options.
+ * Please refer to {@link DefaultSyncConfigImpl} for configuration options.
  */
 @Component(
         // note that the metatype information is generated from DefaultSyncConfig
@@ -82,16 +60,6 @@ public class DefaultSyncHandler implemen
     private static final Logger log = LoggerFactory.getLogger(DefaultSyncHandler.class);
 
     /**
-     * Name of the {@link ExternalIdentity#getExternalId()} property of a synchronized identity.
-     */
-    public static final String REP_EXTERNAL_ID = "rep:externalId";
-
-    /**
-     * Name of the property that stores the time when an identity was synced.
-     */
-    public static final String REP_LAST_SYNCED = "rep:lastSynced";
-
-    /**
      * internal configuration
      */
     private DefaultSyncConfig config;
@@ -112,10 +80,11 @@ public class DefaultSyncHandler implemen
         this.config = config;
     }
 
+    @SuppressWarnings("UnusedDeclaration")
     @Activate
     private void activate(Map<String, Object> properties) {
         ConfigurationParameters cfg = ConfigurationParameters.of(properties);
-        config = DefaultSyncConfig.of(cfg);
+        config = DefaultSyncConfigImpl.of(cfg);
     }
 
     /**
@@ -134,7 +103,7 @@ public class DefaultSyncHandler implemen
     @Override
     public SyncContext createContext(@Nonnull ExternalIdentityProvider idp, @Nonnull UserManager userManager,
                                      @Nonnull ValueFactory valueFactory) throws SyncException {
-        return new ContextImpl(idp, userManager, valueFactory);
+        return new DefaultSyncContext(config, idp, userManager, valueFactory);
     }
 
     /**
@@ -143,12 +112,13 @@ public class DefaultSyncHandler implemen
     @Override
     public SyncedIdentity findIdentity(@Nonnull UserManager userManager, @Nonnull String id)
             throws RepositoryException {
-        return createSyncedIdentity(userManager.getAuthorizable(id));
+        return DefaultSyncContext.createSyncedIdentity(userManager.getAuthorizable(id));
     }
 
     /**
      * {@inheritDoc}
      */
+    @Nonnull
     @Override
     public Iterator<SyncedIdentity> listIdentities(@Nonnull UserManager userManager) throws RepositoryException {
         final Iterator<Authorizable> iter = userManager.findAuthorizables("jcr:primaryType", null);
@@ -158,7 +128,7 @@ public class DefaultSyncHandler implemen
             protected SyncedIdentity getNext() {
                 while (iter.hasNext()) {
                     try {
-                        SyncedIdentity id = createSyncedIdentity(iter.next());
+                        SyncedIdentity id = DefaultSyncContext.createSyncedIdentity(iter.next());
                         if (id != null) {
                             return id;
                         }
@@ -171,640 +141,4 @@ public class DefaultSyncHandler implemen
             }
         };
     }
-
-    /**
-     * Creates a synced identity from the given authorizable.
-     * @param auth the authorizable
-     * @return the id
-     * @throws RepositoryException if an error occurrs
-     */
-    @CheckForNull
-    private static SyncedIdentityImpl createSyncedIdentity(@Nullable Authorizable auth) throws RepositoryException {
-        ExternalIdentityRef ref = auth == null ? null : getIdentityRef(auth);
-        if (ref == null) {
-            return null;
-        } else {
-            Value[] lmValues = auth.getProperty(REP_LAST_SYNCED);
-            long lastModified = -1;
-            if (lmValues != null && lmValues.length > 0) {
-                lastModified = lmValues[0].getLong();
-            }
-            return new SyncedIdentityImpl(auth.getID(), ref, auth.isGroup(), lastModified);
-        }
-    }
-
-    /**
-     * Internal implementation of the sync context
-     */
-    private class ContextImpl implements SyncContext {
-
-        private final ExternalIdentityProvider idp;
-
-        private final UserManager userManager;
-
-        private final ValueFactory valueFactory;
-
-        private boolean keepMissing;
-
-        private boolean forceUserSync;
-
-        private boolean forceGroupSync;
-
-        // we use the same wall clock for the entire context
-        private final long now;
-        private final Value nowValue;
-
-        private ContextImpl(ExternalIdentityProvider idp, UserManager userManager, ValueFactory valueFactory) {
-            this.idp = idp;
-            this.userManager = userManager;
-            this.valueFactory = valueFactory;
-
-            // initialize 'now'
-            final Calendar nowCal = Calendar.getInstance();
-            this.nowValue = valueFactory.createValue(nowCal);
-            this.now = nowCal.getTimeInMillis();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public void close() {
-            // nothing to do
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public boolean isKeepMissing() {
-            return keepMissing;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public SyncContext setKeepMissing(boolean keepMissing) {
-            this.keepMissing = keepMissing;
-            return this;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public boolean isForceUserSync() {
-            return forceUserSync;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public SyncContext setForceUserSync(boolean forceUserSync) {
-            this.forceUserSync = forceUserSync;
-            return this;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public boolean isForceGroupSync() {
-            return forceGroupSync;
-        }
-
-        public SyncContext setForceGroupSync(boolean forceGroupSync) {
-            this.forceGroupSync = forceGroupSync;
-            return this;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public SyncResult sync(@Nonnull ExternalIdentity identity) throws SyncException {
-            try {
-                DebugTimer timer = new DebugTimer();
-                SyncResultImpl ret;
-                boolean created = false;
-                if (identity instanceof ExternalUser) {
-                    User user = getAuthorizable(identity, User.class);
-                    timer.mark("find");
-                    if (user == null) {
-                        user = createUser((ExternalUser) identity);
-                        timer.mark("create");
-                        created = true;
-                    }
-                    ret = syncUser((ExternalUser) identity, user);
-                    timer.mark("sync");
-                } else if (identity instanceof ExternalGroup) {
-                    Group group = getAuthorizable(identity, Group.class);
-                    timer.mark("find");
-                    if (group == null) {
-                        group = createGroup((ExternalGroup) identity);
-                        timer.mark("create");
-                        created = true;
-                    }
-                    ret = syncGroup((ExternalGroup) identity, group);
-                    timer.mark("sync");
-                } else {
-                    throw new IllegalArgumentException("identity must be user or group but was: " + identity);
-                }
-                if (log.isDebugEnabled()) {
-                    log.debug("sync({}) -> {} {}", identity.getExternalId().getString(), identity.getId(), timer.getString());
-                }
-                if (created) {
-                    ret.setStatus(SyncResult.Status.ADD);
-                }
-                return ret;
-            } catch (RepositoryException e) {
-                throw new SyncException(e);
-            }
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public SyncResult sync(@Nonnull String id) throws SyncException {
-            try {
-                DebugTimer timer = new DebugTimer();
-                SyncResultImpl ret;
-                // find authorizable
-                Authorizable auth = userManager.getAuthorizable(id);
-                if (auth == null) {
-                    return new SyncResultImpl(new SyncedIdentityImpl(id, null, false, -1), SyncResult.Status.NO_SUCH_AUTHORIZABLE);
-                }
-                // check if we need to deal with this authorizable
-                ExternalIdentityRef ref = getIdentityRef(auth);
-                if (ref == null || !idp.getName().equals(ref.getProviderName())) {
-                    return new SyncResultImpl(new SyncedIdentityImpl(id, null, false, -1), SyncResult.Status.FOREIGN);
-                }
-
-                if (auth instanceof Group) {
-                    Group group = (Group) auth;
-                    ExternalGroup external = idp.getGroup(id);
-                    timer.mark("retrieve");
-                    if (external == null) {
-                        SyncedIdentityImpl syncId = createSyncedIdentity(auth);
-                        if (group.getDeclaredMembers().hasNext()) {
-                            log.info("won't remove local group with members: {}", id);
-                            ret = new SyncResultImpl(syncId, SyncResult.Status.NOP);
-                        } else if (!keepMissing) {
-                            auth.remove();
-                            log.debug("removing authorizable '{}' that no longer exists on IDP {}", id, idp.getName());
-                            timer.mark("remove");
-                            ret = new SyncResultImpl(syncId, SyncResult.Status.DELETE);
-                        } else {
-                            ret = new SyncResultImpl(syncId, SyncResult.Status.MISSING);
-                            log.info("external identity missing for {}, but purge == false.", id);
-                        }
-                    } else {
-                        ret = syncGroup(external, group);
-                        timer.mark("sync");
-                    }
-                } else {
-                    ExternalUser external = idp.getUser(id);
-                    timer.mark("retrieve");
-                    if (external == null) {
-                        SyncedIdentityImpl syncId = createSyncedIdentity(auth);
-                        if (!keepMissing) {
-                            auth.remove();
-                            log.debug("removing authorizable '{}' that no longer exists on IDP {}", id, idp.getName());
-                            timer.mark("remove");
-                            ret = new SyncResultImpl(syncId, SyncResult.Status.DELETE);
-                        } else {
-                            ret = new SyncResultImpl(syncId, SyncResult.Status.MISSING);
-                            log.info("external identity missing for {}, but purge == false.", id);
-                        }
-                    } else {
-                        ret = syncUser(external, (User) auth);
-                        timer.mark("sync");
-                    }
-                }
-                if (log.isDebugEnabled()) {
-                    log.debug("sync({}) -> {} {}", id, ref.getString(), timer.getString());
-                }
-                return ret;
-            } catch (RepositoryException e) {
-                throw new SyncException(e);
-            } catch (ExternalIdentityException e) {
-                throw new SyncException(e);
-            }
-        }
-
-        /**
-         * Retrieves the repository authorizable that corresponds to the given external identity
-         * @param external the external identity
-         * @param type the authorizable type
-         * @return the repository authorizable or {@code null} if not found.
-         * @throws RepositoryException if an error occurs.
-         * @throws SyncException if the repository contains a colliding authorizable with the same name.
-         */
-        @CheckForNull
-        private <T extends Authorizable> T getAuthorizable(@Nonnull ExternalIdentity external, Class<T> type)
-                throws RepositoryException, SyncException {
-            Authorizable authorizable = userManager.getAuthorizable(external.getId());
-            if (authorizable == null) {
-                authorizable = userManager.getAuthorizable(external.getPrincipalName());
-            }
-            if (authorizable == null) {
-                return null;
-            } else if (type.isInstance(authorizable)) {
-                //noinspection unchecked
-                return (T) authorizable;
-            } else {
-                log.error("Unable to process external {}: {}. Colliding authorizable exists in repository.", type.getSimpleName(), external.getId());
-                throw new SyncException("Unexpected authorizable: " + authorizable);
-            }
-        }
-
-        /**
-         * Creates a new repository user for the given external one.
-         * Note that this method only creates the authorizable but does not perform any synchronization.
-         *
-         * @param externalUser the external user
-         * @return the repository user
-         * @throws RepositoryException if an error occurs
-         */
-        @CheckForNull
-        private User createUser(ExternalUser externalUser) throws RepositoryException {
-            Principal principal = new PrincipalImpl(externalUser.getPrincipalName());
-            User user = userManager.createUser(
-                    externalUser.getId(),
-                    null,
-                    principal,
-                    joinPaths(config.user().getPathPrefix(), externalUser.getIntermediatePath())
-            );
-            user.setProperty(REP_EXTERNAL_ID, valueFactory.createValue(externalUser.getExternalId().getString()));
-            return user;
-        }
-
-        /**
-         * Creates a new repository group for the given external one.
-         * Note that this method only creates the authorizable but does not perform any synchronization.
-         *
-         * @param externalGroup the external group
-         * @return the repository group
-         * @throws RepositoryException if an error occurs
-         */
-        @CheckForNull
-        private Group createGroup(ExternalGroup externalGroup) throws RepositoryException {
-            Principal principal = new PrincipalImpl(externalGroup.getPrincipalName());
-            Group group = userManager.createGroup(
-                    externalGroup.getId(),
-                    principal,
-                    joinPaths(config.group().getPathPrefix(), externalGroup.getIntermediatePath())
-            );
-            group.setProperty(REP_EXTERNAL_ID, valueFactory.createValue(externalGroup.getExternalId().getString()));
-            return group;
-        }
-
-
-        private SyncResultImpl syncUser(@Nonnull ExternalUser external, @Nonnull User user) throws RepositoryException {
-            // first check if user is expired
-            if (!forceUserSync && !isExpired(user, config.user().getExpirationTime(), "Properties")) {
-                SyncedIdentityImpl syncId = createSyncedIdentity(user);
-                return new SyncResultImpl(syncId, SyncResult.Status.NOP);
-            }
-
-            // synchronize the properties
-            syncProperties(external, user, config.user().getPropertyMapping());
-
-            // synchronize auto-group membership
-            applyMembership(user, config.user().getAutoMembership());
-
-            if (isExpired(user, config.user().getMembershipExpirationTime(), "Membership")) {
-                // synchronize external memberships
-                syncMembership(external, user, config.user().getMembershipNestingDepth());
-            }
-
-            // finally "touch" the sync property
-            user.setProperty(REP_LAST_SYNCED, nowValue);
-            SyncedIdentityImpl syncId = createSyncedIdentity(user);
-            return new SyncResultImpl(syncId, SyncResult.Status.UPDATE);
-        }
-
-        private SyncResultImpl syncGroup(ExternalGroup external, Group group) throws RepositoryException {
-            // first check if user is expired
-            if (!forceGroupSync && !isExpired(group, config.group().getExpirationTime(), "Properties")) {
-                SyncedIdentityImpl syncId = createSyncedIdentity(group);
-                return new SyncResultImpl(syncId, SyncResult.Status.NOP);
-            }
-
-            // synchronize the properties
-            syncProperties(external, group, config.group().getPropertyMapping());
-
-            // synchronize auto-group membership
-            applyMembership(group, config.group().getAutoMembership());
-
-            // finally "touch" the sync property
-            group.setProperty(REP_LAST_SYNCED, nowValue);
-            SyncedIdentityImpl syncId = createSyncedIdentity(group);
-            return new SyncResultImpl(syncId, SyncResult.Status.UPDATE);
-        }
-
-        /**
-         * Recursively sync the memberships of an authorizable up-to the specified depth. If the given depth
-         * is equal or less than 0, no syncing is performed.
-         *
-         * @param external the external identity
-         * @param auth the authorizable
-         * @param depth recursion depth.
-         * @throws RepositoryException
-         */
-        private void syncMembership(ExternalIdentity external, Authorizable auth, long depth)
-                throws RepositoryException {
-            if (depth <= 0) {
-                return;
-            }
-            if (log.isDebugEnabled()) {
-                log.debug("Syncing membership '{}' -> '{}'", external.getExternalId().getString(), auth.getID());
-            }
-
-            final DebugTimer timer = new DebugTimer();
-            Iterable<ExternalIdentityRef> externalGroups;
-            try {
-                externalGroups = external.getDeclaredGroups();
-            } catch (ExternalIdentityException e) {
-                log.error("Error while retrieving external declared groups for '{}'", external.getId(), e);
-                return;
-            }
-            timer.mark("fetching");
-
-            // first get the set of the existing groups that are synced ones
-            Map<String, Group> declaredExternalGroups = new HashMap<String, Group>();
-            Iterator<Group> grpIter = auth.declaredMemberOf();
-            while (grpIter.hasNext()) {
-                Group grp = grpIter.next();
-                if (isSameIDP(grp)) {
-                    declaredExternalGroups.put(grp.getID(), grp);
-                }
-            }
-            timer.mark("reading");
-
-            for (ExternalIdentityRef ref: externalGroups) {
-                log.debug("- processing membership {}", ref.getId());
-                // get group
-                ExternalGroup extGroup;
-                try {
-                    extGroup = (ExternalGroup) idp.getIdentity(ref);
-                } catch (ClassCastException e) {
-                    // this should really not be the case, so catching the CCE is ok here.
-                    log.warn("External identity '{}' is not a group, but should be one.", ref.getString());
-                    continue;
-                } catch (ExternalIdentityException e) {
-                    log.warn("Unable to retrieve external group '{}' from provider.", ref.getString(), e);
-                    continue;
-                }
-                if (extGroup == null) {
-                    log.warn("External group for ref '{}' could not be retrieved from provider.", ref);
-                    continue;
-                }
-                log.debug("- idp returned '{}'", extGroup.getId());
-
-                Group grp;
-                try {
-                    grp = (Group) userManager.getAuthorizable(extGroup.getId());
-                } catch (ClassCastException e) {
-                    // this should really not be the case, so catching the CCE is ok here.
-                    log.warn("Authorizable '{}' is not a group, but should be one.", extGroup.getId());
-                    continue;
-                }
-                log.debug("- user manager returned '{}'", grp);
-
-                if (grp == null) {
-                    grp = createGroup(extGroup);
-                    log.debug("- created new group");
-                }
-                syncGroup(extGroup, grp);
-
-                // ensure membership
-                grp.addMember(auth);
-                log.debug("- added '{}' as member to '{}'", auth, grp);
-
-                // remember the declared group
-                declaredExternalGroups.remove(grp.getID());
-
-                // recursively apply further membership
-                if (depth > 1) {
-                    log.debug("- recursively sync group membership of '{}' (depth = {}).", grp.getID(), depth);
-                    syncMembership(extGroup, grp, depth - 1);
-                } else {
-                    log.debug("- group nesting level for '{}' reached", grp.getID());
-                }
-            }
-            timer.mark("adding");
-            // remove us from the lost membership groups
-            for (Group grp: declaredExternalGroups.values()) {
-                grp.removeMember(auth);
-                log.debug("- removing member '{}' for group '{}'", auth.getID(), grp.getID());
-            }
-            if (log.isDebugEnabled()) {
-                timer.mark("removing");
-                log.debug("syncMembership({}) {}", external.getId(), timer.getString());
-            }
-        }
-
-        /**
-         * Ensures that the given authorizable is member of the specific groups. Note that it does not create groups
-         * if missing, nor remove memberships of groups not in the given set.
-         * @param member the authorizable
-         * @param groups set of groups.
-         */
-        private void applyMembership(Authorizable member, Set<String> groups) throws RepositoryException {
-            for (String groupName: groups) {
-                Authorizable group = userManager.getAuthorizable(groupName);
-                if (group == null) {
-                    log.warn("Unable to apply auto-membership to {}. No such group: {}", member.getID(), groupName);
-                } else if (group instanceof Group) {
-                    ((Group) group).addMember(member);
-                } else {
-                    log.warn("Unable to apply auto-membership to {}. Authorizable '{}' is not a group.", member.getID(), groupName);
-                }
-            }
-        }
-
-        /**
-         * Syncs the properties specified in the {@code mapping} from the external identity to the given authorizable.
-         * Note that this method does not check for value equality and just blindly copies or deletes the properties.
-         *
-         * @param ext external identity
-         * @param auth the authorizable
-         * @param mapping the property mapping
-         * @throws RepositoryException if an error occurs
-         */
-        private void syncProperties(ExternalIdentity ext, Authorizable auth, Map<String, String> mapping)
-                throws RepositoryException {
-            Map<String, ?> properties = ext.getProperties();
-            for (Map.Entry<String, String> entry: mapping.entrySet()) {
-                String relPath = entry.getKey();
-                String name = entry.getValue();
-                Object obj = properties.get(name);
-                if (obj == null) {
-                    int nameLen = name.length();
-                    if (nameLen > 1 && name.charAt(0) == '"' && name.charAt(nameLen-1) == '"') {
-                        auth.setProperty(relPath, valueFactory.createValue(name.substring(1, nameLen - 1)));
-                    } else {
-                        auth.removeProperty(relPath);
-                    }
-                } else {
-                    if (obj instanceof Collection) {
-                        auth.setProperty(relPath, createValues((Collection) obj));
-                    } else if (obj instanceof byte[] || obj instanceof char[]) {
-                        auth.setProperty(relPath, createValue(obj));
-                    } else if (obj instanceof Object[]) {
-                        auth.setProperty(relPath, createValues(Arrays.asList((Object[]) obj)));
-                    } else {
-                        auth.setProperty(relPath, createValue(obj));
-                    }
-                }
-            }
-        }
-
-        /**
-         * Checks if the given authorizable needs syncing based on the {@link #REP_LAST_SYNCED} property.
-         * @param auth the authorizable to check
-         * @param expirationTime the expiration time to compare to.
-         * @param type debug message type
-         * @return {@code true} if the authorizable needs sync
-         */
-        private boolean isExpired(Authorizable auth, long expirationTime, String type) throws RepositoryException {
-            Value[] values = auth.getProperty(REP_LAST_SYNCED);
-            if (values == null || values.length == 0) {
-                if (log.isDebugEnabled()) {
-                    log.debug("{} of {} '{}' need sync. " + REP_LAST_SYNCED + " not set.",
-                            type, auth.isGroup() ? "group" : "user", auth.getID());
-                }
-                return true;
-            } else if (now - values[0].getLong() > expirationTime) {
-                if (log.isDebugEnabled()) {
-                    log.debug("{} of {} '{}' need sync. " + REP_LAST_SYNCED + " expired ({} > {})",
-                            type, auth.isGroup() ? "group" : "user", auth.getID(), now - values[0].getLong(), expirationTime);
-                }
-                return true;
-            } else {
-                if (log.isDebugEnabled()) {
-                    log.debug("{} of {} '{}' do not need sync.", type, auth.isGroup() ? "group" : "user", auth.getID());
-                }
-                return false;
-            }
-        }
-
-        /**
-         * Creates a new JCR value of the given object, checking the internal type.
-         * @param v the value
-         * @return the JCR value or null
-         * @throws RepositoryException if an error occurs
-         */
-        @CheckForNull
-        private Value createValue(@Nullable Object v) throws RepositoryException {
-            if (v == null) {
-                return null;
-            } else if (v instanceof Boolean) {
-                return valueFactory.createValue((Boolean) v);
-            } else if (v instanceof Byte || v instanceof Short || v instanceof Integer || v instanceof Long) {
-                return valueFactory.createValue(((Number) v).longValue());
-            } else if (v instanceof Float || v instanceof Double) {
-                return valueFactory.createValue(((Number) v).doubleValue());
-            } else if (v instanceof BigDecimal) {
-                return valueFactory.createValue((BigDecimal) v);
-            } else if (v instanceof Calendar) {
-                return valueFactory.createValue((Calendar) v);
-            } else if (v instanceof Date) {
-                Calendar cal = Calendar.getInstance();
-                cal.setTime((Date) v);
-                return valueFactory.createValue(cal);
-            } else if (v instanceof byte[]) {
-                Binary bin = valueFactory.createBinary(new ByteArrayInputStream((byte[])v));
-                return valueFactory.createValue(bin);
-            } else if (v instanceof char[]) {
-                return valueFactory.createValue(new String((char[]) v));
-            } else {
-                return valueFactory.createValue(String.valueOf(v));
-            }
-        }
-
-        /**
-         * Creates an array of JCR values based on the type.
-         * @param propValues the given values
-         * @return and array of JCR values
-         * @throws RepositoryException if an error occurs
-         */
-        @CheckForNull
-        private Value[] createValues(Collection<?> propValues) throws RepositoryException {
-            List<Value> values = new ArrayList<Value>();
-            for (Object obj : propValues) {
-                Value v = createValue(obj);
-                if (v != null) {
-                    values.add(v);
-                }
-            }
-            return values.toArray(new Value[values.size()]);
-        }
-
-        /**
-         * Checks if the given authorizable was synced from the same IDP by comparing the IDP name of the
-         * {@value #REP_EXTERNAL_ID} property.
-         *
-         * todo: allow multiple IDPs on 1 authorizable
-         *
-         * @param auth the authorizable.
-         * @return {@code true} if same IDP.
-         */
-        private boolean isSameIDP(@Nullable Authorizable auth) throws RepositoryException {
-            ExternalIdentityRef ref = getIdentityRef(auth);
-            return ref != null && idp.getName().equals(ref.getProviderName());
-        }
-
-    }
-
-    /**
-     * Retrieves the external identity ref from the authorizable
-     * @param auth the authorizable
-     * @return the ref
-     * @throws RepositoryException if an error occurs
-     */
-    @CheckForNull
-    private static ExternalIdentityRef getIdentityRef(@Nullable Authorizable auth) throws RepositoryException {
-        if (auth == null) {
-            return null;
-        }
-        Value[] v = auth.getProperty(REP_EXTERNAL_ID);
-        if (v == null || v.length == 0) {
-            return null;
-        }
-        return ExternalIdentityRef.fromString(v[0].getString());
-    }
-
-    /**
-     * Robust relative path concatenation.
-     * @param paths relative paths
-     * @return the concatenated path
-     */
-    private static String joinPaths(String... paths) {
-        StringBuilder result = new StringBuilder();
-        for (String path: paths) {
-            if (path != null && !path.isEmpty()) {
-                int i0 = 0;
-                int i1 = path.length();
-                while (i0 < i1 && path.charAt(i0) == '/') {
-                    i0++;
-                }
-                while (i1 > i0 && path.charAt(i1-1) == '/') {
-                    i1--;
-                }
-                if (i1 > i0) {
-                    if (result.length() > 0) {
-                        result.append('/');
-                    }
-                    result.append(path.substring(i0, i1));
-                }
-            }
-        }
-        return result.length() == 0 ? null : result.toString();
-    }
-
 }
\ No newline at end of file

Modified: jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/SyncMBeanImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/SyncMBeanImpl.java?rev=1706119&r1=1706118&r2=1706119&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/SyncMBeanImpl.java (original)
+++ jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/SyncMBeanImpl.java Wed Sep 30 18:34:45 2015
@@ -46,8 +46,8 @@ import org.apache.jackrabbit.oak.spi.sec
 import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncManager;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncResult;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncedIdentity;
-import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.SyncResultImpl;
-import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.SyncedIdentityImpl;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.basic.DefaultSyncResultImpl;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.basic.DefaultSyncedIdentity;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -219,8 +219,8 @@ public class SyncMBeanImpl implements Sy
                         systemSession.save();
                         list.add(getJSONString(r));
                     } else {
-                        SyncResult r = new SyncResultImpl(
-                                new SyncedIdentityImpl("", ref, false, -1),
+                        SyncResult r = new DefaultSyncResultImpl(
+                                new DefaultSyncedIdentity("", ref, false, -1),
                                 SyncResult.Status.NO_SUCH_IDENTITY
                         );
                         list.add(getJSONString(r));

Modified: jackrabbit/oak/branches/1.0/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleFactoryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleFactoryTest.java?rev=1706119&r1=1706118&r2=1706119&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleFactoryTest.java (original)
+++ jackrabbit/oak/branches/1.0/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleFactoryTest.java Wed Sep 30 18:34:45 2015
@@ -37,7 +37,7 @@ import org.apache.jackrabbit.oak.Abstrac
 import org.apache.jackrabbit.oak.Oak;
 import org.apache.jackrabbit.oak.api.ContentSession;
 import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
-import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncConfig;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.basic.DefaultSyncConfig;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncHandler;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalIDPManagerImpl;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModule;

Modified: jackrabbit/oak/branches/1.0/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTestBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTestBase.java?rev=1706119&r1=1706118&r2=1706119&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTestBase.java (original)
+++ jackrabbit/oak/branches/1.0/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTestBase.java Wed Sep 30 18:34:45 2015
@@ -31,7 +31,7 @@ import org.apache.jackrabbit.api.securit
 import org.apache.jackrabbit.api.security.user.UserManager;
 import org.apache.jackrabbit.oak.AbstractSecurityTest;
 import org.apache.jackrabbit.oak.Oak;
-import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncConfig;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.basic.DefaultSyncConfig;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncHandler;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalIDPManagerImpl;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModule;

Modified: jackrabbit/oak/branches/1.0/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginTestBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginTestBase.java?rev=1706119&r1=1706118&r2=1706119&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginTestBase.java (original)
+++ jackrabbit/oak/branches/1.0/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginTestBase.java Wed Sep 30 18:34:45 2015
@@ -37,7 +37,7 @@ import org.apache.jackrabbit.oak.securit
 import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProvider;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalLoginModuleTestBase;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalUser;
-import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncConfig;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.basic.DefaultSyncConfig;
 import org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfiguration;
 import org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider;
 import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;