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

Print this page
7191662: JCE providers should be located via ServiceLoader
   1 /*
   2  * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   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
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 104     /**
 105      * A description of the provider and its services.
 106      *
 107      * @serial
 108      */
 109     private String info;
 110 
 111     /**
 112      * The provider version number.
 113      *
 114      * @serial
 115      */
 116     private double version;
 117 
 118 
 119     private transient Set<Map.Entry<Object,Object>> entrySet = null;
 120     private transient int entrySetCallCount = 0;
 121 
 122     private transient boolean initialized;
 123 












 124     /**
 125      * Constructs a provider with the specified name, version number,
 126      * and information.
 127      *
 128      * @param name the provider name.
 129      *
 130      * @param version the provider version number.
 131      *
 132      * @param info a description of the provider and its services.
 133      */
 134     protected Provider(String name, double version, String info) {
 135         this.name = name;
 136         this.version = version;
 137         this.info = info;
 138         putId();
 139         initialized = true;
 140     }
 141 
 142     /**









































 143      * Returns the name of this provider.
 144      *
 145      * @return the name of this provider.
 146      */
 147     public String getName() {
 148         return name;
 149     }
 150 
 151     /**
 152      * Returns the version number for this provider.
 153      *
 154      * @return the version number for this provider.
 155      */
 156     public double getVersion() {
 157         return version;
 158     }
 159 
 160     /**
 161      * Returns a human-readable description of the provider and its
 162      * services.  This may return an HTML page, with relevant links.


1562          * @param constructorParameter the value to pass to the constructor,
1563          * or null if this type of service does not use a constructorParameter.
1564          *
1565          * @return a new implementation of this service
1566          *
1567          * @throws InvalidParameterException if the value of
1568          * constructorParameter is invalid for this type of service.
1569          * @throws NoSuchAlgorithmException if instantiation failed for
1570          * any other reason.
1571          */
1572         public Object newInstance(Object constructorParameter)
1573                 throws NoSuchAlgorithmException {
1574             if (registered == false) {
1575                 if (provider.getService(type, algorithm) != this) {
1576                     throw new NoSuchAlgorithmException
1577                         ("Service not registered with Provider "
1578                         + provider.getName() + ": " + this);
1579                 }
1580                 registered = true;
1581             }

1582             try {
1583                 EngineDescription cap = knownEngines.get(type);
1584                 if (cap == null) {
1585                     // unknown engine type, use generic code
1586                     // this is the code path future for non-core
1587                     // optional packages
1588                     return newInstanceGeneric(constructorParameter);
1589                 }
1590                 if (cap.constructorParameterClassName == null) {


1591                     if (constructorParameter != null) {

1592                         throw new InvalidParameterException
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
1606                             ("constructorParameter must be instanceof "
1607                             + cap.constructorParameterClassName.replace('$', '.')
1608                             + " for engine type " + type);
1609                         }
1610                     }
1611                     Class<?> clazz = getImplClass();
1612                     Constructor<?> cons = clazz.getConstructor(paramClass);
1613                     return cons.newInstance(constructorParameter);
1614                 }


1615             } catch (NoSuchAlgorithmException e) {
1616                 throw e;
1617             } catch (InvocationTargetException e) {
1618                 throw new NoSuchAlgorithmException
1619                     ("Error constructing implementation (algorithm: "
1620                     + algorithm + ", provider: " + provider.getName()
1621                     + ", class: " + className + ")", e.getCause());
1622             } catch (Exception e) {
1623                 throw new NoSuchAlgorithmException
1624                     ("Error constructing implementation (algorithm: "
1625                     + algorithm + ", provider: " + provider.getName()
1626                     + ", class: " + className + ")", e);
1627             }
1628         }
1629 
1630         // return the implementation Class object for this service
1631         private Class<?> getImplClass() throws NoSuchAlgorithmException {
1632             try {
1633                 Reference<Class<?>> ref = classRef;
1634                 Class<?> clazz = (ref == null) ? null : ref.get();


1637                     if (cl == null) {
1638                         clazz = Class.forName(className);
1639                     } else {
1640                         clazz = cl.loadClass(className);
1641                     }
1642                     if (!Modifier.isPublic(clazz.getModifiers())) {
1643                         throw new NoSuchAlgorithmException
1644                             ("class configured for " + type + " (provider: " +
1645                             provider.getName() + ") is not public.");
1646                     }
1647                     classRef = new WeakReference<>(clazz);
1648                 }
1649                 return clazz;
1650             } catch (ClassNotFoundException e) {
1651                 throw new NoSuchAlgorithmException
1652                     ("class configured for " + type + " (provider: " +
1653                     provider.getName() + ") cannot be found.", e);
1654             }
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         }
1693 
1694         /**
1695          * Test whether this Service can use the specified parameter.
1696          * Returns false if this service cannot use the parameter. Returns
1697          * true if this service can use the parameter, if a fast test is
1698          * infeasible, or if the status is unknown.
1699          *
1700          * <p>The security provider framework uses this method with
1701          * some types of services to quickly exclude non-matching
1702          * implementations for consideration.
1703          * Applications will typically not need to call it.
1704          *
1705          * <p>For details and the values of parameter that are valid for the
1706          * various types of services see the top of this class and the
1707          * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html">
1708          * Java Cryptography Architecture API Specification &amp;
1709          * Reference</a>.
1710          * Security providers can override it to implement their own test.
1711          *
1712          * @param parameter the parameter to test
1713          *


   1 /*
   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.
   4  *
   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
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 104     /**
 105      * A description of the provider and its services.
 106      *
 107      * @serial
 108      */
 109     private String info;
 110 
 111     /**
 112      * The provider version number.
 113      *
 114      * @serial
 115      */
 116     private double version;
 117 
 118 
 119     private transient Set<Map.Entry<Object,Object>> entrySet = null;
 120     private transient int entrySetCallCount = 0;
 121 
 122     private transient boolean initialized;
 123 
 124     private static Object newInstanceUtil(final Class<?> clazz,
 125         final Class<?> ctrParamClz, final Object ctorParamObj)
 126         throws Exception {
 127         if (ctrParamClz == null) {
 128             Constructor<?> con = clazz.getConstructor();
 129             return con.newInstance();
 130         } else {
 131             Constructor<?> con = clazz.getConstructor(ctrParamClz);
 132             return con.newInstance(ctorParamObj);
 133         }
 134     }
 135 
 136     /**
 137      * Constructs a provider with the specified name, version number,
 138      * and information.
 139      *
 140      * @param name the provider name.
 141      *
 142      * @param version the provider version number.
 143      *
 144      * @param info a description of the provider and its services.
 145      */
 146     protected Provider(String name, double version, String info) {
 147         this.name = name;
 148         this.version = version;
 149         this.info = info;
 150         putId();
 151         initialized = true;
 152     }
 153 
 154     /**
 155      * Apply the supplied configuration argument to this provider instance
 156      * and return the configured provider. Note that if this provider cannot
 157      * be configured in-place, a new provider will be created and returned.
 158      * Therefore, callers should always use the returned provider.
 159      *
 160      * @implSpec
 161      * The default implementation throws {@code UnsupportedOperationException}.
 162      * Subclasses should override this method only if a configuration argument
 163      * is supported.
 164      *
 165      * @param configArg the configuration information for configuring this
 166      *         provider.
 167      *
 168      * @throws UnsupportedOperationException if a configuration argument is
 169      *         not supported.
 170      * @throws NullPointerException if the supplied configuration argument is
 171                null.
 172      * @throws InvalidParameterException if the supplied configuration argument
 173      *         is invalid.
 174      * @return a provider configured with the supplied configuration argument.
 175      *
 176      * @since 1.9
 177      */
 178     public Provider configure(String configArg) {
 179         throw new UnsupportedOperationException("configure is not supported");
 180     }
 181 
 182     /**
 183      * Return the configuration parameter used for configuring this provider
 184      * instance. If no parameter is supplied, null is returned.
 185      *
 186      * @return the string value passed into the {@link #configure} method if
 187      *         specified.
 188      *
 189      * @since 1.9
 190      */
 191     public String getArgument() {
 192        return null;
 193     }
 194 
 195     /**
 196      * Returns the name of this provider.
 197      *
 198      * @return the name of this provider.
 199      */
 200     public String getName() {
 201         return name;
 202     }
 203 
 204     /**
 205      * Returns the version number for this provider.
 206      *
 207      * @return the version number for this provider.
 208      */
 209     public double getVersion() {
 210         return version;
 211     }
 212 
 213     /**
 214      * Returns a human-readable description of the provider and its
 215      * services.  This may return an HTML page, with relevant links.


1615          * @param constructorParameter the value to pass to the constructor,
1616          * or null if this type of service does not use a constructorParameter.
1617          *
1618          * @return a new implementation of this service
1619          *
1620          * @throws InvalidParameterException if the value of
1621          * constructorParameter is invalid for this type of service.
1622          * @throws NoSuchAlgorithmException if instantiation failed for
1623          * any other reason.
1624          */
1625         public Object newInstance(Object constructorParameter)
1626                 throws NoSuchAlgorithmException {
1627             if (registered == false) {
1628                 if (provider.getService(type, algorithm) != this) {
1629                     throw new NoSuchAlgorithmException
1630                         ("Service not registered with Provider "
1631                         + provider.getName() + ": " + this);
1632                 }
1633                 registered = true;
1634             }
1635             Class<?> ctrParamClz;
1636             try {
1637                 EngineDescription cap = knownEngines.get(type);
1638                 if (cap == null) {
1639                     // unknown engine type, use generic code
1640                     // this is the code path future for non-core
1641                     // optional packages
1642                     ctrParamClz = constructorParameter == null?
1643                         null : constructorParameter.getClass();
1644                 } else {
1645                     ctrParamClz = cap.constructorParameterClassName == null?
1646                         null : Class.forName(cap.constructorParameterClassName);
1647                     if (constructorParameter != null) {
1648                         if (ctrParamClz == null) {
1649                             throw new InvalidParameterException
1650                                 ("constructorParameter not used with " + type
1651                                 + " engines");





1652                         } else {


1653                             Class<?> argClass = constructorParameter.getClass();
1654                             if (ctrParamClz.isAssignableFrom(argClass) == false) {
1655                                 throw new InvalidParameterException
1656                                     ("constructorParameter must be instanceof "
1657                                     + cap.constructorParameterClassName.replace('$', '.')
1658                                     + " for engine type " + type);
1659                             }
1660                         }



1661                     }
1662                 }
1663                 return newInstanceUtil(getImplClass(), ctrParamClz, constructorParameter);
1664             } catch (NoSuchAlgorithmException e) {
1665                 throw e;
1666             } catch (InvocationTargetException e) {
1667                 throw new NoSuchAlgorithmException
1668                     ("Error constructing implementation (algorithm: "
1669                     + algorithm + ", provider: " + provider.getName()
1670                     + ", class: " + className + ")", e.getCause());
1671             } catch (Exception e) {
1672                 throw new NoSuchAlgorithmException
1673                     ("Error constructing implementation (algorithm: "
1674                     + algorithm + ", provider: " + provider.getName()
1675                     + ", class: " + className + ")", e);
1676             }
1677         }
1678 
1679         // return the implementation Class object for this service
1680         private Class<?> getImplClass() throws NoSuchAlgorithmException {
1681             try {
1682                 Reference<Class<?>> ref = classRef;
1683                 Class<?> clazz = (ref == null) ? null : ref.get();


1686                     if (cl == null) {
1687                         clazz = Class.forName(className);
1688                     } else {
1689                         clazz = cl.loadClass(className);
1690                     }
1691                     if (!Modifier.isPublic(clazz.getModifiers())) {
1692                         throw new NoSuchAlgorithmException
1693                             ("class configured for " + type + " (provider: " +
1694                             provider.getName() + ") is not public.");
1695                     }
1696                     classRef = new WeakReference<>(clazz);
1697                 }
1698                 return clazz;
1699             } catch (ClassNotFoundException e) {
1700                 throw new NoSuchAlgorithmException
1701                     ("class configured for " + type + " (provider: " +
1702                     provider.getName() + ") cannot be found.", e);
1703             }
1704         }
1705 





































1706         /**
1707          * Test whether this Service can use the specified parameter.
1708          * Returns false if this service cannot use the parameter. Returns
1709          * true if this service can use the parameter, if a fast test is
1710          * infeasible, or if the status is unknown.
1711          *
1712          * <p>The security provider framework uses this method with
1713          * some types of services to quickly exclude non-matching
1714          * implementations for consideration.
1715          * Applications will typically not need to call it.
1716          *
1717          * <p>For details and the values of parameter that are valid for the
1718          * various types of services see the top of this class and the
1719          * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html">
1720          * Java Cryptography Architecture API Specification &amp;
1721          * Reference</a>.
1722          * Security providers can override it to implement their own test.
1723          *
1724          * @param parameter the parameter to test
1725          *