GNU Classpath (0.20) | |
Frames | No Frames |
1: /* Sasl.java -- 2: Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package javax.security.sasl; 40: 41: import java.security.Provider; 42: import java.security.Security; 43: import java.util.Enumeration; 44: import java.util.HashSet; 45: import java.util.Iterator; 46: import java.util.Map; 47: import java.util.Vector; 48: 49: import javax.security.auth.callback.CallbackHandler; 50: 51: /** 52: * <p>A static class for creating SASL clients and servers.</p> 53: * 54: * <p>This class defines the policy of how to locate, load, and instantiate SASL 55: * clients and servers.</p> 56: * 57: * <p>For example, an application or library gets a SASL client instance by 58: * doing something like:</p> 59: * 60: * <pre> 61: *SaslClient sc = 62: * Sasl.createSaslClient(mechanisms, authorizationID, protocol, 63: * serverName, props, callbackHandler); 64: * </pre> 65: * 66: * <p>It can then proceed to use the instance to create an authenticated 67: * connection.</p> 68: * 69: * <p>Similarly, a server gets a SASL server instance by using code that looks 70: * as follows:</p> 71: * 72: * <pre> 73: *SaslServer ss = 74: * Sasl.createSaslServer(mechanism, protocol, serverName, props, 75: * callbackHandler); 76: * </pre> 77: * 78: * @since 1.5 79: */ 80: public class Sasl 81: { 82: 83: // Constants and variables 84: // ------------------------------------------------------------------------- 85: 86: /** 87: * <p>The name of a property that specifies the quality-of-protection to use. 88: * The property contains a comma-separated, ordered list of quality-of- 89: * protection values that the client or server is willing to support. A qop 90: * value is one of:</p> 91: * 92: * <ul> 93: * <li><code>"auth"</code> - authentication only,</li> 94: * <li><code>"auth-int"</code> - authentication plus integrity 95: * protection,</li> 96: * <li><code>"auth-conf"</code> - authentication plus integrity and 97: * confidentiality protection.</li> 98: * </ul> 99: * 100: * <p>The order of the list specifies the preference order of the client or 101: * server.</p> 102: * 103: * <p>If this property is absent, the default qop is <code>"auth"</code>.</p> 104: * 105: * <p>The value of this constant is <code>"javax.security.sasl.qop"</code>.</p> 106: */ 107: public static final String QOP = "javax.security.sasl.qop"; 108: 109: /** 110: * <p>The name of a property that specifies the cipher strength to use. The 111: * property contains a comma-separated, ordered list of cipher strength 112: * values that the client or server is willing to support. A strength value 113: * is one of:</p> 114: * 115: * <ul> 116: * <li><code>"low"</code>,</li> 117: * <li><code>"medium"</code>,</li> 118: * <li><code>"high"</code>.</li> 119: * </ul> 120: * 121: * <p>The order of the list specifies the preference order of the client or 122: * server. An implementation should allow configuration of the meaning of 123: * these values. An application may use the Java Cryptography Extension (JCE) 124: * with JCE-aware mechanisms to control the selection of cipher suites that 125: * match the strength values.</p> 126: * 127: * <p>If this property is absent, the default strength is 128: * <code>"high,medium,low"</code>.</p> 129: * 130: * <p>The value of this constant is <code>"javax.security.sasl.strength"</code>. 131: * </p> 132: */ 133: public static final String STRENGTH = "javax.security.sasl.strength"; 134: 135: /** 136: * <p>The name of a property that specifies whether the server must authenticate 137: * to the client. The property contains <code>"true"</code> if the server 138: * must authenticate the to client; <code>"false"</code> otherwise. The 139: * default is <code>"false"</code>.</p> 140: * 141: * <p>The value of this constant is 142: * <code>"javax.security.sasl.server.authentication"</code>.</p> 143: */ 144: public static final String SERVER_AUTH = "javax.security.sasl.server.authentication"; 145: 146: /** 147: * <p>The name of a property that specifies the maximum size of the receive 148: * buffer in bytes of {@link SaslClient}/{@link SaslServer}. The property 149: * contains the string representation of an integer.</p> 150: * 151: * <p>If this property is absent, the default size is defined by the 152: * mechanism.</p> 153: * 154: * <p>The value of this constant is <code>"javax.security.sasl.maxbuffer"</code>. 155: * </p> 156: */ 157: public static final String MAX_BUFFER = "javax.security.sasl.maxbuffer"; 158: 159: /** 160: * <p>The name of a property that specifies the maximum size of the raw send 161: * buffer in bytes of {@link SaslClient}/{@link SaslServer}. The property 162: * contains the string representation of an integer. The value of this 163: * property is negotiated between the client and server during the 164: * authentication exchange.</p> 165: * 166: * <p>The value of this constant is <code>"javax.security.sasl.rawsendsize"</code>. 167: * </p> 168: */ 169: public static final String RAW_SEND_SIZE = "javax.security.sasl.rawsendsize"; 170: 171: /** 172: * <p>The name of a property that specifies whether mechanisms susceptible 173: * to simple plain passive attacks (e.g., "PLAIN") are not permitted. The 174: * property contains <code>"true"</code> if such mechanisms are not 175: * permitted; <code>"false"</code> if such mechanisms are permitted. The 176: * default is <code>"false"</code>.</p> 177: * 178: * <p>The value of this constant is <code>"javax.security.sasl.policy.noplaintext"</code>. 179: * </p> 180: */ 181: public static final String POLICY_NOPLAINTEXT = "javax.security.sasl.policy.noplaintext"; 182: 183: /** 184: * <p>The name of a property that specifies whether mechanisms susceptible to 185: * active (non-dictionary) attacks are not permitted. The property contains 186: * <code>"true"</code> if mechanisms susceptible to active attacks are not 187: * permitted; <code>"false"</code> if such mechanisms are permitted. The 188: * default is <code>"false"</code>.</p> 189: * 190: * <p>The value of this constant is <code>"javax.security.sasl.policy.noactive"</code>. 191: * </p> 192: */ 193: public static final String POLICY_NOACTIVE = "javax.security.sasl.policy.noactive"; 194: 195: /** 196: * <p>The name of a property that specifies whether mechanisms susceptible to 197: * passive dictionary attacks are not permitted. The property contains 198: * <code>"true"</code> if mechanisms susceptible to dictionary attacks are 199: * not permitted; <code>"false"</code> if such mechanisms are permitted. The 200: * default is <code>"false"</code>.</p> 201: * 202: * <p>The value of this constant is <code>"javax.security.sasl.policy.nodictionary"</code>. 203: * </p> 204: */ 205: public static final String POLICY_NODICTIONARY = "javax.security.sasl.policy.nodictionary"; 206: 207: /** 208: * <p>The name of a property that specifies whether mechanisms that accept 209: * anonymous login are not permitted. The property contains <code>"true"</code> 210: * if mechanisms that accept anonymous login are not permitted; <code>"false" 211: * </code> if such mechanisms are permitted. The default is <code>"false"</code>. 212: * </p> 213: * 214: * <p>The value of this constant is <code>"javax.security.sasl.policy.noanonymous"</code>. 215: * </p> 216: */ 217: public static final String POLICY_NOANONYMOUS = "javax.security.sasl.policy.noanonymous"; 218: 219: /** 220: * The name of a property that specifies whether mechanisms that implement 221: * forward secrecy between sessions are required. Forward secrecy means that 222: * breaking into one session will not automatically provide information for 223: * breaking into future sessions. The property contains <code>"true"</code> 224: * if mechanisms that implement forward secrecy between sessions are 225: * required; <code>"false"</code> if such mechanisms are not required. The 226: * default is <code>"false"</code>. 227: * 228: * <p>The value of this constant is <code>"javax.security.sasl.policy.forward"</code>. 229: * </p> 230: */ 231: public static final String POLICY_FORWARD_SECRECY = "javax.security.sasl.policy.forward"; 232: 233: /** 234: * The name of a property that specifies whether mechanisms that pass client 235: * credentials are required. The property contains <code>"true"</code> if 236: * mechanisms that pass client credentials are required; <code>"false"</code> 237: * if such mechanisms are not required. The default is <code>"false"</code>. 238: * 239: * <p>The value of this constant is <code>"javax.security.sasl.policy.credentials"</code>. 240: * </p> 241: */ 242: public static final String POLICY_PASS_CREDENTIALS = "javax.security.sasl.policy.credentials"; 243: 244: /** 245: * <p>The name of a property that specifies whether to reuse previously 246: * authenticated session information. The property contains <code>"true"</code> 247: * if the mechanism implementation may attempt to reuse previously 248: * authenticated session information; it contains <code>"false"</code> if the 249: * implementation must not reuse previously authenticated session information. 250: * A setting of <code>"true"</code> serves only as a hint; it does not 251: * necessarily entail actual reuse because reuse might not be possible due to 252: * a number of reasons, including, but not limited to, lack of mechanism 253: * support for reuse, expiration of reusable information, and the peer's 254: * refusal to support reuse. The property's default value is <code>"false"</code>. 255: * </p> 256: * 257: * <p>The value of this constant is <code>"javax.security.sasl.reuse"</code>. 258: * Note that all other parameters and properties required to create a SASL 259: * client/server instance must be provided regardless of whether this 260: * property has been supplied. That is, you cannot supply any less 261: * information in anticipation of reuse. Mechanism implementations that 262: * support reuse might allow customization of its implementation for factors 263: * such as cache size, timeouts, and criteria for reuseability. Such 264: * customizations are implementation-dependent.</p> 265: */ 266: public static final String REUSE = "javax.security.sasl.reuse"; 267: 268: private static final String CLIENT_FACTORY_SVC = "SaslClientFactory."; 269: private static final String SERVER_FACTORY_SVC = "SaslServerFactory."; 270: private static final String ALIAS = "Alg.Alias."; 271: 272: // Constructor(s) 273: // ------------------------------------------------------------------------- 274: 275: private Sasl() 276: { 277: super(); 278: } 279: 280: // Class methods 281: // ------------------------------------------------------------------------- 282: 283: /** 284: * Creates a {@link SaslClient} for the specified mechanism. 285: * 286: * <p>This method uses the JCA Security Provider Framework, described in the 287: * "Java Cryptography Architecture API Specification & Reference", for 288: * locating and selecting a {@link SaslClient} implementation.</p> 289: * 290: * <p>First, it obtains an ordered list of {@link SaslClientFactory} 291: * instances from the registered security providers for the 292: * <code>"SaslClientFactory"</code> service and the specified mechanism. It 293: * then invokes <code>createSaslClient()</code> on each factory instance on 294: * the list until one produces a non-null {@link SaslClient} instance. It 295: * returns the non-null {@link SaslClient} instance, or <code>null</code> if 296: * the search fails to produce a non-null {@link SaslClient} instance.</p> 297: * 298: * <p>A security provider for <code>SaslClientFactory</code> registers with 299: * the JCA Security Provider Framework keys of the form:</p> 300: * 301: * <pre> 302: * SaslClientFactory.mechanism_name 303: * </pre> 304: * 305: * <p>and values that are class names of implementations of {@link 306: * SaslClientFactory}.</p> 307: * 308: * <p>For example, a provider that contains a factory class, 309: * <code>com.wiz.sasl.digest.ClientFactory</code>, that supports the 310: * <code>"DIGEST-MD5"</code> mechanism would register the following entry 311: * with the JCA:</p> 312: * 313: * <pre> 314: * SaslClientFactory.DIGEST-MD5 com.wiz.sasl.digest.ClientFactory 315: * </pre> 316: * 317: * <p>See the "Java Cryptography Architecture API Specification & 318: * Reference" for information about how to install and configure security 319: * service providers.</p> 320: * 321: * @param mechanisms the non-null list of mechanism names to try. Each is the 322: * IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5"). 323: * @param authorizationID the possibly <code>null</code> protocol-dependent 324: * identification to be used for authorization. If <code>null</code> or 325: * empty, the server derives an authorization ID from the client's 326: * authentication credentials. When the SASL authentication completes 327: * successfully, the specified entity is granted access. 328: * @param protocol the non-null string name of the protocol for which the 329: * authentication is being performed (e.g. "ldap"). 330: * @param serverName the non-null fully-qualified host name of the server to 331: * authenticate to. 332: * @param props the possibly null set of properties used to select the SASL 333: * mechanism and to configure the authentication exchange of the selected 334: * mechanism. For example, if props contains the {@link Sasl#POLICY_NOPLAINTEXT} 335: * property with the value <code>"true"</code>, then the selected SASL 336: * mechanism must not be susceptible to simple plain passive attacks. In 337: * addition to the standard properties declared in this class, other, 338: * possibly mechanism-specific, properties can be included. Properties not 339: * relevant to the selected mechanism are ignored. 340: * @param cbh the possibly <code>null</code> callback handler to used by the 341: * SASL mechanisms to get further information from the application/library to 342: * complete the authentication. For example, a SASL mechanism might require 343: * the authentication ID, password and realm from the caller. The 344: * authentication ID is requested by using a 345: * {@link javax.security.auth.callback.NameCallback}. The password is 346: * requested by using a {@link javax.security.auth.callback.PasswordCallback}. 347: * The realm is requested by using a {@link RealmChoiceCallback} if there is 348: * a list of realms to choose from, and by using a {@link RealmCallback} if 349: * the realm must be entered. 350: * @return a possibly <code>null</code> {@link SaslClient} created using the 351: * parameters supplied. If <code>null</code>, the method could not find a 352: * {@link SaslClientFactory} that will produce one. 353: * @throws SaslException if a {@link SaslClient} cannot be created because 354: * of an error. 355: */ 356: public static SaslClient createSaslClient(String[] mechanisms, 357: String authorizationID, 358: String protocol, 359: String serverName, Map props, 360: CallbackHandler cbh) 361: throws SaslException 362: { 363: if (mechanisms == null) 364: { 365: return null; 366: } 367: Provider[] providers = Security.getProviders(); 368: if (providers == null || providers.length == 0) 369: { 370: return null; 371: } 372: 373: SaslClient result = null; 374: SaslClientFactory factory = null; 375: String m, clazz = null, upper, alias; 376: int j; 377: Provider p; 378: for (int i = 0; i < mechanisms.length; i++) 379: { 380: m = mechanisms[i]; 381: if (m == null) 382: continue; 383: for (j = 0; j < providers.length; j++) 384: { 385: p = providers[j]; 386: if (p != null) 387: { 388: // try the name as is 389: clazz = p.getProperty(CLIENT_FACTORY_SVC + m); 390: if (clazz == null) // try all uppercase 391: { 392: upper = m.toUpperCase(); 393: clazz = p.getProperty(CLIENT_FACTORY_SVC + upper); 394: if (clazz == null) // try if it's an alias 395: { 396: alias = p.getProperty(ALIAS + CLIENT_FACTORY_SVC + m); 397: if (alias == null) // try all-uppercase alias name 398: { 399: alias = p.getProperty(ALIAS + CLIENT_FACTORY_SVC + upper); 400: if (alias == null) // spit the dummy 401: continue; 402: } 403: clazz = p.getProperty(CLIENT_FACTORY_SVC + alias); 404: } 405: } 406: if (clazz == null) 407: continue; 408: else 409: clazz = clazz.trim(); 410: } 411: 412: try 413: { 414: result = null; 415: factory = (SaslClientFactory) Class.forName(clazz).newInstance(); 416: result = factory.createSaslClient(mechanisms, authorizationID, 417: protocol, serverName, props, cbh); 418: } 419: catch (ClassCastException ignored) // ignore instantiation exceptions 420: { 421: } 422: catch (ClassNotFoundException ignored) 423: { 424: } 425: catch (InstantiationException ignored) 426: { 427: } 428: catch (IllegalAccessException ignored) 429: { 430: } 431: if (result != null) 432: return result; 433: } 434: } 435: return null; 436: } 437: 438: /** 439: * Gets an enumeration of known factories for producing a {@link SaslClient} 440: * instance. This method uses the same sources for locating factories as 441: * <code>createSaslClient()</code>. 442: * 443: * @return a non-null {@link Enumeration} of known factories for producing a 444: * {@link SaslClient} instance. 445: * @see #createSaslClient(String[],String,String,String,Map,CallbackHandler) 446: */ 447: public static Enumeration getSaslClientFactories() 448: { 449: Vector result = new Vector(); 450: HashSet names = new HashSet(); 451: Provider[] providers = Security.getProviders(); 452: Iterator it; 453: if (providers != null) 454: { 455: Provider p; 456: String key; 457: for (int i = 0; i < providers.length; i++) 458: { 459: p = providers[i]; 460: for (it = p.keySet().iterator(); it.hasNext(); ) 461: { 462: key = (String) it.next(); 463: // add key's binding (a) it is a class of a client factory, 464: // and (b) the key does not include blanks 465: if (key.startsWith(CLIENT_FACTORY_SVC) && key.indexOf(" ") == -1) 466: { 467: names.add(p.getProperty(key)); 468: break; 469: } 470: } 471: } 472: } 473: // we have the factory class names in names; instantiate and enumerate 474: String c; 475: for (it = names.iterator(); it.hasNext(); ) 476: { 477: c = (String) it.next(); 478: try 479: { 480: SaslClientFactory f = (SaslClientFactory) Class.forName(c).newInstance(); 481: if (f != null) 482: result.add(f); 483: } catch (ClassCastException ignored) { // ignore instantiation exceptions 484: } catch (ClassNotFoundException ignored) { 485: } catch (InstantiationException ignored) { 486: } catch (IllegalAccessException ignored) { 487: } 488: } 489: 490: return result.elements(); 491: } 492: 493: /** 494: * Creates a {@link SaslServer} for the specified mechanism. 495: * 496: * <p>This method uses the JCA Security Provider Framework, described in the 497: * "Java Cryptography Architecture API Specification & Reference", for 498: * locating and selecting a SaslServer implementation.</p> 499: * 500: * <p>First, it obtains an ordered list of {@link SaslServerFactory} 501: * instances from the registered security providers for the 502: * <code>"SaslServerFactory"</code> service and the specified mechanism. It 503: * then invokes <code>createSaslServer()</code> on each factory instance on 504: * the list until one produces a non-null {@link SaslServer} instance. It 505: * returns the non-null {@link SaslServer} instance, or <code>null</code> if 506: * the search fails to produce a non-null {@link SaslServer} instance.</p> 507: * 508: * <p>A security provider for {@link SaslServerFactory} registers with the 509: * JCA Security Provider Framework keys of the form:</p> 510: * 511: * <pre> 512: * SaslServerFactory.mechanism_name 513: * </pre> 514: * 515: * <p>and values that are class names of implementations of {@link 516: * SaslServerFactory}.</p> 517: * 518: * <p>For example, a provider that contains a factory class, 519: * <code>com.wiz.sasl.digest.ServerFactory</code>, that supports the 520: * <code>"DIGEST-MD5"</code> mechanism would register the following entry 521: * with the JCA:</p> 522: * 523: * <pre> 524: * SaslServerFactory.DIGEST-MD5 com.wiz.sasl.digest.ServerFactory 525: * </pre> 526: * 527: * <p>See the "Java Cryptography Architecture API Specification & 528: * Reference" for information about how to install and configure security 529: * service providers.</p> 530: * 531: * @param mechanism the non-null mechanism name. It must be an 532: * IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5"). 533: * @param protocol the non-null string name of the protocol for which the 534: * authentication is being performed (e.g. "ldap"). 535: * @param serverName the non-null fully qualified host name of the server. 536: * @param props the possibly <code>null</code> set of properties used to 537: * select the SASL mechanism and to configure the authentication exchange of 538: * the selected mechanism. For example, if props contains the {@link 539: * Sasl#POLICY_NOPLAINTEXT} property with the value <code>"true"</code>, then 540: * the selected SASL mechanism must not be susceptible to simple plain 541: * passive attacks. In addition to the standard properties declared in this 542: * class, other, possibly mechanism-specific, properties can be included. 543: * Properties not relevant to the selected mechanism are ignored. 544: * @param cbh the possibly <code>null</code> callback handler to used by the 545: * SASL mechanisms to get further information from the application/library to 546: * complete the authentication. For example, a SASL mechanism might require 547: * the authentication ID, password and realm from the caller. The 548: * authentication ID is requested by using a 549: * {@link javax.security.auth.callback.NameCallback}. The password is 550: * requested by using a {@link javax.security.auth.callback.PasswordCallback}. 551: * The realm is requested by using a {@link RealmChoiceCallback} if there is 552: * a list of realms to choose from, and by using a {@link RealmCallback} if 553: * the realm must be entered. 554: * @return a possibly <code>null</code> {@link SaslServer} created using the 555: * parameters supplied. If <code>null</code>, the method cannot find a 556: * {@link SaslServerFactory} instance that will produce one. 557: * @throws SaslException if a {@link SaslServer} instance cannot be created 558: * because of an error. 559: */ 560: public static SaslServer createSaslServer(String mechanism, String protocol, 561: String serverName, 562: Map props, CallbackHandler cbh) 563: throws SaslException 564: { 565: if (mechanism == null) 566: return null; 567: Provider[] providers = Security.getProviders(); 568: if (providers == null || providers.length == 0) 569: return null; 570: 571: SaslServer result = null; 572: SaslServerFactory factory = null; 573: String clazz = null, upper, alias = null; 574: int j; 575: Provider p; 576: for (j = 0; j < providers.length; j++) 577: { 578: p = providers[j]; 579: if (p != null) 580: { 581: // try the name as is 582: clazz = p.getProperty(SERVER_FACTORY_SVC + mechanism); 583: if (clazz == null) // try all uppercase 584: { 585: upper = mechanism.toUpperCase(); 586: clazz = p.getProperty(SERVER_FACTORY_SVC + upper); 587: if (clazz == null) // try if it's an alias 588: { 589: alias = p.getProperty(ALIAS + SERVER_FACTORY_SVC + mechanism); 590: if (alias == null) // try all-uppercase alias name 591: { 592: alias = p.getProperty(ALIAS + SERVER_FACTORY_SVC + upper); 593: if (alias == null) // spit the dummy 594: continue; 595: } 596: } 597: clazz = p.getProperty(SERVER_FACTORY_SVC + alias); 598: } 599: } 600: if (clazz == null) 601: continue; 602: else 603: clazz = clazz.trim(); 604: 605: try 606: { 607: result = null; 608: factory = (SaslServerFactory) Class.forName(clazz).newInstance(); 609: result = 610: factory.createSaslServer(mechanism, protocol, serverName, props, cbh); 611: } 612: catch (ClassCastException ignored) // ignore instantiation exceptions 613: { 614: } 615: catch (ClassNotFoundException ignored) 616: { 617: } 618: catch (InstantiationException ignored) 619: { 620: } 621: catch (IllegalAccessException ignored) 622: { 623: } 624: if (result != null) 625: return result; 626: } 627: return null; 628: } 629: 630: /** 631: * Gets an enumeration of known factories for producing a {@link SaslServer} 632: * instance. This method uses the same sources for locating factories as 633: * <code>createSaslServer()</code>. 634: * 635: * @return a non-null {@link Enumeration} of known factories for producing a 636: * {@link SaslServer} instance. 637: * @see #createSaslServer(String,String,String,Map,CallbackHandler) 638: */ 639: public static Enumeration getSaslServerFactories() 640: { 641: Vector result = new Vector(); 642: HashSet names = new HashSet(); 643: Provider[] providers = Security.getProviders(); 644: Iterator it; 645: if (providers != null) 646: { 647: Provider p; 648: String key; 649: for (int i = 0; i < providers.length; i++) 650: { 651: p = providers[i]; 652: for (it = p.keySet().iterator(); it.hasNext(); ) 653: { 654: key = (String) it.next(); 655: // add key's binding (a) it is a class of a server factory, 656: // and (b) the key does not include blanks 657: if (key.startsWith(SERVER_FACTORY_SVC) && key.indexOf(" ") == -1) 658: { 659: names.add(p.getProperty(key)); 660: break; 661: } 662: } 663: } 664: } 665: // we have the factory class names in names; instantiate and enumerate 666: String c; 667: for (it = names.iterator(); it.hasNext(); ) 668: { 669: c = (String) it.next(); 670: try 671: { 672: SaslServerFactory f = (SaslServerFactory) Class.forName(c).newInstance(); 673: if (f != null) 674: result.add(f); 675: } 676: catch (ClassCastException ignored) // ignore instantiation exceptions 677: { 678: } 679: catch (ClassNotFoundException ignored) 680: { 681: } 682: catch (InstantiationException ignored) 683: { 684: } 685: catch (IllegalAccessException ignored) 686: { 687: } 688: } 689: 690: return result.elements(); 691: } 692: }
GNU Classpath (0.20) |