Showing the changes to java/pkg/sun/security/jgss/ProviderList.java (1 of 18352 files). Show all
Unified · Split
| @@ -0,0 +1,547 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. | ||
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||
| 4 | * | ||
| 5 | * This code is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms of the GNU General Public License version 2 only, as | ||
| 7 | * published by the Free Software Foundation. Oracle designates this | ||
| 8 | * particular file as subject to the "Classpath" exception as provided | ||
| 9 | * by Oracle in the LICENSE file that accompanied this code. | ||
| 10 | * | ||
| 11 | * This code is distributed in the hope that it will be useful, but WITHOUT | ||
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
| 14 | * version 2 for more details (a copy is included in the LICENSE file that | ||
| 15 | * accompanied this code). | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License version | ||
| 18 | * 2 along with this work; if not, write to the Free Software Foundation, | ||
| 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 20 | * | ||
| 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | ||
| 22 | * or visit www.oracle.com if you need additional information or have any | ||
| 23 | * questions. | ||
| 24 | */ | ||
| 25 | |||
| 26 | package sun.security.jgss; | ||
| 27 | |||
| 28 | import java.lang.reflect.InvocationTargetException; | ||
| 29 | import org.ietf.jgss.*; | ||
| 30 | import java.security.AccessController; | ||
| 31 | import java.security.Provider; | ||
| 32 | import java.security.Security; | ||
| 33 | import java.util.ArrayList; | ||
| 34 | import java.util.HashSet; | ||
| 35 | import java.util.HashMap; | ||
| 36 | import java.util.Enumeration; | ||
| 37 | import java.util.Iterator; | ||
| 38 | import sun.security.jgss.spi.*; | ||
| 39 | import sun.security.jgss.wrapper.NativeGSSFactory; | ||
| 40 | import sun.security.jgss.wrapper.SunNativeProvider; | ||
| 41 | import sun.security.action.GetPropertyAction; | ||
| 42 | |||
| 43 | /** | ||
| 44 | * This class stores the list of providers that this | ||
| 45 | * GSS-Implementation is configured to use. The GSSManagerImpl class | ||
| 46 | * queries this class whenever it needs a mechanism's factory.<p> | ||
| 47 | * | ||
| 48 | * This class stores an ordered list of pairs of the form | ||
| 49 | * <provider, oid>. When it attempts to instantiate a mechanism | ||
| 50 | * defined by oid o, it steps through the list looking for an entry | ||
| 51 | * with oid=o, or with oid=null. (An entry with oid=null matches all | ||
| 52 | * mechanisms.) When it finds such an entry, the corresponding | ||
| 53 | * provider is approached for the mechanism's factory class. | ||
| 54 | * At instantiation time this list in initialized to contain those | ||
| 55 | * system wide providers that contain a property of the form | ||
| 56 | * "GssApiMechanism.x.y.z..." where "x.y.z..." is a numeric object | ||
| 57 | * identifier with numbers x, y, z, etc. Such a property is defined | ||
| 58 | * to map to that provider's implementation of the MechanismFactory | ||
| 59 | * interface for the mechanism x.y.z... | ||
| 60 | * As and when a MechanismFactory is instantiated, it is | ||
| 61 | * cached for future use. <p> | ||
| 62 | * | ||
| 63 | * An application can cause more providers to be added by means of | ||
| 64 | * the addProviderAtFront and addProviderAtEnd methods on | ||
| 65 | * GSSManager which get delegated to this class. The | ||
| 66 | * addProviderAtFront method can also cause a change in the ordering | ||
| 67 | * of the providers without adding any new providers, by causing a | ||
| 68 | * provider to move up in a list. The method addProviderAtEnd can | ||
| 69 | * only add providers at the end of the list if they are not already | ||
| 70 | * in the list. The rationale is that an application will call | ||
| 71 | * addProviderAtFront when it wants a provider to be used in | ||
| 72 | * preference over the default ones. And it will call | ||
| 73 | * addProviderAtEnd when it wants a provider to be used in case | ||
| 74 | * the system ones don't suffice.<p> | ||
| 75 | * | ||
| 76 | * If a mechanism's factory is being obtained from a provider as a | ||
| 77 | * result of encountering a entryof the form <provider, oid> where | ||
| 78 | * oid is non-null, then the assumption is that the application added | ||
| 79 | * this entry and it wants this mechanism to be obtained from this | ||
| 80 | * provider. Thus is the provider does not actually contain the | ||
| 81 | * requested mechanism, an exception will be thrown. However, if the | ||
| 82 | * entry were of the form <provider, null>, then it is viewed more | ||
| 83 | * liberally and is simply skipped over if the provider does not claim to | ||
| 84 | * support the requested mechanism. | ||
| 85 | */ | ||
| 86 | |||
| 87 | public final class ProviderList { | ||
| 88 | |||
| 89 | private static final String PROV_PROP_PREFIX = "GssApiMechanism."; | ||
| 90 | private static final int PROV_PROP_PREFIX_LEN = | ||
| 91 | PROV_PROP_PREFIX.length(); | ||
| 92 | |||
| 93 | private static final String SPI_MECH_FACTORY_TYPE | ||
| 94 | = "sun.security.jgss.spi.MechanismFactory"; | ||
| 95 | |||
| 96 | // Undocumented property? | ||
| 97 | private static final String DEFAULT_MECH_PROP = | ||
| 98 | "sun.security.jgss.mechanism"; | ||
| 99 | |||
| 100 | public static final Oid DEFAULT_MECH_OID; | ||
| 101 | |||
| 102 | static { | ||
| 103 | /* | ||
| 104 | * Set the default mechanism. Kerberos v5 is the default | ||
| 105 | * mechanism unless it is overridden by a system property. | ||
| 106 | * with a valid OID value | ||
| 107 | */ | ||
| 108 | Oid defOid = null; | ||
| 109 | String defaultOidStr = AccessController.doPrivileged | ||
| 110 | (new GetPropertyAction(DEFAULT_MECH_PROP)); | ||
| 111 | if (defaultOidStr != null) { | ||
| 112 | defOid = GSSUtil.createOid(defaultOidStr); | ||
| 113 | } | ||
| 114 | DEFAULT_MECH_OID = | ||
| 115 | (defOid == null ? GSSUtil.GSS_KRB5_MECH_OID : defOid); | ||
| 116 | } | ||
| 117 | |||
| 118 | private ArrayList<PreferencesEntry> preferences = | ||
| 119 | new ArrayList<PreferencesEntry>(5); | ||
| 120 | private HashMap<PreferencesEntry, MechanismFactory> factories = | ||
| 121 | new HashMap<PreferencesEntry, MechanismFactory>(5); | ||
| 122 | private HashSet<Oid> mechs = new HashSet<Oid>(5); | ||
| 123 | |||
| 124 | final private GSSCaller caller; | ||
| 125 | |||
| 126 | public ProviderList(GSSCaller caller, boolean useNative) { | ||
| 127 | this.caller = caller; | ||
| 128 | Provider[] provList; | ||
| 129 | if (useNative) { | ||
| 130 | provList = new Provider[1]; | ||
| 131 | provList[0] = new SunNativeProvider(); | ||
| 132 | } else { | ||
| 133 | provList = Security.getProviders(); | ||
| 134 | } | ||
| 135 | |||
| 136 | for (int i = 0; i < provList.length; i++) { | ||
| 137 | Provider prov = provList[i]; | ||
| 138 | try { | ||
| 139 | addProviderAtEnd(prov, null); | ||
| 140 | } catch (GSSException ge) { | ||
| 141 | // Move on to the next provider | ||
| 142 | GSSUtil.debug("Error in adding provider " + | ||
| 143 | prov.getName() + ": " + ge); | ||
| 144 | } | ||
| 145 | } // End of for loop | ||
| 146 | } | ||
| 147 | |||
| 148 | /** | ||
| 149 | * Determines if the given provider property represents a GSS-API | ||
| 150 | * Oid to MechanismFactory mapping. | ||
| 151 | * @return true if this is a GSS-API property, false otherwise. | ||
| 152 | */ | ||
| 153 | private boolean isMechFactoryProperty(String prop) { | ||
| 154 | return (prop.startsWith(PROV_PROP_PREFIX) || | ||
| 155 | prop.regionMatches(true, 0, // Try ignoring case | ||
| 156 | PROV_PROP_PREFIX, 0, | ||
| 157 | PROV_PROP_PREFIX_LEN)); | ||
| 158 | } | ||
| 159 | |||
| 160 | private Oid getOidFromMechFactoryProperty(String prop) | ||
| 161 | throws GSSException { | ||
| 162 | |||
| 163 | String oidPart = prop.substring(PROV_PROP_PREFIX_LEN); | ||
| 164 | return new Oid(oidPart); | ||
| 165 | } | ||
| 166 | |||
| 167 | // So the existing code do not have to be changed | ||
| 168 | synchronized public MechanismFactory getMechFactory(Oid mechOid) | ||
| 169 | throws GSSException { | ||
| 170 | if (mechOid == null) mechOid = ProviderList.DEFAULT_MECH_OID; | ||
| 171 | return getMechFactory(mechOid, null); | ||
| 172 | } | ||
| 173 | |||
| 174 | /** | ||
| 175 | * Obtains a MechanismFactory for a given mechanism. If the | ||
| 176 | * specified provider is not null, then the impl from the | ||
| 177 | * provider is used. Otherwise, the most preferred impl based | ||
| 178 | * on the configured preferences is used. | ||
| 179 | * @param mechOid the oid of the desired mechanism | ||
| 180 | * @return a MechanismFactory for the desired mechanism. | ||
| 181 | * @throws GSSException when the specified provider does not | ||
| 182 | * support the desired mechanism, or when no provider supports | ||
| 183 | * the desired mechanism. | ||
| 184 | */ | ||
| 185 | synchronized public MechanismFactory getMechFactory(Oid mechOid, | ||
| 186 | Provider p) | ||
| 187 | throws GSSException { | ||
| 188 | |||
| 189 | if (mechOid == null) mechOid = ProviderList.DEFAULT_MECH_OID; | ||
| 190 | |||
| 191 | if (p == null) { | ||
| 192 | // Iterate thru all preferences to find right provider | ||
| 193 | String className; | ||
| 194 | PreferencesEntry entry; | ||
| 195 | |||
| 196 | Iterator<PreferencesEntry> list = preferences.iterator(); | ||
| 197 | while (list.hasNext()) { | ||
| 198 | entry = list.next(); | ||
| 199 | if (entry.impliesMechanism(mechOid)) { | ||
| 200 | MechanismFactory retVal = getMechFactory(entry, mechOid); | ||
| 201 | if (retVal != null) return retVal; | ||
| 202 | } | ||
| 203 | } // end of while loop | ||
| 204 | throw new GSSExceptionImpl(GSSException.BAD_MECH, mechOid); | ||
| 205 | } else { | ||
| 206 | // Use the impl from the specified provider; return null if the | ||
| 207 | // the mech is unsupported by the specified provider. | ||
| 208 | PreferencesEntry entry = new PreferencesEntry(p, mechOid); | ||
| 209 | return getMechFactory(entry, mechOid); | ||
| 210 | } | ||
| 211 | } | ||
| 212 | |||
| 213 | /** | ||
| 214 | * Helper routine that uses a preferences entry to obtain an | ||
| 215 | * implementation of a MechanismFactory from it. | ||
| 216 | * @param e the preferences entry that contains the provider and | ||
| 217 | * either a null of an explicit oid that matched the oid of the | ||
| 218 | * desired mechanism. | ||
| 219 | * @param mechOid the oid of the desired mechanism | ||
| 220 | * @throws GSSException If the application explicitly requested | ||
| 221 | * this entry's provider to be used for the desired mechanism but | ||
| 222 | * some problem is encountered | ||
| 223 | */ | ||
| 224 | private MechanismFactory getMechFactory(PreferencesEntry e, Oid mechOid) | ||
| 225 | throws GSSException { | ||
| 226 | Provider p = e.getProvider(); | ||
| 227 | |||
| 228 | /* | ||
| 229 | * See if a MechanismFactory was previously instantiated for | ||
| 230 | * this provider and mechanism combination. | ||
| 231 | */ | ||
| 232 | PreferencesEntry searchEntry = new PreferencesEntry(p, mechOid); | ||
| 233 | MechanismFactory retVal = factories.get(searchEntry); | ||
| 234 | if (retVal == null) { | ||
| 235 | /* | ||
| 236 | * Apparently not. Now try to instantiate this class from | ||
| 237 | * the provider. | ||
| 238 | */ | ||
| 239 | String prop = PROV_PROP_PREFIX + mechOid.toString(); | ||
| 240 | String className = p.getProperty(prop); | ||
| 241 | if (className != null) { | ||
| 242 | retVal = getMechFactoryImpl(p, className, mechOid, caller); | ||
| 243 | factories.put(searchEntry, retVal); | ||
| 244 | } else { | ||
| 245 | /* | ||
| 246 | * This provider does not support this mechanism. | ||
| 247 | * If the application explicitly requested that | ||
| 248 | * this provider be used for this mechanism, then | ||
| 249 | * throw an exception | ||
| 250 | */ | ||
| 251 | if (e.getOid() != null) { | ||
| 252 | throw new GSSExceptionImpl(GSSException.BAD_MECH, | ||
| 253 | "Provider " + p.getName() + | ||
| 254 | " does not support mechanism " + mechOid); | ||
| 255 | } | ||
| 256 | } | ||
| 257 | } | ||
| 258 | return retVal; | ||
| 259 | } | ||
| 260 | |||
| 261 | /** | ||
| 262 | * Helper routine to obtain a MechanismFactory implementation | ||
| 263 | * from the same class loader as the provider of this | ||
| 264 | * implementation. | ||
| 265 | * @param p the provider whose classloader must be used for | ||
| 266 | * instantiating the desired MechanismFactory | ||
| 267 | * @ param className the name of the MechanismFactory class | ||
| 268 | * @throws GSSException If some error occurs when trying to | ||
| 269 | * instantiate this MechanismFactory. | ||
| 270 | */ | ||
| 271 | private static MechanismFactory getMechFactoryImpl(Provider p, | ||
| 272 | String className, | ||
| 273 | Oid mechOid, | ||
| 274 | GSSCaller caller) | ||
| 275 | throws GSSException { | ||
| 276 | |||
| 277 | try { | ||
| 278 | Class<?> baseClass = Class.forName(SPI_MECH_FACTORY_TYPE); | ||
| 279 | |||
| 280 | /* | ||
| 281 | * Load the implementation class with the same class loader | ||
| 282 | * that was used to load the provider. | ||
| 283 | * In order to get the class loader of a class, the | ||
| 284 | * caller's class loader must be the same as or an ancestor of | ||
| 285 | * the class loader being returned. Otherwise, the caller must | ||
| 286 | * have "getClassLoader" permission, or a SecurityException | ||
| 287 | * will be thrown. | ||
| 288 | */ | ||
| 289 | |||
| 290 | ClassLoader cl = p.getClass().getClassLoader(); | ||
| 291 | Class<?> implClass; | ||
| 292 | if (cl != null) { | ||
| 293 | implClass = cl.loadClass(className); | ||
| 294 | } else { | ||
| 295 | implClass = Class.forName(className); | ||
| 296 | } | ||
| 297 | |||
| 298 | if (baseClass.isAssignableFrom(implClass)) { | ||
| 299 | |||
| 300 | java.lang.reflect.Constructor<?> c = | ||
| 301 | implClass.getConstructor(GSSCaller.class); | ||
| 302 | MechanismFactory mf = (MechanismFactory) (c.newInstance(caller)); | ||
| 303 | |||
| 304 | if (mf instanceof NativeGSSFactory) { | ||
| 305 | ((NativeGSSFactory) mf).setMech(mechOid); | ||
| 306 | } | ||
| 307 | return mf; | ||
| 308 | } else { | ||
| 309 | throw createGSSException(p, className, "is not a " + | ||
| 310 | SPI_MECH_FACTORY_TYPE, null); | ||
| 311 | } | ||
| 312 | } catch (ClassNotFoundException e) { | ||
| 313 | throw createGSSException(p, className, "cannot be created", e); | ||
| 314 | } catch (NoSuchMethodException e) { | ||
| 315 | throw createGSSException(p, className, "cannot be created", e); | ||
| 316 | } catch (InvocationTargetException e) { | ||
| 317 | throw createGSSException(p, className, "cannot be created", e); | ||
| 318 | } catch (InstantiationException e) { | ||
| 319 | throw createGSSException(p, className, "cannot be created", e); | ||
| 320 | } catch (IllegalAccessException e) { | ||
| 321 | throw createGSSException(p, className, "cannot be created", e); | ||
| 322 | } catch (SecurityException e) { | ||
| 323 | throw createGSSException(p, className, "cannot be created", e); | ||
| 324 | } | ||
| 325 | } | ||
| 326 | |||
| 327 | // Only used by getMechFactoryImpl | ||
| 328 | private static GSSException createGSSException(Provider p, | ||
| 329 | String className, | ||
| 330 | String trailingMsg, | ||
| 331 | Exception cause) { | ||
| 332 | String errClassInfo = className + " configured by " + | ||
| 333 | p.getName() + " for GSS-API Mechanism Factory "; | ||
| 334 | return new GSSExceptionImpl(GSSException.BAD_MECH, | ||
| 335 | errClassInfo + trailingMsg, | ||
| 336 | cause); | ||
| 337 | } | ||
| 338 | |||
| 339 | public Oid[] getMechs() { | ||
| 340 | return mechs.toArray(new Oid[] {}); | ||
| 341 | } | ||
| 342 | |||
| 343 | synchronized public void addProviderAtFront(Provider p, Oid mechOid) | ||
| 344 | throws GSSException { | ||
| 345 | |||
| 346 | PreferencesEntry newEntry = new PreferencesEntry(p, mechOid); | ||
| 347 | PreferencesEntry oldEntry; | ||
| 348 | boolean foundSomeMech; | ||
| 349 | |||
| 350 | Iterator<PreferencesEntry> list = preferences.iterator(); | ||
| 351 | while (list.hasNext()) { | ||
| 352 | oldEntry = list.next(); | ||
| 353 | if (newEntry.implies(oldEntry)) | ||
| 354 | list.remove(); | ||
| 355 | } | ||
| 356 | |||
| 357 | if (mechOid == null) { | ||
| 358 | foundSomeMech = addAllMechsFromProvider(p); | ||
| 359 | } else { | ||
| 360 | String oidStr = mechOid.toString(); | ||
| 361 | if (p.getProperty(PROV_PROP_PREFIX + oidStr) == null) | ||
| 362 | throw new GSSExceptionImpl(GSSException.BAD_MECH, | ||
| 363 | "Provider " + p.getName() | ||
| 364 | + " does not support " | ||
| 365 | + oidStr); | ||
| 366 | mechs.add(mechOid); | ||
| 367 | foundSomeMech = true; | ||
| 368 | } | ||
| 369 | |||
| 370 | if (foundSomeMech) { | ||
| 371 | preferences.add(0, newEntry); | ||
| 372 | } | ||
| 373 | } | ||
| 374 | |||
| 375 | synchronized public void addProviderAtEnd(Provider p, Oid mechOid) | ||
| 376 | throws GSSException { | ||
| 377 | |||
| 378 | PreferencesEntry newEntry = new PreferencesEntry(p, mechOid); | ||
| 379 | PreferencesEntry oldEntry; | ||
| 380 | boolean foundSomeMech; | ||
| 381 | |||
| 382 | Iterator<PreferencesEntry> list = preferences.iterator(); | ||
| 383 | while (list.hasNext()) { | ||
| 384 | oldEntry = list.next(); | ||
| 385 | if (oldEntry.implies(newEntry)) | ||
| 386 | return; | ||
| 387 | } | ||
| 388 | |||
| 389 | // System.out.println("addProviderAtEnd: No it is not redundant"); | ||
| 390 | |||
| 391 | if (mechOid == null) | ||
| 392 | foundSomeMech = addAllMechsFromProvider(p); | ||
| 393 | else { | ||
| 394 | String oidStr = mechOid.toString(); | ||
| 395 | if (p.getProperty(PROV_PROP_PREFIX + oidStr) == null) | ||
| 396 | throw new GSSExceptionImpl(GSSException.BAD_MECH, | ||
| 397 | "Provider " + p.getName() | ||
| 398 | + " does not support " | ||
| 399 | + oidStr); | ||
| 400 | mechs.add(mechOid); | ||
| 401 | foundSomeMech = true; | ||
| 402 | } | ||
| 403 | |||
| 404 | if (foundSomeMech) { | ||
| 405 | preferences.add(newEntry); | ||
| 406 | } | ||
| 407 | } | ||
| 408 | |||
| 409 | /** | ||
| 410 | * Helper routine to go through all properties contined in a | ||
| 411 | * provider and add its mechanisms to the list of supported | ||
| 412 | * mechanisms. If no default mechanism has been assinged so far, | ||
| 413 | * it sets the default MechanismFactory and Oid as well. | ||
| 414 | * @param p the provider to query | ||
| 415 | * @return true if there is at least one mechanism that this | ||
| 416 | * provider contributed, false otherwise | ||
| 417 | */ | ||
| 418 | private boolean addAllMechsFromProvider(Provider p) { | ||
| 419 | |||
| 420 | String prop; | ||
| 421 | boolean retVal = false; | ||
| 422 | |||
| 423 | // Get all props for this provider | ||
| 424 | Enumeration<Object> props = p.keys(); | ||
| 425 | |||
| 426 | // See if there are any GSS prop's | ||
| 427 | while (props.hasMoreElements()) { | ||
| 428 | prop = (String) props.nextElement(); | ||
| 429 | if (isMechFactoryProperty(prop)) { | ||
| 430 | // Ok! This is a GSS provider! | ||
| 431 | try { | ||
| 432 | Oid mechOid = getOidFromMechFactoryProperty(prop); | ||
| 433 | mechs.add(mechOid); | ||
| 434 | retVal = true; | ||
| 435 | } catch (GSSException e) { | ||
| 436 | // Skip to next property | ||
| 437 | GSSUtil.debug("Ignore the invalid property " + | ||
| 438 | prop + " from provider " + p.getName()); | ||
| 439 | } | ||
| 440 | } // Processed GSS property | ||
| 441 | } // while loop | ||
| 442 | |||
| 443 | return retVal; | ||
| 444 | |||
| 445 | } | ||
| 446 | |||
| 447 | /** | ||
| 448 | * Stores a provider and a mechanism oid indicating that the | ||
| 449 | * provider should be used for the mechanism. If the mechanism | ||
| 450 | * Oid is null, then it indicates that this preference holds for | ||
| 451 | * any mechanism.<p> | ||
| 452 | * | ||
| 453 | * The ProviderList maintains an ordered list of | ||
| 454 | * PreferencesEntry's and iterates thru them as it tries to | ||
| 455 | * instantiate MechanismFactory's. | ||
| 456 | */ | ||
| 457 | private static final class PreferencesEntry { | ||
| 458 | private Provider p; | ||
| 459 | private Oid oid; | ||
| 460 | PreferencesEntry(Provider p, Oid oid) { | ||
| 461 | this.p = p; | ||
| 462 | this.oid = oid; | ||
| 463 | } | ||
| 464 | |||
| 465 | public boolean equals(Object other) { | ||
| 466 | if (this == other) { | ||
| 467 | return true; | ||
| 468 | } | ||
| 469 | |||
| 470 | if (!(other instanceof PreferencesEntry)) { | ||
| 471 | return false; | ||
| 472 | } | ||
| 473 | |||
| 474 | PreferencesEntry that = (PreferencesEntry)other; | ||
| 475 | if (this.p.getName().equals(that.p.getName())) { | ||
| 476 | if (this.oid != null && that.oid != null) { | ||
| 477 | return this.oid.equals(that.oid); | ||
| 478 | } else { | ||
| 479 | return (this.oid == null && that.oid == null); | ||
| 480 | } | ||
| 481 | } | ||
| 482 | |||
| 483 | return false; | ||
| 484 | } | ||
| 485 | |||
| 486 | public int hashCode() { | ||
| 487 | int result = 17; | ||
| 488 | |||
| 489 | result = 37 * result + p.getName().hashCode(); | ||
| 490 | if (oid != null) { | ||
| 491 | result = 37 * result + oid.hashCode(); | ||
| 492 | } | ||
| 493 | |||
| 494 | return result; | ||
| 495 | } | ||
| 496 | |||
| 497 | /** | ||
| 498 | * Determines if a preference implies another. A preference | ||
| 499 | * implies another if the latter is subsumed by the | ||
| 500 | * former. e.g., <Provider1, null> implies <Provider1, OidX> | ||
| 501 | * because the null in the former indicates that it should | ||
| 502 | * be used for all mechanisms. | ||
| 503 | */ | ||
| 504 | boolean implies(Object other) { | ||
| 505 | |||
| 506 | if (other instanceof PreferencesEntry) { | ||
| 507 | PreferencesEntry temp = (PreferencesEntry) other; | ||
| 508 | return (equals(temp) || | ||
| 509 | p.getName().equals(temp.p.getName()) && | ||
| 510 | oid == null); | ||
| 511 | } else { | ||
| 512 | return false; | ||
| 513 | } | ||
| 514 | } | ||
| 515 | |||
| 516 | Provider getProvider() { | ||
| 517 | return p; | ||
| 518 | } | ||
| 519 | |||
| 520 | Oid getOid() { | ||
| 521 | return oid; | ||
| 522 | } | ||
| 523 | |||
| 524 | /** | ||
| 525 | * Determines if this entry is applicable to the desired | ||
| 526 | * mechanism. The entry is applicable to the desired mech if | ||
| 527 | * it contains the same oid or if it contains a null oid | ||
| 528 | * indicating that it is applicable to all mechs. | ||
| 529 | * @param mechOid the desired mechanism | ||
| 530 | * @return true if the provider in this entry should be | ||
| 531 | * queried for this mechanism. | ||
| 532 | */ | ||
| 533 | boolean impliesMechanism(Oid oid) { | ||
| 534 | return (this.oid == null || this.oid.equals(oid)); | ||
| 535 | } | ||
| 536 | |||
| 537 | // For debugging | ||
| 538 | public String toString() { | ||
| 539 | StringBuffer buf = new StringBuffer("<"); | ||
| 540 | buf.append(p.getName()); | ||
| 541 | buf.append(", "); | ||
| 542 | buf.append(oid); | ||
| 543 | buf.append(">"); | ||
| 544 | return buf.toString(); | ||
| 545 | } | ||
| 546 | } | ||
| 547 | } | ||