Source Code Cross Referenced for Security.java in  » 6.0-JDK-Modules » j2me » java » security » Java Source Code / Java DocumentationJava Source Code and Java Documentation

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 geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » j2me » java.security 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * @(#)Security.java	1.110 06/10/11
0003:         *
0004:         * Copyright  1990-2006 Sun Microsystems, Inc. All Rights Reserved.  
0005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER  
0006:         *   
0007:         * This program is free software; you can redistribute it and/or  
0008:         * modify it under the terms of the GNU General Public License version  
0009:         * 2 only, as published by the Free Software Foundation.   
0010:         *   
0011:         * This program is distributed in the hope that it will be useful, but  
0012:         * WITHOUT ANY WARRANTY; without even the implied warranty of  
0013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  
0014:         * General Public License version 2 for more details (a copy is  
0015:         * included at /legal/license.txt).   
0016:         *   
0017:         * You should have received a copy of the GNU General Public License  
0018:         * version 2 along with this work; if not, write to the Free Software  
0019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  
0020:         * 02110-1301 USA   
0021:         *   
0022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa  
0023:         * Clara, CA 95054 or visit www.sun.com if you need additional  
0024:         * information or have any questions. 
0025:         *
0026:         */
0027:
0028:        package java.security;
0029:
0030:        import java.lang.reflect.*;
0031:        import java.util.*;
0032:        import java.io.*;
0033:        import java.net.URL;
0034:        import java.security.InvalidParameterException;
0035:        import sun.security.util.Debug;
0036:        import sun.security.util.PropertyExpander;
0037:
0038:        /**
0039:         * <p>This class centralizes all security properties and common security
0040:         * methods. One of its primary uses is to manage providers.
0041:         *
0042:         * @author Benjamin Renaud
0043:         * @version 1.101 10/17/00
0044:         */
0045:
0046:        public final class Security {
0047:
0048:            // Do providers need to be reloaded?
0049:            private static boolean reloadProviders = true;
0050:
0051:            /* Are we debugging? -- for developers */
0052:            static final boolean debug = false;
0053:            private static final Debug sdebug = Debug.getInstance("properties");
0054:
0055:            /* Are we displaying errors? -- for users */
0056:            static final boolean error = true;
0057:
0058:            /* The java.security properties */
0059:            private static Properties props;
0060:
0061:            /* A vector of providers, in order of priority */
0062:            private static Vector providers;
0063:
0064:            // Where we cache provider properties
0065:            private static Hashtable providerPropertiesCache;
0066:
0067:            // Where we cache engine provider properties
0068:            private static Hashtable engineCache;
0069:
0070:            // Where we cache search results
0071:            private static Hashtable searchResultsCache;
0072:
0073:            // providers currently attempting to be loaded
0074:            private static Hashtable providerLoads;
0075:
0076:            // An element in the cache
0077:            private static class ProviderProperty {
0078:                String className;
0079:                Provider provider;
0080:            }
0081:
0082:            // Number of statically registered security providers. No duplicates.
0083:            private static int numOfStaticProviders = 0;
0084:
0085:            /* A vector of statically registered providers' master class names,
0086:             * in order of priority. No duplicates.
0087:             */
0088:            private static Vector providerMasterClassNames = new Vector(6);
0089:
0090:            // Index for the vector providerMasterClassNames.
0091:            // It points to the next provider which we should try to load.
0092:            private static int indexStaticProviders = 0;
0093:
0094:            // Does the indexStaticProviders need to be reset?
0095:            private static boolean resetProviderIndex = false;
0096:
0097:            static {
0098:                // doPrivileged here because there are multiple
0099:                // things in initialize that might require privs.
0100:                // (the FileInputStream call and the File.exists call,
0101:                // the securityPropFile call, etc)
0102:                AccessController.doPrivileged(new PrivilegedAction() {
0103:                    public Object run() {
0104:                        initialize();
0105:                        return null;
0106:                    }
0107:                });
0108:            }
0109:
0110:            private static void initialize() {
0111:                props = new Properties();
0112:                providers = new Vector();
0113:                providerPropertiesCache = new Hashtable();
0114:                engineCache = new Hashtable();
0115:                searchResultsCache = new Hashtable(5);
0116:                providerLoads = new Hashtable(1);
0117:                boolean loadedProps = false;
0118:                boolean overrideAll = false;
0119:
0120:                // first load the system properties file
0121:                // to determine the value of security.overridePropertiesFile
0122:                File propFile = securityPropFile("java.security");
0123:                if (propFile.exists()) {
0124:                    try {
0125:                        FileInputStream is = new FileInputStream(propFile);
0126:                        // Inputstream has been buffered in Properties class
0127:                        props.load(is);
0128:                        is.close();
0129:                        loadedProps = true;
0130:
0131:                        if (sdebug != null) {
0132:                            sdebug.println("reading security properties file: "
0133:                                    + propFile);
0134:                        }
0135:                    } catch (IOException e) {
0136:                        if (sdebug != null) {
0137:                            sdebug
0138:                                    .println("unable to load security properties from "
0139:                                            + propFile);
0140:                            e.printStackTrace();
0141:                        }
0142:                    }
0143:                }
0144:
0145:                if ("true".equalsIgnoreCase(props
0146:                        .getProperty("security.overridePropertiesFile"))) {
0147:
0148:                    String extraPropFile = System
0149:                            .getProperty("java.security.properties");
0150:                    if (extraPropFile != null && extraPropFile.startsWith("=")) {
0151:                        overrideAll = true;
0152:                        extraPropFile = extraPropFile.substring(1);
0153:                    }
0154:
0155:                    if (overrideAll) {
0156:                        props = new Properties();
0157:                        if (sdebug != null) {
0158:                            sdebug
0159:                                    .println("overriding other security properties files!");
0160:                        }
0161:                    }
0162:
0163:                    // now load the user-specified file so its values
0164:                    // will win if they conflict with the earlier values
0165:                    if (extraPropFile != null) {
0166:                        try {
0167:                            URL propURL;
0168:
0169:                            extraPropFile = PropertyExpander
0170:                                    .expand(extraPropFile);
0171:                            propFile = new File(extraPropFile);
0172:                            if (propFile.exists()) {
0173:                                propURL = new URL("file:"
0174:                                        + propFile.getCanonicalPath());
0175:                            } else {
0176:                                propURL = new URL(extraPropFile);
0177:                            }
0178:                            BufferedInputStream bis = new BufferedInputStream(
0179:                                    propURL.openStream());
0180:                            props.load(bis);
0181:                            bis.close();
0182:                            loadedProps = true;
0183:
0184:                            if (sdebug != null) {
0185:                                sdebug
0186:                                        .println("reading security properties file: "
0187:                                                + propURL);
0188:                                if (overrideAll) {
0189:                                    sdebug
0190:                                            .println("overriding other security properties files!");
0191:                                }
0192:                            }
0193:                        } catch (Exception e) {
0194:                            if (sdebug != null) {
0195:                                sdebug
0196:                                        .println("unable to load security properties from "
0197:                                                + extraPropFile);
0198:                                e.printStackTrace();
0199:                            }
0200:                        }
0201:                    }
0202:                }
0203:
0204:                if (!loadedProps) {
0205:                    initializeStatic();
0206:                    if (sdebug != null) {
0207:                        sdebug.println("unable to load security properties "
0208:                                + "-- using defaults");
0209:                    }
0210:                }
0211:
0212:                // Not loading providers here. Just counts how many providers
0213:                // are statically registered. This reduces the startup 
0214:                // footprint.
0215:                countProviders();
0216:            }
0217:
0218:            /* 
0219:             * Initialize to default values, if <java.home>/lib/java.security
0220:             * is not found.
0221:             */
0222:            private static void initializeStatic() {
0223:                props.put("security.provider.1", "sun.security.provider.Sun");
0224:            }
0225:
0226:            /**
0227:             * Don't let anyone instantiate this. 
0228:             */
0229:            private Security() {
0230:            }
0231:
0232:            /**
0233:             * Loops through provider declarations, which are expected to be
0234:             * of the form:
0235:             *
0236:             * security.provider.1=sun.security.provider.Sun
0237:             * security.provider.2=sun.security.jsafe.Jsafe
0238:             * etc.
0239:             *
0240:             * The order determines the default search order when looking for 
0241:             * an algorithm.
0242:             */
0243:            private static synchronized void countProviders() {
0244:
0245:                int i = 1;
0246:
0247:                while (true) {
0248:                    String name = props.getProperty("security.provider." + i);
0249:                    if (name == null) {
0250:                        break;
0251:                    } else {
0252:                        String fullClassName = name.trim();
0253:                        if (fullClassName.length() == 0) {
0254:                            System.err.println("invalid entry for "
0255:                                    + "security.provider." + i);
0256:                            break;
0257:                        } else {
0258:                            // Get rid of duplicate providers.
0259:                            if (!providerMasterClassNames
0260:                                    .contains(fullClassName)) {
0261:                                providerMasterClassNames.add(fullClassName);
0262:                            }
0263:                            i++;
0264:                        }
0265:                    }
0266:                }
0267:
0268:                // Get the number of statically registered providers.
0269:                numOfStaticProviders = providerMasterClassNames.size();
0270:
0271:            }
0272:
0273:            /*
0274:             * Reload the providers (provided as extensions) that could not be loaded 
0275:             * (because there was no system class loader available) when this class
0276:             * was initialized.
0277:             */
0278:            private static synchronized void reloadProviders() {
0279:                if (reloadProviders) {
0280:                    sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
0281:                    if (l != null) {
0282:                        synchronized (Security.class) {
0283:                            reloadProviders = false;
0284:                            // We don't want loadOneMoreProvider() to do
0285:                            // anything from now on since this method will 
0286:                            // load all static providers.
0287:                            indexStaticProviders = numOfStaticProviders;
0288:                            resetProviderIndex = false;
0289:                            providers.removeAllElements();
0290:                            // i is an index for the vector 
0291:                            // providerMasterClassNames. So it starts from 0.
0292:                            int i = 0;
0293:                            while (i < numOfStaticProviders) {
0294:                                final String name = (String) providerMasterClassNames
0295:                                        .elementAt(i);
0296:                                i++;
0297:                                Provider prov = (Provider) AccessController
0298:                                        .doPrivileged(new PrivilegedAction() {
0299:                                            public Object run() {
0300:                                                return Provider
0301:                                                        .loadProvider(name);
0302:                                            }
0303:                                        });
0304:                                if (prov != null) {
0305:                                    providers.addElement(prov);
0306:                                }
0307:                            }
0308:                            // empty provider-property cache
0309:                            providerPropertiesCache.clear();
0310:                            engineCache.clear();
0311:                            searchResultsCache.clear();
0312:                        }
0313:                    }
0314:                }
0315:            }
0316:
0317:            /**
0318:             * Try our best to load one more statically registered provider.
0319:             * This is used by getEngineClassName(String algName, String engineType).
0320:             */
0321:            private static synchronized void loadOneMoreProvider() {
0322:                // suspend provider reloading inside this method
0323:                boolean restore = false;
0324:                if (reloadProviders) {
0325:                    restore = true;
0326:                    reloadProviders = false;
0327:                }
0328:                try {
0329:                    sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
0330:                    /* 
0331:                     * Even if the launcher l is null, we still want to
0332:                     * load providers if we can. See bug 4418903.
0333:                     * When we first see that the launcher isn't null, we
0334:                     * could be in one of the following situations:
0335:                     * a) some providers were loaded out of the priority order.
0336:                     *    For example, 6 providers are statically configured, and
0337:                     *    provider 2 and 4 are loaded. The field resetProviderIndex
0338:                     *    should be "true". So we can try to load providers
0339:                     *    according to the priority order when the launcher isn't null.
0340:                     * b) some providers were loaded, but not out of order.
0341:                     *    For example, 6 providers are statically configured, and
0342:                     *    provider 1 and 2 are loaded. The field resetProviderIndex
0343:                     *    should be "false". So we just try to load the next
0344:                     *    provider whose index is indexStaticProviders.
0345:                     * c) no providers were loaded. The field resetProviderIndex
0346:                     *    should be "false". So we just try to load the first
0347:                     *    provider. Note: indexStaticProviders is 0 in this case.
0348:                     */
0349:
0350:                    if (indexStaticProviders >= numOfStaticProviders) {
0351:                        return;
0352:                    }
0353:
0354:                    Provider prov = null;
0355:
0356:                    while (indexStaticProviders < numOfStaticProviders) {
0357:                        final String name = (String) providerMasterClassNames
0358:                                .elementAt(indexStaticProviders);
0359:
0360:                        // determine if the loadProvider call below is looping.
0361:                        // this may occur if the provider to be loaded is signed.
0362:                        // if looping, continue
0363:                        if (providerLoads.get(name) != null) {
0364:                            indexStaticProviders++;
0365:                            continue;
0366:                        } else {
0367:                            providerLoads.put(name, name);
0368:                        }
0369:
0370:                        prov = (Provider) AccessController
0371:                                .doPrivileged(new PrivilegedAction() {
0372:                                    public Object run() {
0373:                                        return Provider.loadProvider(name);
0374:                                    }
0375:                                });
0376:
0377:                        // indexStaticProviders points to the next provider we
0378:                        // should try to load.
0379:                        indexStaticProviders++;
0380:                        providerLoads.remove(name);
0381:
0382:                        if (prov != null) {
0383:                            /* This must manipulate the datastructure
0384:                               directly, because going through addProviders
0385:                               causes a security check to happen, which
0386:                               sometimes will cause the security
0387:                               initialization to fail with bad
0388:                               consequences. */
0389:                            providers.addElement(prov);
0390:                            // empty provider-property cache
0391:                            providerPropertiesCache.clear();
0392:                            engineCache.clear();
0393:                            searchResultsCache.clear();
0394:                            break;
0395:                        } else {
0396:                            if (l == null) {
0397:                                // Set resetProviderIndex to true since we may load
0398:                                // providers out of the priority order.
0399:                                resetProviderIndex = true;
0400:                            }
0401:                        }
0402:                    }
0403:                } finally {
0404:                    // resume provider reloading if necessary
0405:                    if (restore) {
0406:                        reloadProviders = true;
0407:                    }
0408:                }
0409:            }
0410:
0411:            private static File securityPropFile(String filename) {
0412:                // maybe check for a system property which will specify where to
0413:                // look. Someday.
0414:                String sep = File.separator;
0415:                return new File(System.getProperty("java.home") + sep + "lib"
0416:                        + sep + "security" + sep + filename);
0417:            }
0418:
0419:            /**
0420:             * Looks up providers, and returns the property (and its associated
0421:             * provider) mapping the key, if any.
0422:             * The order in which the providers are looked up is the
0423:             * provider-preference order, as specificed in the security
0424:             * properties file.
0425:             */
0426:            private static ProviderProperty getProviderProperty(String key) {
0427:                ProviderProperty entry = (ProviderProperty) providerPropertiesCache
0428:                        .get(key);
0429:                if (entry != null) {
0430:                    return entry;
0431:                }
0432:
0433:                for (int i = 0; i < providers.size(); i++) {
0434:
0435:                    String matchKey = null;
0436:                    Provider prov = (Provider) providers.elementAt(i);
0437:                    String prop = prov.getProperty(key);
0438:
0439:                    if (prop == null) {
0440:                        // Is there a match if we do a case-insensitive property name
0441:                        // comparison? Let's try ...
0442:                        for (Enumeration enum_ = prov.keys(); enum_
0443:                                .hasMoreElements()
0444:                                && prop == null;) {
0445:                            matchKey = (String) enum_.nextElement();
0446:                            if (key.equalsIgnoreCase(matchKey)) {
0447:                                prop = prov.getProperty(matchKey);
0448:                                break;
0449:                            }
0450:                        }
0451:                    }
0452:
0453:                    if (prop != null) {
0454:                        ProviderProperty newEntry = new ProviderProperty();
0455:                        newEntry.className = prop;
0456:                        newEntry.provider = prov;
0457:                        providerPropertiesCache.put(key, newEntry);
0458:                        if (matchKey != null) {
0459:                            // Store the property value in the cache under the exact
0460:                            // property name, as specified by the provider
0461:                            providerPropertiesCache.put(matchKey, newEntry);
0462:                        }
0463:                        return newEntry;
0464:                    }
0465:                }
0466:
0467:                return entry;
0468:            }
0469:
0470:            /**
0471:             * Returns the property (if any) mapping the key for the given provider.
0472:             */
0473:            private static String getProviderProperty(String key,
0474:                    Provider provider) {
0475:                String prop = provider.getProperty(key);
0476:                if (prop == null) {
0477:                    // Is there a match if we do a case-insensitive property name
0478:                    // comparison? Let's try ...
0479:                    for (Enumeration enum_ = provider.keys(); enum_
0480:                            .hasMoreElements()
0481:                            && prop == null;) {
0482:                        String matchKey = (String) enum_.nextElement();
0483:                        if (key.equalsIgnoreCase(matchKey)) {
0484:                            prop = provider.getProperty(matchKey);
0485:                            break;
0486:                        }
0487:                    }
0488:                }
0489:                return prop;
0490:            }
0491:
0492:            /**
0493:             * We always map names to standard names
0494:             */
0495:            private static String getStandardName(String alias,
0496:                    String engineType, Provider prov) {
0497:                return getProviderProperty("Alg.Alias." + engineType + "."
0498:                        + alias, prov);
0499:            }
0500:
0501:            /** 
0502:             * Gets a specified property for an algorithm. The algorithm name
0503:             * should be a standard name. See Appendix A in the <a href=
0504:             * "../../../guide/security/CryptoSpec.html#AppA">
0505:             * Java Cryptography Architecture API Specification &amp; Reference </a> 
0506:             * for information about standard algorithm names.
0507:             * One possible use is by specialized algorithm parsers, which may map 
0508:             * classes to algorithms which they understand (much like Key parsers 
0509:             * do).
0510:             *
0511:             * param algName the algorithm name.
0512:             *
0513:             * param propName the name of the property to get.
0514:             * 
0515:             * return the value of the specified property.  
0516:             *
0517:             * deprecated This method used to return the value of a proprietary
0518:             * property in the master file of the "SUN" Cryptographic Service
0519:             * Provider in order to determine how to parse algorithm-specific
0520:             * parameters. Use the new provider-based and algorithm-independent
0521:             * <code>AlgorithmParameters</code> and <code>KeyFactory</code> engine
0522:             * classes (introduced in the Java 2 platform) instead.
0523:             *
0524:            public static String getAlgorithmProperty(String algName,
0525:            				      String propName) {
0526:            reloadProviders();
0527:            ProviderProperty entry = getProviderProperty("Alg." + propName
0528:            					     + "." + algName);
0529:            if (entry != null) {
0530:                return entry.className;
0531:            } else {
0532:                return null;
0533:            }
0534:            }
0535:             */
0536:
0537:            /*
0538:             * Lookup the algorithm in our list of providers. Process
0539:             * each provider in priority order one at a time looking for
0540:             * either the direct engine property or a matching alias.
0541:             */
0542:            private static ProviderProperty getEngineClassName(String algName,
0543:                    String engineType) throws NoSuchAlgorithmException {
0544:                ProviderProperty pp;
0545:                String key = engineType;
0546:
0547:                if (algName != null)
0548:                    key += "." + algName;
0549:                pp = (ProviderProperty) engineCache.get(key);
0550:                if (pp != null)
0551:                    return pp;
0552:
0553:                synchronized (Security.class) {
0554:                    sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
0555:                    /*
0556:                     * In case some providers have been loaded out of the
0557:                     * priority order when the launcher l is null, we should
0558:                     * clear the vector "providers" and reset the indexStaticProviders
0559:                     * to zero when the launcher l isn't null.
0560:                     *
0561:                     * We should only do the above if the "reloadProviders" is true
0562:                     * which means that the method reloadProviders() hasn't
0563:                     * load all statically registered providers yet.
0564:                     * Once the reloadProviders() method has loaded all statically
0565:                     * registered providers, we shouldn't clear the vector
0566:                     * "providers" in this getEngineClassName() method.
0567:                     */
0568:                    if ((reloadProviders == true) && (l != null)
0569:                            && (resetProviderIndex == true)) {
0570:                        resetProviderIndex = false;
0571:                        indexStaticProviders = 0;
0572:                        providers.removeAllElements();
0573:                        providerPropertiesCache.clear();
0574:                        engineCache.clear();
0575:                        searchResultsCache.clear();
0576:                        providerLoads.clear();
0577:                    }
0578:
0579:                    // We should call loadOneMoreProvider() if no provider
0580:                    // has been loaded yet. Otherwise, we may not be able to
0581:                    // get in the following "for" loop.
0582:                    if (providers.size() == 0) {
0583:                        loadOneMoreProvider();
0584:                    }
0585:                    for (int i = 0; i < providers.size(); i++) {
0586:                        Provider prov = (Provider) providers.elementAt(i);
0587:                        try {
0588:                            pp = getEngineClassName(algName, prov, engineType);
0589:                        } catch (NoSuchAlgorithmException e) {
0590:                            if (i == providers.size() - 1) {
0591:                                // The requested algorithm may be available in
0592:                                // a registered provider which hasn't been loaded
0593:                                // yet. Let's try to load one more registered
0594:                                // provider. The method loadOneMoreProvider()
0595:                                // won't do anything if we have tried to load all
0596:                                // registered providers.
0597:                                loadOneMoreProvider();
0598:                            }
0599:                            continue;
0600:                        }
0601:
0602:                        /* Cache it */
0603:                        engineCache.put(key, pp);
0604:                        return pp;
0605:                    }
0606:                }
0607:
0608:                throw new NoSuchAlgorithmException(algName.toUpperCase() + " "
0609:                        + engineType + " not available");
0610:            }
0611:
0612:            private static ProviderProperty getEngineClassName(String algName,
0613:                    String provider, String engineType)
0614:                    throws NoSuchAlgorithmException, NoSuchProviderException {
0615:                if (provider == null) {
0616:                    return getEngineClassName(algName, engineType);
0617:                }
0618:
0619:                // check if the provider is installed
0620:                Provider prov = getProvider(provider);
0621:                if (prov == null) {
0622:                    throw new NoSuchProviderException("no such provider: "
0623:                            + provider);
0624:                }
0625:
0626:                return getEngineClassName(algName, prov, engineType);
0627:            }
0628:
0629:            /**
0630:             * The parameter provider cannot be null.
0631:             */
0632:            private static ProviderProperty getEngineClassName(String algName,
0633:                    Provider provider, String engineType)
0634:                    throws NoSuchAlgorithmException {
0635:                String key;
0636:                if (engineType.equalsIgnoreCase("SecureRandom")
0637:                        && algName == null)
0638:                    key = engineType;
0639:                else
0640:                    key = engineType + "." + algName;
0641:
0642:                String className = getProviderProperty(key, provider);
0643:                if (className == null) {
0644:                    if (engineType.equalsIgnoreCase("SecureRandom")
0645:                            && algName == null)
0646:                        throw new NoSuchAlgorithmException(
0647:                                "SecureRandom not available for provider "
0648:                                        + provider.getName());
0649:                    else {
0650:                        // try algName as alias name
0651:                        String stdName = getStandardName(algName, engineType,
0652:                                provider);
0653:                        if (stdName != null)
0654:                            key = engineType + "." + stdName;
0655:                        if ((stdName == null)
0656:                                || (className = getProviderProperty(key,
0657:                                        provider)) == null)
0658:                            throw new NoSuchAlgorithmException(
0659:                                    "no such algorithm: " + algName
0660:                                            + " for provider "
0661:                                            + provider.getName());
0662:                    }
0663:                }
0664:
0665:                ProviderProperty entry = new ProviderProperty();
0666:                entry.className = className;
0667:                entry.provider = provider;
0668:
0669:                return entry;
0670:            }
0671:
0672:            /**
0673:             * Adds a new provider, at a specified position. The position is
0674:             * the preference order in which providers are searched for
0675:             * requested algorithms. Note that it is not guaranteed that this
0676:             * preference will be respected. The position is 1-based, that is,
0677:             * 1 is most preferred, followed by 2, and so on.
0678:             * 
0679:             * <p>If the given provider is installed at the requested position,
0680:             * the provider that used to be at that position, and all providers
0681:             * with a position greater than <code>position</code>, are shifted up
0682:             * one position (towards the end of the list of installed providers).
0683:             * 
0684:             * <p>A provider cannot be added if it is already installed.
0685:             * 
0686:             * <p>First, if there is a security manager, its
0687:             * <code>checkSecurityAccess</code> 
0688:             * method is called with the string
0689:             * <code>"insertProvider."+provider.getName()</code> 
0690:             * to see if it's ok to add a new provider. 
0691:             * If the default implementation of <code>checkSecurityAccess</code> 
0692:             * is used (i.e., that method is not overriden), then this will result in
0693:             * a call to the security manager's <code>checkPermission</code> method
0694:             * with a
0695:             * <code>SecurityPermission("insertProvider."+provider.getName())</code>
0696:             * permission.
0697:             *
0698:             * @param provider the provider to be added.
0699:             *
0700:             * @param position the preference position that the caller would
0701:             * like for this provider.
0702:             * 
0703:             * @return the actual preference position in which the provider was 
0704:             * added, or -1 if the provider was not added because it is
0705:             * already installed.
0706:             *
0707:             * @throws  SecurityException
0708:             *          if a security manager exists and its <code>{@link
0709:             *          java.lang.SecurityManager#checkSecurityAccess}</code> method
0710:             *          denies access to add a new provider
0711:             *
0712:             * @see #getProvider
0713:             * @see #removeProvider 
0714:             * @see java.security.SecurityPermission
0715:             */
0716:            public static synchronized int insertProviderAt(Provider provider,
0717:                    int position) {
0718:                reloadProviders();
0719:
0720:                check("insertProvider." + provider.getName());
0721:
0722:                /* First check if the provider is already installed */
0723:                Provider already = getProvider(provider.getName());
0724:                if (already != null) {
0725:                    return -1;
0726:                }
0727:
0728:                int size = providers.size();
0729:                if (position > size || position <= 0) {
0730:                    position = size + 1;
0731:                }
0732:
0733:                providers.insertElementAt(provider, position - 1);
0734:
0735:                // empty provider-property cache
0736:                providerPropertiesCache.clear();
0737:                engineCache.clear();
0738:                searchResultsCache.clear();
0739:
0740:                return position;
0741:            }
0742:
0743:            /**
0744:             * Adds a provider to the next position available.
0745:             *
0746:             * <p>First, if there is a security manager, its
0747:             * <code>checkSecurityAccess</code> 
0748:             * method is called with the string
0749:             * <code>"insertProvider."+provider.getName()</code> 
0750:             * to see if it's ok to add a new provider. 
0751:             * If the default implementation of <code>checkSecurityAccess</code> 
0752:             * is used (i.e., that method is not overriden), then this will result in
0753:             * a call to the security manager's <code>checkPermission</code> method
0754:             * with a
0755:             * <code>SecurityPermission("insertProvider."+provider.getName())</code>
0756:             * permission.
0757:             * 
0758:             * @param provider the provider to be added.
0759:             *
0760:             * @return the preference position in which the provider was 
0761:             * added, or -1 if the provider was not added because it is
0762:             * already installed.
0763:             *
0764:             * @throws  SecurityException
0765:             *          if a security manager exists and its <code>{@link
0766:             *          java.lang.SecurityManager#checkSecurityAccess}</code> method
0767:             *          denies access to add a new provider
0768:             * 
0769:             * @see #getProvider
0770:             * @see #removeProvider
0771:             * @see java.security.SecurityPermission
0772:             */
0773:            public static int addProvider(Provider provider) {
0774:                /*
0775:                 * We can't assign a position here because the statically
0776:                 * registered providers may not have been installed yet. 
0777:                 * insertProviderAt() will fix that value after it has 
0778:                 * loaded the static providers.
0779:                 */
0780:                return insertProviderAt(provider, 0);
0781:            }
0782:
0783:            /**
0784:             * Removes the provider with the specified name.
0785:             *
0786:             * <p>When the specified provider is removed, all providers located
0787:             * at a position greater than where the specified provider was are shifted
0788:             * down one position (towards the head of the list of installed
0789:             * providers).
0790:             *
0791:             * <p>This method returns silently if the provider is not installed.
0792:             * 
0793:             * <p>First, if there is a security manager, its
0794:             * <code>checkSecurityAccess</code> 
0795:             * method is called with the string <code>"removeProvider."+name</code> 
0796:             * to see if it's ok to remove the provider. 
0797:             * If the default implementation of <code>checkSecurityAccess</code> 
0798:             * is used (i.e., that method is not overriden), then this will result in
0799:             * a call to the security manager's <code>checkPermission</code> method
0800:             * with a <code>SecurityPermission("removeProvider."+name)</code>
0801:             * permission.
0802:             *
0803:             * @param name the name of the provider to remove.
0804:             *
0805:             * @throws  SecurityException
0806:             *          if a security manager exists and its <code>{@link
0807:             *          java.lang.SecurityManager#checkSecurityAccess}</code> method
0808:             *          denies
0809:             *          access to remove the provider
0810:             *
0811:             * @see #getProvider
0812:             * @see #addProvider
0813:             */
0814:            public static synchronized void removeProvider(String name) {
0815:                reloadProviders();
0816:                check("removeProvider." + name);
0817:                Provider provider = getProvider(name);
0818:                if (provider != null) {
0819:                    for (Iterator i = providers.iterator(); i.hasNext();)
0820:                        if (i.next() == provider)
0821:                            i.remove();
0822:
0823:                    // empty provider-property cache
0824:                    providerPropertiesCache.clear();
0825:                    engineCache.clear();
0826:                    searchResultsCache.clear();
0827:                }
0828:            }
0829:
0830:            /**
0831:             * Returns an array containing all the installed providers. The order of
0832:             * the providers in the array is their preference order.
0833:             * 
0834:             * @return an array of all the installed providers.
0835:             */
0836:            public static synchronized Provider[] getProviders() {
0837:                reloadProviders();
0838:                Provider[] result = new Provider[providers.size()];
0839:                providers.copyInto(result);
0840:
0841:                return result;
0842:            }
0843:
0844:            /**
0845:             * Returns the provider installed with the specified name, if
0846:             * any. Returns null if no provider with the specified name is
0847:             * installed.
0848:             * 
0849:             * @param name the name of the provider to get.
0850:             * 
0851:             * @return the provider of the specified name.
0852:             *
0853:             * @see #removeProvider
0854:             * @see #addProvider
0855:             */
0856:            public static synchronized Provider getProvider(String name) {
0857:                reloadProviders();
0858:                Enumeration enum_ = providers.elements();
0859:                while (enum_.hasMoreElements()) {
0860:                    Provider prov = (Provider) enum_.nextElement();
0861:                    if (prov.getName().equals(name)) {
0862:                        return prov;
0863:                    }
0864:                }
0865:                return null;
0866:            }
0867:
0868:            /**
0869:             * Returns an array containing all installed providers that satisfy the
0870:             * specified selection criterion, or null if no such providers have been
0871:             * installed. The returned providers are ordered
0872:             * according to their <a href=
0873:             * "#insertProviderAt(java.security.Provider, int)">preference order</a>. 
0874:             * 
0875:             * <p> A cryptographic service is always associated with a particular
0876:             * algorithm or type. For example, a digital signature service is
0877:             * always associated with a particular algorithm (e.g., DSA),
0878:             * and a CertificateFactory service is always associated with
0879:             * a particular certificate type (e.g., X.509).
0880:             * NOTE: <B>java.security.cert.CertificateFactory</B> is found in J2ME CDC 
0881:             * profiles such as J2ME Foundation Profile.
0882:             *
0883:             * <p>The selection criterion must be specified in one of the following two formats:
0884:             * <ul>
0885:             * <li> <i>&lt;crypto_service>.&lt;algorithm_or_type></i> <p> The
0886:             * cryptographic service name must not contain any dots.
0887:             * <p> A 
0888:             * provider satisfies the specified selection criterion iff the provider implements the 
0889:             * specified algorithm or type for the specified cryptographic service.
0890:             * <p> For example, "CertificateFactory.X.509" 
0891:             * would be satisfied by any provider that supplied
0892:             * a CertificateFactory implementation for X.509 certificates.
0893:             * NOTE: <B>java.security.cert.CertificateFactory</B> is found in J2ME CDC 
0894:             * profiles such as J2ME Foundation Profile.
0895:             * <li> <i>&lt;crypto_service>.&lt;algorithm_or_type> &lt;attribute_name>:&lt attribute_value></i>
0896:             * <p> The cryptographic service name must not contain any dots. There
0897:             * must be one or more space charaters between the the <i>&lt;algorithm_or_type></i>
0898:             * and the <i>&lt;attribute_name></i>.
0899:             * <p> A provider satisfies this selection criterion iff the
0900:             * provider implements the specified algorithm or type for the specified 
0901:             * cryptographic service and its implementation meets the
0902:             * constraint expressed by the specified attribute name/value pair.
0903:             * <p> For example, "Signature.SHA1withDSA KeySize:1024" would be
0904:             * satisfied by any provider that implemented
0905:             * the SHA1withDSA signature algorithm with a keysize of 1024 (or larger).
0906:             * NOTE: <B>java.security.Signature</B> is found in J2ME CDC profiles such as 
0907:             * J2ME Foundation Profile.
0908:             *  
0909:             * </ul>
0910:             *
0911:             * <p> See Appendix A in the <a href=
0912:             * "../../../guide/security/CryptoSpec.html#AppA">
0913:             * Java Cryptogaphy Architecture API Specification &amp; Reference </a>
0914:             * for information about standard cryptographic service names, standard
0915:             * algorithm names and standard attribute names.
0916:             *
0917:             * @param filter the criterion for selecting
0918:             * providers. The filter is case-insensitive.
0919:             *
0920:             * @return all the installed providers that satisfy the selection
0921:             * criterion, or null if no such providers have been installed.
0922:             *
0923:             * @throws InvalidParameterException
0924:             *         if the filter is not in the required format
0925:             *
0926:             * @see #getProviders(java.util.Map)
0927:             */
0928:            public static Provider[] getProviders(String filter) {
0929:                String key = null;
0930:                String value = null;
0931:                int index = filter.indexOf(':');
0932:
0933:                if (index == -1) {
0934:                    key = new String(filter);
0935:                    value = "";
0936:                } else {
0937:                    key = filter.substring(0, index);
0938:                    value = filter.substring(index + 1);
0939:                }
0940:
0941:                Hashtable hashtableFilter = new Hashtable(1);
0942:                hashtableFilter.put(key, value);
0943:
0944:                return (getProviders(hashtableFilter));
0945:            }
0946:
0947:            /**
0948:             * Returns an array containing all installed providers that satisfy the specified
0949:             * selection criteria, or null if no such providers have been installed. 
0950:             * The returned providers are ordered
0951:             * according to their <a href=
0952:             * "#insertProviderAt(java.security.Provider, int)">preference order</a>. 
0953:             * 
0954:             * <p>The selection criteria are represented by a map.
0955:             * Each map entry represents a selection criterion. 
0956:             * A provider is selected iff it satisfies all selection
0957:             * criteria. The key for any entry in such a map must be in one of the
0958:             * following two formats:
0959:             * <ul>
0960:             * <li> <i>&lt;crypto_service>.&lt;algorithm_or_type></i>
0961:             * <p> The cryptographic service name must not contain any dots.
0962:             * <p> The value associated with the key must be an empty string.
0963:             * <p> A provider
0964:             * satisfies this selection criterion iff the provider implements the 
0965:             * specified algorithm or type for the specified cryptographic service.
0966:             * <li>  <i>&lt;crypto_service>.&lt;algorithm_or_type> &lt;attribute_name></i>
0967:             * <p> The cryptographic service name must not contain any dots. There
0968:             * must be one or more space charaters between the <i>&lt;algorithm_or_type></i>
0969:             * and the <i>&lt;attribute_name></i>.
0970:             * <p> The value associated with the key must be a non-empty string.
0971:             * A provider satisfies this selection criterion iff the
0972:             * provider implements the specified algorithm or type for the specified 
0973:             * cryptographic service and its implementation meets the
0974:             * constraint expressed by the specified attribute name/value pair. 
0975:             * </ul>
0976:             *
0977:             * <p> See Appendix A in the <a href=
0978:             * "../../../guide/security/CryptoSpec.html#AppA">
0979:             * Java Cryptogaphy Architecture API Specification &amp; Reference </a>
0980:             * for information about standard cryptographic service names, standard
0981:             * algorithm names and standard attribute names.
0982:             *
0983:             * @param filter the criteria for selecting
0984:             * providers. The filter is case-insensitive.
0985:             *
0986:             * @return all the installed providers that satisfy the selection
0987:             * criteria, or null if no such providers have been installed. 
0988:             *
0989:             * @throws InvalidParameterException
0990:             *         if the filter is not in the required format
0991:             *
0992:             * @see #getProviders(java.lang.String)
0993:             */
0994:            public static Provider[] getProviders(Map filter) {
0995:                // Get all installed providers first.
0996:                // Then only return those providers who satisfy the selection criteria.
0997:                Provider[] allProviders = Security.getProviders();
0998:                Set keySet = filter.keySet();
0999:                LinkedHashSet candidates = new LinkedHashSet(5);
1000:
1001:                // Returns all installed providers
1002:                // if the selection criteria is null.
1003:                if ((keySet == null) || (allProviders == null)) {
1004:                    return allProviders;
1005:                }
1006:
1007:                boolean firstSearch = true;
1008:
1009:                // For each selection criterion, remove providers
1010:                // which don't satisfy the criterion from the candidate set.
1011:                for (Iterator ite = keySet.iterator(); ite.hasNext();) {
1012:                    String key = (String) ite.next();
1013:                    String value = (String) filter.get(key);
1014:
1015:                    LinkedHashSet newCandidates = getAllQualifyingCandidates(
1016:                            key, value, allProviders);
1017:                    if (firstSearch) {
1018:                        candidates = newCandidates;
1019:                        firstSearch = false;
1020:                    }
1021:
1022:                    if ((newCandidates != null) && !newCandidates.isEmpty()) {
1023:                        // For each provider in the candidates set, if it
1024:                        // isn't in the newCandidate set, we should remove
1025:                        // it from the candidate set.
1026:                        for (Iterator cansIte = candidates.iterator(); cansIte
1027:                                .hasNext();) {
1028:                            Provider prov = (Provider) cansIte.next();
1029:                            if (!newCandidates.contains(prov)) {
1030:                                cansIte.remove();
1031:                            }
1032:                        }
1033:                    } else {
1034:                        candidates = null;
1035:                        break;
1036:                    }
1037:                }
1038:
1039:                if ((candidates == null) || (candidates.isEmpty()))
1040:                    return null;
1041:
1042:                Object[] candidatesArray = candidates.toArray();
1043:                Provider[] result = new Provider[candidatesArray.length];
1044:
1045:                for (int i = 0; i < result.length; i++) {
1046:                    result[i] = (Provider) candidatesArray[i];
1047:                }
1048:
1049:                return result;
1050:            }
1051:
1052:            private static boolean checkSuperclass(Class subclass,
1053:                    Class super class) {
1054:                while (!subclass.equals(super class)) {
1055:                    subclass = subclass.getSuperclass();
1056:                    if (subclass == null) {
1057:                        return false;
1058:                    }
1059:                }
1060:                return true;
1061:            }
1062:
1063:            /*
1064:             * Returns an array of objects: the first object in the array is
1065:             * an instance of an implementation of the requested algorithm
1066:             * and type, and the second object in the array identifies the provider
1067:             * of that implementation.
1068:             * The <code>provider</code> argument can be null, in which case all
1069:             * configured providers will be searched in order of preference.
1070:             */
1071:            static Object[] getImpl(String algorithm, String type,
1072:                    String provider) throws NoSuchAlgorithmException,
1073:                    NoSuchProviderException {
1074:                ProviderProperty pp = getEngineClassName(algorithm, provider,
1075:                        type);
1076:                return doGetImpl(algorithm, type, pp);
1077:            }
1078:
1079:            static Object[] getImpl(String algorithm, String type,
1080:                    String provider, Object params)
1081:                    throws NoSuchAlgorithmException, NoSuchProviderException,
1082:                    InvalidAlgorithmParameterException {
1083:                ProviderProperty pp = getEngineClassName(algorithm, provider,
1084:                        type);
1085:                return doGetImpl(algorithm, type, pp, params);
1086:            }
1087:
1088:            /*
1089:             * Returns an array of objects: the first object in the array is
1090:             * an instance of an implementation of the requested algorithm
1091:             * and type, and the second object in the array identifies the provider
1092:             * of that implementation.
1093:             * The <code>provider</code> argument cannot be null.
1094:             */
1095:            static Object[] getImpl(String algorithm, String type,
1096:                    Provider provider) throws NoSuchAlgorithmException {
1097:                ProviderProperty pp = getEngineClassName(algorithm, provider,
1098:                        type);
1099:                return doGetImpl(algorithm, type, pp);
1100:            }
1101:
1102:            static Object[] getImpl(String algorithm, String type,
1103:                    Provider provider, Object params)
1104:                    throws NoSuchAlgorithmException,
1105:                    InvalidAlgorithmParameterException {
1106:                ProviderProperty pp = getEngineClassName(algorithm, provider,
1107:                        type);
1108:                return doGetImpl(algorithm, type, pp, params);
1109:            }
1110:
1111:            private static Object[] doGetImpl(String algorithm, String type,
1112:                    ProviderProperty pp) throws NoSuchAlgorithmException {
1113:                try {
1114:                    return doGetImpl(algorithm, type, pp, null);
1115:                } catch (InvalidAlgorithmParameterException e) {
1116:                    // should not occur
1117:                    throw new NoSuchAlgorithmException(e.getMessage());
1118:                }
1119:            }
1120:
1121:            private static Object[] doGetImpl(String algorithm, String type,
1122:                    ProviderProperty pp, Object params)
1123:                    throws NoSuchAlgorithmException,
1124:                    InvalidAlgorithmParameterException {
1125:                String className = pp.className;
1126:                String providerName = pp.provider.getName();
1127:
1128:                try {
1129:                    // java.security.<type>.Spi is a system class, therefore
1130:                    // Class.forName() always works
1131:                    Class typeClass;
1132:                    if (type.equals("CertificateFactory")
1133:                            || type.equals("CertPathBuilder")
1134:                            || type.equals("CertPathValidator")
1135:                            || type.equals("CertStore")) {
1136:                        typeClass = Class.forName("java.security.cert." + type
1137:                                + "Spi");
1138:                    } else {
1139:                        typeClass = Class.forName("java.security." + type
1140:                                + "Spi");
1141:                    }
1142:
1143:                    // Load the implementation class using the same class loader that
1144:                    // was used to load the associated provider.
1145:                    // In order to get the class loader of a class, the caller's class
1146:                    // loader must be the same as or an ancestor of the class loader
1147:                    // being returned.
1148:                    // Since java.security.Security is a system class, it can get the
1149:                    // class loader of any class (the system class loader is an
1150:                    // ancestor of all class loaders).
1151:                    ClassLoader cl = pp.provider.getClass().getClassLoader();
1152:                    Class implClass;
1153:                    if (cl != null) {
1154:                        implClass = cl.loadClass(className);
1155:                    } else {
1156:                        implClass = Class.forName(className);
1157:                    }
1158:
1159:                    if (checkSuperclass(implClass, typeClass)) {
1160:                        Object obj;
1161:                        if (type.equals("CertStore")) {
1162:                            Constructor cons = implClass
1163:                                    .getConstructor(new Class[] { Class
1164:                                            .forName("java.security.cert.CertStoreParameters") });
1165:                            obj = cons.newInstance(new Object[] { params });
1166:                        } else
1167:                            obj = implClass.newInstance();
1168:                        return new Object[] { obj, pp.provider };
1169:                    } else {
1170:                        throw new NoSuchAlgorithmException(
1171:                                "class configured for " + type + ": "
1172:                                        + className + " not a " + type);
1173:                    }
1174:                } catch (ClassNotFoundException e) {
1175:                    throw new NoSuchAlgorithmException("class configured for "
1176:                            + type + "(provider: " + providerName + ")"
1177:                            + "cannot be found.\n" + e.getMessage());
1178:                } catch (InstantiationException e) {
1179:                    throw (NoSuchAlgorithmException) new NoSuchAlgorithmException(
1180:                            "class " + className + " configured for " + type
1181:                                    + "(provider: " + providerName
1182:                                    + ") cannot be " + "instantiated.\n")
1183:                            .initCause(e);
1184:                } catch (IllegalAccessException e) {
1185:                    throw new NoSuchAlgorithmException("class " + className
1186:                            + " configured for " + type + "(provider: "
1187:                            + providerName + ") cannot be accessed.\n"
1188:                            + e.getMessage());
1189:                } catch (SecurityException e) {
1190:                    throw new NoSuchAlgorithmException("class " + className
1191:                            + " configured for " + type + "(provider: "
1192:                            + providerName + ") cannot be accessed.\n"
1193:                            + e.getMessage());
1194:                } catch (NoSuchMethodException e) {
1195:                    throw new NoSuchAlgorithmException("constructor for "
1196:                            + "class " + className + " configured for " + type
1197:                            + "(provider: " + providerName
1198:                            + ") cannot be instantiated.\n" + e.getMessage());
1199:                } catch (InvocationTargetException e) {
1200:                    Throwable t = e.getCause();
1201:                    if (t != null
1202:                            && t instanceof  InvalidAlgorithmParameterException)
1203:                        throw (InvalidAlgorithmParameterException) t;
1204:                    else
1205:                        throw new InvalidAlgorithmParameterException(
1206:                                "constructor " + "for class " + className
1207:                                        + " configured for " + type
1208:                                        + "(provider: " + providerName
1209:                                        + ") cannot be instantiated.\n"
1210:                                        + e.getMessage());
1211:                }
1212:            }
1213:
1214:            /**
1215:             * Gets a security property value.
1216:             *
1217:             * <p>First, if there is a security manager, its
1218:             * <code>checkPermission</code>  method is called with a 
1219:             * <code>java.security.SecurityPermission("getProperty."+key)</code>
1220:             * permission to see if it's ok to retrieve the specified
1221:             * security property value.. 
1222:             *
1223:             * @param key the key of the property being retrieved.
1224:             *
1225:             * @return the value of the security property corresponding to key.
1226:             *
1227:             * @throws  SecurityException
1228:             *          if a security manager exists and its <code>{@link
1229:             *          java.lang.SecurityManager#checkPermission}</code> method
1230:             *          denies
1231:             *          access to retrieve the specified security property value
1232:             * 
1233:             * @see #setProperty
1234:             * @see java.security.SecurityPermission
1235:             */
1236:            public static String getProperty(String key) {
1237:                SecurityManager sm = System.getSecurityManager();
1238:                if (sm != null) {
1239:                    sm.checkPermission(new SecurityPermission("getProperty."
1240:                            + key));
1241:                }
1242:                String name = props.getProperty(key);
1243:                if (name != null)
1244:                    name = name.trim(); // could be a class name with trailing ws
1245:                return name;
1246:            }
1247:
1248:            /**
1249:             * Sets a security property value.
1250:             *
1251:             * <p>First, if there is a security manager, its
1252:             * <code>checkPermission</code> method is called with a 
1253:             * <code>java.security.SecurityPermission("setProperty."+key)</code>
1254:             * permission to see if it's ok to set the specified
1255:             * security property value.
1256:             *
1257:             * @param key the name of the property to be set.
1258:             *
1259:             * @param datum the value of the property to be set.
1260:             *
1261:             * @throws  SecurityException
1262:             *          if a security manager exists and its <code>{@link
1263:             *          java.lang.SecurityManager#checkPermission}</code> method
1264:             *          denies access to set the specified security property value
1265:             * 
1266:             * @see #getProperty
1267:             * @see java.security.SecurityPermission
1268:             */
1269:            public static void setProperty(String key, String datum) {
1270:                check("setProperty." + key);
1271:                props.put(key, datum);
1272:                invalidateSMCache(key); /* See below. */
1273:            }
1274:
1275:            /*
1276:             * Implementation detail:  If the property we just set in
1277:             * setProperty() was either "package.access" or
1278:             * "package.definition", we need to signal to the SecurityManager
1279:             * class that the value has just changed, and that it should
1280:             * invalidate it's local cache values.
1281:             *
1282:             * Rather than create a new API entry for this function,
1283:             * we use reflection to set a private variable.
1284:             */
1285:            private static void invalidateSMCache(String key) {
1286:
1287:                final boolean pa = key.equals("package.access");
1288:                final boolean pd = key.equals("package.definition");
1289:
1290:                if (pa || pd) {
1291:                    AccessController.doPrivileged(new PrivilegedAction() {
1292:                        public Object run() {
1293:                            try {
1294:                                /* Get the class via the bootstrap class loader. */
1295:                                Class cl = Class.forName(
1296:                                        "java.lang.SecurityManager", false,
1297:                                        null);
1298:                                Field f = null;
1299:                                boolean accessible = false;
1300:
1301:                                if (pa) {
1302:                                    f = cl
1303:                                            .getDeclaredField("packageAccessValid");
1304:                                    accessible = f.isAccessible();
1305:                                    f.setAccessible(true);
1306:                                } else {
1307:                                    f = cl
1308:                                            .getDeclaredField("packageDefinitionValid");
1309:                                    accessible = f.isAccessible();
1310:                                    f.setAccessible(true);
1311:                                }
1312:                                f.setBoolean(f, false);
1313:                                f.setAccessible(accessible);
1314:                            } catch (Exception e1) {
1315:                                /* If we couldn't get the class, it hasn't
1316:                                 * been loaded yet.  If there is no such
1317:                                 * field, we shouldn't try to set it.  There
1318:                                 * shouldn't be a security execption, as we
1319:                                 * are loaded by boot class loader, and we
1320:                                 * are inside a doPrivileged() here.
1321:                                 *
1322:                                 * NOOP: don't do anything...
1323:                                 */
1324:                            }
1325:                            return null;
1326:                        } /* run */
1327:                    }); /* PrivilegedAction */
1328:                } /* if */
1329:            }
1330:
1331:            private static void check(String directive) {
1332:                SecurityManager security = System.getSecurityManager();
1333:                if (security != null) {
1334:                    security.checkSecurityAccess(directive);
1335:                }
1336:            }
1337:
1338:            /**
1339:             * Print an error message that may be significant to a user.
1340:             */
1341:            static void error(String msg) {
1342:                if (debug) {
1343:                    System.err.println(msg);
1344:                }
1345:            }
1346:
1347:            /**
1348:             * Print an error message that may be significant to a user.
1349:             */
1350:            static void error(String msg, Throwable t) {
1351:                error(msg);
1352:                if (debug) {
1353:                    t.printStackTrace();
1354:                }
1355:            }
1356:
1357:            /**
1358:             * Print an debugging message that may be significant to a developer.
1359:             */
1360:            static void debug(String msg) {
1361:                if (debug) {
1362:                    System.err.println(msg);
1363:                }
1364:            }
1365:
1366:            /**
1367:             * Print an debugging message that may be significant to a developer.
1368:             */
1369:            static void debug(String msg, Throwable t) {
1370:                if (debug) {
1371:                    t.printStackTrace();
1372:                    System.err.println(msg);
1373:                }
1374:            }
1375:
1376:            /*
1377:             * Returns all providers who satisfy the specified
1378:             * criterion.
1379:             */
1380:            private static LinkedHashSet getAllQualifyingCandidates(
1381:                    String filterKey, String filterValue,
1382:                    Provider[] allProviders) {
1383:                String[] filterComponents = getFilterComponents(filterKey,
1384:                        filterValue);
1385:
1386:                // The first component is the service name.
1387:                // The second is the algorithm name.
1388:                // If the third isn't null, that is the attrinute name.
1389:                String serviceName = filterComponents[0];
1390:                String algName = filterComponents[1];
1391:                String attrName = filterComponents[2];
1392:
1393:                // Check whether we can find anything in the cache
1394:                String cacheKey = serviceName + '.' + algName;
1395:                LinkedHashSet candidates = (LinkedHashSet) searchResultsCache
1396:                        .get(cacheKey);
1397:
1398:                // If there is no entry for the cacheKey in the cache,
1399:                // let's build an entry for it first.
1400:                LinkedHashSet forCache = getProvidersNotUsingCache(serviceName,
1401:                        algName, null, null, null, allProviders);
1402:
1403:                if ((forCache == null) || (forCache.isEmpty())) {
1404:                    return null;
1405:                } else {
1406:                    searchResultsCache.put(cacheKey, forCache);
1407:                    if (attrName == null) {
1408:                        return forCache;
1409:                    }
1410:                    return getProvidersNotUsingCache(serviceName, algName,
1411:                            attrName, filterValue, candidates, allProviders);
1412:                }
1413:            }
1414:
1415:            private static LinkedHashSet getProvidersNotUsingCache(
1416:                    String serviceName, String algName, String attrName,
1417:                    String filterValue, LinkedHashSet candidates,
1418:                    Provider[] allProviders) {
1419:                if ((attrName != null) && (candidates != null)
1420:                        && (!candidates.isEmpty())) {
1421:                    for (Iterator cansIte = candidates.iterator(); cansIte
1422:                            .hasNext();) {
1423:                        Provider prov = (Provider) cansIte.next();
1424:                        if (!isCriterionSatisfied(prov, serviceName, algName,
1425:                                attrName, filterValue)) {
1426:                            cansIte.remove();
1427:                        }
1428:                    }
1429:                }
1430:
1431:                if ((candidates == null) || (candidates.isEmpty())) {
1432:                    if (candidates == null)
1433:                        candidates = new LinkedHashSet(5);
1434:                    for (int i = 0; i < allProviders.length; i++) {
1435:                        if (isCriterionSatisfied(allProviders[i], serviceName,
1436:                                algName, attrName, filterValue)) {
1437:                            candidates.add(allProviders[i]);
1438:                        }
1439:                    }
1440:                }
1441:
1442:                return candidates;
1443:            }
1444:
1445:            /*
1446:             * Returns true if the given provider satisfies
1447:             * the selection criterion key:value.
1448:             */
1449:            private static boolean isCriterionSatisfied(Provider prov,
1450:                    String serviceName, String algName, String attrName,
1451:                    String filterValue) {
1452:                String key = serviceName + '.' + algName;
1453:
1454:                if (attrName != null) {
1455:                    key += ' ' + attrName;
1456:                }
1457:                // Check whether the provider has a property
1458:                // whose key is the same as the given key.
1459:                String propValue = getProviderProperty(key, prov);
1460:
1461:                if (propValue == null) {
1462:                    // Check whether we have an alias instead
1463:                    // of a standard name in the key.
1464:                    String standardName = getProviderProperty("Alg.Alias."
1465:                            + serviceName + "." + algName, prov);
1466:                    if (standardName != null) {
1467:                        key = serviceName + "." + standardName;
1468:
1469:                        if (attrName != null) {
1470:                            key += ' ' + attrName;
1471:                        }
1472:
1473:                        propValue = getProviderProperty(key, prov);
1474:                    }
1475:
1476:                    if (propValue == null) {
1477:                        // The provider doesn't have the given
1478:                        // key in its property list.
1479:                        return false;
1480:                    }
1481:                }
1482:
1483:                // If the key is in the format of:
1484:                // <crypto_service>.<algorithm_or_type>,
1485:                // there is no need to check the value.
1486:
1487:                if (attrName == null) {
1488:                    return true;
1489:                }
1490:
1491:                // If we get here, the key must be in the
1492:                // format of <crypto_service>.<algorithm_or_provider> <attribute_name>.
1493:                if (isStandardAttr(attrName)) {
1494:                    return isConstraintSatisfied(attrName, filterValue,
1495:                            propValue);
1496:                } else {
1497:                    return filterValue.equalsIgnoreCase(propValue);
1498:                }
1499:            }
1500:
1501:            /*
1502:             * Returns true if the attribute is a standard attribute;
1503:             * otherwise, returns false.
1504:             */
1505:            private static boolean isStandardAttr(String attribute) {
1506:                // For now, we just have two standard attributes: KeySize and ImplementedIn.
1507:                if (attribute.equalsIgnoreCase("KeySize"))
1508:                    return true;
1509:
1510:                if (attribute.equalsIgnoreCase("ImplementedIn"))
1511:                    return true;
1512:
1513:                return false;
1514:            }
1515:
1516:            /*
1517:             * Returns true if the requested attribute value is supported;
1518:             * otherwise, returns false.
1519:             */
1520:            private static boolean isConstraintSatisfied(String attribute,
1521:                    String value, String prop) {
1522:                // For KeySize, prop is the max key size the
1523:                // provider supports for a specific <crypto_service>.<algorithm>.
1524:                if (attribute.equalsIgnoreCase("KeySize")) {
1525:                    int requestedSize = (new Integer(value)).intValue();
1526:                    int maxSize = (new Integer(prop)).intValue();
1527:                    if (requestedSize <= maxSize) {
1528:                        return true;
1529:                    } else {
1530:                        return false;
1531:                    }
1532:                }
1533:
1534:                // For Type, prop is the type of the implementation
1535:                // for a specific <crypto service>.<algorithm>.
1536:                if (attribute.equalsIgnoreCase("ImplementedIn")) {
1537:                    return value.equalsIgnoreCase(prop);
1538:                }
1539:
1540:                return false;
1541:            }
1542:
1543:            static String[] getFilterComponents(String filterKey,
1544:                    String filterValue) {
1545:                int algIndex = filterKey.indexOf('.');
1546:
1547:                if (algIndex < 0) {
1548:                    // There must be a dot in the filter, and the dot
1549:                    // shouldn't be at the beginning of this string.
1550:                    throw new InvalidParameterException("Invalid filter");
1551:                }
1552:
1553:                String serviceName = filterKey.substring(0, algIndex);
1554:                String algName = null;
1555:                String attrName = null;
1556:
1557:                if (filterValue.length() == 0) {
1558:                    // The filterValue is an empty string. So the filterKey 
1559:                    // should be in the format of <crypto_service>.<algorithm_or_type>.
1560:                    algName = filterKey.substring(algIndex + 1).trim();
1561:                    if (algName.length() == 0) {
1562:                        // There must be a algorithm or type name.
1563:                        throw new InvalidParameterException("Invalid filter");
1564:                    }
1565:                } else {
1566:                    // The filterValue is a non-empty string. So the filterKey must be
1567:                    // in the format of
1568:                    // <crypto_service>.<algorithm_or_type> <attribute_name>
1569:                    int attrIndex = filterKey.indexOf(' ');
1570:
1571:                    if (attrIndex == -1) {
1572:                        // There is no attribute name in the filter.
1573:                        throw new InvalidParameterException("Invalid filter");
1574:                    } else {
1575:                        attrName = filterKey.substring(attrIndex + 1).trim();
1576:                        if (attrName.length() == 0) {
1577:                            // There is no attribute name in the filter.
1578:                            throw new InvalidParameterException(
1579:                                    "Invalid filter");
1580:                        }
1581:                    }
1582:
1583:                    // There must be an algorithm name in the filter.
1584:                    if ((attrIndex < algIndex) || (algIndex == attrIndex - 1)) {
1585:                        throw new InvalidParameterException("Invalid filter");
1586:                    } else {
1587:                        algName = filterKey.substring(algIndex + 1, attrIndex);
1588:                    }
1589:                }
1590:
1591:                String[] result = new String[3];
1592:                result[0] = serviceName;
1593:                result[1] = algName;
1594:                result[2] = attrName;
1595:
1596:                return result;
1597:            }
1598:
1599:            /**
1600:             * Returns a Set of Strings containing the names of all available
1601:             * algorithms or types for the specified Java cryptographic service
1602:             * (e.g., Signature, MessageDigest, Cipher, Mac, KeyStore). Returns
1603:             * an empty Set if there is no provider that supports the  
1604:             * specified service. For a complete list of Java cryptographic
1605:             * services, please see the 
1606:             * <a href="../../../guide/security/CryptoSpec.html">Java 
1607:             * Cryptography Architecture API Specification &amp; Reference</a>.
1608:             * Note: the returned set is immutable.
1609:             *
1610:             * @param serviceName the name of the Java cryptographic 
1611:             * service (e.g., Signature, MessageDigest, Cipher, Mac, KeyStore).
1612:             * Note: this parameter is case-insensitive.
1613:             *
1614:             * NOTE: <B>java.security.Signature, java.security.KeyStore</B> are found 
1615:             * in J2ME CDC profiles such as J2ME Foundation Profile. <B> Cipher,
1616:             * Mac </B> are found in J2ME CDC optional packages such as J2ME Security
1617:             * Optional Package.
1618:             *
1619:             * @return a Set of Strings containing the names of all available 
1620:             * algorithms or types for the specified Java cryptographic service
1621:             * or an empty set if no provider supports the specified service.
1622:             *
1623:             * @since 1.4
1624:             **/
1625:            public static Set getAlgorithms(String serviceName) {
1626:                HashSet result = new HashSet();
1627:
1628:                if ((serviceName == null) || (serviceName.length() == 0)
1629:                        || (serviceName.endsWith("."))) {
1630:                    return result;
1631:                }
1632:
1633:                Provider[] providers = Security.getProviders();
1634:
1635:                for (int i = 0; i < providers.length; i++) {
1636:                    // Check the keys for each provider.
1637:                    for (Enumeration e = providers[i].keys(); e
1638:                            .hasMoreElements();) {
1639:                        String currentKey = ((String) e.nextElement())
1640:                                .toUpperCase();
1641:                        if (currentKey.startsWith(serviceName.toUpperCase())) {
1642:                            // We should skip the currentKey if it contains a 
1643:                            // whitespace. The reason is: such an entry in the
1644:                            // provider property contains attributes for the
1645:                            // implementation of an algorithm. We are only interested
1646:                            // in entries which lead to the implementation
1647:                            // classes.
1648:                            if (currentKey.indexOf(" ") < 0) {
1649:                                result.add(currentKey.substring(serviceName
1650:                                        .length() + 1));
1651:                            }
1652:                        }
1653:                    }
1654:                }
1655:                return Collections.unmodifiableSet(result);
1656:            }
1657:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.