001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /**
019: * @author Boris V. Kuznetsov
020: * @version $Revision$
021: */package java.security;
022:
023: import java.io.IOException;
024: import java.io.InputStream;
025: import java.io.NotActiveException;
026: import java.util.ArrayList;
027: import java.util.Collection;
028: import java.util.Collections;
029: import java.util.Enumeration;
030: import java.util.HashMap;
031: import java.util.HashSet;
032: import java.util.Iterator;
033: import java.util.List;
034: import java.util.Map;
035: import java.util.Properties;
036: import java.util.Set;
037:
038: import org.apache.harmony.luni.util.TwoKeyHashMap;
039: import org.apache.harmony.security.Util;
040: import org.apache.harmony.security.fortress.Services;
041: import org.apache.harmony.security.internal.nls.Messages;
042:
043: public abstract class Provider extends Properties {
044: private static final long serialVersionUID = -4298000515446427739L;
045:
046: private String name;
047:
048: private double version;
049:
050: // String representation of the provider version number.
051: private transient String versionString;
052:
053: private String info;
054:
055: //The provider preference order number.
056: // Equals -1 for non registered provider.
057: private transient int providerNumber = -1;
058:
059: // Contains "Service.Algorithm" and Provider.Service classes added using
060: // putService()
061: private transient TwoKeyHashMap<String, String, Service> serviceTable;
062:
063: // Contains "Service.Alias" and Provider.Service classes added using
064: // putService()
065: private transient TwoKeyHashMap<String, String, Service> aliasTable;
066:
067: // Contains "Service.Algorithm" and Provider.Service classes added using
068: // put()
069: private transient TwoKeyHashMap<String, String, Service> propertyServiceTable;
070:
071: // Contains "Service.Alias" and Provider.Service classes added using put()
072: private transient TwoKeyHashMap<String, String, Service> propertyAliasTable;
073:
074: // The properties changed via put()
075: private transient Properties changedProperties;
076:
077: // For getService(String type, String algorithm) optimization:
078: // previous result
079: private transient Provider.Service returnedService;
080: // previous parameters
081: private transient String lastAlgorithm;
082: // last name
083: private transient String lastServiceName;
084:
085: // For getServices() optimization:
086: private transient Set<Service> lastServicesSet;
087:
088: // For getService(String type) optimization:
089: private transient String lastType;
090: // last Service found by type
091: private transient Provider.Service lastServicesByType;
092:
093: protected Provider(String name, double version, String info) {
094: this .name = name;
095: this .version = version;
096: this .info = info;
097: versionString = String.valueOf(version);
098: putProviderInfo();
099: }
100:
101: /**
102: * Returns the name of this provider.
103: *
104: *
105: *
106: * @return String name of the provider
107: */
108: public String getName() {
109: return name;
110: }
111:
112: /**
113: * Returns the version number for the services being provided
114: *
115: *
116: *
117: * @return double version number for the services being provided
118: */
119: public double getVersion() {
120: return version;
121: }
122:
123: /**
124: * Returns the generic information about the services being provided.
125: *
126: *
127: *
128: * @return String generic description of the services being provided
129: */
130: public String getInfo() {
131: return info;
132: }
133:
134: /**
135: * Answers a string containing a concise, human-readable description of the
136: * receiver.
137: *
138: *
139: * @return a printable representation for the receiver.
140: */
141: public String toString() {
142: return name + " version " + version; //$NON-NLS-1$
143: }
144:
145: public synchronized void clear() {
146: SecurityManager sm = System.getSecurityManager();
147: if (sm != null) {
148: sm.checkSecurityAccess("clearProviderProperties." + name); //$NON-NLS-1$
149: }
150: super .clear();
151: if (serviceTable != null) {
152: serviceTable.clear();
153: }
154: if (propertyServiceTable != null) {
155: propertyServiceTable.clear();
156: }
157: if (aliasTable != null) {
158: aliasTable.clear();
159: }
160: if (propertyAliasTable != null) {
161: propertyAliasTable.clear();
162: }
163: if (changedProperties != null) {
164: changedProperties.clear();
165: }
166: putProviderInfo();
167: if (providerNumber != -1) {
168: // if registered then refresh Services
169: Services.setNeedRefresh();
170: }
171: servicesChanged();
172: }
173:
174: public synchronized void load(InputStream inStream)
175: throws IOException {
176: Properties tmp = new Properties();
177: tmp.load(inStream);
178: myPutAll(tmp);
179: }
180:
181: public synchronized void putAll(Map<?, ?> t) {
182:
183: // Implementation note:
184: // checkSecurityAccess method call is NOT specified
185: // Do it as in put(Object key, Object value).
186:
187: SecurityManager sm = System.getSecurityManager();
188: if (sm != null) {
189: sm.checkSecurityAccess("putProviderProperty." + name); //$NON-NLS-1$
190: }
191: myPutAll(t);
192: }
193:
194: private void myPutAll(Map<?, ?> t) {
195: if (changedProperties == null) {
196: changedProperties = new Properties();
197: }
198: Iterator<? extends Map.Entry<?, ?>> it = t.entrySet()
199: .iterator();
200: Object key;
201: Object value;
202: while (it.hasNext()) {
203: Map.Entry<?, ?> entry = it.next();
204: key = entry.getKey();
205: if (key instanceof String
206: && ((String) key).startsWith("Provider.")) { //$NON-NLS-1$
207: // Provider service type is reserved
208: continue;
209: }
210: value = entry.getValue();
211: super .put(key, value);
212: if (changedProperties.remove(key) == null) {
213: removeFromPropertyServiceTable(key);
214: }
215: changedProperties.put(key, value);
216: }
217: if (providerNumber != -1) {
218: // if registered then refresh Services
219: Services.setNeedRefresh();
220: }
221: }
222:
223: public synchronized Set<Map.Entry<Object, Object>> entrySet() {
224: return Collections.unmodifiableSet(super .entrySet());
225: }
226:
227: public Set<Object> keySet() {
228: return Collections.unmodifiableSet(super .keySet());
229: }
230:
231: public Collection<Object> values() {
232: return Collections.unmodifiableCollection(super .values());
233: }
234:
235: public synchronized Object put(Object key, Object value) {
236: SecurityManager sm = System.getSecurityManager();
237: if (sm != null) {
238: sm.checkSecurityAccess("putProviderProperty." + name); //$NON-NLS-1$
239: }
240: if (key instanceof String
241: && ((String) key).startsWith("Provider.")) { //$NON-NLS-1$
242: // Provider service type is reserved
243: return null;
244: }
245: if (providerNumber != -1) {
246: // if registered then refresh Services
247: Services.setNeedRefresh();
248: }
249: if (changedProperties != null
250: && changedProperties.remove(key) == null) {
251: removeFromPropertyServiceTable(key);
252: }
253: if (changedProperties == null) {
254: changedProperties = new Properties();
255: }
256: changedProperties.put(key, value);
257: return super .put(key, value);
258: }
259:
260: public synchronized Object remove(Object key) {
261: SecurityManager sm = System.getSecurityManager();
262: if (sm != null) {
263: sm.checkSecurityAccess("removeProviderProperty." + name); //$NON-NLS-1$
264: }
265: if (key instanceof String
266: && ((String) key).startsWith("Provider.")) { //$NON-NLS-1$
267: // Provider service type is reserved
268: return null;
269: }
270: if (providerNumber != -1) {
271: // if registered then refresh Services
272: Services.setNeedRefresh();
273: }
274: if (changedProperties != null
275: && changedProperties.remove(key) == null) {
276: removeFromPropertyServiceTable(key);
277: }
278: return super .remove(key);
279: }
280:
281: /**
282: * Returns true if this provider implements the given algorithm. Caller
283: * must specify the cryptographic service and specify constraints via the
284: * attribute name and value.
285: *
286: * @param serv
287: * Crypto service
288: * @param alg
289: * Algorithm or type
290: * @param attribute
291: * The attribute name or null
292: * @param val
293: * The attribute value
294: * @return
295: */
296: boolean implements Alg(String serv, String alg, String attribute,
297: String val) {
298: String servAlg = serv + "." + alg; //$NON-NLS-1$
299: String prop = getPropertyIgnoreCase(servAlg);
300: if (prop == null) {
301: alg = getPropertyIgnoreCase("Alg.Alias." + servAlg); //$NON-NLS-1$
302: if (alg != null) {
303: servAlg = serv + "." + alg; //$NON-NLS-1$
304: prop = getPropertyIgnoreCase(servAlg); //$NON-NLS-1$
305: }
306: }
307: if (prop != null) {
308: if (attribute == null) {
309: return true;
310: } else {
311: return checkAttribute(servAlg, attribute, val); //$NON-NLS-1$
312: }
313: }
314: return false;
315: }
316:
317: // Returns true if this provider has the same value as is given for the
318: // given attribute
319: private boolean checkAttribute(String servAlg, String attribute,
320: String val) {
321:
322: String attributeValue = getPropertyIgnoreCase(servAlg + ' '
323: + attribute);
324: if (attributeValue != null) {
325: if (Util.equalsIgnoreCase(attribute, "KeySize")) { //$NON-NLS-1$
326: if (Integer.valueOf(attributeValue).compareTo(
327: Integer.valueOf(val)) >= 0) {
328: return true;
329: }
330: } else { // other attributes
331: if (Util.equalsIgnoreCase(attributeValue, val)) {
332: return true;
333: }
334: }
335: }
336: return false;
337: }
338:
339: /**
340: *
341: * Set the provider preference order number.
342: *
343: * @param n
344: */
345: void setProviderNumber(int n) {
346: providerNumber = n;
347: }
348:
349: /**
350: *
351: * Get the provider preference order number.
352: *
353: * @return
354: */
355: int getProviderNumber() {
356: return providerNumber;
357: }
358:
359: /**
360: * Get the service of the specified type
361: *
362: */
363: synchronized Provider.Service getService(String type) {
364: updatePropertyServiceTable();
365: if (lastServicesByType != null && type.equals(lastType)) {
366: return lastServicesByType;
367: }
368: Provider.Service service;
369: for (Iterator<Service> it = getServices().iterator(); it
370: .hasNext();) {
371: service = it.next();
372: if (type.equals(service.type)) {
373: lastType = type;
374: lastServicesByType = service;
375: return service;
376: }
377: }
378: return null;
379: }
380:
381: public synchronized Provider.Service getService(String type,
382: String algorithm) {
383: if (type == null || algorithm == null) {
384: throw new NullPointerException();
385: }
386:
387: if (type.equals(lastServiceName)
388: && Util.equalsIgnoreCase(algorithm, lastAlgorithm)) {
389: return returnedService;
390: }
391:
392: String alg = Util.toUpperCase(algorithm);
393: Object o = null;
394: if (serviceTable != null) {
395: o = serviceTable.get(type, alg);
396: }
397: if (o == null && aliasTable != null) {
398: o = aliasTable.get(type, alg);
399: }
400: if (o == null) {
401: updatePropertyServiceTable();
402: }
403: if (o == null && propertyServiceTable != null) {
404: o = propertyServiceTable.get(type, alg);
405: }
406: if (o == null && propertyAliasTable != null) {
407: o = propertyAliasTable.get(type, alg);
408: }
409:
410: if (o != null) {
411: lastServiceName = type;
412: lastAlgorithm = algorithm;
413: returnedService = (Provider.Service) o;
414: return returnedService;
415: }
416: return null;
417: }
418:
419: public synchronized Set<Provider.Service> getServices() {
420: updatePropertyServiceTable();
421: if (lastServicesSet != null) {
422: return lastServicesSet;
423: }
424: if (serviceTable != null) {
425: lastServicesSet = new HashSet<Service>(serviceTable
426: .values());
427: } else {
428: lastServicesSet = new HashSet<Service>();
429: }
430: if (propertyServiceTable != null) {
431: lastServicesSet.addAll(propertyServiceTable.values());
432: }
433: lastServicesSet = Collections.unmodifiableSet(lastServicesSet);
434: return lastServicesSet;
435: }
436:
437: protected synchronized void putService(Provider.Service s) {
438: if (s == null) {
439: throw new NullPointerException();
440: }
441: SecurityManager sm = System.getSecurityManager();
442: if (sm != null) {
443: sm.checkSecurityAccess("putProviderProperty." + name); //$NON-NLS-1$
444: }
445: if ("Provider".equals(s.getType())) { // Provider service type cannot be //$NON-NLS-1$
446: // added
447: return;
448: }
449: servicesChanged();
450: if (serviceTable == null) {
451: serviceTable = new TwoKeyHashMap<String, String, Service>(
452: 128);
453: }
454: serviceTable.put(s.type, Util.toUpperCase(s.algorithm), s);
455: if (s.aliases != null) {
456: if (aliasTable == null) {
457: aliasTable = new TwoKeyHashMap<String, String, Service>(
458: 256);
459: }
460: for (Iterator<String> it = s.getAliases(); it.hasNext();) {
461: aliasTable.put(s.type, Util.toUpperCase(it.next()), s);
462: }
463: }
464: serviceInfoToProperties(s);
465: }
466:
467: protected synchronized void removeService(Provider.Service s) {
468: if (s == null) {
469: throw new NullPointerException();
470: }
471: SecurityManager sm = System.getSecurityManager();
472: if (sm != null) {
473: sm.checkSecurityAccess("removeProviderProperty." + name); //$NON-NLS-1$
474: }
475: servicesChanged();
476: if (serviceTable != null) {
477: serviceTable.remove(s.type, Util.toUpperCase(s.algorithm));
478: }
479: if (aliasTable != null && s.aliases != null) {
480: for (Iterator<String> it = s.getAliases(); it.hasNext();) {
481: aliasTable.remove(s.type, Util.toUpperCase(it.next()));
482: }
483: }
484: serviceInfoFromProperties(s);
485: }
486:
487: // Add Service information to the provider's properties.
488: private void serviceInfoToProperties(Provider.Service s) {
489: super .put(s.type + "." + s.algorithm, s.className); //$NON-NLS-1$
490: if (s.aliases != null) {
491: for (Iterator<String> i = s.aliases.iterator(); i.hasNext();) {
492: super
493: .put(
494: "Alg.Alias." + s.type + "." + i.next(), s.algorithm); //$NON-NLS-1$ //$NON-NLS-2$
495: }
496: }
497: if (s.attributes != null) {
498: for (Iterator<Map.Entry<String, String>> i = s.attributes
499: .entrySet().iterator(); i.hasNext();) {
500: Map.Entry<String, String> entry = i.next();
501: super .put(s.type
502: + "." + s.algorithm + " " + entry.getKey(), //$NON-NLS-1$ //$NON-NLS-2$
503: entry.getValue());
504: }
505: }
506: if (providerNumber != -1) {
507: // if registered then refresh Services
508: Services.setNeedRefresh();
509: }
510: }
511:
512: // Remove Service information from the provider's properties.
513: private void serviceInfoFromProperties(Provider.Service s) {
514: super .remove(s.type + "." + s.algorithm); //$NON-NLS-1$
515: if (s.aliases != null) {
516: for (Iterator<String> i = s.aliases.iterator(); i.hasNext();) {
517: super .remove("Alg.Alias." + s.type + "." + i.next()); //$NON-NLS-1$ //$NON-NLS-2$
518: }
519: }
520: if (s.attributes != null) {
521: for (Iterator<Map.Entry<String, String>> i = s.attributes
522: .entrySet().iterator(); i.hasNext();) {
523: Map.Entry<String, String> entry = i.next();
524: super .remove(s.type
525: + "." + s.algorithm + " " + entry.getKey()); //$NON-NLS-1$ //$NON-NLS-2$
526: }
527: }
528: if (providerNumber != -1) {
529: // if registered then refresh Services
530: Services.setNeedRefresh();
531: }
532: }
533:
534: // Remove property information from provider Services
535: private void removeFromPropertyServiceTable(Object key) {
536: if (key == null || !(key instanceof String)) {
537: return;
538: }
539: String k = (String) key;
540: if (k.startsWith("Provider.")) { // Provider service type is reserved //$NON-NLS-1$
541: return;
542: }
543: Provider.Service s;
544: String serviceName;
545: String algorithm = null;
546: String attribute = null;
547: int i;
548: if (k.startsWith("Alg.Alias.")) { // Alg.Alias.<crypto_service>.<aliasName>=<standardName> //$NON-NLS-1$
549: String aliasName;
550: String service_alias = k.substring(10);
551: i = service_alias.indexOf("."); //$NON-NLS-1$
552: serviceName = service_alias.substring(0, i);
553: aliasName = service_alias.substring(i + 1);
554: if (propertyAliasTable != null) {
555: propertyAliasTable.remove(serviceName, Util
556: .toUpperCase(aliasName));
557: }
558: if (propertyServiceTable != null) {
559: for (Iterator<Service> it = propertyServiceTable
560: .values().iterator(); it.hasNext();) {
561: s = it.next();
562: if (s.aliases.contains(aliasName)) {
563: s.aliases.remove(aliasName);
564: return;
565: }
566: }
567: }
568: return;
569: }
570: int j = k.indexOf("."); //$NON-NLS-1$
571: if (j == -1) { // unknown format
572: return;
573: }
574:
575: i = k.indexOf(" "); //$NON-NLS-1$
576: if (i == -1) { // <crypto_service>.<algorithm_or_type>=<className>
577: serviceName = k.substring(0, j);
578: algorithm = k.substring(j + 1);
579: if (propertyServiceTable != null) {
580: Provider.Service ser = propertyServiceTable.remove(
581: serviceName, Util.toUpperCase(algorithm));
582: if (ser != null && propertyAliasTable != null
583: && ser.aliases != null) {
584: for (Iterator<String> it = ser.aliases.iterator(); it
585: .hasNext();) {
586: propertyAliasTable.remove(serviceName, Util
587: .toUpperCase(it.next()));
588: }
589: }
590: }
591: } else { // <crypto_service>.<algorithm_or_type>
592: // <attribute_name>=<attrValue>
593: attribute = k.substring(i + 1);
594: serviceName = k.substring(0, j);
595: algorithm = k.substring(j + 1, i);
596: if (propertyServiceTable != null) {
597: Object o = propertyServiceTable.get(serviceName, Util
598: .toUpperCase(algorithm));
599: if (o != null) {
600: s = (Provider.Service) o;
601: s.attributes.remove(attribute);
602: }
603: }
604: }
605: }
606:
607: // Update provider Services if the properties was changed
608: private void updatePropertyServiceTable() {
609: Object _key;
610: Object _value;
611: Provider.Service s;
612: String serviceName;
613: String algorithm;
614: if (changedProperties == null || changedProperties.isEmpty()) {
615: return;
616: }
617: for (Iterator<Map.Entry<Object, Object>> it = changedProperties
618: .entrySet().iterator(); it.hasNext();) {
619: Map.Entry<Object, Object> entry = it.next();
620: _key = entry.getKey();
621: _value = entry.getValue();
622: if (_key == null || _value == null
623: || !(_key instanceof String)
624: || !(_value instanceof String)) {
625: continue;
626: }
627: String key = (String) _key;
628: String value = (String) _value;
629: if (key.startsWith("Provider")) { // Provider service type is reserved //$NON-NLS-1$
630: continue;
631: }
632: int i;
633: if (key.startsWith("Alg.Alias.")) { // Alg.Alias.<crypto_service>.<aliasName>=<standardName> //$NON-NLS-1$
634: String aliasName;
635: String service_alias = key.substring(10);
636: i = service_alias.indexOf("."); //$NON-NLS-1$
637: serviceName = service_alias.substring(0, i);
638: aliasName = service_alias.substring(i + 1);
639: algorithm = value;
640: String algUp = Util.toUpperCase(algorithm);
641: Object o = null;
642: if (propertyServiceTable == null) {
643: propertyServiceTable = new TwoKeyHashMap<String, String, Service>(
644: 128);
645: } else {
646: o = propertyServiceTable.get(serviceName, algUp);
647: }
648: if (o != null) {
649: s = (Provider.Service) o;
650: s.aliases.add(aliasName);
651: if (propertyAliasTable == null) {
652: propertyAliasTable = new TwoKeyHashMap<String, String, Service>(
653: 256);
654: }
655: propertyAliasTable.put(serviceName, Util
656: .toUpperCase(aliasName), s);
657: } else {
658: String className = (String) changedProperties
659: .get(serviceName + "." + algorithm); //$NON-NLS-1$
660: if (className != null) {
661: List<String> l = new ArrayList<String>();
662: l.add(aliasName);
663: s = new Provider.Service(this , serviceName,
664: algorithm, className, l,
665: new HashMap<String, String>());
666: propertyServiceTable.put(serviceName, algUp, s);
667: if (propertyAliasTable == null) {
668: propertyAliasTable = new TwoKeyHashMap<String, String, Service>(
669: 256);
670: }
671: propertyAliasTable.put(serviceName, Util
672: .toUpperCase(aliasName), s);
673: }
674: }
675: continue;
676: }
677: int j = key.indexOf("."); //$NON-NLS-1$
678: if (j == -1) { // unknown format
679: continue;
680: }
681: i = key.indexOf(" "); //$NON-NLS-1$
682: if (i == -1) { // <crypto_service>.<algorithm_or_type>=<className>
683: serviceName = key.substring(0, j);
684: algorithm = key.substring(j + 1);
685: String alg = Util.toUpperCase(algorithm);
686: Object o = null;
687: if (propertyServiceTable != null) {
688: o = propertyServiceTable.get(serviceName, alg);
689: }
690: if (o != null) {
691: s = (Provider.Service) o;
692: s.className = value;
693: } else {
694: s = new Provider.Service(this , serviceName,
695: algorithm, value, new ArrayList<String>(),
696: new HashMap<String, String>());
697: if (propertyServiceTable == null) {
698: propertyServiceTable = new TwoKeyHashMap<String, String, Service>(
699: 128);
700: }
701: propertyServiceTable.put(serviceName, alg, s);
702:
703: }
704: } else { // <crypto_service>.<algorithm_or_type>
705: // <attribute_name>=<attrValue>
706: serviceName = key.substring(0, j);
707: algorithm = key.substring(j + 1, i);
708: String attribute = key.substring(i + 1);
709: String alg = Util.toUpperCase(algorithm);
710: Object o = null;
711: if (propertyServiceTable != null) {
712: o = propertyServiceTable.get(serviceName, alg);
713: }
714: if (o != null) {
715: s = (Provider.Service) o;
716: s.attributes.put(attribute, value);
717: } else {
718: String className = (String) changedProperties
719: .get(serviceName + "." + algorithm); //$NON-NLS-1$
720: if (className != null) {
721: Map<String, String> m = new HashMap<String, String>();
722: m.put(attribute, value);
723: s = new Provider.Service(this , serviceName,
724: algorithm, className,
725: new ArrayList<String>(), m);
726: if (propertyServiceTable == null) {
727: propertyServiceTable = new TwoKeyHashMap<String, String, Service>(
728: 128);
729: }
730: propertyServiceTable.put(serviceName, alg, s);
731: }
732: }
733: }
734: }
735: servicesChanged();
736: changedProperties.clear();
737: }
738:
739: private void servicesChanged() {
740: lastServicesByType = null;
741: lastServiceName = null;
742: lastServicesSet = null;
743: }
744:
745: // These attributes should be placed in each Provider object:
746: // Provider.id name, Provider.id version, Provider.id info,
747: // Provider.id className
748: private void putProviderInfo() {
749: super .put("Provider.id name", null != name ? name : "null"); //$NON-NLS-1$
750: super .put("Provider.id version", versionString); //$NON-NLS-1$
751: super .put("Provider.id info", null != info ? info : "null"); //$NON-NLS-1$
752: super .put("Provider.id className", this .getClass().getName()); //$NON-NLS-1$
753: }
754:
755: // Searches for the property with the specified key in the provider
756: // properties. Key is not case-sensitive.
757: //
758: // @param prop
759: // @return the property value with the specified key value.
760: private String getPropertyIgnoreCase(String key) {
761: String res = getProperty(key);
762: if (res != null) {
763: return res;
764: }
765: for (Enumeration<?> e = propertyNames(); e.hasMoreElements();) {
766: String pname = (String) e.nextElement();
767: if (Util.equalsIgnoreCase(key, pname)) {
768: return getProperty(pname);
769: }
770: }
771: return null;
772: }
773:
774: public static class Service {
775: // The provider
776: private Provider provider;
777:
778: // The type of this service
779: private String type;
780:
781: // The algorithm name
782: private String algorithm;
783:
784: // The class implementing this service
785: private String className;
786:
787: // The aliases
788: private List<String> aliases;
789:
790: // The attributes
791: private Map<String, String> attributes;
792:
793: // Service implementation
794: private Class<?> implementation;
795:
796: // For newInstance() optimization
797: private String lastClassName;
798:
799: public Service(Provider provider, String type,
800: String algorithm, String className,
801: List<String> aliases, Map<String, String> attributes) {
802: if (provider == null || type == null || algorithm == null
803: || className == null) {
804: throw new NullPointerException();
805: }
806: this .provider = provider;
807: this .type = type;
808: this .algorithm = algorithm;
809: this .className = className;
810: this .aliases = aliases;
811: this .attributes = attributes;
812: }
813:
814: public final String getType() {
815: return type;
816: }
817:
818: public final String getAlgorithm() {
819: return algorithm;
820: }
821:
822: public final Provider getProvider() {
823: return provider;
824: }
825:
826: public final String getClassName() {
827: return className;
828: }
829:
830: public final String getAttribute(String name) {
831: if (name == null) {
832: throw new NullPointerException();
833: }
834: if (attributes == null) {
835: return null;
836: }
837: return attributes.get(name);
838: }
839:
840: Iterator<String> getAliases() {
841: if (aliases == null) {
842: aliases = new ArrayList<String>(0);
843: }
844: return aliases.iterator();
845: }
846:
847: public Object newInstance(Object constructorParameter)
848: throws NoSuchAlgorithmException {
849: if (implementation == null
850: || !className.equals(lastClassName)) {
851: NoSuchAlgorithmException result = AccessController
852: .doPrivileged(new PrivilegedAction<NoSuchAlgorithmException>() {
853: public NoSuchAlgorithmException run() {
854: ClassLoader cl = provider.getClass()
855: .getClassLoader();
856: if (cl == null) {
857: cl = ClassLoader
858: .getSystemClassLoader();
859: }
860: try {
861: implementation = Class.forName(
862: className, true, cl);
863: } catch (Exception e) {
864: return new NoSuchAlgorithmException(
865: Messages.getString(
866: "security.11", //$NON-NLS-1$
867: new Object[] {
868: type,
869: algorithm,
870: e }));
871: }
872: lastClassName = className;
873: return null;
874: }
875: });
876: if (result != null) {
877: throw result;
878: }
879: }
880: if (constructorParameter == null) {
881: try {
882: return implementation.newInstance();
883: } catch (Exception e) {
884: throw new NoSuchAlgorithmException(Messages
885: .getString("security.199", //$NON-NLS-1$
886: type, algorithm), e);
887: }
888: } else {
889: if (!supportsParameter(constructorParameter)) {
890: throw new InvalidParameterException(Messages
891: .getString("security.12", type)); //$NON-NLS-1$
892: }
893:
894: Class[] parameterTypes = new Class[1];
895: Object[] initargs = { constructorParameter };
896: try {
897: if (Util.equalsIgnoreCase(type, "CertStore")) { //$NON-NLS-1$
898: parameterTypes[0] = Class
899: .forName("java.security.cert.CertStoreParameters"); //$NON-NLS-1$
900: } else {
901: parameterTypes[0] = constructorParameter
902: .getClass();
903: }
904: return implementation
905: .getConstructor(parameterTypes)
906: .newInstance(initargs);
907: } catch (Exception e) {
908: throw new NoSuchAlgorithmException(Messages
909: .getString("security.199", //$NON-NLS-1$
910: type, algorithm), e);
911: }
912: }
913: }
914:
915: public boolean supportsParameter(Object parameter) {
916: return true;
917: }
918:
919: /**
920: * Answers a string containing a concise, human-readable
921: * description of the receiver.
922: *
923: *
924: * @return a printable representation for the receiver.
925: */
926: public String toString() {
927: String result = "Provider " + provider.getName() + " Service " //$NON-NLS-1$ //$NON-NLS-2$
928: + type + "." + algorithm + " " + className; //$NON-NLS-1$ //$NON-NLS-2$
929: if (aliases != null) {
930: result = result + "\nAliases " + aliases.toString(); //$NON-NLS-1$
931: }
932: if (attributes != null) {
933: result = result
934: + "\nAttributes " + attributes.toString(); //$NON-NLS-1$
935: }
936: return result;
937: }
938: }
939:
940: private void readObject(java.io.ObjectInputStream in)
941: throws NotActiveException, IOException,
942: ClassNotFoundException {
943: in.defaultReadObject();
944: versionString = String.valueOf(version);
945: providerNumber = -1;
946: }
947: }
|