1. /*
  2. * @(#)Provider.java 1.42 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.security;
  8. import java.io.*;
  9. import java.util.*;
  10. /**
  11. * This class represents a "provider" for the
  12. * Java Security API, where a provider implements some or all parts of
  13. * Java Security, including:<ul>
  14. *
  15. * <li>Algorithms (such as DSA, RSA, MD5 or SHA-1).
  16. *
  17. * <li>Key generation, conversion, and management facilities (such as for
  18. * algorithm-specific keys).
  19. *
  20. * </ul>
  21. *
  22. * <p>Each provider has a name and a version number, and is configured
  23. * in each runtime it is installed in.
  24. *
  25. * <p>See <a href =
  26. * "../../../guide/security/CryptoSpec.html#Provider">The Provider Class</a>
  27. * in the "Java Cryptography Architecture API Specification & Reference"
  28. * for information about how providers work and how to install them.
  29. *
  30. * @version 1.42 01/11/29
  31. * @author Benjamin Renaud
  32. */
  33. public abstract class Provider extends Properties {
  34. /**
  35. * The provider name.
  36. *
  37. * @serial
  38. */
  39. private String name;
  40. /**
  41. * A description of the provider and its services.
  42. *
  43. * @serial
  44. */
  45. private String info;
  46. /**
  47. * The provider version number.
  48. *
  49. * @serial
  50. */
  51. private double version;
  52. private transient Set entrySet = null;
  53. private transient int entrySetCallCount = 0;
  54. /**
  55. * Constructs a provider with the specified name, version number,
  56. * and information.
  57. *
  58. * @param name the provider name.
  59. *
  60. * @param version the provider version number.
  61. *
  62. * @param info a description of the provider and its services.
  63. */
  64. protected Provider(String name, double version, String info) {
  65. this.name = name;
  66. this.version = version;
  67. this.info = info;
  68. }
  69. /**
  70. * Constructs a provider with the specified name. Assigns it
  71. * version 1.0.
  72. *
  73. * @param name the provider name.
  74. */
  75. Provider(String name) {
  76. this(name, 1.0, "no information available");
  77. }
  78. /**
  79. * Returns the name of this provider.
  80. *
  81. * @return the name of this provider.
  82. */
  83. public String getName() {
  84. return name;
  85. }
  86. /**
  87. * Returns the version number for this provider.
  88. *
  89. * @return the version number for this provider.
  90. */
  91. public double getVersion() {
  92. return version;
  93. }
  94. /**
  95. * Returns a human-readable description of the provider and its
  96. * services. This may return an HTML page, with relevant links.
  97. *
  98. * @return a description of the provider and its services.
  99. */
  100. public String getInfo() {
  101. return info;
  102. }
  103. /*
  104. * Instantiates a provider forom its fully-qualified class name.
  105. *
  106. * <p>The assumption is made that providers configured in the
  107. * security properties file will always be supplied as part
  108. * of an INSTALLED extension or specified on the class path
  109. * (and therefore can be loaded using the class loader returned by
  110. * a call to <code>ClassLoader.getSystemClassLoader</code>, whose
  111. * delegation parent is the extension class loader for installed
  112. * extensions).
  113. *
  114. * <p>If an applet or application wants to install a provider that is
  115. * supplied within a BUNDLED extension, it will be able to do so
  116. * only at runtime, by calling the <code>Security.addProvider</code>
  117. * method (which is subject to a security check).
  118. */
  119. static Provider loadProvider(String name) {
  120. try {
  121. ClassLoader cl = ClassLoader.getSystemClassLoader();
  122. Class provClass;
  123. if (cl != null) {
  124. provClass = cl.loadClass(name);
  125. } else {
  126. provClass = Class.forName(name);
  127. }
  128. Object obj = provClass.newInstance();
  129. if (obj instanceof Provider) {
  130. return (Provider)obj;
  131. } else {
  132. debug(name + " not a provider");
  133. }
  134. } catch (Exception e) {
  135. debug("error loading provider " + name, e);
  136. }
  137. return null;
  138. }
  139. /**
  140. * Returns a string with the name and the version number
  141. * of this provider.
  142. *
  143. * @return the string with the name and the version number
  144. * for this provider.
  145. */
  146. public String toString() {
  147. return name + " version " + version;
  148. }
  149. /*
  150. * override the following methods to ensure that provider
  151. * information can only be changed if the caller has the appropriate
  152. * permissions.
  153. */
  154. /**
  155. * Clears this provider so that it no longer contains the properties
  156. * used to look up facilities implemented by the provider.
  157. *
  158. * <p>First, if there is a security manager, its <code>checkSecurityAccess</code>
  159. * method is called with the string <code>"clearProviderProperties."+name</code>
  160. * (where <code>name</code> is the provider name) to see if it's ok to clear this provider.
  161. * If the default implementation of <code>checkSecurityAccess</code>
  162. * is used (that is, that method is not overriden), then this results in
  163. * a call to the security manager's <code>checkPermission</code> method with a
  164. * <code>SecurityPermission("clearProviderProperties."+name)</code>
  165. * permission.
  166. *
  167. * @throws SecurityException
  168. * if a security manager exists and its <code>{@link
  169. * java.lang.SecurityManager#checkSecurityAccess}</code> method denies
  170. * access to clear this provider
  171. *
  172. * @since JDK1.2
  173. */
  174. public synchronized void clear() {
  175. check("clearProviderProperties."+name);
  176. super.clear();
  177. }
  178. /**
  179. * Reads a property list (key and element pairs) from the input stream.
  180. *
  181. * @param in the input stream.
  182. * @exception IOException if an error occurred when reading from the
  183. * input stream.
  184. * @see java.util.Properties#load
  185. */
  186. public synchronized void load(InputStream inStream) throws IOException {
  187. check("loadProviderProperties."+name);
  188. super.load(inStream);
  189. }
  190. /**
  191. * Copies all of the mappings from the specified Map to this provider.
  192. * These mappings will replace any properties that this provider had
  193. * for any of the keys currently in the specified Map.
  194. *
  195. * @since JDK1.2
  196. */
  197. public synchronized void putAll(Map t) {
  198. check("putAllProviderProperties."+name);
  199. super.putAll(t);
  200. }
  201. /**
  202. * Returns an unmodifiable Set view of the property entries contained
  203. * in this Provider.
  204. *
  205. * @see java.util.Map.Entry
  206. * @since JDK1.2
  207. */
  208. public synchronized Set entrySet() {
  209. if (entrySet == null) {
  210. if (entrySetCallCount++ == 0) // Initial call
  211. entrySet = Collections.unmodifiableMap(this).entrySet();
  212. else
  213. return super.entrySet(); // Recursive call
  214. }
  215. // This exception will be thrown if the implementation of
  216. // Collections.unmodifiableMap.entrySet() is changed such that it
  217. // no longer calls entrySet() on the backing Map. (Provider's
  218. // entrySet implementation depends on this "implementation detail",
  219. // which is unlikely to change.
  220. if (entrySetCallCount != 2)
  221. throw new RuntimeException("Internal error.");
  222. return entrySet;
  223. }
  224. /**
  225. * Returns an unmodifiable Set view of the property keys contained in
  226. * this provider.
  227. *
  228. * @since JDK1.2
  229. */
  230. public Set keySet() {
  231. return Collections.unmodifiableSet(super.keySet());
  232. }
  233. /*
  234. * Returns an unmodifiable Collection view of the property values
  235. * contained in this provider.
  236. *
  237. * @since JDK1.2
  238. */
  239. public Collection values() {
  240. return Collections.unmodifiableCollection(super.values());
  241. }
  242. /**
  243. * Sets the <code>key</code> property to have the specified
  244. * <code>value</code>.
  245. *
  246. * <p>First, if there is a security manager, its <code>checkSecurityAccess</code>
  247. * method is called with the string <code>"putProviderProperty."+name</code>,
  248. * where <code>name</code> is the provider name,
  249. * to see if it's ok to set this provider's property values.
  250. * If the default implementation of <code>checkSecurityAccess</code>
  251. * is used (that is, that method is not overriden), then this results in
  252. * a call to the security manager's <code>checkPermission</code> method with a
  253. * <code>SecurityPermission("putProviderProperty."+name)</code>
  254. * permission.
  255. *
  256. * @param key the property key.
  257. *
  258. * @param value the property value.
  259. *
  260. * @return the previous value of the specified property
  261. * (<code>key</code>), or null if it did not have one.
  262. *
  263. * @throws SecurityException
  264. * if a security manager exists and its <code>{@link
  265. * java.lang.SecurityManager#checkSecurityAccess}</code> method denies
  266. * access to set property values.
  267. *
  268. * @since JDK1.2
  269. */
  270. public synchronized Object put(Object key, Object value) {
  271. check("putProviderProperty."+name);
  272. return super.put(key, value);
  273. }
  274. /**
  275. * Removes the <code>key</code> property (and its corresponding
  276. * <code>value</code>).
  277. *
  278. * <p>First, if there is a security manager, its <code>checkSecurityAccess</code>
  279. * method is called with the string <code>""removeProviderProperty."+name</code>,
  280. * where <code>name</code> is the provider name,
  281. * to see if it's ok to remove this provider's properties.
  282. * If the default implementation of <code>checkSecurityAccess</code>
  283. * is used (that is, that method is not overriden), then this results in
  284. * a call to the security manager's <code>checkPermission</code> method with a
  285. * <code>SecurityPermission("removeProviderProperty."+name)</code>
  286. * permission.
  287. *
  288. * @param key the key for the property to be removed.
  289. *
  290. * @return the value to which the key had been mapped,
  291. * or null if the key did not have a mapping.
  292. *
  293. * @throws SecurityException
  294. * if a security manager exists and its <code>{@link
  295. * java.lang.SecurityManager#checkSecurityAccess}</code> method denies
  296. * access to remove this provider's properties.
  297. *
  298. * @since JDK1.2
  299. */
  300. public synchronized Object remove(Object key) {
  301. check("removeProviderProperty."+name);
  302. return super.remove(key);
  303. }
  304. private static void check(String directive) {
  305. SecurityManager security = System.getSecurityManager();
  306. if (security != null) {
  307. security.checkSecurityAccess(directive);
  308. }
  309. }
  310. private static void debug(String msg) {
  311. Security.debug(msg);
  312. }
  313. private static void debug(String msg, Throwable t) {
  314. Security.debug(msg, t);
  315. }
  316. // Declare serialVersionUID to be compatible with JDK1.1
  317. static final long serialVersionUID = -4298000515446427739L;
  318. }