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