Source Code Cross Referenced for Security.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.lang.reflect.*;
0029        import java.util.*;
0030        import java.util.concurrent.ConcurrentHashMap;
0031        import java.io.*;
0032        import java.net.URL;
0033        import sun.security.util.Debug;
0034        import sun.security.util.PropertyExpander;
0035
0036        import java.security.Provider.Service;
0037
0038        import sun.security.jca.*;
0039
0040        /**
0041         * <p>This class centralizes all security properties and common security
0042         * methods. One of its primary uses is to manage providers.
0043         *
0044         * @author Benjamin Renaud
0045         * @version 1.140, 05/05/07
0046         */
0047
0048        public final class Security {
0049
0050            /* Are we debugging? -- for developers */
0051            private static final Debug sdebug = Debug.getInstance("properties");
0052
0053            /* The java.security properties */
0054            private static Properties props;
0055
0056            // An element in the cache
0057            private static class ProviderProperty {
0058                String className;
0059                Provider provider;
0060            }
0061
0062            static {
0063                // doPrivileged here because there are multiple
0064                // things in initialize that might require privs.
0065                // (the FileInputStream call and the File.exists call,
0066                // the securityPropFile call, etc)
0067                AccessController.doPrivileged(new PrivilegedAction<Void>() {
0068                    public Void run() {
0069                        initialize();
0070                        return null;
0071                    }
0072                });
0073            }
0074
0075            private static void initialize() {
0076                props = new Properties();
0077                boolean loadedProps = false;
0078                boolean overrideAll = false;
0079
0080                // first load the system properties file
0081                // to determine the value of security.overridePropertiesFile
0082                File propFile = securityPropFile("java.security");
0083                if (propFile.exists()) {
0084                    InputStream is = null;
0085                    try {
0086                        FileInputStream fis = new FileInputStream(propFile);
0087                        is = new BufferedInputStream(fis);
0088                        props.load(is);
0089                        loadedProps = true;
0090
0091                        if (sdebug != null) {
0092                            sdebug.println("reading security properties file: "
0093                                    + propFile);
0094                        }
0095                    } catch (IOException e) {
0096                        if (sdebug != null) {
0097                            sdebug
0098                                    .println("unable to load security properties from "
0099                                            + propFile);
0100                            e.printStackTrace();
0101                        }
0102                    } finally {
0103                        if (is != null) {
0104                            try {
0105                                is.close();
0106                            } catch (IOException ioe) {
0107                                if (sdebug != null) {
0108                                    sdebug
0109                                            .println("unable to close input stream");
0110                                }
0111                            }
0112                        }
0113                    }
0114                }
0115
0116                if ("true".equalsIgnoreCase(props
0117                        .getProperty("security.overridePropertiesFile"))) {
0118
0119                    String extraPropFile = System
0120                            .getProperty("java.security.properties");
0121                    if (extraPropFile != null && extraPropFile.startsWith("=")) {
0122                        overrideAll = true;
0123                        extraPropFile = extraPropFile.substring(1);
0124                    }
0125
0126                    if (overrideAll) {
0127                        props = new Properties();
0128                        if (sdebug != null) {
0129                            sdebug
0130                                    .println("overriding other security properties files!");
0131                        }
0132                    }
0133
0134                    // now load the user-specified file so its values
0135                    // will win if they conflict with the earlier values
0136                    if (extraPropFile != null) {
0137                        BufferedInputStream bis = null;
0138                        try {
0139                            URL propURL;
0140
0141                            extraPropFile = PropertyExpander
0142                                    .expand(extraPropFile);
0143                            propFile = new File(extraPropFile);
0144                            if (propFile.exists()) {
0145                                propURL = new URL("file:"
0146                                        + propFile.getCanonicalPath());
0147                            } else {
0148                                propURL = new URL(extraPropFile);
0149                            }
0150                            bis = new BufferedInputStream(propURL.openStream());
0151                            props.load(bis);
0152                            loadedProps = true;
0153
0154                            if (sdebug != null) {
0155                                sdebug
0156                                        .println("reading security properties file: "
0157                                                + propURL);
0158                                if (overrideAll) {
0159                                    sdebug
0160                                            .println("overriding other security properties files!");
0161                                }
0162                            }
0163                        } catch (Exception e) {
0164                            if (sdebug != null) {
0165                                sdebug
0166                                        .println("unable to load security properties from "
0167                                                + extraPropFile);
0168                                e.printStackTrace();
0169                            }
0170                        } finally {
0171                            if (bis != null) {
0172                                try {
0173                                    bis.close();
0174                                } catch (IOException ioe) {
0175                                    if (sdebug != null) {
0176                                        sdebug
0177                                                .println("unable to close input stream");
0178                                    }
0179                                }
0180                            }
0181                        }
0182                    }
0183                }
0184
0185                if (!loadedProps) {
0186                    initializeStatic();
0187                    if (sdebug != null) {
0188                        sdebug.println("unable to load security properties "
0189                                + "-- using defaults");
0190                    }
0191                }
0192
0193            }
0194
0195            /* 
0196             * Initialize to default values, if <java.home>/lib/java.security
0197             * is not found.
0198             */
0199            private static void initializeStatic() {
0200                props.put("security.provider.1", "sun.security.provider.Sun");
0201                props.put("security.provider.2", "sun.security.rsa.SunRsaSign");
0202                props.put("security.provider.3",
0203                        "com.sun.net.ssl.internal.ssl.Provider");
0204                props.put("security.provider.4",
0205                        "com.sun.crypto.provider.SunJCE");
0206                props.put("security.provider.5",
0207                        "sun.security.jgss.SunProvider");
0208                props.put("security.provider.6",
0209                        "com.sun.security.sasl.Provider");
0210            }
0211
0212            /**
0213             * Don't let anyone instantiate this. 
0214             */
0215            private Security() {
0216            }
0217
0218            private static File securityPropFile(String filename) {
0219                // maybe check for a system property which will specify where to
0220                // look. Someday.
0221                String sep = File.separator;
0222                return new File(System.getProperty("java.home") + sep + "lib"
0223                        + sep + "security" + sep + filename);
0224            }
0225
0226            /**
0227             * Looks up providers, and returns the property (and its associated
0228             * provider) mapping the key, if any.
0229             * The order in which the providers are looked up is the
0230             * provider-preference order, as specificed in the security
0231             * properties file.
0232             */
0233            private static ProviderProperty getProviderProperty(String key) {
0234                ProviderProperty entry = null;
0235
0236                List<Provider> providers = Providers.getProviderList()
0237                        .providers();
0238                for (int i = 0; i < providers.size(); i++) {
0239
0240                    String matchKey = null;
0241                    Provider prov = providers.get(i);
0242                    String prop = prov.getProperty(key);
0243
0244                    if (prop == null) {
0245                        // Is there a match if we do a case-insensitive property name
0246                        // comparison? Let's try ...
0247                        for (Enumeration<Object> e = prov.keys(); e
0248                                .hasMoreElements()
0249                                && prop == null;) {
0250                            matchKey = (String) e.nextElement();
0251                            if (key.equalsIgnoreCase(matchKey)) {
0252                                prop = prov.getProperty(matchKey);
0253                                break;
0254                            }
0255                        }
0256                    }
0257
0258                    if (prop != null) {
0259                        ProviderProperty newEntry = new ProviderProperty();
0260                        newEntry.className = prop;
0261                        newEntry.provider = prov;
0262                        return newEntry;
0263                    }
0264                }
0265
0266                return entry;
0267            }
0268
0269            /**
0270             * Returns the property (if any) mapping the key for the given provider.
0271             */
0272            private static String getProviderProperty(String key,
0273                    Provider provider) {
0274                String prop = provider.getProperty(key);
0275                if (prop == null) {
0276                    // Is there a match if we do a case-insensitive property name
0277                    // comparison? Let's try ...
0278                    for (Enumeration<Object> e = provider.keys(); e
0279                            .hasMoreElements()
0280                            && prop == null;) {
0281                        String matchKey = (String) e.nextElement();
0282                        if (key.equalsIgnoreCase(matchKey)) {
0283                            prop = provider.getProperty(matchKey);
0284                            break;
0285                        }
0286                    }
0287                }
0288                return prop;
0289            }
0290
0291            /** 
0292             * Gets a specified property for an algorithm. The algorithm name
0293             * should be a standard name. See Appendix A in the <a href=
0294             * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
0295             * Java Cryptography Architecture API Specification &amp; Reference </a> 
0296             * for information about standard algorithm names.
0297             * One possible use is by specialized algorithm parsers, which may map 
0298             * classes to algorithms which they understand (much like Key parsers 
0299             * do).
0300             *
0301             * @param algName the algorithm name.
0302             *
0303             * @param propName the name of the property to get.
0304             * 
0305             * @return the value of the specified property.  
0306             *
0307             * @deprecated This method used to return the value of a proprietary
0308             * property in the master file of the "SUN" Cryptographic Service
0309             * Provider in order to determine how to parse algorithm-specific
0310             * parameters. Use the new provider-based and algorithm-independent
0311             * <code>AlgorithmParameters</code> and <code>KeyFactory</code> engine
0312             * classes (introduced in the J2SE version 1.2 platform) instead.
0313             */
0314            @Deprecated
0315            public static String getAlgorithmProperty(String algName,
0316                    String propName) {
0317                ProviderProperty entry = getProviderProperty("Alg." + propName
0318                        + "." + algName);
0319                if (entry != null) {
0320                    return entry.className;
0321                } else {
0322                    return null;
0323                }
0324            }
0325
0326            /**
0327             * Adds a new provider, at a specified position. The position is
0328             * the preference order in which providers are searched for
0329             * requested algorithms.  The position is 1-based, that is,
0330             * 1 is most preferred, followed by 2, and so on.
0331             * 
0332             * <p>If the given provider is installed at the requested position,
0333             * the provider that used to be at that position, and all providers
0334             * with a position greater than <code>position</code>, are shifted up
0335             * one position (towards the end of the list of installed providers).
0336             * 
0337             * <p>A provider cannot be added if it is already installed.
0338             * 
0339             * <p>First, if there is a security manager, its
0340             * <code>checkSecurityAccess</code> 
0341             * method is called with the string
0342             * <code>"insertProvider."+provider.getName()</code> 
0343             * to see if it's ok to add a new provider. 
0344             * If the default implementation of <code>checkSecurityAccess</code> 
0345             * is used (i.e., that method is not overriden), then this will result in
0346             * a call to the security manager's <code>checkPermission</code> method
0347             * with a
0348             * <code>SecurityPermission("insertProvider."+provider.getName())</code>
0349             * permission.
0350             *
0351             * @param provider the provider to be added.
0352             *
0353             * @param position the preference position that the caller would
0354             * like for this provider.
0355             * 
0356             * @return the actual preference position in which the provider was 
0357             * added, or -1 if the provider was not added because it is
0358             * already installed.
0359             *
0360             * @throws  NullPointerException if provider is null
0361             * @throws  SecurityException
0362             *          if a security manager exists and its <code>{@link
0363             *          java.lang.SecurityManager#checkSecurityAccess}</code> method
0364             *          denies access to add a new provider
0365             *
0366             * @see #getProvider
0367             * @see #removeProvider 
0368             * @see java.security.SecurityPermission
0369             */
0370            public static synchronized int insertProviderAt(Provider provider,
0371                    int position) {
0372                String providerName = provider.getName();
0373                check("insertProvider." + providerName);
0374                ProviderList list = Providers.getFullProviderList();
0375                ProviderList newList = ProviderList.insertAt(list, provider,
0376                        position - 1);
0377                if (list == newList) {
0378                    return -1;
0379                }
0380                Providers.setProviderList(newList);
0381                return newList.getIndex(providerName) + 1;
0382            }
0383
0384            /**
0385             * Adds a provider to the next position available.
0386             *
0387             * <p>First, if there is a security manager, its
0388             * <code>checkSecurityAccess</code> 
0389             * method is called with the string
0390             * <code>"insertProvider."+provider.getName()</code> 
0391             * to see if it's ok to add a new provider. 
0392             * If the default implementation of <code>checkSecurityAccess</code> 
0393             * is used (i.e., that method is not overriden), then this will result in
0394             * a call to the security manager's <code>checkPermission</code> method
0395             * with a
0396             * <code>SecurityPermission("insertProvider."+provider.getName())</code>
0397             * permission.
0398             * 
0399             * @param provider the provider to be added.
0400             *
0401             * @return the preference position in which the provider was 
0402             * added, or -1 if the provider was not added because it is
0403             * already installed.
0404             *
0405             * @throws  NullPointerException if provider is null
0406             * @throws  SecurityException
0407             *          if a security manager exists and its <code>{@link
0408             *          java.lang.SecurityManager#checkSecurityAccess}</code> method
0409             *          denies access to add a new provider
0410             * 
0411             * @see #getProvider
0412             * @see #removeProvider
0413             * @see java.security.SecurityPermission
0414             */
0415            public static int addProvider(Provider provider) {
0416                /*
0417                 * We can't assign a position here because the statically
0418                 * registered providers may not have been installed yet. 
0419                 * insertProviderAt() will fix that value after it has 
0420                 * loaded the static providers.
0421                 */
0422                return insertProviderAt(provider, 0);
0423            }
0424
0425            /**
0426             * Removes the provider with the specified name.
0427             *
0428             * <p>When the specified provider is removed, all providers located
0429             * at a position greater than where the specified provider was are shifted
0430             * down one position (towards the head of the list of installed
0431             * providers).
0432             *
0433             * <p>This method returns silently if the provider is not installed or
0434             * if name is null.
0435             * 
0436             * <p>First, if there is a security manager, its
0437             * <code>checkSecurityAccess</code> 
0438             * method is called with the string <code>"removeProvider."+name</code> 
0439             * to see if it's ok to remove the provider. 
0440             * If the default implementation of <code>checkSecurityAccess</code> 
0441             * is used (i.e., that method is not overriden), then this will result in
0442             * a call to the security manager's <code>checkPermission</code> method
0443             * with a <code>SecurityPermission("removeProvider."+name)</code>
0444             * permission.
0445             *
0446             * @param name the name of the provider to remove.
0447             *
0448             * @throws  SecurityException
0449             *          if a security manager exists and its <code>{@link
0450             *          java.lang.SecurityManager#checkSecurityAccess}</code> method
0451             *          denies
0452             *          access to remove the provider
0453             *
0454             * @see #getProvider
0455             * @see #addProvider
0456             */
0457            public static synchronized void removeProvider(String name) {
0458                check("removeProvider." + name);
0459                ProviderList list = Providers.getFullProviderList();
0460                ProviderList newList = ProviderList.remove(list, name);
0461                Providers.setProviderList(newList);
0462            }
0463
0464            /**
0465             * Returns an array containing all the installed providers. The order of
0466             * the providers in the array is their preference order.
0467             * 
0468             * @return an array of all the installed providers.
0469             */
0470            public static Provider[] getProviders() {
0471                return Providers.getFullProviderList().toArray();
0472            }
0473
0474            /**
0475             * Returns the provider installed with the specified name, if
0476             * any. Returns null if no provider with the specified name is
0477             * installed or if name is null.
0478             * 
0479             * @param name the name of the provider to get.
0480             * 
0481             * @return the provider of the specified name.
0482             *
0483             * @see #removeProvider
0484             * @see #addProvider
0485             */
0486            public static Provider getProvider(String name) {
0487                return Providers.getProviderList().getProvider(name);
0488            }
0489
0490            /**
0491             * Returns an array containing all installed providers that satisfy the
0492             * specified selection criterion, or null if no such providers have been
0493             * installed. The returned providers are ordered
0494             * according to their <a href=
0495             * "#insertProviderAt(java.security.Provider, int)">preference order</a>. 
0496             *  
0497             * <p> A cryptographic service is always associated with a particular
0498             * algorithm or type. For example, a digital signature service is
0499             * always associated with a particular algorithm (e.g., DSA),
0500             * and a CertificateFactory service is always associated with
0501             * a particular certificate type (e.g., X.509).
0502             *
0503             * <p>The selection criterion must be specified in one of the following two
0504             * formats:
0505             * <ul>
0506             * <li> <i>&lt;crypto_service>.&lt;algorithm_or_type></i> <p> The
0507             * cryptographic service name must not contain any dots.
0508             * <p> A 
0509             * provider satisfies the specified selection criterion iff the provider 
0510             * implements the 
0511             * specified algorithm or type for the specified cryptographic service.
0512             * <p> For example, "CertificateFactory.X.509" 
0513             * would be satisfied by any provider that supplied
0514             * a CertificateFactory implementation for X.509 certificates.
0515             * <li> <i>&lt;crypto_service>.&lt;algorithm_or_type> 
0516             * &lt;attribute_name>:&lt attribute_value></i>
0517             * <p> The cryptographic service name must not contain any dots. There
0518             * must be one or more space charaters between the the
0519             * <i>&lt;algorithm_or_type></i> and the <i>&lt;attribute_name></i>.
0520             *  <p> A provider satisfies this selection criterion iff the
0521             * provider implements the specified algorithm or type for the specified 
0522             * cryptographic service and its implementation meets the
0523             * constraint expressed by the specified attribute name/value pair.
0524             * <p> For example, "Signature.SHA1withDSA KeySize:1024" would be
0525             * satisfied by any provider that implemented
0526             * the SHA1withDSA signature algorithm with a keysize of 1024 (or larger).
0527             *
0528             * </ul>
0529             *
0530             * <p> See Appendix A in the <a href=
0531             * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
0532             * Java Cryptography Architecture API Specification &amp; Reference </a>
0533             * for information about standard cryptographic service names, standard
0534             * algorithm names and standard attribute names.
0535             *
0536             * @param filter the criterion for selecting
0537             * providers. The filter is case-insensitive.
0538             *
0539             * @return all the installed providers that satisfy the selection
0540             * criterion, or null if no such providers have been installed.
0541             *
0542             * @throws InvalidParameterException
0543             *         if the filter is not in the required format
0544             * @throws NullPointerException if filter is null
0545             *
0546             * @see #getProviders(java.util.Map)
0547             * @since 1.3
0548             */
0549            public static Provider[] getProviders(String filter) {
0550                String key = null;
0551                String value = null;
0552                int index = filter.indexOf(':');
0553
0554                if (index == -1) {
0555                    key = filter;
0556                    value = "";
0557                } else {
0558                    key = filter.substring(0, index);
0559                    value = filter.substring(index + 1);
0560                }
0561
0562                Hashtable<String, String> hashtableFilter = new Hashtable<String, String>(
0563                        1);
0564                hashtableFilter.put(key, value);
0565
0566                return (getProviders(hashtableFilter));
0567            }
0568
0569            /**
0570             * Returns an array containing all installed providers that satisfy the 
0571             * specified* selection criteria, or null if no such providers have been
0572             * installed. The returned providers are ordered
0573             * according to their <a href=
0574             * "#insertProviderAt(java.security.Provider, int)">preference order</a>. 
0575             * 
0576             * <p>The selection criteria are represented by a map.
0577             * Each map entry represents a selection criterion. 
0578             * A provider is selected iff it satisfies all selection
0579             * criteria. The key for any entry in such a map must be in one of the
0580             * following two formats:
0581             * <ul>
0582             * <li> <i>&lt;crypto_service>.&lt;algorithm_or_type></i>
0583             * <p> The cryptographic service name must not contain any dots.
0584             * <p> The value associated with the key must be an empty string.
0585             * <p> A provider
0586             * satisfies this selection criterion iff the provider implements the 
0587             * specified algorithm or type for the specified cryptographic service.
0588             * <li>  <i>&lt;crypto_service>.&lt;algorithm_or_type> &lt;attribute_name></i>
0589             * <p> The cryptographic service name must not contain any dots. There
0590             * must be one or more space charaters between the <i>&lt;algorithm_or_type></i>
0591             * and the <i>&lt;attribute_name></i>.
0592             * <p> The value associated with the key must be a non-empty string.
0593             * A provider satisfies this selection criterion iff the
0594             * provider implements the specified algorithm or type for the specified 
0595             * cryptographic service and its implementation meets the
0596             * constraint expressed by the specified attribute name/value pair. 
0597             * </ul>
0598             *
0599             * <p> See Appendix A in the <a href=
0600             * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
0601             * Java Cryptography Architecture API Specification &amp; Reference </a>
0602             * for information about standard cryptographic service names, standard
0603             * algorithm names and standard attribute names.
0604             *
0605             * @param filter the criteria for selecting
0606             * providers. The filter is case-insensitive.
0607             *
0608             * @return all the installed providers that satisfy the selection
0609             * criteria, or null if no such providers have been installed. 
0610             *
0611             * @throws InvalidParameterException
0612             *         if the filter is not in the required format
0613             * @throws NullPointerException if filter is null
0614             *
0615             * @see #getProviders(java.lang.String)
0616             * @since 1.3
0617             */
0618            public static Provider[] getProviders(Map<String, String> filter) {
0619                // Get all installed providers first.
0620                // Then only return those providers who satisfy the selection criteria.
0621                Provider[] allProviders = Security.getProviders();
0622                Set<String> keySet = filter.keySet();
0623                LinkedHashSet<Provider> candidates = new LinkedHashSet<Provider>(
0624                        5);
0625
0626                // Returns all installed providers
0627                // if the selection criteria is null.
0628                if ((keySet == null) || (allProviders == null)) {
0629                    return allProviders;
0630                }
0631
0632                boolean firstSearch = true;
0633
0634                // For each selection criterion, remove providers
0635                // which don't satisfy the criterion from the candidate set.
0636                for (Iterator<String> ite = keySet.iterator(); ite.hasNext();) {
0637                    String key = ite.next();
0638                    String value = filter.get(key);
0639
0640                    LinkedHashSet<Provider> newCandidates = getAllQualifyingCandidates(
0641                            key, value, allProviders);
0642                    if (firstSearch) {
0643                        candidates = newCandidates;
0644                        firstSearch = false;
0645                    }
0646
0647                    if ((newCandidates != null) && !newCandidates.isEmpty()) {
0648                        // For each provider in the candidates set, if it
0649                        // isn't in the newCandidate set, we should remove
0650                        // it from the candidate set.
0651                        for (Iterator<Provider> cansIte = candidates.iterator(); cansIte
0652                                .hasNext();) {
0653                            Provider prov = cansIte.next();
0654                            if (!newCandidates.contains(prov)) {
0655                                cansIte.remove();
0656                            }
0657                        }
0658                    } else {
0659                        candidates = null;
0660                        break;
0661                    }
0662                }
0663
0664                if ((candidates == null) || (candidates.isEmpty()))
0665                    return null;
0666
0667                Object[] candidatesArray = candidates.toArray();
0668                Provider[] result = new Provider[candidatesArray.length];
0669
0670                for (int i = 0; i < result.length; i++) {
0671                    result[i] = (Provider) candidatesArray[i];
0672                }
0673
0674                return result;
0675            }
0676
0677            // Map containing cached Spi Class objects of the specified type
0678            private static final Map<String, Class> spiMap = new ConcurrentHashMap<String, Class>();
0679
0680            /**
0681             * Return the Class object for the given engine type 
0682             * (e.g. "MessageDigest"). Works for Spis in the java.security package
0683             * only.
0684             */
0685            private static Class getSpiClass(String type) {
0686                Class clazz = spiMap.get(type);
0687                if (clazz != null) {
0688                    return clazz;
0689                }
0690                try {
0691                    clazz = Class.forName("java.security." + type + "Spi");
0692                    spiMap.put(type, clazz);
0693                    return clazz;
0694                } catch (ClassNotFoundException e) {
0695                    throw (Error) new AssertionError("Spi class not found")
0696                            .initCause(e);
0697                }
0698            }
0699
0700            /*
0701             * Returns an array of objects: the first object in the array is
0702             * an instance of an implementation of the requested algorithm
0703             * and type, and the second object in the array identifies the provider
0704             * of that implementation.
0705             * The <code>provider</code> argument can be null, in which case all
0706             * configured providers will be searched in order of preference.
0707             */
0708            static Object[] getImpl(String algorithm, String type,
0709                    String provider) throws NoSuchAlgorithmException,
0710                    NoSuchProviderException {
0711                if (provider == null) {
0712                    return GetInstance.getInstance(type, getSpiClass(type),
0713                            algorithm).toArray();
0714                } else {
0715                    return GetInstance.getInstance(type, getSpiClass(type),
0716                            algorithm, provider).toArray();
0717                }
0718            }
0719
0720            static Object[] getImpl(String algorithm, String type,
0721                    String provider, Object params)
0722                    throws NoSuchAlgorithmException, NoSuchProviderException,
0723                    InvalidAlgorithmParameterException {
0724                if (provider == null) {
0725                    return GetInstance.getInstance(type, getSpiClass(type),
0726                            algorithm, params).toArray();
0727                } else {
0728                    return GetInstance.getInstance(type, getSpiClass(type),
0729                            algorithm, params, provider).toArray();
0730                }
0731            }
0732
0733            /*
0734             * Returns an array of objects: the first object in the array is
0735             * an instance of an implementation of the requested algorithm
0736             * and type, and the second object in the array identifies the provider
0737             * of that implementation.
0738             * The <code>provider</code> argument cannot be null.
0739             */
0740            static Object[] getImpl(String algorithm, String type,
0741                    Provider provider) throws NoSuchAlgorithmException {
0742                return GetInstance.getInstance(type, getSpiClass(type),
0743                        algorithm, provider).toArray();
0744            }
0745
0746            static Object[] getImpl(String algorithm, String type,
0747                    Provider provider, Object params)
0748                    throws NoSuchAlgorithmException,
0749                    InvalidAlgorithmParameterException {
0750                return GetInstance.getInstance(type, getSpiClass(type),
0751                        algorithm, params, provider).toArray();
0752            }
0753
0754            /**
0755             * Gets a security property value.
0756             *
0757             * <p>First, if there is a security manager, its
0758             * <code>checkPermission</code>  method is called with a 
0759             * <code>java.security.SecurityPermission("getProperty."+key)</code>
0760             * permission to see if it's ok to retrieve the specified
0761             * security property value.. 
0762             *
0763             * @param key the key of the property being retrieved.
0764             *
0765             * @return the value of the security property corresponding to key.
0766             *
0767             * @throws  SecurityException
0768             *          if a security manager exists and its <code>{@link
0769             *          java.lang.SecurityManager#checkPermission}</code> method
0770             *          denies
0771             *          access to retrieve the specified security property value
0772             * @throws  NullPointerException is key is null
0773             * 
0774             * @see #setProperty
0775             * @see java.security.SecurityPermission
0776             */
0777            public static String getProperty(String key) {
0778                SecurityManager sm = System.getSecurityManager();
0779                if (sm != null) {
0780                    sm.checkPermission(new SecurityPermission("getProperty."
0781                            + key));
0782                }
0783                String name = props.getProperty(key);
0784                if (name != null)
0785                    name = name.trim(); // could be a class name with trailing ws
0786                return name;
0787            }
0788
0789            /**
0790             * Sets a security property value.
0791             *
0792             * <p>First, if there is a security manager, its
0793             * <code>checkPermission</code> method is called with a 
0794             * <code>java.security.SecurityPermission("setProperty."+key)</code>
0795             * permission to see if it's ok to set the specified
0796             * security property value.
0797             *
0798             * @param key the name of the property to be set.
0799             *
0800             * @param datum the value of the property to be set.
0801             *
0802             * @throws  SecurityException
0803             *          if a security manager exists and its <code>{@link
0804             *          java.lang.SecurityManager#checkPermission}</code> method
0805             *          denies access to set the specified security property value
0806             * @throws  NullPointerException if key or datum is null
0807             * 
0808             * @see #getProperty
0809             * @see java.security.SecurityPermission
0810             */
0811            public static void setProperty(String key, String datum) {
0812                check("setProperty." + key);
0813                props.put(key, datum);
0814                invalidateSMCache(key); /* See below. */
0815            }
0816
0817            /*
0818             * Implementation detail:  If the property we just set in
0819             * setProperty() was either "package.access" or
0820             * "package.definition", we need to signal to the SecurityManager
0821             * class that the value has just changed, and that it should
0822             * invalidate it's local cache values.
0823             *
0824             * Rather than create a new API entry for this function,
0825             * we use reflection to set a private variable.
0826             */
0827            private static void invalidateSMCache(String key) {
0828
0829                final boolean pa = key.equals("package.access");
0830                final boolean pd = key.equals("package.definition");
0831
0832                if (pa || pd) {
0833                    AccessController.doPrivileged(new PrivilegedAction<Void>() {
0834                        public Void run() {
0835                            try {
0836                                /* Get the class via the bootstrap class loader. */
0837                                Class cl = Class.forName(
0838                                        "java.lang.SecurityManager", false,
0839                                        null);
0840                                Field f = null;
0841                                boolean accessible = false;
0842
0843                                if (pa) {
0844                                    f = cl
0845                                            .getDeclaredField("packageAccessValid");
0846                                    accessible = f.isAccessible();
0847                                    f.setAccessible(true);
0848                                } else {
0849                                    f = cl
0850                                            .getDeclaredField("packageDefinitionValid");
0851                                    accessible = f.isAccessible();
0852                                    f.setAccessible(true);
0853                                }
0854                                f.setBoolean(f, false);
0855                                f.setAccessible(accessible);
0856                            } catch (Exception e1) {
0857                                /* If we couldn't get the class, it hasn't
0858                                 * been loaded yet.  If there is no such
0859                                 * field, we shouldn't try to set it.  There
0860                                 * shouldn't be a security execption, as we
0861                                 * are loaded by boot class loader, and we
0862                                 * are inside a doPrivileged() here.
0863                                 *
0864                                 * NOOP: don't do anything...
0865                                 */
0866                            }
0867                            return null;
0868                        } /* run */
0869                    }); /* PrivilegedAction */
0870                } /* if */
0871            }
0872
0873            private static void check(String directive) {
0874                SecurityManager security = System.getSecurityManager();
0875                if (security != null) {
0876                    security.checkSecurityAccess(directive);
0877                }
0878            }
0879
0880            /*
0881             * Returns all providers who satisfy the specified
0882             * criterion.
0883             */
0884            private static LinkedHashSet<Provider> getAllQualifyingCandidates(
0885                    String filterKey, String filterValue,
0886                    Provider[] allProviders) {
0887                String[] filterComponents = getFilterComponents(filterKey,
0888                        filterValue);
0889
0890                // The first component is the service name.
0891                // The second is the algorithm name.
0892                // If the third isn't null, that is the attrinute name.
0893                String serviceName = filterComponents[0];
0894                String algName = filterComponents[1];
0895                String attrName = filterComponents[2];
0896
0897                return getProvidersNotUsingCache(serviceName, algName,
0898                        attrName, filterValue, allProviders);
0899            }
0900
0901            private static LinkedHashSet<Provider> getProvidersNotUsingCache(
0902                    String serviceName, String algName, String attrName,
0903                    String filterValue, Provider[] allProviders) {
0904                LinkedHashSet<Provider> candidates = new LinkedHashSet<Provider>(
0905                        5);
0906                for (int i = 0; i < allProviders.length; i++) {
0907                    if (isCriterionSatisfied(allProviders[i], serviceName,
0908                            algName, attrName, filterValue)) {
0909                        candidates.add(allProviders[i]);
0910                    }
0911                }
0912                return candidates;
0913            }
0914
0915            /*
0916             * Returns true if the given provider satisfies
0917             * the selection criterion key:value.
0918             */
0919            private static boolean isCriterionSatisfied(Provider prov,
0920                    String serviceName, String algName, String attrName,
0921                    String filterValue) {
0922                String key = serviceName + '.' + algName;
0923
0924                if (attrName != null) {
0925                    key += ' ' + attrName;
0926                }
0927                // Check whether the provider has a property
0928                // whose key is the same as the given key.
0929                String propValue = getProviderProperty(key, prov);
0930
0931                if (propValue == null) {
0932                    // Check whether we have an alias instead
0933                    // of a standard name in the key.
0934                    String standardName = getProviderProperty("Alg.Alias."
0935                            + serviceName + "." + algName, prov);
0936                    if (standardName != null) {
0937                        key = serviceName + "." + standardName;
0938
0939                        if (attrName != null) {
0940                            key += ' ' + attrName;
0941                        }
0942
0943                        propValue = getProviderProperty(key, prov);
0944                    }
0945
0946                    if (propValue == null) {
0947                        // The provider doesn't have the given
0948                        // key in its property list.
0949                        return false;
0950                    }
0951                }
0952
0953                // If the key is in the format of:
0954                // <crypto_service>.<algorithm_or_type>,
0955                // there is no need to check the value.
0956
0957                if (attrName == null) {
0958                    return true;
0959                }
0960
0961                // If we get here, the key must be in the
0962                // format of <crypto_service>.<algorithm_or_provider> <attribute_name>.
0963                if (isStandardAttr(attrName)) {
0964                    return isConstraintSatisfied(attrName, filterValue,
0965                            propValue);
0966                } else {
0967                    return filterValue.equalsIgnoreCase(propValue);
0968                }
0969            }
0970
0971            /*
0972             * Returns true if the attribute is a standard attribute;
0973             * otherwise, returns false.
0974             */
0975            private static boolean isStandardAttr(String attribute) {
0976                // For now, we just have two standard attributes: 
0977                // KeySize and ImplementedIn.
0978                if (attribute.equalsIgnoreCase("KeySize"))
0979                    return true;
0980
0981                if (attribute.equalsIgnoreCase("ImplementedIn"))
0982                    return true;
0983
0984                return false;
0985            }
0986
0987            /*
0988             * Returns true if the requested attribute value is supported;
0989             * otherwise, returns false.
0990             */
0991            private static boolean isConstraintSatisfied(String attribute,
0992                    String value, String prop) {
0993                // For KeySize, prop is the max key size the
0994                // provider supports for a specific <crypto_service>.<algorithm>.
0995                if (attribute.equalsIgnoreCase("KeySize")) {
0996                    int requestedSize = Integer.parseInt(value);
0997                    int maxSize = Integer.parseInt(prop);
0998                    if (requestedSize <= maxSize) {
0999                        return true;
1000                    } else {
1001                        return false;
1002                    }
1003                }
1004
1005                // For Type, prop is the type of the implementation
1006                // for a specific <crypto service>.<algorithm>.
1007                if (attribute.equalsIgnoreCase("ImplementedIn")) {
1008                    return value.equalsIgnoreCase(prop);
1009                }
1010
1011                return false;
1012            }
1013
1014            static String[] getFilterComponents(String filterKey,
1015                    String filterValue) {
1016                int algIndex = filterKey.indexOf('.');
1017
1018                if (algIndex < 0) {
1019                    // There must be a dot in the filter, and the dot
1020                    // shouldn't be at the beginning of this string.
1021                    throw new InvalidParameterException("Invalid filter");
1022                }
1023
1024                String serviceName = filterKey.substring(0, algIndex);
1025                String algName = null;
1026                String attrName = null;
1027
1028                if (filterValue.length() == 0) {
1029                    // The filterValue is an empty string. So the filterKey 
1030                    // should be in the format of <crypto_service>.<algorithm_or_type>.
1031                    algName = filterKey.substring(algIndex + 1).trim();
1032                    if (algName.length() == 0) {
1033                        // There must be a algorithm or type name.
1034                        throw new InvalidParameterException("Invalid filter");
1035                    }
1036                } else {
1037                    // The filterValue is a non-empty string. So the filterKey must be
1038                    // in the format of
1039                    // <crypto_service>.<algorithm_or_type> <attribute_name>
1040                    int attrIndex = filterKey.indexOf(' ');
1041
1042                    if (attrIndex == -1) {
1043                        // There is no attribute name in the filter.
1044                        throw new InvalidParameterException("Invalid filter");
1045                    } else {
1046                        attrName = filterKey.substring(attrIndex + 1).trim();
1047                        if (attrName.length() == 0) {
1048                            // There is no attribute name in the filter.
1049                            throw new InvalidParameterException(
1050                                    "Invalid filter");
1051                        }
1052                    }
1053
1054                    // There must be an algorithm name in the filter.
1055                    if ((attrIndex < algIndex) || (algIndex == attrIndex - 1)) {
1056                        throw new InvalidParameterException("Invalid filter");
1057                    } else {
1058                        algName = filterKey.substring(algIndex + 1, attrIndex);
1059                    }
1060                }
1061
1062                String[] result = new String[3];
1063                result[0] = serviceName;
1064                result[1] = algName;
1065                result[2] = attrName;
1066
1067                return result;
1068            }
1069
1070            /**
1071             * Returns a Set of Strings containing the names of all available
1072             * algorithms or types for the specified Java cryptographic service
1073             * (e.g., Signature, MessageDigest, Cipher, Mac, KeyStore). Returns
1074             * an empty Set if there is no provider that supports the  
1075             * specified service or if serviceName is null. For a complete list 
1076             * of Java cryptographic services, please see the 
1077             * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html">Java 
1078             * Cryptography Architecture API Specification &amp; Reference</a>.
1079             * Note: the returned set is immutable.
1080             *
1081             * @param serviceName the name of the Java cryptographic 
1082             * service (e.g., Signature, MessageDigest, Cipher, Mac, KeyStore).
1083             * Note: this parameter is case-insensitive.
1084             *
1085             * @return a Set of Strings containing the names of all available 
1086             * algorithms or types for the specified Java cryptographic service
1087             * or an empty set if no provider supports the specified service.
1088             *
1089             * @since 1.4
1090             **/
1091            public static Set<String> getAlgorithms(String serviceName) {
1092
1093                if ((serviceName == null) || (serviceName.length() == 0)
1094                        || (serviceName.endsWith("."))) {
1095                    return Collections.EMPTY_SET;
1096                }
1097
1098                HashSet<String> result = new HashSet<String>();
1099                Provider[] providers = Security.getProviders();
1100
1101                for (int i = 0; i < providers.length; i++) {
1102                    // Check the keys for each provider.
1103                    for (Enumeration<Object> e = providers[i].keys(); e
1104                            .hasMoreElements();) {
1105                        String currentKey = ((String) e.nextElement())
1106                                .toUpperCase();
1107                        if (currentKey.startsWith(serviceName.toUpperCase())) {
1108                            // We should skip the currentKey if it contains a 
1109                            // whitespace. The reason is: such an entry in the
1110                            // provider property contains attributes for the
1111                            // implementation of an algorithm. We are only interested
1112                            // in entries which lead to the implementation
1113                            // classes.
1114                            if (currentKey.indexOf(" ") < 0) {
1115                                result.add(currentKey.substring(serviceName
1116                                        .length() + 1));
1117                            }
1118                        }
1119                    }
1120                }
1121                return Collections.unmodifiableSet(result);
1122            }
1123        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.