Index: oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/SyncRuntimeException.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/SyncRuntimeException.java	(revision )
+++ oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/SyncRuntimeException.java	(revision )
@@ -0,0 +1,30 @@
+/*
+ * 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.oak.spi.security.authentication.external.impl.jmx;
+
+import javax.annotation.Nonnull;
+
+class SyncRuntimeException extends RuntimeException {
+
+    public SyncRuntimeException(@Nonnull String message) {
+        super(message);
+    }
+
+    public SyncRuntimeException(@Nonnull String message, @Nonnull Throwable throwable) {
+        super(message, throwable);
+    }
+}
\ No newline at end of file
Index: oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/SyncMBeanImpl.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/SyncMBeanImpl.java	(revision 1708645)
+++ oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/SyncMBeanImpl.java	(revision )
@@ -21,7 +21,6 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
-
 import javax.annotation.Nonnull;
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
@@ -57,6 +56,9 @@
 
     private static final Logger log = LoggerFactory.getLogger(SyncMBeanImpl.class);
 
+    private static final String ERROR_CREATE_DELEGATEE = "Unable to create delegatee";
+    private static final String ERROR_SYNC_USER = "Error while syncing user {}";
+
     private final Repository repository;
 
     private final SyncManager syncManager;
@@ -81,19 +83,15 @@
         SyncHandler handler = syncManager.getSyncHandler(syncName);
         if (handler == null) {
             log.error("No sync manager available for name {}.", syncName);
-            throw new IllegalArgumentException("No sync manager available for name " + syncName);
+            throw new SyncRuntimeException("No sync manager available for name " + syncName);
         }
         ExternalIdentityProvider idp = idpManager.getProvider(idpName);
         if (idp == null) {
             log.error("No idp available for name", idpName);
-            throw new IllegalArgumentException("No idp manager available for name " + idpName);
+            throw new SyncRuntimeException("No idp manager available for name " + idpName);
         }
-        try {
-            return new Delegatee(handler, idp);
+        return new Delegatee(handler, idp);
-        } catch (SyncException e) {
-            throw new IllegalArgumentException("Unable to create delegatee", e);
-        }
+    }
-    }
 
     private final class Delegatee {
 
@@ -107,7 +105,7 @@
 
         private Session systemSession;
 
-        private Delegatee(@Nonnull SyncHandler handler, @Nonnull ExternalIdentityProvider idp) throws SyncException {
+        private Delegatee(@Nonnull SyncHandler handler, @Nonnull ExternalIdentityProvider idp) {
             this.handler = handler;
             this.idp = idp;
             try {
@@ -123,13 +121,21 @@
                     }
                 });
             } catch (PrivilegedActionException e) {
-                throw new SyncException(e);
+                throw new SyncRuntimeException(ERROR_CREATE_DELEGATEE, e);
             }
+
             try {
-                context = handler.createContext(idp, userMgr = ((JackrabbitSession) systemSession).getUserManager(), systemSession.getValueFactory());
-            } catch (Exception e) {
+                if (!(systemSession instanceof JackrabbitSession)) {
+                    throw new SyncRuntimeException("Unable to create SyncContext: JackrabbitSession required.");
+                }
+                userMgr = ((JackrabbitSession) systemSession).getUserManager();
+                context = handler.createContext(idp, userMgr, systemSession.getValueFactory());
+            } catch (RepositoryException e) {
                 systemSession.logout();
-                throw new SyncException(e);
+                throw new SyncRuntimeException(ERROR_CREATE_DELEGATEE, e);
+            } catch (SyncException e) {
+                systemSession.logout();
+                throw new SyncRuntimeException(ERROR_CREATE_DELEGATEE, e);
             }
 
             log.info("Created delegatee for SyncMBean with session: {} {}", systemSession, systemSession.getUserID());
@@ -153,17 +159,15 @@
             context.setKeepMissing(!purge)
                     .setForceGroupSync(true)
                     .setForceUserSync(true);
-            List<String> result = new ArrayList<String>();
+            List<String> list = new ArrayList<String>();
             for (String userId: userIds) {
                 try {
-                    SyncResult r = context.sync(userId);
-                    systemSession.save();
-                    result.add(getJSONString(r));
-                } catch (Exception e) {
-                    log.warn("Error while syncing user {}", userId, e);
+                    list(list, syncUser(userId));
+                } catch (SyncException e) {
+                    log.warn(ERROR_SYNC_USER, userId, e);
                 }
             }
-            return result.toArray(new String[result.size()]);
+            return list.toArray(new String[list.size()]);
         }
 
         /**
@@ -181,11 +185,9 @@
                     SyncedIdentity id = iter.next();
                     if (isMyIDP(id)) {
                         try {
-                            SyncResult r = context.sync(id.getId());
-                            systemSession.save();
-                            list.add(getJSONString(r));
-                        } catch (Exception e) {
-                            log.error("Error while syncing user {}", id, e);
+                            list(list, syncUser(id.getId()));
+                        } catch (SyncException e) {
+                            log.error(ERROR_SYNC_USER, id, e);
                             list.add(getJSONString(id, e));
                         }
                     }
@@ -207,23 +209,22 @@
                 ExternalIdentityRef ref = ExternalIdentityRef.fromString(externalId);
                 try {
                     ExternalIdentity id = idp.getIdentity(ref);
+                    SyncResult r;
                     if (id != null) {
-                        SyncResult r = context.sync(id);
-                        systemSession.save();
-                        list.add(getJSONString(r));
+                        r = syncUser(id);
                     } else {
-                        SyncResult r = new DefaultSyncResultImpl(
+                        r = new DefaultSyncResultImpl(
                                 new DefaultSyncedIdentity("", ref, false, -1),
                                 SyncResult.Status.NO_SUCH_IDENTITY
                         );
-                        list.add(getJSONString(r));
                     }
+                    list(list, r);
                 } catch (ExternalIdentityException e) {
                     log.warn("error while fetching the external identity {}", externalId, e);
-                    list.add(getJSONString(ref, e));
-                } catch (Exception e) {
-                    log.error("Error while syncing user {}", ref, e);
-                    list.add(getJSONString(ref, e));
+                    list(list, ref, e);
+                } catch (SyncException e) {
+                    log.error(ERROR_SYNC_USER, ref, e);
+                    list(list, ref, e);
                 }
             }
             return list.toArray(new String[list.size()]);
@@ -241,8 +242,7 @@
                 while (iter.hasNext()) {
                     ExternalUser user = iter.next();
                     try {
-                        SyncResult r = context.sync(user);
-                        systemSession.save();
+                        SyncResult r = syncUser(user);
                         if (r.getIdentity() == null) {
                             r = new DefaultSyncResultImpl(
                                     new DefaultSyncedIdentity(user.getId(), user.getExternalId(), false, -1),
@@ -252,15 +252,15 @@
                         } else {
                             log.info("synced {}", r.getIdentity());
                         }
-                        list.add(getJSONString(r));
-                    } catch (Exception e) {
-                        log.error("Error while syncing user {}", user, e);
-                        list.add(getJSONString(user.getExternalId(), e));
+                        list(list, r);
+                    } catch (SyncException e) {
+                        log.error(ERROR_SYNC_USER, user, e);
+                        list(list, user.getExternalId(), e);
                     }
                 }
                 return list.toArray(new String[list.size()]);
             } catch (ExternalIdentityException e) {
-                throw new IllegalArgumentException("Unable to retrieve external users", e);
+                throw new SyncRuntimeException("Unable to retrieve external users", e);
             }
         }
 
@@ -277,11 +277,11 @@
                     if (isMyIDP(id)) {
                         try {
                             ExternalIdentityRef ref = id.getExternalIdRef();
-                            ExternalIdentity extId = ref == null ? null : idp.getIdentity(ref);
+                            ExternalIdentity extId = (ref == null) ? null : idp.getIdentity(ref);
                             if (extId == null) {
                                 list.add(id.getId());
                             }
-                        } catch (Exception e) {
+                        } catch (ExternalIdentityException e) {
                             log.error("Error while fetching external identity {}", id, e);
                         }
                     }
@@ -298,27 +298,56 @@
         @Nonnull
         public String[] purgeOrphanedUsers() {
             context.setKeepMissing(false);
-            List<String> result = new ArrayList<String>();
+            List<String> list = new ArrayList<String>();
             for (String userId: listOrphanedUsers()) {
                 try {
-                    SyncResult r = context.sync(userId);
-                    systemSession.save();
-                    result.add(getJSONString(r));
-                } catch (Exception e) {
-                    log.warn("Error while syncing user {}", userId, e);
+                    list(list, syncUser(userId));
+                } catch (SyncException e) {
+                    log.warn(ERROR_SYNC_USER, userId, e);
                 }
             }
-            return result.toArray(new String[result.size()]);
+            return list.toArray(new String[list.size()]);
         }
 
         private boolean isMyIDP(@Nonnull SyncedIdentity id) {
-            String providerName = id.getExternalIdRef() == null
-                    ? null
-                    : id.getExternalIdRef().getProviderName();
+            ExternalIdentityRef ref = id.getExternalIdRef();
+            String providerName = (ref == null) ? null : ref.getProviderName();
             return providerName != null && (providerName.isEmpty() || providerName.equals(idp.getName()));
         }
+
+
+        @Nonnull
+        private SyncResult syncUser(@Nonnull ExternalIdentity id) throws SyncException {
+            try {
+                SyncResult r = context.sync(id);
+                systemSession.save();
+                return r;
+            } catch (RepositoryException e) {
+                throw new SyncException(e);
-    }
+            }
+        }
 
+        @Nonnull
+        private SyncResult syncUser(@Nonnull String userId) throws SyncException {
+            try {
+                SyncResult r = context.sync(userId);
+                systemSession.save();
+                return r;
+            } catch (RepositoryException e) {
+                throw new SyncException(e);
+            }
+        }
+    }
+
+    private static void list(@Nonnull List<String> list, @Nonnull SyncResult r) {
+        list.add(getJSONString(r));
+    }
+
+    private static void list(@Nonnull List<String> list, @Nonnull ExternalIdentityRef idRef, @Nonnull Exception e) {
+        list.add(getJSONString(idRef, e));
+    }
+
+    @Nonnull
     private static String getJSONString(@Nonnull SyncResult r) {
         String op;
         switch (r.getStatus()) {
@@ -356,14 +385,17 @@
         return String.format("{op:\"%s\",uid:%s,eid:%s}", op, uid, eid);
     }
 
+    @Nonnull
     private static String getJSONString(@Nonnull SyncedIdentity id, @Nonnull Exception e) {
         String uid = JsonUtil.getJsonString(id.getId());
-        String eid = (id.getExternalIdRef() == null) ? "\"\"" : JsonUtil.getJsonString(id.getExternalIdRef().getString());
+        ExternalIdentityRef ref = id.getExternalIdRef();
+        String eid = (ref == null) ? "\"\"" : JsonUtil.getJsonString(ref.getString());
         String msg = JsonUtil.getJsonString(e.toString());
         return String.format("{op:\"ERR\",uid:%s,eid:%s,msg:%s}", uid, eid, msg);
     }
 
-    private static String getJSONString(ExternalIdentityRef ref, Exception e) {
+    @Nonnull
+    private static String getJSONString(@Nonnull ExternalIdentityRef ref, @Nonnull Exception e) {
         String eid = JsonUtil.getJsonString(ref.getString());
         String msg = JsonUtil.getJsonString(e.toString());
         return String.format("{op:\"ERR\",uid:\"\",eid:%s,msg:%s}", eid, msg);
\ No newline at end of file
