001: /*
002: * @(#)Provider.java 1.56 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package java.security;
029:
030: import java.io.*;
031: import java.util.*;
032:
033: /**
034: * This class represents a "provider" for the
035: * Java Security API, where a provider implements some or all parts of
036: * Java Security. Services that a provider may implement include:
037: *
038: * <ul>
039: *
040: * <li>Algorithms (such as DSA, RSA, MD5 or SHA-1).
041: *
042: * <li>Key generation, conversion, and management facilities (such as for
043: * algorithm-specific keys).
044: *
045: *</ul>
046: *
047: * <p>Each provider has a name and a version number, and is configured
048: * in each runtime it is installed in.
049: *
050: * <p>See <a href =
051: * "../../../guide/security/CryptoSpec.html#Provider">The Provider Class</a>
052: * in the "Java Cryptography Architecture API Specification & Reference"
053: * for information about how a particular type of provider, the
054: * cryptographic service provider, works and is installed. However,
055: * please note that a provider can be used to implement any security
056: * service in Java that uses a pluggable architecture with a choice
057: * of implementations that fit underneath.
058: *
059: * @version 1.48, 02/02/00
060: * @author Benjamin Renaud
061: */
062: public abstract class Provider extends Properties {
063:
064: private static final sun.security.util.Debug debug = sun.security.util.Debug
065: .getInstance("jca", "Provider");
066:
067: /**
068: * The provider name.
069: *
070: * @serial
071: */
072: private String name;
073:
074: /**
075: * A description of the provider and its services.
076: *
077: * @serial
078: */
079: private String info;
080:
081: /**
082: * The provider version number.
083: *
084: * @serial
085: */
086: private double version;
087:
088: private transient Set entrySet = null;
089: private transient int entrySetCallCount = 0;
090:
091: /**
092: * Constructs a provider with the specified name, version number,
093: * and information.
094: *
095: * @param name the provider name.
096: *
097: * @param version the provider version number.
098: *
099: * @param info a description of the provider and its services.
100: */
101: protected Provider(String name, double version, String info) {
102: this .name = name;
103: this .version = version;
104: this .info = info;
105: }
106:
107: /**
108: * Constructs a provider with the specified name. Assigns it
109: * version 1.0.
110: *
111: * @param name the provider name.
112: */
113: Provider(String name) {
114: this (name, 1.0, "no information available");
115: }
116:
117: /**
118: * Returns the name of this provider.
119: *
120: * @return the name of this provider.
121: */
122: public String getName() {
123: return name;
124: }
125:
126: /**
127: * Returns the version number for this provider.
128: *
129: * @return the version number for this provider.
130: */
131: public double getVersion() {
132: return version;
133: }
134:
135: /**
136: * Returns a human-readable description of the provider and its
137: * services. This may return an HTML page, with relevant links.
138: *
139: * @return a description of the provider and its services.
140: */
141: public String getInfo() {
142: return info;
143: }
144:
145: /*
146: * Instantiates a provider from its fully-qualified class name.
147: *
148: * <p>The assumption is made that providers configured in the
149: * security properties file will always be supplied as part
150: * of an INSTALLED extension or specified on the class path
151: * (and therefore can be loaded using the class loader returned by
152: * a call to <code>ClassLoader.getSystemClassLoader</code>, whose
153: * delegation parent is the extension class loader for installed
154: * extensions).
155: *
156: * <p>If an applet or application wants to install a provider that is
157: * supplied within a BUNDLED extension, it will be able to do so
158: * only at runtime, by calling the <code>Security.addProvider</code>
159: * method (which is subject to a security check).
160: */
161: static Provider loadProvider(String name) {
162: try {
163: ClassLoader cl = ClassLoader.getSystemClassLoader();
164: Class provClass;
165: if (cl != null) {
166: provClass = cl.loadClass(name);
167: } else {
168: provClass = Class.forName(name);
169: }
170: Object obj = provClass.newInstance();
171: if (obj instanceof Provider) {
172: if (debug != null) {
173: debug.println("Loaded provider " + name);
174: }
175: return (Provider) obj;
176: } else {
177: if (debug != null) {
178: debug.println(name + " is not a provider");
179: }
180: }
181: } catch (Exception e) {
182: if (debug != null) {
183: debug.println("Error loading provider " + name);
184: e.printStackTrace();
185: }
186: }
187: return null;
188: }
189:
190: /**
191: * Returns a string with the name and the version number
192: * of this provider.
193: *
194: * @return the string with the name and the version number
195: * for this provider.
196: */
197: public String toString() {
198: return name + " version " + version;
199: }
200:
201: /*
202: * override the following methods to ensure that provider
203: * information can only be changed if the caller has the appropriate
204: * permissions.
205: */
206:
207: /**
208: * Clears this provider so that it no longer contains the properties
209: * used to look up facilities implemented by the provider.
210: *
211: * <p>First, if there is a security manager, its <code>checkSecurityAccess</code>
212: * method is called with the string <code>"clearProviderProperties."+name</code>
213: * (where <code>name</code> is the provider name) to see if it's ok to clear this provider.
214: * If the default implementation of <code>checkSecurityAccess</code>
215: * is used (that is, that method is not overriden), then this results in
216: * a call to the security manager's <code>checkPermission</code> method with a
217: * <code>SecurityPermission("clearProviderProperties."+name)</code>
218: * permission.
219: *
220: * @throws SecurityException
221: * if a security manager exists and its <code>{@link
222: * java.lang.SecurityManager#checkSecurityAccess}</code> method denies
223: * access to clear this provider
224: *
225: * @since 1.2
226: */
227: public synchronized void clear() {
228: check("clearProviderProperties." + name);
229: if (debug != null) {
230: debug.println("Remove " + name + " provider properties");
231: }
232: super .clear();
233: }
234:
235: /**
236: * Reads a property list (key and element pairs) from the input stream.
237: *
238: * @param inStream the input stream.
239: * @exception IOException if an error occurred when reading from the
240: * input stream.
241: * @see java.util.Properties#load
242: */
243: public synchronized void load(InputStream inStream)
244: throws IOException {
245: check("putProviderProperty." + name);
246: if (debug != null) {
247: debug.println("Load " + name + " provider properties");
248: }
249: Properties tempProperties = new Properties();
250: tempProperties.load(inStream);
251: putAllInternal(tempProperties);
252: }
253:
254: /**
255: * Copies all of the mappings from the specified Map to this provider.
256: * These mappings will replace any properties that this provider had
257: * for any of the keys currently in the specified Map.
258: *
259: * @since 1.2
260: */
261: public synchronized void putAll(Map t) {
262: check("putProviderProperty." + name);
263: if (debug != null) {
264: debug.println("Put all " + name + " provider properties");
265: }
266: putAllInternal(t);
267: }
268:
269: /**
270: * Copies all of the mappings from the specified Map to this provider.
271: * Internal method to be called AFTER the security check has been
272: * performed.
273: */
274: private void putAllInternal(Map t) {
275: Iterator i = t.entrySet().iterator();
276: while (i.hasNext()) {
277: Map.Entry e = (Map.Entry) i.next();
278: super .put(e.getKey(), e.getValue());
279: }
280: }
281:
282: /**
283: * Returns an unmodifiable Set view of the property entries contained
284: * in this Provider.
285: *
286: * @see java.util.Map.Entry
287: * @since 1.2
288: */
289: public synchronized Set entrySet() {
290: if (entrySet == null) {
291: if (entrySetCallCount++ == 0) // Initial call
292: entrySet = Collections.unmodifiableMap(this ).entrySet();
293: else
294: return super .entrySet(); // Recursive call
295: }
296:
297: // This exception will be thrown if the implementation of
298: // Collections.unmodifiableMap.entrySet() is changed such that it
299: // no longer calls entrySet() on the backing Map. (Provider's
300: // entrySet implementation depends on this "implementation detail"
301: if (entrySetCallCount != 2)
302: throw new RuntimeException("Internal error.");
303:
304: return entrySet;
305: }
306:
307: /**
308: * Returns an unmodifiable Set view of the property keys contained in
309: * this provider.
310: *
311: * @since 1.2
312: */
313: public Set keySet() {
314: return Collections.unmodifiableSet(super .keySet());
315: }
316:
317: /**
318: * Returns an unmodifiable Collection view of the property values
319: * contained in this provider.
320: *
321: * @since 1.2
322: */
323: public Collection values() {
324: return Collections.unmodifiableCollection(super .values());
325: }
326:
327: /**
328: * Sets the <code>key</code> property to have the specified
329: * <code>value</code>.
330: *
331: * <p>First, if there is a security manager, its <code>checkSecurityAccess</code>
332: * method is called with the string <code>"putProviderProperty."+name</code>,
333: * where <code>name</code> is the provider name,
334: * to see if it's ok to set this provider's property values.
335: * If the default implementation of <code>checkSecurityAccess</code>
336: * is used (that is, that method is not overriden), then this results in
337: * a call to the security manager's <code>checkPermission</code> method with a
338: * <code>SecurityPermission("putProviderProperty."+name)</code>
339: * permission.
340: *
341: * @param key the property key.
342: *
343: * @param value the property value.
344: *
345: * @return the previous value of the specified property
346: * (<code>key</code>), or null if it did not have one.
347: *
348: * @throws SecurityException
349: * if a security manager exists and its <code>{@link
350: * java.lang.SecurityManager#checkSecurityAccess}</code> method denies
351: * access to set property values.
352: *
353: * @since 1.2
354: */
355: public synchronized Object put(Object key, Object value) {
356: check("putProviderProperty." + name);
357: if (debug != null) {
358: debug.println("Set " + name + " provider property [" + key
359: + "/" + value + "]");
360: }
361: return super .put(key, value);
362: }
363:
364: /**
365: * Removes the <code>key</code> property (and its corresponding
366: * <code>value</code>).
367: *
368: * <p>First, if there is a security manager, its <code>checkSecurityAccess</code>
369: * method is called with the string <code>""removeProviderProperty."+name</code>,
370: * where <code>name</code> is the provider name,
371: * to see if it's ok to remove this provider's properties.
372: * If the default implementation of <code>checkSecurityAccess</code>
373: * is used (that is, that method is not overriden), then this results in
374: * a call to the security manager's <code>checkPermission</code> method with a
375: * <code>SecurityPermission("removeProviderProperty."+name)</code>
376: * permission.
377: *
378: * @param key the key for the property to be removed.
379: *
380: * @return the value to which the key had been mapped,
381: * or null if the key did not have a mapping.
382: *
383: * @throws SecurityException
384: * if a security manager exists and its <code>{@link
385: * java.lang.SecurityManager#checkSecurityAccess}</code> method denies
386: * access to remove this provider's properties.
387: *
388: * @since 1.2
389: */
390: public synchronized Object remove(Object key) {
391: check("removeProviderProperty." + name);
392: if (debug != null) {
393: debug.println("Remove " + name + " provider property "
394: + key);
395: }
396: return super .remove(key);
397: }
398:
399: private static void check(String directive) {
400: SecurityManager security = System.getSecurityManager();
401: if (security != null) {
402: security.checkSecurityAccess(directive);
403: }
404: }
405:
406: // Declare serialVersionUID to be compatible with JDK1.1
407: static final long serialVersionUID = -4298000515446427739L;
408: }
|