Source Code Cross Referenced for Provider.java in  » 6.0-JDK-Core » security » java » security » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » security » java.security 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 1996-2006 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025
0026        package java.security;
0027
0028        import java.io.*;
0029        import java.util.*;
0030        import static java.util.Locale.ENGLISH;
0031        import java.lang.ref.*;
0032        import java.lang.reflect.*;
0033
0034        import java.security.cert.CertStoreParameters;
0035        import javax.security.auth.login.Configuration;
0036
0037        /**
0038         * This class represents a "provider" for the
0039         * Java Security API, where a provider implements some or all parts of
0040         * Java Security. Services that a provider may implement include:
0041         *
0042         * <ul>
0043         *
0044         * <li>Algorithms (such as DSA, RSA, MD5 or SHA-1).
0045         *
0046         * <li>Key generation, conversion, and management facilities (such as for
0047         * algorithm-specific keys).
0048         *
0049         *</ul>
0050         *
0051         * <p>Each provider has a name and a version number, and is configured
0052         * in each runtime it is installed in.
0053         *
0054         * <p>See <a href =
0055         * "../../../technotes/guides/security/crypto/CryptoSpec.html#Provider">The Provider Class</a>
0056         * in the "Java Cryptography Architecture API Specification &amp; Reference"
0057         * for information about how a particular type of provider, the
0058         * cryptographic service provider, works and is installed. However,
0059         * please note that a provider can be used to implement any security
0060         * service in Java that uses a pluggable architecture with a choice
0061         * of implementations that fit underneath. 
0062         *
0063         * <p>Some provider implementations may encounter unrecoverable internal
0064         * errors during their operation, for example a failure to communicate with a 
0065         * security token. A {@link ProviderException} should be used to indicate 
0066         * such errors.
0067         *
0068         * <p>The service type <code>Provider</code> is reserved for use by the
0069         * security framework. Services of this type cannot be added, removed,
0070         * or modified by applications.
0071         * The following attributes are automatically placed in each Provider object:
0072         * <table cellspacing=4>
0073         * <tr><th>Name</th><th>Value</th>
0074         * <tr><td><code>Provider.id name</code></td>
0075         *    <td><code>String.valueOf(provider.getName())</code></td>
0076         * <tr><td><code>Provider.id version</code></td>
0077         *     <td><code>String.valueOf(provider.getVersion())</code></td>
0078         * <tr><td><code>Provider.id info</code></td>
0079         <td><code>String.valueOf(provider.getInfo())</code></td>
0080         * <tr><td><code>Provider.id className</code></td>
0081         *     <td><code>provider.getClass().getName()</code></td>
0082         * </table>
0083         *
0084         * @version 1.84, 05/05/07
0085         * @author Benjamin Renaud
0086         * @author Andreas Sterbenz
0087         */
0088        public abstract class Provider extends Properties {
0089
0090            // Declare serialVersionUID to be compatible with JDK1.1
0091            static final long serialVersionUID = -4298000515446427739L;
0092
0093            private static final sun.security.util.Debug debug = sun.security.util.Debug
0094                    .getInstance("provider", "Provider");
0095
0096            /**
0097             * The provider name.
0098             *
0099             * @serial
0100             */
0101            private String name;
0102
0103            /**
0104             * A description of the provider and its services.
0105             *
0106             * @serial
0107             */
0108            private String info;
0109
0110            /**
0111             * The provider version number.
0112             *
0113             * @serial
0114             */
0115            private double version;
0116
0117            private transient Set<Map.Entry<Object, Object>> entrySet = null;
0118            private transient int entrySetCallCount = 0;
0119
0120            private transient boolean initialized;
0121
0122            /**
0123             * Constructs a provider with the specified name, version number,
0124             * and information.
0125             *
0126             * @param name the provider name.
0127             *
0128             * @param version the provider version number.
0129             *
0130             * @param info a description of the provider and its services.
0131             */
0132            protected Provider(String name, double version, String info) {
0133                this .name = name;
0134                this .version = version;
0135                this .info = info;
0136                putId();
0137                initialized = true;
0138            }
0139
0140            /**
0141             * Returns the name of this provider.
0142             *
0143             * @return the name of this provider.
0144             */
0145            public String getName() {
0146                return name;
0147            }
0148
0149            /**
0150             * Returns the version number for this provider.
0151             *
0152             * @return the version number for this provider.
0153             */
0154            public double getVersion() {
0155                return version;
0156            }
0157
0158            /**
0159             * Returns a human-readable description of the provider and its
0160             * services.  This may return an HTML page, with relevant links.
0161             *
0162             * @return a description of the provider and its services.
0163             */
0164            public String getInfo() {
0165                return info;
0166            }
0167
0168            /**
0169             * Returns a string with the name and the version number
0170             * of this provider.
0171             *
0172             * @return the string with the name and the version number
0173             * for this provider.
0174             */
0175            public String toString() {
0176                return name + " version " + version;
0177            }
0178
0179            /*
0180             * override the following methods to ensure that provider
0181             * information can only be changed if the caller has the appropriate
0182             * permissions.
0183             */
0184
0185            /**
0186             * Clears this provider so that it no longer contains the properties
0187             * used to look up facilities implemented by the provider.
0188             * 
0189             * <p>First, if there is a security manager, its 
0190             * <code>checkSecurityAccess</code> method is called with the string 
0191             * <code>"clearProviderProperties."+name</code> (where <code>name</code> 
0192             * is the provider name) to see if it's ok to clear this provider.
0193             * If the default implementation of <code>checkSecurityAccess</code> 
0194             * is used (that is, that method is not overriden), then this results in
0195             * a call to the security manager's <code>checkPermission</code> method 
0196             * with a <code>SecurityPermission("clearProviderProperties."+name)</code>
0197             * permission.
0198             *
0199             * @throws  SecurityException
0200             *          if a security manager exists and its <code>{@link
0201             *          java.lang.SecurityManager#checkSecurityAccess}</code> method 
0202             *          denies access to clear this provider
0203             *
0204             * @since 1.2
0205             */
0206            public synchronized void clear() {
0207                check("clearProviderProperties." + name);
0208                if (debug != null) {
0209                    debug.println("Remove " + name + " provider properties");
0210                }
0211                implClear();
0212            }
0213
0214            /**
0215             * Reads a property list (key and element pairs) from the input stream.
0216             *
0217             * @param inStream   the input stream.
0218             * @exception  IOException  if an error occurred when reading from the
0219             *               input stream.
0220             * @see java.util.Properties#load
0221             */
0222            public synchronized void load(InputStream inStream)
0223                    throws IOException {
0224                check("putProviderProperty." + name);
0225                if (debug != null) {
0226                    debug.println("Load " + name + " provider properties");
0227                }
0228                Properties tempProperties = new Properties();
0229                tempProperties.load(inStream);
0230                implPutAll(tempProperties);
0231            }
0232
0233            /**
0234             * Copies all of the mappings from the specified Map to this provider.
0235             * These mappings will replace any properties that this provider had 
0236             * for any of the keys currently in the specified Map. 
0237             *
0238             * @since 1.2
0239             */
0240            public synchronized void putAll(Map<?, ?> t) {
0241                check("putProviderProperty." + name);
0242                if (debug != null) {
0243                    debug.println("Put all " + name + " provider properties");
0244                }
0245                implPutAll(t);
0246            }
0247
0248            /**
0249             * Returns an unmodifiable Set view of the property entries contained 
0250             * in this Provider.
0251             *
0252             * @see   java.util.Map.Entry
0253             * @since 1.2
0254             */
0255            public synchronized Set<Map.Entry<Object, Object>> entrySet() {
0256                checkInitialized();
0257                if (entrySet == null) {
0258                    if (entrySetCallCount++ == 0) // Initial call
0259                        entrySet = Collections.unmodifiableMap(this ).entrySet();
0260                    else
0261                        return super .entrySet(); // Recursive call
0262                }
0263
0264                // This exception will be thrown if the implementation of 
0265                // Collections.unmodifiableMap.entrySet() is changed such that it
0266                // no longer calls entrySet() on the backing Map.  (Provider's
0267                // entrySet implementation depends on this "implementation detail",
0268                // which is unlikely to change.
0269                if (entrySetCallCount != 2)
0270                    throw new RuntimeException("Internal error.");
0271
0272                return entrySet;
0273            }
0274
0275            /**
0276             * Returns an unmodifiable Set view of the property keys contained in 
0277             * this provider.
0278             *
0279             * @since 1.2
0280             */
0281            public Set<Object> keySet() {
0282                checkInitialized();
0283                return Collections.unmodifiableSet(super .keySet());
0284            }
0285
0286            /**
0287             * Returns an unmodifiable Collection view of the property values 
0288             * contained in this provider.
0289             *
0290             * @since 1.2
0291             */
0292            public Collection<Object> values() {
0293                checkInitialized();
0294                return Collections.unmodifiableCollection(super .values());
0295            }
0296
0297            /**
0298             * Sets the <code>key</code> property to have the specified
0299             * <code>value</code>.
0300             * 
0301             * <p>First, if there is a security manager, its 
0302             * <code>checkSecurityAccess</code> method is called with the string 
0303             * <code>"putProviderProperty."+name</code>, where <code>name</code> is the
0304             * provider name, to see if it's ok to set this provider's property values. 
0305             * If the default implementation of <code>checkSecurityAccess</code>
0306             * is used (that is, that method is not overriden), then this results in
0307             * a call to the security manager's <code>checkPermission</code> method 
0308             * with a <code>SecurityPermission("putProviderProperty."+name)</code>
0309             * permission.
0310             *
0311             * @param key the property key.
0312             *
0313             * @param value the property value.
0314             *
0315             * @return the previous value of the specified property
0316             * (<code>key</code>), or null if it did not have one.
0317             *
0318             * @throws  SecurityException
0319             *          if a security manager exists and its <code>{@link
0320             *          java.lang.SecurityManager#checkSecurityAccess}</code> method 
0321             *          denies access to set property values.
0322             *
0323             * @since 1.2
0324             */
0325            public synchronized Object put(Object key, Object value) {
0326                check("putProviderProperty." + name);
0327                if (debug != null) {
0328                    debug.println("Set " + name + " provider property [" + key
0329                            + "/" + value + "]");
0330                }
0331                return implPut(key, value);
0332            }
0333
0334            /**
0335             * Removes the <code>key</code> property (and its corresponding
0336             * <code>value</code>).
0337             * 
0338             * <p>First, if there is a security manager, its 
0339             * <code>checkSecurityAccess</code> method is called with the string 
0340             * <code>"removeProviderProperty."+name</code>, where <code>name</code> is
0341             * the provider name, to see if it's ok to remove this provider's 
0342             * properties. If the default implementation of 
0343             * <code>checkSecurityAccess</code> is used (that is, that method is not 
0344             * overriden), then this results in a call to the security manager's 
0345             * <code>checkPermission</code> method with a
0346             * <code>SecurityPermission("removeProviderProperty."+name)</code>
0347             * permission.
0348             *
0349             * @param key the key for the property to be removed.
0350             *
0351             * @return the value to which the key had been mapped,
0352             * or null if the key did not have a mapping.
0353             *
0354             * @throws  SecurityException
0355             *          if a security manager exists and its <code>{@link
0356             *          java.lang.SecurityManager#checkSecurityAccess}</code> method 
0357             *          denies access to remove this provider's properties.
0358             *
0359             * @since 1.2
0360             */
0361            public synchronized Object remove(Object key) {
0362                check("removeProviderProperty." + name);
0363                if (debug != null) {
0364                    debug.println("Remove " + name + " provider property "
0365                            + key);
0366                }
0367                return implRemove(key);
0368            }
0369
0370            // let javadoc show doc from superclass
0371            public Object get(Object key) {
0372                checkInitialized();
0373                return super .get(key);
0374            }
0375
0376            // let javadoc show doc from superclass
0377            public Enumeration<Object> keys() {
0378                checkInitialized();
0379                return super .keys();
0380            }
0381
0382            // let javadoc show doc from superclass
0383            public Enumeration<Object> elements() {
0384                checkInitialized();
0385                return super .elements();
0386            }
0387
0388            // let javadoc show doc from superclass
0389            public String getProperty(String key) {
0390                checkInitialized();
0391                return super .getProperty(key);
0392            }
0393
0394            private void checkInitialized() {
0395                if (!initialized) {
0396                    throw new IllegalStateException();
0397                }
0398            }
0399
0400            private void check(String directive) {
0401                checkInitialized();
0402                SecurityManager security = System.getSecurityManager();
0403                if (security != null) {
0404                    security.checkSecurityAccess(directive);
0405                }
0406            }
0407
0408            // legacy properties changed since last call to any services method?
0409            private transient boolean legacyChanged;
0410            // serviceMap changed since last call to getServices()
0411            private transient boolean servicesChanged;
0412
0413            // Map<String,String>
0414            private transient Map<String, String> legacyStrings;
0415
0416            // Map<ServiceKey,Service>
0417            // used for services added via putService(), initialized on demand
0418            private transient Map<ServiceKey, Service> serviceMap;
0419
0420            // Map<ServiceKey,Service>
0421            // used for services added via legacy methods, init on demand
0422            private transient Map<ServiceKey, Service> legacyMap;
0423
0424            // Set<Service>
0425            // Unmodifiable set of all services. Initialized on demand.
0426            private transient Set<Service> serviceSet;
0427
0428            // register the id attributes for this provider
0429            // this is to ensure that equals() and hashCode() do not incorrectly
0430            // report to different provider objects as the same
0431            private void putId() {
0432                // note: name and info may be null
0433                super .put("Provider.id name", String.valueOf(name));
0434                super .put("Provider.id version", String.valueOf(version));
0435                super .put("Provider.id info", String.valueOf(info));
0436                super .put("Provider.id className", this .getClass().getName());
0437            }
0438
0439            private void readObject(ObjectInputStream in) throws IOException,
0440                    ClassNotFoundException {
0441                Map<Object, Object> copy = new HashMap<Object, Object>();
0442                for (Map.Entry<Object, Object> entry : super .entrySet()) {
0443                    copy.put(entry.getKey(), entry.getValue());
0444                }
0445                defaults = null;
0446                in.defaultReadObject();
0447                implClear();
0448                initialized = true;
0449                putAll(copy);
0450            }
0451
0452            /**
0453             * Copies all of the mappings from the specified Map to this provider.
0454             * Internal method to be called AFTER the security check has been
0455             * performed.
0456             */
0457            private void implPutAll(Map t) {
0458                for (Map.Entry e : ((Map<?, ?>) t).entrySet()) {
0459                    implPut(e.getKey(), e.getValue());
0460                }
0461            }
0462
0463            private Object implRemove(Object key) {
0464                if (key instanceof  String) {
0465                    String keyString = (String) key;
0466                    if (keyString.startsWith("Provider.")) {
0467                        return null;
0468                    }
0469                    legacyChanged = true;
0470                    if (legacyStrings == null) {
0471                        legacyStrings = new LinkedHashMap<String, String>();
0472                    }
0473                    legacyStrings.remove(keyString);
0474                }
0475                return super .remove(key);
0476            }
0477
0478            private Object implPut(Object key, Object value) {
0479                if ((key instanceof  String) && (value instanceof  String)) {
0480                    String keyString = (String) key;
0481                    if (keyString.startsWith("Provider.")) {
0482                        return null;
0483                    }
0484                    legacyChanged = true;
0485                    if (legacyStrings == null) {
0486                        legacyStrings = new LinkedHashMap<String, String>();
0487                    }
0488                    legacyStrings.put(keyString, (String) value);
0489                }
0490                return super .put(key, value);
0491            }
0492
0493            private void implClear() {
0494                if (legacyStrings != null) {
0495                    legacyStrings.clear();
0496                }
0497                if (legacyMap != null) {
0498                    legacyMap.clear();
0499                }
0500                if (serviceMap != null) {
0501                    serviceMap.clear();
0502                }
0503                legacyChanged = false;
0504                servicesChanged = false;
0505                serviceSet = null;
0506                super .clear();
0507                putId();
0508            }
0509
0510            // used as key in the serviceMap and legacyMap HashMaps
0511            private static class ServiceKey {
0512                private final String type;
0513                private final String algorithm;
0514                private final String originalAlgorithm;
0515
0516                private ServiceKey(String type, String algorithm, boolean intern) {
0517                    this .type = type;
0518                    this .originalAlgorithm = algorithm;
0519                    algorithm = algorithm.toUpperCase(ENGLISH);
0520                    this .algorithm = intern ? algorithm.intern() : algorithm;
0521                }
0522
0523                public int hashCode() {
0524                    return type.hashCode() + algorithm.hashCode();
0525                }
0526
0527                public boolean equals(Object obj) {
0528                    if (this  == obj) {
0529                        return true;
0530                    }
0531                    if (obj instanceof  ServiceKey == false) {
0532                        return false;
0533                    }
0534                    ServiceKey other = (ServiceKey) obj;
0535                    return this .type.equals(other.type)
0536                            && this .algorithm.equals(other.algorithm);
0537                }
0538
0539                boolean matches(String type, String algorithm) {
0540                    return (this .type == type)
0541                            && (this .originalAlgorithm == algorithm);
0542                }
0543            }
0544
0545            /**
0546             * Ensure all the legacy String properties are fully parsed into
0547             * service objects.
0548             */
0549            private void ensureLegacyParsed() {
0550                if ((legacyChanged == false) || (legacyStrings == null)) {
0551                    return;
0552                }
0553                serviceSet = null;
0554                if (legacyMap == null) {
0555                    legacyMap = new LinkedHashMap<ServiceKey, Service>();
0556                } else {
0557                    legacyMap.clear();
0558                }
0559                for (Map.Entry<String, String> entry : legacyStrings.entrySet()) {
0560                    parseLegacyPut(entry.getKey(), entry.getValue());
0561                }
0562                removeInvalidServices(legacyMap);
0563                legacyChanged = false;
0564            }
0565
0566            /**
0567             * Remove all invalid services from the Map. Invalid services can only
0568             * occur if the legacy properties are inconsistent or incomplete.
0569             */
0570            private void removeInvalidServices(Map<ServiceKey, Service> map) {
0571                for (Iterator t = map.entrySet().iterator(); t.hasNext();) {
0572                    Map.Entry entry = (Map.Entry) t.next();
0573                    Service s = (Service) entry.getValue();
0574                    if (s.isValid() == false) {
0575                        t.remove();
0576                    }
0577                }
0578            }
0579
0580            private String[] getTypeAndAlgorithm(String key) {
0581                int i = key.indexOf(".");
0582                if (i < 1) {
0583                    if (debug != null) {
0584                        debug.println("Ignoring invalid entry in provider "
0585                                + name + ":" + key);
0586                    }
0587                    return null;
0588                }
0589                String type = key.substring(0, i);
0590                String alg = key.substring(i + 1);
0591                return new String[] { type, alg };
0592            }
0593
0594            private final static String ALIAS_PREFIX = "Alg.Alias.";
0595            private final static String ALIAS_PREFIX_LOWER = "alg.alias.";
0596            private final static int ALIAS_LENGTH = ALIAS_PREFIX.length();
0597
0598            private void parseLegacyPut(String name, String value) {
0599                if (name.toLowerCase(ENGLISH).startsWith(ALIAS_PREFIX_LOWER)) {
0600                    // e.g. put("Alg.Alias.MessageDigest.SHA", "SHA-1");
0601                    // aliasKey ~ MessageDigest.SHA
0602                    String stdAlg = value;
0603                    String aliasKey = name.substring(ALIAS_LENGTH);
0604                    String[] typeAndAlg = getTypeAndAlgorithm(aliasKey);
0605                    if (typeAndAlg == null) {
0606                        return;
0607                    }
0608                    String type = getEngineName(typeAndAlg[0]);
0609                    String aliasAlg = typeAndAlg[1].intern();
0610                    ServiceKey key = new ServiceKey(type, stdAlg, true);
0611                    Service s = (Service) legacyMap.get(key);
0612                    if (s == null) {
0613                        s = new Service(this );
0614                        s.type = type;
0615                        s.algorithm = stdAlg;
0616                        legacyMap.put(key, s);
0617                    }
0618                    legacyMap.put(new ServiceKey(type, aliasAlg, true), s);
0619                    s.addAlias(aliasAlg);
0620                } else {
0621                    String[] typeAndAlg = getTypeAndAlgorithm(name);
0622                    if (typeAndAlg == null) {
0623                        return;
0624                    }
0625                    int i = typeAndAlg[1].indexOf(' ');
0626                    if (i == -1) {
0627                        // e.g. put("MessageDigest.SHA-1", "sun.security.provider.SHA");
0628                        String type = getEngineName(typeAndAlg[0]);
0629                        String stdAlg = typeAndAlg[1].intern();
0630                        String className = value;
0631                        ServiceKey key = new ServiceKey(type, stdAlg, true);
0632                        Service s = (Service) legacyMap.get(key);
0633                        if (s == null) {
0634                            s = new Service(this );
0635                            s.type = type;
0636                            s.algorithm = stdAlg;
0637                            legacyMap.put(key, s);
0638                        }
0639                        s.className = className;
0640                    } else { // attribute
0641                        // e.g. put("MessageDigest.SHA-1 ImplementedIn", "Software");
0642                        String attributeValue = value;
0643                        String type = getEngineName(typeAndAlg[0]);
0644                        String attributeString = typeAndAlg[1];
0645                        String stdAlg = attributeString.substring(0, i)
0646                                .intern();
0647                        String attributeName = attributeString.substring(i + 1);
0648                        // kill additional spaces
0649                        while (attributeName.startsWith(" ")) {
0650                            attributeName = attributeName.substring(1);
0651                        }
0652                        attributeName = attributeName.intern();
0653                        ServiceKey key = new ServiceKey(type, stdAlg, true);
0654                        Service s = (Service) legacyMap.get(key);
0655                        if (s == null) {
0656                            s = new Service(this );
0657                            s.type = type;
0658                            s.algorithm = stdAlg;
0659                            legacyMap.put(key, s);
0660                        }
0661                        s.addAttribute(attributeName, attributeValue);
0662                    }
0663                }
0664            }
0665
0666            /**
0667             * Get the service describing this Provider's implementation of the
0668             * specified type of this algorithm or alias. If no such
0669             * implementation exists, this method returns null. If there are two
0670             * matching services, one added to this provider using 
0671             * {@link #putService putService()} and one added via {@link #put put()},
0672             * the service added via {@link #putService putService()} is returned.
0673             *
0674             * @param type the type of {@link Service service} requested
0675             * (for example, <code>MessageDigest</code>)
0676             * @param algorithm the case insensitive algorithm name (or alternate 
0677             * alias) of the service requested (for example, <code>SHA-1</code>)
0678             *
0679             * @return the service describing this Provider's matching service
0680             * or null if no such service exists
0681             *
0682             * @throws NullPointerException if type or algorithm is null
0683             *
0684             * @since 1.5
0685             */
0686            public synchronized Service getService(String type, String algorithm) {
0687                checkInitialized();
0688                // avoid allocating a new key object if possible
0689                ServiceKey key = previousKey;
0690                if (key.matches(type, algorithm) == false) {
0691                    key = new ServiceKey(type, algorithm, false);
0692                    previousKey = key;
0693                }
0694                if (serviceMap != null) {
0695                    Service service = serviceMap.get(key);
0696                    if (service != null) {
0697                        return service;
0698                    }
0699                }
0700                ensureLegacyParsed();
0701                return (legacyMap != null) ? legacyMap.get(key) : null;
0702            }
0703
0704            // ServiceKey from previous getService() call
0705            // by re-using it if possible we avoid allocating a new object
0706            // and the toUpperCase() call.
0707            // re-use will occur e.g. as the framework traverses the provider
0708            // list and queries each provider with the same values until it finds
0709            // a matching service
0710            private static volatile ServiceKey previousKey = new ServiceKey("",
0711                    "", false);
0712
0713            /**
0714             * Get an unmodifiable Set of all services supported by
0715             * this Provider.
0716             *
0717             * @return an unmodifiable Set of all services supported by
0718             * this Provider
0719             *
0720             * @since 1.5
0721             */
0722            public synchronized Set<Service> getServices() {
0723                checkInitialized();
0724                if (legacyChanged || servicesChanged) {
0725                    serviceSet = null;
0726                }
0727                if (serviceSet == null) {
0728                    ensureLegacyParsed();
0729                    Set<Service> set = new LinkedHashSet<Service>();
0730                    if (serviceMap != null) {
0731                        set.addAll(serviceMap.values());
0732                    }
0733                    if (legacyMap != null) {
0734                        set.addAll(legacyMap.values());
0735                    }
0736                    serviceSet = Collections.unmodifiableSet(set);
0737                    servicesChanged = false;
0738                }
0739                return serviceSet;
0740            }
0741
0742            /**
0743             * Add a service. If a service of the same type with the same algorithm
0744             * name exists and it was added using {@link #putService putService()}, 
0745             * it is replaced by the new service. 
0746             * This method also places information about this service
0747             * in the provider's Hashtable values in the format described in the
0748             * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html">
0749             * Java Cryptography Architecture API Specification &amp; Reference </a>.
0750             *
0751             * <p>Also, if there is a security manager, its 
0752             * <code>checkSecurityAccess</code> method is called with the string 
0753             * <code>"putProviderProperty."+name</code>, where <code>name</code> is 
0754             * the provider name, to see if it's ok to set this provider's property 
0755             * values. If the default implementation of <code>checkSecurityAccess</code>
0756             * is used (that is, that method is not overriden), then this results in
0757             * a call to the security manager's <code>checkPermission</code> method with
0758             * a <code>SecurityPermission("putProviderProperty."+name)</code>
0759             * permission.
0760             *
0761             * @param s the Service to add
0762             *
0763             * @throws SecurityException
0764             *      if a security manager exists and its <code>{@link
0765             *      java.lang.SecurityManager#checkSecurityAccess}</code> method denies
0766             *      access to set property values.
0767             * @throws NullPointerException if s is null
0768             *
0769             * @since 1.5
0770             */
0771            protected synchronized void putService(Service s) {
0772                check("putProviderProperty." + name);
0773                if (debug != null) {
0774                    debug.println(name + ".putService(): " + s);
0775                }
0776                if (s == null) {
0777                    throw new NullPointerException();
0778                }
0779                if (s.getProvider() != this ) {
0780                    throw new IllegalArgumentException(
0781                            "service.getProvider() must match this Provider object");
0782                }
0783                if (serviceMap == null) {
0784                    serviceMap = new LinkedHashMap<ServiceKey, Service>();
0785                }
0786                servicesChanged = true;
0787                String type = s.getType();
0788                String algorithm = s.getAlgorithm();
0789                ServiceKey key = new ServiceKey(type, algorithm, true);
0790                // remove existing service
0791                implRemoveService(serviceMap.get(key));
0792                serviceMap.put(key, s);
0793                for (String alias : s.getAliases()) {
0794                    serviceMap.put(new ServiceKey(type, alias, true), s);
0795                }
0796                putPropertyStrings(s);
0797            }
0798
0799            /**
0800             * Put the string properties for this Service in this Provider's
0801             * Hashtable.
0802             */
0803            private void putPropertyStrings(Service s) {
0804                String type = s.getType();
0805                String algorithm = s.getAlgorithm();
0806                // use super() to avoid permission check and other processing
0807                super .put(type + "." + algorithm, s.getClassName());
0808                for (String alias : s.getAliases()) {
0809                    super .put(ALIAS_PREFIX + type + "." + alias, algorithm);
0810                }
0811                for (Map.Entry<UString, String> entry : s.attributes.entrySet()) {
0812                    String key = type + "." + algorithm + " " + entry.getKey();
0813                    super .put(key, entry.getValue());
0814                }
0815            }
0816
0817            /**
0818             * Remove the string properties for this Service from this Provider's
0819             * Hashtable.
0820             */
0821            private void removePropertyStrings(Service s) {
0822                String type = s.getType();
0823                String algorithm = s.getAlgorithm();
0824                // use super() to avoid permission check and other processing
0825                super .remove(type + "." + algorithm);
0826                for (String alias : s.getAliases()) {
0827                    super .remove(ALIAS_PREFIX + type + "." + alias);
0828                }
0829                for (Map.Entry<UString, String> entry : s.attributes.entrySet()) {
0830                    String key = type + "." + algorithm + " " + entry.getKey();
0831                    super .remove(key);
0832                }
0833            }
0834
0835            /**
0836             * Remove a service previously added using 
0837             * {@link #putService putService()}. The specified service is removed from
0838             * this provider. It will no longer be returned by 
0839             * {@link #getService getService()} and its information will be removed 
0840             * from this provider's Hashtable.
0841             *
0842             * <p>Also, if there is a security manager, its 
0843             * <code>checkSecurityAccess</code> method is called with the string 
0844             * <code>"removeProviderProperty."+name</code>, where <code>name</code> is 
0845             * the provider name, to see if it's ok to remove this provider's 
0846             * properties. If the default implementation of 
0847             * <code>checkSecurityAccess</code> is used (that is, that method is not 
0848             * overriden), then this results in a call to the security manager's 
0849             * <code>checkPermission</code> method with a
0850             * <code>SecurityPermission("removeProviderProperty."+name)</code>
0851             * permission.
0852             *
0853             * @param s the Service to be removed
0854             *
0855             * @throws  SecurityException
0856             *          if a security manager exists and its <code>{@link
0857             *          java.lang.SecurityManager#checkSecurityAccess}</code> method denies
0858             *          access to remove this provider's properties.
0859             * @throws NullPointerException if s is null
0860             *
0861             * @since 1.5
0862             */
0863            protected synchronized void removeService(Service s) {
0864                check("removeProviderProperty." + name);
0865                if (debug != null) {
0866                    debug.println(name + ".removeService(): " + s);
0867                }
0868                if (s == null) {
0869                    throw new NullPointerException();
0870                }
0871                implRemoveService(s);
0872            }
0873
0874            private void implRemoveService(Service s) {
0875                if ((s == null) || (serviceMap == null)) {
0876                    return;
0877                }
0878                String type = s.getType();
0879                String algorithm = s.getAlgorithm();
0880                ServiceKey key = new ServiceKey(type, algorithm, false);
0881                Service oldService = serviceMap.get(key);
0882                if (s != oldService) {
0883                    return;
0884                }
0885                servicesChanged = true;
0886                serviceMap.remove(key);
0887                for (String alias : s.getAliases()) {
0888                    serviceMap.remove(new ServiceKey(type, alias, false));
0889                }
0890                removePropertyStrings(s);
0891            }
0892
0893            // Wrapped String that behaves in a case insensitive way for equals/hashCode
0894            private static class UString {
0895                final String string;
0896                final String lowerString;
0897
0898                UString(String s) {
0899                    this .string = s;
0900                    this .lowerString = s.toLowerCase(ENGLISH);
0901                }
0902
0903                public int hashCode() {
0904                    return lowerString.hashCode();
0905                }
0906
0907                public boolean equals(Object obj) {
0908                    if (this  == obj) {
0909                        return true;
0910                    }
0911                    if (obj instanceof  UString == false) {
0912                        return false;
0913                    }
0914                    UString other = (UString) obj;
0915                    return lowerString.equals(other.lowerString);
0916                }
0917
0918                public String toString() {
0919                    return string;
0920                }
0921            }
0922
0923            // describe relevant properties of a type of engine
0924            private static class EngineDescription {
0925                final String name;
0926                final boolean supportsParameter;
0927                final String constructorParameterClassName;
0928                private volatile Class constructorParameterClass;
0929
0930                EngineDescription(String name, boolean sp, String paramName) {
0931                    this .name = name;
0932                    this .supportsParameter = sp;
0933                    this .constructorParameterClassName = paramName;
0934                }
0935
0936                Class getConstructorParameterClass()
0937                        throws ClassNotFoundException {
0938                    Class clazz = constructorParameterClass;
0939                    if (clazz == null) {
0940                        clazz = Class.forName(constructorParameterClassName);
0941                        constructorParameterClass = clazz;
0942                    }
0943                    return clazz;
0944                }
0945            }
0946
0947            // built in knowledge of the engine types shipped as part of the JDK
0948            private static final Map<String, EngineDescription> knownEngines;
0949
0950            private static void addEngine(String name, boolean sp,
0951                    String paramName) {
0952                EngineDescription ed = new EngineDescription(name, sp,
0953                        paramName);
0954                // also index by canonical name to avoid toLowerCase() for some lookups
0955                knownEngines.put(name.toLowerCase(ENGLISH), ed);
0956                knownEngines.put(name, ed);
0957            }
0958
0959            static {
0960                knownEngines = new HashMap<String, EngineDescription>();
0961                // JCA
0962                addEngine("AlgorithmParameterGenerator", false, null);
0963                addEngine("AlgorithmParameters", false, null);
0964                addEngine("KeyFactory", false, null);
0965                addEngine("KeyPairGenerator", false, null);
0966                addEngine("KeyStore", false, null);
0967                addEngine("MessageDigest", false, null);
0968                addEngine("SecureRandom", false, null);
0969                addEngine("Signature", true, null);
0970                addEngine("CertificateFactory", false, null);
0971                addEngine("CertPathBuilder", false, null);
0972                addEngine("CertPathValidator", false, null);
0973                addEngine("CertStore", false,
0974                        "java.security.cert.CertStoreParameters");
0975                // JCE
0976                addEngine("Cipher", true, null);
0977                addEngine("ExemptionMechanism", false, null);
0978                addEngine("Mac", true, null);
0979                addEngine("KeyAgreement", true, null);
0980                addEngine("KeyGenerator", false, null);
0981                addEngine("SecretKeyFactory", false, null);
0982                // JSSE
0983                addEngine("KeyManagerFactory", false, null);
0984                addEngine("SSLContext", false, null);
0985                addEngine("TrustManagerFactory", false, null);
0986                // JGSS
0987                addEngine("GssApiMechanism", false, null);
0988                // SASL
0989                addEngine("SaslClientFactory", false, null);
0990                addEngine("SaslServerFactory", false, null);
0991                // POLICY
0992                addEngine("Policy", false, "java.security.Policy$Parameters");
0993                // CONFIGURATION
0994                addEngine("Configuration", false,
0995                        "javax.security.auth.login.Configuration$Parameters");
0996                // XML DSig
0997                addEngine("XMLSignatureFactory", false, null);
0998                addEngine("KeyInfoFactory", false, null);
0999                addEngine("TransformService", false, null);
1000                // Smart Card I/O
1001                addEngine("TerminalFactory", false, "java.lang.Object");
1002            }
1003
1004            // get the "standard" (mixed-case) engine name for arbitary case engine name
1005            // if there is no known engine by that name, return s
1006            private static String getEngineName(String s) {
1007                // try original case first, usually correct
1008                EngineDescription e = knownEngines.get(s);
1009                if (e == null) {
1010                    e = knownEngines.get(s.toLowerCase(ENGLISH));
1011                }
1012                return (e == null) ? s : e.name;
1013            }
1014
1015            /**
1016             * The description of a security service. It encapsulates the properties
1017             * of a service and contains a factory method to obtain new implementation
1018             * instances of this service.
1019             *
1020             * <p>Each service has a provider that offers the service, a type,
1021             * an algorithm name, and the name of the class that implements the
1022             * service. Optionally, it also includes a list of alternate algorithm
1023             * names for this service (aliases) and attributes, which are a map of
1024             * (name, value) String pairs.
1025             *
1026             * <p>This class defines the methods {@link #supportsParameter 
1027             * supportsParameter()} and {@link #newInstance newInstance()}
1028             * which are used by the Java security framework when it searches for
1029             * suitable services and instantes them. The valid arguments to those 
1030             * methods depend on the type of service. For the service types defined 
1031             * within Java SE, see the
1032             * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html">
1033             * Java Cryptography Architecture API Specification &amp; Reference </a>
1034             * for the valid values.
1035             * Note that components outside of Java SE can define additional types of 
1036             * services and their behavior.
1037             *
1038             * <p>Instances of this class are immutable.
1039             *
1040             * @since 1.5
1041             */
1042            public static class Service {
1043
1044                private String type, algorithm, className;
1045                private final Provider provider;
1046                private List<String> aliases;
1047                private Map<UString, String> attributes;
1048
1049                // Reference to the cached implementation Class object
1050                private volatile Reference<Class> classRef;
1051
1052                // flag indicating whether this service has its attributes for
1053                // supportedKeyFormats or supportedKeyClasses set
1054                // if null, the values have not been initialized
1055                // if TRUE, at least one of supportedFormats/Classes is non null
1056                private volatile Boolean hasKeyAttributes;
1057
1058                // supported encoding formats
1059                private String[] supportedFormats;
1060
1061                // names of the supported key (super) classes
1062                private Class[] supportedClasses;
1063
1064                // whether this service has been registered with the Provider
1065                private boolean registered;
1066
1067                private static final Class[] CLASS0 = new Class[0];
1068
1069                // this constructor and these methods are used for parsing
1070                // the legacy string properties.
1071
1072                private Service(Provider provider) {
1073                    this .provider = provider;
1074                    aliases = Collections.<String> emptyList();
1075                    attributes = Collections.<UString, String> emptyMap();
1076                }
1077
1078                private boolean isValid() {
1079                    return (type != null) && (algorithm != null)
1080                            && (className != null);
1081                }
1082
1083                private void addAlias(String alias) {
1084                    if (aliases.isEmpty()) {
1085                        aliases = new ArrayList<String>(2);
1086                    }
1087                    aliases.add(alias);
1088                }
1089
1090                void addAttribute(String type, String value) {
1091                    if (attributes.isEmpty()) {
1092                        attributes = new HashMap<UString, String>(8);
1093                    }
1094                    attributes.put(new UString(type), value);
1095                }
1096
1097                /**
1098                 * Construct a new service.
1099                 *
1100                 * @param provider the provider that offers this service
1101                 * @param type the type of this service
1102                 * @param algorithm the algorithm name
1103                 * @param className the name of the class implementing this service
1104                 * @param aliases List of aliases or null if algorithm has no aliases
1105                 * @param attributes Map of attributes or null if this implementation
1106                 *		     has no attributes
1107                 *
1108                 * @throws NullPointerException if provider, type, algorithm, or
1109                 * className is null
1110                 */
1111                public Service(Provider provider, String type,
1112                        String algorithm, String className,
1113                        List<String> aliases, Map<String, String> attributes) {
1114                    if ((provider == null) || (type == null)
1115                            || (algorithm == null) || (className == null)) {
1116                        throw new NullPointerException();
1117                    }
1118                    this .provider = provider;
1119                    this .type = getEngineName(type);
1120                    this .algorithm = algorithm;
1121                    this .className = className;
1122                    if (aliases == null) {
1123                        this .aliases = Collections.<String> emptyList();
1124                    } else {
1125                        this .aliases = new ArrayList<String>(aliases);
1126                    }
1127                    if (attributes == null) {
1128                        this .attributes = Collections
1129                                .<UString, String> emptyMap();
1130                    } else {
1131                        this .attributes = new HashMap<UString, String>();
1132                        for (Map.Entry<String, String> entry : attributes
1133                                .entrySet()) {
1134                            this .attributes.put(new UString(entry.getKey()),
1135                                    entry.getValue());
1136                        }
1137                    }
1138                }
1139
1140                /**
1141                 * Get the type of this service. For example, <code>MessageDigest</code>.
1142                 *
1143                 * @return the type of this service
1144                 */
1145                public final String getType() {
1146                    return type;
1147                }
1148
1149                /**
1150                 * Return the name of the algorithm of this service. For example,
1151                 * <code>SHA-1</code>.
1152                 *
1153                 * @return the algorithm of this service
1154                 */
1155                public final String getAlgorithm() {
1156                    return algorithm;
1157                }
1158
1159                /**
1160                 * Return the Provider of this service.
1161                 *
1162                 * @return the Provider of this service
1163                 */
1164                public final Provider getProvider() {
1165                    return provider;
1166                }
1167
1168                /**
1169                 * Return the name of the class implementing this service.
1170                 *
1171                 * @return the name of the class implementing this service
1172                 */
1173                public final String getClassName() {
1174                    return className;
1175                }
1176
1177                // internal only
1178                private final List<String> getAliases() {
1179                    return aliases;
1180                }
1181
1182                /**
1183                 * Return the value of the specified attribute or null if this
1184                 * attribute is not set for this Service.
1185                 *
1186                 * @param name the name of the requested attribute
1187                 *
1188                 * @return the value of the specified attribute or null if the
1189                 *         attribute is not present
1190                 *
1191                 * @throws NullPointerException if name is null
1192                 */
1193                public final String getAttribute(String name) {
1194                    if (name == null) {
1195                        throw new NullPointerException();
1196                    }
1197                    return attributes.get(new UString(name));
1198                }
1199
1200                /**
1201                 * Return a new instance of the implementation described by this
1202                 * service. The security provider framework uses this method to
1203                 * construct implementations. Applications will typically not need 
1204                 * to call it.
1205                 *
1206                 * <p>The default implementation uses reflection to invoke the
1207                 * standard constructor for this type of service.
1208                 * Security providers can override this method to implement
1209                 * instantiation in a different way.
1210                 * For details and the values of constructorParameter that are 
1211                 * valid for the various types of services see the
1212                 * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html">
1213                 * Java Cryptography Architecture API Specification &amp; 
1214                 * Reference</a>.
1215                 *
1216                 * @param constructorParameter the value to pass to the constructor,
1217                 * or null if this type of service does not use a constructorParameter.
1218                 *
1219                 * @return a new implementation of this service
1220                 *
1221                 * @throws InvalidParameterException if the value of 
1222                 * constructorParameter is invalid for this type of service.
1223                 * @throws NoSuchAlgorithmException if instantation failed for
1224                 * any other reason.
1225                 */
1226                public Object newInstance(Object constructorParameter)
1227                        throws NoSuchAlgorithmException {
1228                    if (registered == false) {
1229                        if (provider.getService(type, algorithm) != this ) {
1230                            throw new NoSuchAlgorithmException(
1231                                    "Service not registered with Provider "
1232                                            + provider.getName() + ": " + this );
1233                        }
1234                        registered = true;
1235                    }
1236                    try {
1237                        EngineDescription cap = knownEngines.get(type);
1238                        if (cap == null) {
1239                            // unknown engine type, use generic code
1240                            // this is the code path future for non-core
1241                            // optional packages
1242                            return newInstanceGeneric(constructorParameter);
1243                        }
1244                        if (cap.constructorParameterClassName == null) {
1245                            if (constructorParameter != null) {
1246                                throw new InvalidParameterException(
1247                                        "constructorParameter not used with "
1248                                                + type + " engines");
1249                            }
1250                            Class clazz = getImplClass();
1251                            return clazz.newInstance();
1252                        } else {
1253                            Class paramClass = cap
1254                                    .getConstructorParameterClass();
1255                            if (constructorParameter != null) {
1256                                Class argClass = constructorParameter
1257                                        .getClass();
1258                                if (paramClass.isAssignableFrom(argClass) == false) {
1259                                    throw new InvalidParameterException(
1260                                            "constructorParameter must be instanceof "
1261                                                    + cap.constructorParameterClassName
1262                                                            .replace('$', '.')
1263                                                    + " for engine type "
1264                                                    + type);
1265                                }
1266                            }
1267                            Class clazz = getImplClass();
1268                            Constructor cons = clazz.getConstructor(paramClass);
1269                            return cons.newInstance(constructorParameter);
1270                        }
1271                    } catch (NoSuchAlgorithmException e) {
1272                        throw e;
1273                    } catch (InvocationTargetException e) {
1274                        throw new NoSuchAlgorithmException(
1275                                "Error constructing implementation (algorithm: "
1276                                        + algorithm + ", provider: "
1277                                        + provider.getName() + ", class: "
1278                                        + className + ")", e.getCause());
1279                    } catch (Exception e) {
1280                        throw new NoSuchAlgorithmException(
1281                                "Error constructing implementation (algorithm: "
1282                                        + algorithm + ", provider: "
1283                                        + provider.getName() + ", class: "
1284                                        + className + ")", e);
1285                    }
1286                }
1287
1288                // return the implementation Class object for this service
1289                private Class getImplClass() throws NoSuchAlgorithmException {
1290                    try {
1291                        Reference<Class> ref = classRef;
1292                        Class clazz = (ref == null) ? null : ref.get();
1293                        if (clazz == null) {
1294                            ClassLoader cl = provider.getClass()
1295                                    .getClassLoader();
1296                            if (cl == null) {
1297                                clazz = Class.forName(className);
1298                            } else {
1299                                clazz = cl.loadClass(className);
1300                            }
1301                            classRef = new WeakReference<Class>(clazz);
1302                        }
1303                        return clazz;
1304                    } catch (ClassNotFoundException e) {
1305                        throw new NoSuchAlgorithmException(
1306                                "class configured for " + type + "(provider: "
1307                                        + provider.getName() + ")"
1308                                        + "cannot be found.", e);
1309                    }
1310                }
1311
1312                /**
1313                 * Generic code path for unknown engine types. Call the
1314                 * no-args constructor if constructorParameter is null, otherwise
1315                 * use the first matching constructor.
1316                 */
1317                private Object newInstanceGeneric(Object constructorParameter)
1318                        throws Exception {
1319                    Class clazz = getImplClass();
1320                    if (constructorParameter == null) {
1321                        Object o = clazz.newInstance();
1322                        return o;
1323                    }
1324                    Class argClass = constructorParameter.getClass();
1325                    Constructor[] cons = clazz.getConstructors();
1326                    // find first public constructor that can take the
1327                    // argument as parameter
1328                    for (int i = 0; i < cons.length; i++) {
1329                        Constructor con = cons[i];
1330                        Class[] paramTypes = con.getParameterTypes();
1331                        if (paramTypes.length != 1) {
1332                            continue;
1333                        }
1334                        if (paramTypes[0].isAssignableFrom(argClass) == false) {
1335                            continue;
1336                        }
1337                        Object o = con
1338                                .newInstance(new Object[] { constructorParameter });
1339                        return o;
1340                    }
1341                    throw new NoSuchAlgorithmException(
1342                            "No constructor matching " + argClass.getName()
1343                                    + " found in class " + className);
1344                }
1345
1346                /**
1347                 * Test whether this Service can use the specified parameter.
1348                 * Returns false if this service cannot use the parameter. Returns
1349                 * true if this service can use the parameter, if a fast test is
1350                 * infeasible, or if the status is unknown.
1351                 *
1352                 * <p>The security provider framework uses this method with
1353                 * some types of services to quickly exclude non-matching
1354                 * implementations for consideration. 
1355                 * Applications will typically not need to call it.
1356                 *
1357                 * <p>For details and the values of parameter that are valid for the 
1358                 * various types of services see the top of this class and the
1359                 * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html">
1360                 * Java Cryptography Architecture API Specification &amp; 
1361                 * Reference</a>.
1362                 * Security providers can override it to implement their own test.
1363                 *
1364                 * @param parameter the parameter to test
1365                 *
1366                 * @return false if this this service cannot use the specified
1367                 * parameter; true if it can possibly use the parameter
1368                 *
1369                 * @throws InvalidParameterException if the value of parameter is 
1370                 * invalid for this type of service or if this method cannot be 
1371                 * used with this type of service
1372                 */
1373                public boolean supportsParameter(Object parameter) {
1374                    EngineDescription cap = knownEngines.get(type);
1375                    if (cap == null) {
1376                        // unknown engine type, return true by default
1377                        return true;
1378                    }
1379                    if (cap.supportsParameter == false) {
1380                        throw new InvalidParameterException(
1381                                "supportsParameter() not " + "used with "
1382                                        + type + " engines");
1383                    }
1384                    // allow null for keys without attributes for compatibility
1385                    if ((parameter != null)
1386                            && (parameter instanceof  Key == false)) {
1387                        throw new InvalidParameterException(
1388                                "Parameter must be instanceof Key for engine "
1389                                        + type);
1390                    }
1391                    if (hasKeyAttributes() == false) {
1392                        return true;
1393                    }
1394                    if (parameter == null) {
1395                        return false;
1396                    }
1397                    Key key = (Key) parameter;
1398                    if (supportsKeyFormat(key)) {
1399                        return true;
1400                    }
1401                    if (supportsKeyClass(key)) {
1402                        return true;
1403                    }
1404                    return false;
1405                }
1406
1407                /**
1408                 * Return whether this service has its Supported* properties for
1409                 * keys defined. Parses the attributes if not yet initialized.
1410                 */
1411                private boolean hasKeyAttributes() {
1412                    Boolean b = hasKeyAttributes;
1413                    if (b == null) {
1414                        synchronized (this ) {
1415                            String s;
1416                            s = getAttribute("SupportedKeyFormats");
1417                            if (s != null) {
1418                                supportedFormats = s.split("\\|");
1419                            }
1420                            s = getAttribute("SupportedKeyClasses");
1421                            if (s != null) {
1422                                String[] classNames = s.split("\\|");
1423                                List<Class> classList = new ArrayList<Class>(
1424                                        classNames.length);
1425                                for (String className : classNames) {
1426                                    Class clazz = getKeyClass(className);
1427                                    if (clazz != null) {
1428                                        classList.add(clazz);
1429                                    }
1430                                }
1431                                supportedClasses = classList.toArray(CLASS0);
1432                            }
1433                            boolean bool = (supportedFormats != null)
1434                                    || (supportedClasses != null);
1435                            b = Boolean.valueOf(bool);
1436                            hasKeyAttributes = b;
1437                        }
1438                    }
1439                    return b.booleanValue();
1440                }
1441
1442                // get the key class object of the specified name
1443                private Class getKeyClass(String name) {
1444                    try {
1445                        return Class.forName(name);
1446                    } catch (ClassNotFoundException e) {
1447                        // ignore
1448                    }
1449                    try {
1450                        ClassLoader cl = provider.getClass().getClassLoader();
1451                        if (cl != null) {
1452                            return cl.loadClass(name);
1453                        }
1454                    } catch (ClassNotFoundException e) {
1455                        // ignore
1456                    }
1457                    return null;
1458                }
1459
1460                private boolean supportsKeyFormat(Key key) {
1461                    if (supportedFormats == null) {
1462                        return false;
1463                    }
1464                    String format = key.getFormat();
1465                    if (format == null) {
1466                        return false;
1467                    }
1468                    for (String supportedFormat : supportedFormats) {
1469                        if (supportedFormat.equals(format)) {
1470                            return true;
1471                        }
1472                    }
1473                    return false;
1474                }
1475
1476                private boolean supportsKeyClass(Key key) {
1477                    if (supportedClasses == null) {
1478                        return false;
1479                    }
1480                    Class keyClass = key.getClass();
1481                    for (Class clazz : supportedClasses) {
1482                        if (clazz.isAssignableFrom(keyClass)) {
1483                            return true;
1484                        }
1485                    }
1486                    return false;
1487                }
1488
1489                /**
1490                 * Return a String representation of this service.
1491                 *
1492                 * @return a String representation of this service.
1493                 */
1494                public String toString() {
1495                    String aString = aliases.isEmpty() ? "" : "\r\n  aliases: "
1496                            + aliases.toString();
1497                    String attrs = attributes.isEmpty() ? ""
1498                            : "\r\n  attributes: " + attributes.toString();
1499                    return provider.getName() + ": " + type + "." + algorithm
1500                            + " -> " + className + aString + attrs + "\r\n";
1501                }
1502
1503            }
1504
1505        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.