src/java.base/share/classes/java/security/Provider.java

Print this page
7191662: JCE providers should be located via ServiceLoader

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -119,10 +119,22 @@
     private transient Set<Map.Entry<Object,Object>> entrySet = null;
     private transient int entrySetCallCount = 0;
 
     private transient boolean initialized;
 
+    private static Object newInstanceUtil(final Class<?> clazz,
+        final Class<?> ctrParamClz, final Object ctorParamObj)
+        throws Exception {
+        if (ctrParamClz == null) {
+            Constructor<?> con = clazz.getConstructor();
+            return con.newInstance();
+        } else {
+            Constructor<?> con = clazz.getConstructor(ctrParamClz);
+            return con.newInstance(ctorParamObj);
+        }
+    }
+
     /**
      * Constructs a provider with the specified name, version number,
      * and information.
      *
      * @param name the provider name.

@@ -138,10 +150,51 @@
         putId();
         initialized = true;
     }
 
     /**
+     * Apply the supplied configuration argument to this provider instance
+     * and return the configured provider. Note that if this provider cannot
+     * be configured in-place, a new provider will be created and returned.
+     * Therefore, callers should always use the returned provider.
+     *
+     * @implSpec
+     * The default implementation throws {@code UnsupportedOperationException}.
+     * Subclasses should override this method only if a configuration argument
+     * is supported.
+     *
+     * @param configArg the configuration information for configuring this
+     *         provider.
+     *
+     * @throws UnsupportedOperationException if a configuration argument is
+     *         not supported.
+     * @throws NullPointerException if the supplied configuration argument is
+               null.
+     * @throws InvalidParameterException if the supplied configuration argument
+     *         is invalid.
+     * @return a provider configured with the supplied configuration argument.
+     *
+     * @since 1.9
+     */
+    public Provider configure(String configArg) {
+        throw new UnsupportedOperationException("configure is not supported");
+    }
+
+    /**
+     * Return the configuration parameter used for configuring this provider
+     * instance. If no parameter is supplied, null is returned.
+     *
+     * @return the string value passed into the {@link #configure} method if
+     *         specified.
+     *
+     * @since 1.9
+     */
+    public String getArgument() {
+       return null;
+    }
+
+    /**
      * Returns the name of this provider.
      *
      * @return the name of this provider.
      */
     public String getName() {

@@ -1577,43 +1630,39 @@
                         ("Service not registered with Provider "
                         + provider.getName() + ": " + this);
                 }
                 registered = true;
             }
+            Class<?> ctrParamClz;
             try {
                 EngineDescription cap = knownEngines.get(type);
                 if (cap == null) {
                     // unknown engine type, use generic code
                     // this is the code path future for non-core
                     // optional packages
-                    return newInstanceGeneric(constructorParameter);
-                }
-                if (cap.constructorParameterClassName == null) {
+                    ctrParamClz = constructorParameter == null?
+                        null : constructorParameter.getClass();
+                } else {
+                    ctrParamClz = cap.constructorParameterClassName == null?
+                        null : Class.forName(cap.constructorParameterClassName);
                     if (constructorParameter != null) {
+                        if (ctrParamClz == null) {
                         throw new InvalidParameterException
                             ("constructorParameter not used with " + type
                             + " engines");
-                    }
-                    Class<?> clazz = getImplClass();
-                    Class<?>[] empty = {};
-                    Constructor<?> con = clazz.getConstructor(empty);
-                    return con.newInstance();
                 } else {
-                    Class<?> paramClass = cap.getConstructorParameterClass();
-                    if (constructorParameter != null) {
                         Class<?> argClass = constructorParameter.getClass();
-                        if (paramClass.isAssignableFrom(argClass) == false) {
+                            if (ctrParamClz.isAssignableFrom(argClass) == false) {
                             throw new InvalidParameterException
                             ("constructorParameter must be instanceof "
                             + cap.constructorParameterClassName.replace('$', '.')
                             + " for engine type " + type);
                         }
                     }
-                    Class<?> clazz = getImplClass();
-                    Constructor<?> cons = clazz.getConstructor(paramClass);
-                    return cons.newInstance(constructorParameter);
                 }
+                }
+                return newInstanceUtil(getImplClass(), ctrParamClz, constructorParameter);
             } catch (NoSuchAlgorithmException e) {
                 throw e;
             } catch (InvocationTargetException e) {
                 throw new NoSuchAlgorithmException
                     ("Error constructing implementation (algorithm: "

@@ -1652,47 +1701,10 @@
                     ("class configured for " + type + " (provider: " +
                     provider.getName() + ") cannot be found.", e);
             }
         }
 
-        /**
-         * Generic code path for unknown engine types. Call the
-         * no-args constructor if constructorParameter is null, otherwise
-         * use the first matching constructor.
-         */
-        private Object newInstanceGeneric(Object constructorParameter)
-                throws Exception {
-            Class<?> clazz = getImplClass();
-            if (constructorParameter == null) {
-                // create instance with public no-arg constructor if it exists
-                try {
-                    Class<?>[] empty = {};
-                    Constructor<?> con = clazz.getConstructor(empty);
-                    return con.newInstance();
-                } catch (NoSuchMethodException e) {
-                    throw new NoSuchAlgorithmException("No public no-arg "
-                        + "constructor found in class " + className);
-                }
-            }
-            Class<?> argClass = constructorParameter.getClass();
-            Constructor<?>[] cons = clazz.getConstructors();
-            // find first public constructor that can take the
-            // argument as parameter
-            for (Constructor<?> con : cons) {
-                Class<?>[] paramTypes = con.getParameterTypes();
-                if (paramTypes.length != 1) {
-                    continue;
-                }
-                if (paramTypes[0].isAssignableFrom(argClass) == false) {
-                    continue;
-                }
-                return con.newInstance(constructorParameter);
-            }
-            throw new NoSuchAlgorithmException("No public constructor matching "
-                + argClass.getName() + " found in class " + className);
-        }
-
         /**
          * Test whether this Service can use the specified parameter.
          * Returns false if this service cannot use the parameter. Returns
          * true if this service can use the parameter, if a fast test is
          * infeasible, or if the status is unknown.