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 & 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 & 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() { |
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 |