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