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