jdk/src/java.base/share/classes/java/security/Provider.java
changeset 31270 e6470b24700d
parent 30033 b9c86c17164a
child 32649 2ee9017c7597
equal deleted inserted replaced
31269:14968253ce7e 31270:e6470b24700d
     1 /*
     1 /*
     2  * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    39  * Java Security API, where a provider implements some or all parts of
    39  * Java Security API, where a provider implements some or all parts of
    40  * Java Security. Services that a provider may implement include:
    40  * Java Security. Services that a provider may implement include:
    41  *
    41  *
    42  * <ul>
    42  * <ul>
    43  *
    43  *
    44  * <li>Algorithms (such as DSA, RSA, MD5 or SHA-1).
    44  * <li>Algorithms (such as DSA, RSA, or SHA-256).
    45  *
    45  *
    46  * <li>Key generation, conversion, and management facilities (such as for
    46  * <li>Key generation, conversion, and management facilities (such as for
    47  * algorithm-specific keys).
    47  * algorithm-specific keys).
    48  *
    48  *
    49  *</ul>
    49  * </ul>
    50  *
       
    51  * <p>Each provider has a name and a version number, and is configured
       
    52  * in each runtime it is installed in.
       
    53  *
       
    54  * <p>See <a href =
       
    55  * "../../../technotes/guides/security/crypto/CryptoSpec.html#Provider">The Provider Class</a>
       
    56  * in the "Java Cryptography Architecture API Specification &amp; Reference"
       
    57  * for information about how a particular type of provider, the
       
    58  * cryptographic service provider, works and is installed. However,
       
    59  * please note that a provider can be used to implement any security
       
    60  * service in Java that uses a pluggable architecture with a choice
       
    61  * of implementations that fit underneath.
       
    62  *
    50  *
    63  * <p>Some provider implementations may encounter unrecoverable internal
    51  * <p>Some provider implementations may encounter unrecoverable internal
    64  * errors during their operation, for example a failure to communicate with a
    52  * errors during their operation, for example a failure to communicate with a
    65  * security token. A {@link ProviderException} should be used to indicate
    53  * security token. A {@link ProviderException} should be used to indicate
    66  * such errors.
    54  * such errors.
       
    55  *
       
    56  * <p>Please note that a provider can be used to implement any security
       
    57  * service in Java that uses a pluggable architecture with a choice
       
    58  * of implementations that fit underneath.
    67  *
    59  *
    68  * <p>The service type {@code Provider} is reserved for use by the
    60  * <p>The service type {@code Provider} is reserved for use by the
    69  * security framework. Services of this type cannot be added, removed,
    61  * security framework. Services of this type cannot be added, removed,
    70  * or modified by applications.
    62  * or modified by applications.
    71  * The following attributes are automatically placed in each Provider object:
    63  * The following attributes are automatically placed in each Provider object:
    80        <td>{@code String.valueOf(provider.getInfo())}</td>
    72        <td>{@code String.valueOf(provider.getInfo())}</td>
    81  * <tr><td>{@code Provider.id className}</td>
    73  * <tr><td>{@code Provider.id className}</td>
    82  *     <td>{@code provider.getClass().getName()}</td>
    74  *     <td>{@code provider.getClass().getName()}</td>
    83  * </table>
    75  * </table>
    84  *
    76  *
       
    77  * <p>Each provider has a name and a version number. A provider normally
       
    78  * identifies itself with a file named {@code java.security.Provider}
       
    79  * in the resource directory {@code META-INF/services}.
       
    80  * Security providers are looked up via the {@link ServiceLoader} mechanism
       
    81  * using the {@link ClassLoader#getSystemClassLoader application class loader}.
       
    82  *
       
    83  * <p>Providers may be configured such that they are automatically
       
    84  * installed and made available at runtime via the
       
    85  * {@link Security#getProviders() Security.getProviders()} method.
       
    86  * The mechanism for configuring and installing security providers is
       
    87  * implementation-specific.
       
    88  *
       
    89  * @implNote
       
    90  * The JDK implementation supports static registration of the security
       
    91  * providers via the {@code conf/security/java.security} file in the Java
       
    92  * installation directory. These providers are automatically installed by
       
    93  * the JDK runtime, see <a href =
       
    94  * "../../../technotes/guides/security/crypto/CryptoSpec.html#Provider">The Provider Class</a>
       
    95  * in the "Java Cryptography Architecture API Specification &amp; Reference"
       
    96  * for information about how a particular type of provider, the cryptographic
       
    97  * service provider, works and is installed.
       
    98  *
    85  * @author Benjamin Renaud
    99  * @author Benjamin Renaud
    86  * @author Andreas Sterbenz
   100  * @author Andreas Sterbenz
    87  */
   101  */
    88 public abstract class Provider extends Properties {
   102 public abstract class Provider extends Properties {
    89 
   103 
   118 
   132 
   119     private transient Set<Map.Entry<Object,Object>> entrySet = null;
   133     private transient Set<Map.Entry<Object,Object>> entrySet = null;
   120     private transient int entrySetCallCount = 0;
   134     private transient int entrySetCallCount = 0;
   121 
   135 
   122     private transient boolean initialized;
   136     private transient boolean initialized;
       
   137 
       
   138     private static Object newInstanceUtil(final Class<?> clazz,
       
   139         final Class<?> ctrParamClz, final Object ctorParamObj)
       
   140         throws Exception {
       
   141         if (ctrParamClz == null) {
       
   142             Constructor<?> con = clazz.getConstructor();
       
   143             return con.newInstance();
       
   144         } else {
       
   145             Constructor<?> con = clazz.getConstructor(ctrParamClz);
       
   146             return con.newInstance(ctorParamObj);
       
   147         }
       
   148     }
   123 
   149 
   124     /**
   150     /**
   125      * Constructs a provider with the specified name, version number,
   151      * Constructs a provider with the specified name, version number,
   126      * and information.
   152      * and information.
   127      *
   153      *
   138         putId();
   164         putId();
   139         initialized = true;
   165         initialized = true;
   140     }
   166     }
   141 
   167 
   142     /**
   168     /**
       
   169      * Apply the supplied configuration argument to this provider instance
       
   170      * and return the configured provider. Note that if this provider cannot
       
   171      * be configured in-place, a new provider will be created and returned.
       
   172      * Therefore, callers should always use the returned provider.
       
   173      *
       
   174      * @implSpec
       
   175      * The default implementation throws {@code UnsupportedOperationException}.
       
   176      * Subclasses should override this method only if a configuration argument
       
   177      * is supported.
       
   178      *
       
   179      * @param configArg the configuration information for configuring this
       
   180      *         provider.
       
   181      *
       
   182      * @throws UnsupportedOperationException if a configuration argument is
       
   183      *         not supported.
       
   184      * @throws NullPointerException if the supplied configuration argument is
       
   185                null.
       
   186      * @throws InvalidParameterException if the supplied configuration argument
       
   187      *         is invalid.
       
   188      * @return a provider configured with the supplied configuration argument.
       
   189      *
       
   190      * @since 1.9
       
   191      */
       
   192     public Provider configure(String configArg) {
       
   193         throw new UnsupportedOperationException("configure is not supported");
       
   194     }
       
   195 
       
   196     /**
   143      * Returns the name of this provider.
   197      * Returns the name of this provider.
   144      *
   198      *
   145      * @return the name of this provider.
   199      * @return the name of this provider.
   146      */
   200      */
   147     public String getName() {
   201     public String getName() {
   210     }
   264     }
   211 
   265 
   212     /**
   266     /**
   213      * Reads a property list (key and element pairs) from the input stream.
   267      * Reads a property list (key and element pairs) from the input stream.
   214      *
   268      *
   215      * @param inStream   the input stream.
   269      * @param inStream the input stream.
   216      * @exception  IOException  if an error occurred when reading from the
   270      * @exception IOException if an error occurred when reading from the
   217      *               input stream.
   271      *               input stream.
   218      * @see java.util.Properties#load
   272      * @see java.util.Properties#load
   219      */
   273      */
   220     @Override
   274     @Override
   221     public synchronized void load(InputStream inStream) throws IOException {
   275     public synchronized void load(InputStream inStream) throws IOException {
  1577                         ("Service not registered with Provider "
  1631                         ("Service not registered with Provider "
  1578                         + provider.getName() + ": " + this);
  1632                         + provider.getName() + ": " + this);
  1579                 }
  1633                 }
  1580                 registered = true;
  1634                 registered = true;
  1581             }
  1635             }
       
  1636             Class<?> ctrParamClz;
  1582             try {
  1637             try {
  1583                 EngineDescription cap = knownEngines.get(type);
  1638                 EngineDescription cap = knownEngines.get(type);
  1584                 if (cap == null) {
  1639                 if (cap == null) {
  1585                     // unknown engine type, use generic code
  1640                     // unknown engine type, use generic code
  1586                     // this is the code path future for non-core
  1641                     // this is the code path future for non-core
  1587                     // optional packages
  1642                     // optional packages
  1588                     return newInstanceGeneric(constructorParameter);
  1643                     ctrParamClz = constructorParameter == null?
  1589                 }
  1644                         null : constructorParameter.getClass();
  1590                 if (cap.constructorParameterClassName == null) {
  1645                 } else {
       
  1646                     ctrParamClz = cap.constructorParameterClassName == null?
       
  1647                         null : Class.forName(cap.constructorParameterClassName);
  1591                     if (constructorParameter != null) {
  1648                     if (constructorParameter != null) {
  1592                         throw new InvalidParameterException
  1649                         if (ctrParamClz == null) {
  1593                             ("constructorParameter not used with " + type
       
  1594                             + " engines");
       
  1595                     }
       
  1596                     Class<?> clazz = getImplClass();
       
  1597                     Class<?>[] empty = {};
       
  1598                     Constructor<?> con = clazz.getConstructor(empty);
       
  1599                     return con.newInstance();
       
  1600                 } else {
       
  1601                     Class<?> paramClass = cap.getConstructorParameterClass();
       
  1602                     if (constructorParameter != null) {
       
  1603                         Class<?> argClass = constructorParameter.getClass();
       
  1604                         if (paramClass.isAssignableFrom(argClass) == false) {
       
  1605                             throw new InvalidParameterException
  1650                             throw new InvalidParameterException
  1606                             ("constructorParameter must be instanceof "
  1651                                 ("constructorParameter not used with " + type
  1607                             + cap.constructorParameterClassName.replace('$', '.')
  1652                                 + " engines");
  1608                             + " for engine type " + type);
  1653                         } else {
       
  1654                             Class<?> argClass = constructorParameter.getClass();
       
  1655                             if (ctrParamClz.isAssignableFrom(argClass) == false) {
       
  1656                                 throw new InvalidParameterException
       
  1657                                     ("constructorParameter must be instanceof "
       
  1658                                     + cap.constructorParameterClassName.replace('$', '.')
       
  1659                                     + " for engine type " + type);
       
  1660                             }
  1609                         }
  1661                         }
  1610                     }
  1662                     }
  1611                     Class<?> clazz = getImplClass();
       
  1612                     Constructor<?> cons = clazz.getConstructor(paramClass);
       
  1613                     return cons.newInstance(constructorParameter);
       
  1614                 }
  1663                 }
       
  1664                 return newInstanceUtil(getImplClass(), ctrParamClz, constructorParameter);
  1615             } catch (NoSuchAlgorithmException e) {
  1665             } catch (NoSuchAlgorithmException e) {
  1616                 throw e;
  1666                 throw e;
  1617             } catch (InvocationTargetException e) {
  1667             } catch (InvocationTargetException e) {
  1618                 throw new NoSuchAlgorithmException
  1668                 throw new NoSuchAlgorithmException
  1619                     ("Error constructing implementation (algorithm: "
  1669                     ("Error constructing implementation (algorithm: "
  1650             } catch (ClassNotFoundException e) {
  1700             } catch (ClassNotFoundException e) {
  1651                 throw new NoSuchAlgorithmException
  1701                 throw new NoSuchAlgorithmException
  1652                     ("class configured for " + type + " (provider: " +
  1702                     ("class configured for " + type + " (provider: " +
  1653                     provider.getName() + ") cannot be found.", e);
  1703                     provider.getName() + ") cannot be found.", e);
  1654             }
  1704             }
  1655         }
       
  1656 
       
  1657         /**
       
  1658          * Generic code path for unknown engine types. Call the
       
  1659          * no-args constructor if constructorParameter is null, otherwise
       
  1660          * use the first matching constructor.
       
  1661          */
       
  1662         private Object newInstanceGeneric(Object constructorParameter)
       
  1663                 throws Exception {
       
  1664             Class<?> clazz = getImplClass();
       
  1665             if (constructorParameter == null) {
       
  1666                 // create instance with public no-arg constructor if it exists
       
  1667                 try {
       
  1668                     Class<?>[] empty = {};
       
  1669                     Constructor<?> con = clazz.getConstructor(empty);
       
  1670                     return con.newInstance();
       
  1671                 } catch (NoSuchMethodException e) {
       
  1672                     throw new NoSuchAlgorithmException("No public no-arg "
       
  1673                         + "constructor found in class " + className);
       
  1674                 }
       
  1675             }
       
  1676             Class<?> argClass = constructorParameter.getClass();
       
  1677             Constructor<?>[] cons = clazz.getConstructors();
       
  1678             // find first public constructor that can take the
       
  1679             // argument as parameter
       
  1680             for (Constructor<?> con : cons) {
       
  1681                 Class<?>[] paramTypes = con.getParameterTypes();
       
  1682                 if (paramTypes.length != 1) {
       
  1683                     continue;
       
  1684                 }
       
  1685                 if (paramTypes[0].isAssignableFrom(argClass) == false) {
       
  1686                     continue;
       
  1687                 }
       
  1688                 return con.newInstance(constructorParameter);
       
  1689             }
       
  1690             throw new NoSuchAlgorithmException("No public constructor matching "
       
  1691                 + argClass.getName() + " found in class " + className);
       
  1692         }
  1705         }
  1693 
  1706 
  1694         /**
  1707         /**
  1695          * Test whether this Service can use the specified parameter.
  1708          * Test whether this Service can use the specified parameter.
  1696          * Returns false if this service cannot use the parameter. Returns
  1709          * Returns false if this service cannot use the parameter. Returns