jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ang...@apache.org
Subject svn commit: r1401335 - /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/
Date Tue, 23 Oct 2012 16:11:34 GMT
Author: angela
Date: Tue Oct 23 16:11:33 2012
New Revision: 1401335

URL: http://svn.apache.org/viewvc?rev=1401335&view=rev
Log:
 OAK-91 - Implement Authentication Support (WIP)

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/DefaultSyncHandler.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalGroup.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModule.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalUser.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncException.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncHandler.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncMode.java

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/DefaultSyncHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/DefaultSyncHandler.java?rev=1401335&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/DefaultSyncHandler.java
(added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/DefaultSyncHandler.java
Tue Oct 23 16:11:33 2012
@@ -0,0 +1,180 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.CheckForNull;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+
+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.oak.api.Root;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.plugins.value.ValueFactoryImpl;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * DefaultSyncHandler... TODO
+ */
+public class DefaultSyncHandler implements SyncHandler {
+
+    /**
+     * logger instance
+     */
+    private static final Logger log = LoggerFactory.getLogger(DefaultSyncHandler.class);
+
+    private UserManager userManager;
+    private Root root;
+    private SyncMode mode;
+    private ConfigurationParameters options;
+
+    private ValueFactory valueFactory;
+
+    private boolean initialized;
+
+    @Override
+    public boolean initialize(UserManager userManager, Root root, SyncMode mode,
+                              ConfigurationParameters options) throws SyncException {
+        if (userManager == null || root == null) {
+            throw new SyncException("Error while initializing sync handler.");
+        }
+        this.userManager = userManager;
+        this.root = root;
+        this.mode = mode;
+        this.options = (options == null) ? ConfigurationParameters.EMPTY : options;
+
+        valueFactory = new ValueFactoryImpl(root.getBlobFactory(), NamePathMapper.DEFAULT);
+        initialized = true;
+        return true;
+    }
+
+    @Override
+    public boolean sync(ExternalUser externalUser) throws SyncException {
+        checkInitialized();
+        try {
+            User user = getUser(externalUser);
+            if (user == null) {
+                createUser(externalUser);
+            } else {
+                updateUser(externalUser, user);
+            }
+            return true;
+        } catch (RepositoryException e) {
+            throw new SyncException(e);
+        }
+    }
+
+    //--------------------------------------------------------------------------
+    private void checkInitialized() {
+        if (!initialized) {
+            throw new IllegalStateException("not initialized");
+        }
+    }
+
+    @CheckForNull
+    private User getUser(ExternalUser externalUser) throws RepositoryException {
+        // TODO: deal with colliding authorizable that is group.
+
+        Authorizable authorizable = userManager.getAuthorizable(externalUser.getId());
+        if (authorizable == null) {
+            authorizable = userManager.getAuthorizable(externalUser.getPrincipal());
+        }
+
+        return (authorizable == null) ? null : (User) authorizable;
+    }
+
+    @CheckForNull
+    private User createUser(ExternalUser externalUser) throws RepositoryException, SyncException
{
+        if (mode.contains(SyncMode.MODE_CREATE_USER)) {
+            User user = userManager.createUser(externalUser.getId(), null, externalUser.getPrincipal(),
externalUser.getPath());
+            syncAuthorizable(externalUser, user);
+            return user;
+        } else {
+            return null;
+        }
+    }
+
+    @CheckForNull
+    private Group createGroup(ExternalGroup externalGroup) throws RepositoryException, SyncException
{
+        if (mode.contains(SyncMode.MODE_CREATE_GROUPS)) {
+            Group group = userManager.createGroup(externalGroup.getId(), externalGroup.getPrincipal(),
externalGroup.getPath());
+            syncAuthorizable(externalGroup, group);
+            return group;
+        } else {
+            return null;
+        }
+    }
+
+    private void updateUser(ExternalUser externalUser, User user) throws RepositoryException,
SyncException {
+        if (mode.contains(SyncMode.MODE_UPDATE)) {
+            syncAuthorizable(externalUser, user);
+        }
+    }
+
+    private void syncAuthorizable(ExternalUser externalUser, Authorizable authorizable) throws
RepositoryException, SyncException {
+        for (ExternalGroup externalGroup : externalUser.getGroups()) {
+            String groupId = externalGroup.getId();
+            Group group;
+            Authorizable a = userManager.getAuthorizable(groupId);
+            if (a == null) {
+                group = createGroup(externalGroup);
+            } else {
+                group = (a.isGroup()) ? (Group) a : null;
+            }
+
+            if (group != null) {
+                group.addMember(authorizable);
+            } else {
+                log.debug("No such group " + groupId + "; Ignoring group membership.");
+            }
+        }
+
+        Map<String, ?> properties = externalUser.getProperties();
+        for (String key : properties.keySet()) {
+            Object prop = properties.get(key);
+            if (prop instanceof Collection) {
+                Value[] values = createValues((Collection) prop);
+                authorizable.setProperty(key, values);
+            } else {
+                Value value = createValue(prop);
+                authorizable.setProperty(key, value);
+            }
+        }
+    }
+
+    private Value createValue(Object propValue) {
+        // TODO
+        return null;
+    }
+
+    private Value[] createValues(Collection<?> propValues) {
+        List<Value> values = new ArrayList<Value>();
+        for (Object obj : propValues) {
+            values.add(createValue(obj));
+        }
+        return values.toArray(new Value[values.size()]);
+    }
+}
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalGroup.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalGroup.java?rev=1401335&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalGroup.java
(added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalGroup.java
Tue Oct 23 16:11:33 2012
@@ -0,0 +1,23 @@
+/*
+ * 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;
+
+/**
+ * ExternalGroup... TODO
+ */
+public interface ExternalGroup extends ExternalUser {
+}
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModule.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModule.java?rev=1401335&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModule.java
(added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModule.java
Tue Oct 23 16:11:33 2012
@@ -0,0 +1,138 @@
+/*
+ * 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;
+
+import java.util.Collections;
+import java.util.Set;
+import javax.jcr.SimpleCredentials;
+import javax.security.auth.login.LoginException;
+
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.spi.security.authentication.AbstractLoginModule;
+import org.apache.jackrabbit.util.Text;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ExternalLoginModule... TODO
+ */
+public abstract class ExternalLoginModule extends AbstractLoginModule {
+
+    /**
+     * logger instance
+     */
+    private static final Logger log = LoggerFactory.getLogger(ExternalLoginModule.class);
+
+    public static final String PARAM_SYNC_MODE = "syncMode";
+    public static final SyncMode DEFAULT_SYNC_MODE = SyncMode.DEFAULT_SYNC;
+
+    private static final String PARAM_SYNC_HANDLER = "syncHandler";
+    private static final String DEFAULT_SYNC_HANDLER = DefaultSyncHandler.class.getName();
+
+    //------------------------------------------------< ExternalLoginModule >---
+    /**
+     * TODO
+     *
+     * @return
+     */
+    protected abstract boolean loginSucceeded();
+
+    /**
+     * TODO
+     *
+     * @return
+     */
+    protected abstract ExternalUser getExternalUser();
+
+    /**
+     * TODO
+     *
+     * @return
+     * @throws SyncException
+     */
+    protected SyncHandler getSyncHandler() throws SyncException {
+        String shClass = options.getConfigValue(PARAM_SYNC_HANDLER, DEFAULT_SYNC_HANDLER);
+        Object syncHandler;
+        try {
+            syncHandler = Class.forName(shClass).newInstance();
+        } catch (Exception e) {
+            throw new SyncException("Error while getting SyncHandler:", e);
+        }
+
+        if (syncHandler.getClass().isAssignableFrom(SyncHandler.class)) {
+            return (SyncHandler) syncHandler;
+        } else {
+            throw new SyncException("Invalid SyncHandler class configured: " + syncHandler.getClass().getName());
+        }
+    }
+
+    //------------------------------------------------< AbstractLoginModule >---
+
+    /**
+     * Default implementation of the {@link #getSupportedCredentials()} method
+     * that only lists {@link SimpleCredentials} as supported. Subclasses that
+     * wish to support other or additional credential implementations should
+     * override this method.
+     *
+     * @return An immutable set containing only the {@link SimpleCredentials} class.
+     */
+    @Override
+    protected Set<Class> getSupportedCredentials() {
+        Class scClass = SimpleCredentials.class;
+        return Collections.singleton(scClass);
+    }
+
+    //--------------------------------------------------------< LoginModule >---
+
+    /**
+     * TODO
+     *
+     * @return
+     * @throws LoginException
+     */
+    @Override
+    public boolean commit() throws LoginException {
+        if (!loginSucceeded()) {
+            return false;
+        }
+
+        try {
+            SyncHandler handler = getSyncHandler();
+            Root root = getRoot();
+            String smValue = options.getConfigValue(PARAM_SYNC_MODE, null);
+            SyncMode syncMode;
+            if (smValue == null) {
+                syncMode = DEFAULT_SYNC_MODE;
+            } else {
+                syncMode = SyncMode.fromStrings(Text.explode(smValue, ',', false));
+            }
+            if (handler.initialize(getUserManager(), root, syncMode, options)) {
+                handler.sync(getExternalUser());
+                root.commit();
+                return true;
+            } else {
+                log.warn("Failed to initialize sync handler.");
+                return false;
+            }
+        } catch (SyncException e) {
+            throw new LoginException("User synchronization failed: " + e);
+        } catch (CommitFailedException e) {
+            throw new LoginException("User synchronization failed: " + e);
+        }
+    }
+}
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalUser.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalUser.java?rev=1401335&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalUser.java
(added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalUser.java
Tue Oct 23 16:11:33 2012
@@ -0,0 +1,37 @@
+/*
+ * 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;
+
+import java.security.Principal;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * ExternalUser... TODO
+ */
+public interface ExternalUser {
+
+    String getId();
+
+    Principal getPrincipal();
+
+    String getPath();
+
+    Set<ExternalGroup> getGroups();
+
+    Map<String, ?> getProperties();
+}
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncException.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncException.java?rev=1401335&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncException.java
(added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncException.java
Tue Oct 23 16:11:33 2012
@@ -0,0 +1,35 @@
+/*
+ * 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;
+
+/**
+ * SyncException... TODO
+ */
+public class SyncException extends Exception {
+
+    public SyncException(String s) {
+        super(s);
+    }
+
+    public SyncException(Throwable throwable) {
+        super(throwable);
+    }
+
+    public SyncException(String s, Throwable throwable) {
+        super(s, throwable);
+    }
+}
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncHandler.java?rev=1401335&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncHandler.java
(added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncHandler.java
Tue Oct 23 16:11:33 2012
@@ -0,0 +1,32 @@
+/*
+ * 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;
+
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+
+/**
+ * SyncHandler... TODO
+ */
+public interface SyncHandler {
+
+    boolean initialize(UserManager userManager, Root root, SyncMode mode,
+                       ConfigurationParameters options) throws SyncException;
+
+    boolean sync(ExternalUser externalUser) throws SyncException;
+}
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncMode.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncMode.java?rev=1401335&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncMode.java
(added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncMode.java
Tue Oct 23 16:11:33 2012
@@ -0,0 +1,78 @@
+/*
+ * 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;
+
+/**
+ * SyncMode... TODO: define sync-modes
+ */
+public class SyncMode {
+
+    public static final int MODE_NO_SYNC = 0;
+    public static final int MODE_CREATE_USER = 1;
+    public static final int MODE_CREATE_GROUPS = 2;
+    public static final int MODE_UPDATE = 4;
+
+    public static final String CREATE_USER_NAME = "createUser";
+    public static final String CREATE_GROUP_NAME = "createGroup";
+    public static final String UPDATE = "update";
+
+    public static final SyncMode DEFAULT_SYNC = new SyncMode(MODE_CREATE_USER|MODE_CREATE_GROUPS|MODE_UPDATE);
+
+    private final int mode;
+
+    private SyncMode(int mode) {
+        this.mode = mode;
+    }
+
+    public boolean contains(int mode) {
+        return (this.mode & mode) == mode;
+    }
+
+    public static SyncMode fromString(String name) {
+        int mode;
+        if (CREATE_USER_NAME.equals(name)) {
+            mode = MODE_CREATE_USER;
+        } else if (CREATE_GROUP_NAME.equals(name)) {
+            mode = MODE_CREATE_GROUPS;
+        } else if (UPDATE.equals(name)) {
+            mode = MODE_UPDATE;
+        } else {
+            throw new IllegalArgumentException("invalid sync mode name " + name);
+        }
+        return fromInt(mode);
+    }
+
+    public static SyncMode fromStrings(String[] names) {
+        int mode = MODE_NO_SYNC;
+        for (String name : names) {
+            mode |= fromString(name.trim()).mode;
+        }
+        return new SyncMode(mode);
+    }
+
+    private static SyncMode fromInt(int mode) {
+        if (mode == DEFAULT_SYNC.mode) {
+            return DEFAULT_SYNC;
+        }
+
+        if (mode < 0 || mode > DEFAULT_SYNC.mode) {
+            throw new IllegalArgumentException("invalid sync mode: " + mode);
+        } else {
+            return new SyncMode(mode);
+        }
+    }
+}
\ No newline at end of file



Mime
View raw message