From a29d38f5f95a652b4150f1af71f94efb239ac472 Mon Sep 17 00:00:00 2001 From: Dustin Johnson Date: Fri, 4 Jan 2013 09:53:51 -0600 Subject: [PATCH] Issue #1451 Allow overriding of IUserManager via ServiceLoader. Change-Id: Iec63c05fe7365051e7bd1a01ecca701b5553c9e9 Former-commit-id: 452729a647e5ad1e1bf12a5e9c3833142caf4b67 [formerly 452729a647e5ad1e1bf12a5e9c3833142caf4b67 [formerly 46d756ba5cd37ae22fc31ae67dac0751c2c02985]] Former-commit-id: 19f1b30437e2523fdf302a2dfad8beeba7548dc0 Former-commit-id: 818664e557a527080688008685f1453a98290a2d --- .../uf/viz/core/auth/IUserManagerLoader.java | 47 +++++ .../uf/viz/core/auth/UserController.java | 181 +++++++++++------- .../uf/common/util/ServiceLoaderUtil.java | 72 +++++++ 3 files changed, 227 insertions(+), 73 deletions(-) create mode 100644 cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/auth/IUserManagerLoader.java create mode 100644 edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/ServiceLoaderUtil.java diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/auth/IUserManagerLoader.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/auth/IUserManagerLoader.java new file mode 100644 index 0000000000..d01036d7f5 --- /dev/null +++ b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/auth/IUserManagerLoader.java @@ -0,0 +1,47 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.viz.core.auth; + +/** + * Defines a method of retrieving the {@link IUserManager} implementation. + * Intentionally package-private as all access should be constrained to + * {@link UserController}. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jan 04, 2013 1451      djohnson     Initial creation
+ * 
+ * 
+ * + * @author djohnson + * @version 1.0 + */ +interface IUserManagerLoader { + /** + * Load the {@link IUserManager} that should be used on the system. + * + * @return the user manager + */ + IUserManager getUserManager(); +} diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/auth/UserController.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/auth/UserController.java index a6f50a0a6e..5424cf81cb 100644 --- a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/auth/UserController.java +++ b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/auth/UserController.java @@ -38,6 +38,7 @@ import com.raytheon.uf.common.auth.user.IUser; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.util.ServiceLoaderUtil; import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.requests.INotAuthHandler; @@ -51,6 +52,7 @@ import com.raytheon.uf.viz.core.requests.INotAuthHandler; * ------------ ---------- ----------- -------------------------- * May 21, 2010 mschenke Initial creation * Nov 06, 2012 1302 djohnson Add ability to retrieve the {@link IUserManager}. + * Jan 04, 2013 1451 djohnson Move static block code to an implementation of an interface. * * * @@ -59,92 +61,125 @@ import com.raytheon.uf.viz.core.requests.INotAuthHandler; */ public class UserController { - private static IUFStatusHandler statusHandler = UFStatus - .getHandler(UserController.class, "CAVE"); - private static final String EXTENSION_POINT = "com.raytheon.uf.viz.core.userManager"; + /** + * Loads the {@link IUserManager} implementation from extension points. This + * code was moved in verbatim from the static block below. + */ + private static class ExtensionPointManagerLoader implements + IUserManagerLoader { + + private static final IUFStatusHandler statusHandler = UFStatus.getHandler( + ExtensionPointManagerLoader.class, "CAVE"); + + private static final String EXTENSION_POINT = "com.raytheon.uf.viz.core.userManager"; - private static IUserManager manager; + private static final ExtensionPointManagerLoader INSTANCE = new ExtensionPointManagerLoader(); + + private ExtensionPointManagerLoader() { + } - static { - IExtensionRegistry registry = Platform.getExtensionRegistry(); - IExtensionPoint point = registry.getExtensionPoint(EXTENSION_POINT); - if (point != null) { - IExtension[] extensions = point.getExtensions(); + /** + * {@inheritDoc} + */ + @Override + public IUserManager getUserManager() { + IUserManager manager = null; - for (IExtension ext : extensions) { - for (IConfigurationElement elem : ext - .getConfigurationElements()) { - if (manager != null) { - statusHandler - .handle(Priority.PROBLEM, - "Not using user authentication manager: " - + elem.getAttribute("class") - + ".\nViz does not currently support multiple authentication methods," - + " using first one found in extension point. Remove any authentication" - + " plugins not on edex server"); - } else { - try { - manager = (IUserManager) elem - .createExecutableExtension("class"); - } catch (CoreException e) { + IExtensionRegistry registry = Platform.getExtensionRegistry(); + IExtensionPoint point = registry.getExtensionPoint(EXTENSION_POINT); + if (point != null) { + IExtension[] extensions = point.getExtensions(); + + for (IExtension ext : extensions) { + for (IConfigurationElement elem : ext + .getConfigurationElements()) { + if (manager != null) { statusHandler .handle(Priority.PROBLEM, - "Error creating IUserManager from extension point", - e); + "Not using user authentication manager: " + + elem.getAttribute("class") + + ".\nViz does not currently support multiple authentication methods," + + " using first one found in extension point. Remove any authentication" + + " plugins not on edex server"); + } else { + try { + manager = (IUserManager) elem + .createExecutableExtension("class"); + } catch (CoreException e) { + statusHandler + .handle(Priority.PROBLEM, + "Error creating IUserManager from extension point", + e); + } } } } } + + if (manager == null) { + manager = new IUserManager() { + @Override + public IUser getUserObject() { + return null; + } + + @Override + public void updateUserObject(IUser user, + IAuthenticationData authData) { + + } + + @Override + public INotAuthHandler getNotAuthHandler() { + return new INotAuthHandler() { + @Override + public Object notAuthenticated( + UserNotAuthenticated response) + throws VizException { + throw new VizException( + "Could not perform request, user is not authenticated with server."); + } + + @Override + public Object notAuthorized( + UserNotAuthorized response) + throws VizException { + throw new VizException(response.getMessage()); + } + }; + } + + /** + * {@inheritDoc} + */ + @Override + public List getPermissions(String application) { + return Collections.emptyList(); + } + + @Override + public List getRoles(String application) { + return Collections.emptyList(); + } + + }; + } + return manager; } + } - if (manager == null) { - manager = new IUserManager() { - @Override - public IUser getUserObject() { - return null; - } + private static final IUserManager manager; + static { + // This static block will perform exactly as before, with a few + // caveats... + // If a service loader config file for the interface is present on the + // classpath, it can change the implementation, such as in a test case + IUserManagerLoader userManagerLoader = ServiceLoaderUtil.load( + IUserManagerLoader.class, ExtensionPointManagerLoader.INSTANCE); - @Override - public void updateUserObject(IUser user, - IAuthenticationData authData) { - - } - - @Override - public INotAuthHandler getNotAuthHandler() { - return new INotAuthHandler() { - @Override - public Object notAuthenticated( - UserNotAuthenticated response) - throws VizException { - throw new VizException( - "Could not perform request, user is not authenticated with server."); - } - - @Override - public Object notAuthorized(UserNotAuthorized response) - throws VizException { - throw new VizException(response.getMessage()); - } - }; - } - - /** - * {@inheritDoc} - */ - @Override - public List getPermissions(String application) { - return Collections.emptyList(); - } - - @Override - public List getRoles(String application) { - return Collections.emptyList(); - } - - }; - } + // manager is now final, it can't be changed once it is initialized + manager = userManagerLoader.getUserManager(); } diff --git a/edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/ServiceLoaderUtil.java b/edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/ServiceLoaderUtil.java new file mode 100644 index 0000000000..b0d664d908 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/ServiceLoaderUtil.java @@ -0,0 +1,72 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.util; + +import java.util.Iterator; +import java.util.ServiceLoader; + +/** + * Utilities for interacting with {@link ServiceLoader}. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jan 04, 2013 1451       djohnson     Initial creation
+ * 
+ * 
+ * + * @author djohnson + * @version 1.0 + */ + +public final class ServiceLoaderUtil { + /** + * Prevent construction. + */ + private ServiceLoaderUtil() { + } + + /** + * Loads the first implementation of an interface found using + * {@link ServiceLoader}. If no results are found, will return the provided + * default implementation. + * + * @param interfaceClass + * the class instance to search for a service loader + * implementation of + * @param defaultImplementation + * the default implementation + * @return the loaded implementation, or the default implementation is no + * configuration file found + */ + public static T load(Class interfaceClass, T defaultImplementation) { + ServiceLoader overridden = ServiceLoader.load(interfaceClass); + + final Iterator iter = overridden.iterator(); + if (iter.hasNext()) { + return iter.next(); + } + + return defaultImplementation; + } +}