GNU Classpath (0.95) | |
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, 360: Map<String, ?> props, 361: CallbackHandler cbh) 362: throws SaslException 363: { 364: if (mechanisms == null) 365: { 366: return null; 367: } 368: Provider[] providers = Security.getProviders(); 369: if (providers == null || providers.length == 0) 370: { 371: return null; 372: } 373: 374: SaslClient result = null; 375: SaslClientFactory factory = null; 376: String m, clazz = null, upper, alias; 377: int j; 378: Provider p; 379: for (int i = 0; i < mechanisms.length; i++) 380: { 381: m = mechanisms[i]; 382: if (m == null) 383: continue; 384: for (j = 0; j < providers.length; j++) 385: { 386: p = providers[j]; 387: if (p != null) 388: { 389: // try the name as is 390: clazz = p.getProperty(CLIENT_FACTORY_SVC + m); 391: if (clazz == null) // try all uppercase 392: { 393: upper = m.toUpperCase(); 394: clazz = p.getProperty(CLIENT_FACTORY_SVC + upper); 395: if (clazz == null) // try if it's an alias 396: { 397: alias = p.getProperty(ALIAS + CLIENT_FACTORY_SVC + m); 398: if (alias == null) // try all-uppercase alias name 399: { 400: alias = p.getProperty(ALIAS + CLIENT_FACTORY_SVC + upper); 401: if (alias == null) // spit the dummy 402: continue; 403: } 404: clazz = p.getProperty(CLIENT_FACTORY_SVC + alias); 405: } 406: } 407: if (clazz == null) 408: continue; 409: else 410: clazz = clazz.trim(); 411: } 412: 413: try 414: { 415: result = null; 416: factory = (SaslClientFactory) Class.forName(clazz).newInstance(); 417: result = factory.createSaslClient(mechanisms, authorizationID, 418: protocol, serverName, props, cbh); 419: } 420: catch (ClassCastException ignored) // ignore instantiation exceptions 421: { 422: } 423: catch (ClassNotFoundException ignored) 424: { 425: } 426: catch (InstantiationException ignored) 427: { 428: } 429: catch (IllegalAccessException ignored) 430: { 431: } 432: if (result != null) 433: return result; 434: } 435: } 436: return null; 437: } 438: 439: /** 440: * Gets an enumeration of known factories for producing a {@link SaslClient} 441: * instance. This method uses the same sources for locating factories as 442: * <code>createSaslClient()</code>. 443: * 444: * @return a non-null {@link Enumeration} of known factories for producing a 445: * {@link SaslClient} instance. 446: * @see #createSaslClient(String[],String,String,String,Map,CallbackHandler) 447: */ 448: public static Enumeration<SaslClientFactory> getSaslClientFactories() 449: { 450: Vector result = new Vector(); 451: HashSet names = new HashSet(); 452: Provider[] providers = Security.getProviders(); 453: Iterator it; 454: if (providers != null) 455: { 456: Provider p; 457: String key; 458: for (int i = 0; i < providers.length; i++) 459: { 460: p = providers[i]; 461: for (it = p.keySet().iterator(); it.hasNext(); ) 462: { 463: key = (String) it.next(); 464: // add key's binding (a) it is a class of a client factory, 465: // and (b) the key does not include blanks 466: if (key.startsWith(CLIENT_FACTORY_SVC) && key.indexOf(" ") == -1) 467: { 468: names.add(p.getProperty(key)); 469: break; 470: } 471: } 472: } 473: } 474: // we have the factory class names in names; instantiate and enumerate 475: String c; 476: for (it = names.iterator(); it.hasNext(); ) 477: { 478: c = (String) it.next(); 479: try 480: { 481: SaslClientFactory f = (SaslClientFactory) Class.forName(c).newInstance(); 482: if (f != null) 483: result.add(f); 484: } catch (ClassCastException ignored) { // ignore instantiation exceptions 485: } catch (ClassNotFoundException ignored) { 486: } catch (InstantiationException ignored) { 487: } catch (IllegalAccessException ignored) { 488: } 489: } 490: 491: return result.elements(); 492: } 493: 494: /** 495: * Creates a {@link SaslServer} for the specified mechanism. 496: * 497: * <p>This method uses the JCA Security Provider Framework, described in the 498: * "Java Cryptography Architecture API Specification & Reference", for 499: * locating and selecting a SaslServer implementation.</p> 500: * 501: * <p>First, it obtains an ordered list of {@link SaslServerFactory} 502: * instances from the registered security providers for the 503: * <code>"SaslServerFactory"</code> service and the specified mechanism. It 504: * then invokes <code>createSaslServer()</code> on each factory instance on 505: * the list until one produces a non-null {@link SaslServer} instance. It 506: * returns the non-null {@link SaslServer} instance, or <code>null</code> if 507: * the search fails to produce a non-null {@link SaslServer} instance.</p> 508: * 509: * <p>A security provider for {@link SaslServerFactory} registers with the 510: * JCA Security Provider Framework keys of the form:</p> 511: * 512: * <pre> 513: * SaslServerFactory.mechanism_name 514: * </pre> 515: * 516: * <p>and values that are class names of implementations of {@link 517: * SaslServerFactory}.</p> 518: * 519: * <p>For example, a provider that contains a factory class, 520: * <code>com.wiz.sasl.digest.ServerFactory</code>, that supports the 521: * <code>"DIGEST-MD5"</code> mechanism would register the following entry 522: * with the JCA:</p> 523: * 524: * <pre> 525: * SaslServerFactory.DIGEST-MD5 com.wiz.sasl.digest.ServerFactory 526: * </pre> 527: * 528: * <p>See the "Java Cryptography Architecture API Specification & 529: * Reference" for information about how to install and configure security 530: * service providers.</p> 531: * 532: * @param mechanism the non-null mechanism name. It must be an 533: * IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5"). 534: * @param protocol the non-null string name of the protocol for which the 535: * authentication is being performed (e.g. "ldap"). 536: * @param serverName the non-null fully qualified host name of the server. 537: * @param props the possibly <code>null</code> set of properties used to 538: * select the SASL mechanism and to configure the authentication exchange of 539: * the selected mechanism. For example, if props contains the {@link 540: * Sasl#POLICY_NOPLAINTEXT} property with the value <code>"true"</code>, then 541: * the selected SASL mechanism must not be susceptible to simple plain 542: * passive attacks. In addition to the standard properties declared in this 543: * class, other, possibly mechanism-specific, properties can be included. 544: * Properties not relevant to the selected mechanism are ignored. 545: * @param cbh the possibly <code>null</code> callback handler to used by the 546: * SASL mechanisms to get further information from the application/library to 547: * complete the authentication. For example, a SASL mechanism might require 548: * the authentication ID, password and realm from the caller. The 549: * authentication ID is requested by using a 550: * {@link javax.security.auth.callback.NameCallback}. The password is 551: * requested by using a {@link javax.security.auth.callback.PasswordCallback}. 552: * The realm is requested by using a {@link RealmChoiceCallback} if there is 553: * a list of realms to choose from, and by using a {@link RealmCallback} if 554: * the realm must be entered. 555: * @return a possibly <code>null</code> {@link SaslServer} created using the 556: * parameters supplied. If <code>null</code>, the method cannot find a 557: * {@link SaslServerFactory} instance that will produce one. 558: * @throws SaslException if a {@link SaslServer} instance cannot be created 559: * because of an error. 560: */ 561: public static SaslServer createSaslServer(String mechanism, String protocol, 562: String serverName, 563: Map<String, ?> props, 564: CallbackHandler cbh) 565: throws SaslException 566: { 567: if (mechanism == null) 568: return null; 569: Provider[] providers = Security.getProviders(); 570: if (providers == null || providers.length == 0) 571: return null; 572: 573: SaslServer result = null; 574: SaslServerFactory factory = null; 575: String clazz = null, upper, alias = null; 576: int j; 577: Provider p; 578: for (j = 0; j < providers.length; j++) 579: { 580: p = providers[j]; 581: if (p != null) 582: { 583: // try the name as is 584: clazz = p.getProperty(SERVER_FACTORY_SVC + mechanism); 585: if (clazz == null) // try all uppercase 586: { 587: upper = mechanism.toUpperCase(); 588: clazz = p.getProperty(SERVER_FACTORY_SVC + upper); 589: if (clazz == null) // try if it's an alias 590: { 591: alias = p.getProperty(ALIAS + SERVER_FACTORY_SVC + mechanism); 592: if (alias == null) // try all-uppercase alias name 593: { 594: alias = p.getProperty(ALIAS + SERVER_FACTORY_SVC + upper); 595: if (alias == null) // spit the dummy 596: continue; 597: } 598: } 599: clazz = p.getProperty(SERVER_FACTORY_SVC + alias); 600: } 601: } 602: if (clazz == null) 603: continue; 604: else 605: clazz = clazz.trim(); 606: 607: try 608: { 609: result = null; 610: factory = (SaslServerFactory) Class.forName(clazz).newInstance(); 611: result = 612: factory.createSaslServer(mechanism, protocol, serverName, props, cbh); 613: } 614: catch (ClassCastException ignored) // ignore instantiation exceptions 615: { 616: } 617: catch (ClassNotFoundException ignored) 618: { 619: } 620: catch (InstantiationException ignored) 621: { 622: } 623: catch (IllegalAccessException ignored) 624: { 625: } 626: if (result != null) 627: return result; 628: } 629: return null; 630: } 631: 632: /** 633: * Gets an enumeration of known factories for producing a {@link SaslServer} 634: * instance. This method uses the same sources for locating factories as 635: * <code>createSaslServer()</code>. 636: * 637: * @return a non-null {@link Enumeration} of known factories for producing a 638: * {@link SaslServer} instance. 639: * @see #createSaslServer(String,String,String,Map,CallbackHandler) 640: */ 641: public static Enumeration<SaslServerFactory> getSaslServerFactories() 642: { 643: Vector result = new Vector(); 644: HashSet names = new HashSet(); 645: Provider[] providers = Security.getProviders(); 646: Iterator it; 647: if (providers != null) 648: { 649: Provider p; 650: String key; 651: for (int i = 0; i < providers.length; i++) 652: { 653: p = providers[i]; 654: for (it = p.keySet().iterator(); it.hasNext(); ) 655: { 656: key = (String) it.next(); 657: // add key's binding (a) it is a class of a server factory, 658: // and (b) the key does not include blanks 659: if (key.startsWith(SERVER_FACTORY_SVC) && key.indexOf(" ") == -1) 660: { 661: names.add(p.getProperty(key)); 662: break; 663: } 664: } 665: } 666: } 667: // we have the factory class names in names; instantiate and enumerate 668: String c; 669: for (it = names.iterator(); it.hasNext(); ) 670: { 671: c = (String) it.next(); 672: try 673: { 674: SaslServerFactory f = (SaslServerFactory) Class.forName(c).newInstance(); 675: if (f != null) 676: result.add(f); 677: } 678: catch (ClassCastException ignored) // ignore instantiation exceptions 679: { 680: } 681: catch (ClassNotFoundException ignored) 682: { 683: } 684: catch (InstantiationException ignored) 685: { 686: } 687: catch (IllegalAccessException ignored) 688: { 689: } 690: } 691: 692: return result.elements(); 693: } 694: }
GNU Classpath (0.95) |