GNU Classpath (0.17) | ||
Frames | No Frames |
1: /* Security.java --- Java base security class implementation 2: Copyright (C) 1999, 2001, 2002, 2003, 2004 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 java.security; 40: 41: import gnu.classpath.SystemProperties; 42: 43: import gnu.classpath.Configuration; 44: 45: import java.io.IOException; 46: import java.io.InputStream; 47: import java.net.URL; 48: import java.util.Collections; 49: import java.util.Enumeration; 50: import java.util.HashMap; 51: import java.util.HashSet; 52: import java.util.Iterator; 53: import java.util.LinkedHashSet; 54: import java.util.Map; 55: import java.util.Properties; 56: import java.util.Set; 57: import java.util.Vector; 58: 59: /** 60: * This class centralizes all security properties and common security methods. 61: * One of its primary uses is to manage providers. 62: * 63: * @author Mark Benvenuto (ivymccough@worldnet.att.net) 64: */ 65: public final class Security 66: { 67: private static final String ALG_ALIAS = "Alg.Alias."; 68: 69: private static Vector providers = new Vector(); 70: private static Properties secprops = new Properties(); 71: 72: static 73: { 74: String base = SystemProperties.getProperty("gnu.classpath.home.url"); 75: String vendor = SystemProperties.getProperty("gnu.classpath.vm.shortname"); 76: 77: // Try VM specific security file 78: boolean loaded = loadProviders (base, vendor); 79: 80: // Append classpath standard provider if possible 81: if (!loadProviders (base, "classpath") 82: && !loaded 83: && providers.size() == 0) 84: { 85: if (Configuration.DEBUG) 86: { 87: /* No providers found and both security files failed to 88: * load properly. Give a warning in case of DEBUG is 89: * enabled. Could be done with java.util.logging later. 90: */ 91: System.err.println 92: ("WARNING: could not properly read security provider files:"); 93: System.err.println 94: (" " + base + "/security/" + vendor 95: + ".security"); 96: System.err.println 97: (" " + base + "/security/" + "classpath" 98: + ".security"); 99: System.err.println 100: (" Falling back to standard GNU security provider"); 101: } 102: providers.addElement (new gnu.java.security.provider.Gnu()); 103: } 104: } 105: // This class can't be instantiated. 106: private Security() 107: { 108: } 109: 110: /** 111: * Tries to load the vender specific security providers from the given 112: * base URL. Returns true if the resource could be read and completely 113: * parsed successfully, false otherwise. 114: */ 115: private static boolean loadProviders(String baseUrl, String vendor) 116: { 117: if (baseUrl == null || vendor == null) 118: return false; 119: 120: boolean result = true; 121: String secfilestr = baseUrl + "/security/" + vendor + ".security"; 122: try 123: { 124: InputStream fin = new URL(secfilestr).openStream(); 125: secprops.load(fin); 126: 127: int i = 1; 128: String name; 129: while ((name = secprops.getProperty("security.provider." + i)) != null) 130: { 131: Exception exception = null; 132: try 133: { 134: providers.addElement(Class.forName(name).newInstance()); 135: } 136: catch (ClassNotFoundException x) 137: { 138: exception = x; 139: } 140: catch (InstantiationException x) 141: { 142: exception = x; 143: } 144: catch (IllegalAccessException x) 145: { 146: exception = x; 147: } 148: 149: if (exception != null) 150: { 151: System.err.println ("WARNING: Error loading security provider " 152: + name + ": " + exception); 153: result = false; 154: } 155: i++; 156: } 157: } 158: catch (IOException ignored) 159: { 160: result = false; 161: } 162: 163: return result; 164: } 165: 166: /** 167: * Gets a specified property for an algorithm. The algorithm name should be a 168: * standard name. See Appendix A in the Java Cryptography Architecture API 169: * Specification & Reference for information about standard algorithm 170: * names. One possible use is by specialized algorithm parsers, which may map 171: * classes to algorithms which they understand (much like {@link Key} parsers 172: * do). 173: * 174: * @param algName the algorithm name. 175: * @param propName the name of the property to get. 176: * @return the value of the specified property. 177: * @deprecated This method used to return the value of a proprietary property 178: * in the master file of the "SUN" Cryptographic Service Provider in order to 179: * determine how to parse algorithm-specific parameters. Use the new 180: * provider-based and algorithm-independent {@link AlgorithmParameters} and 181: * {@link KeyFactory} engine classes (introduced in the Java 2 platform) 182: * instead. 183: */ 184: public static String getAlgorithmProperty(String algName, String propName) 185: { 186: if (algName == null || propName == null) 187: return null; 188: 189: String property = String.valueOf(propName) + "." + String.valueOf(algName); 190: Provider p; 191: for (Iterator i = providers.iterator(); i.hasNext(); ) 192: { 193: p = (Provider) i.next(); 194: for (Iterator j = p.keySet().iterator(); j.hasNext(); ) 195: { 196: String key = (String) j.next(); 197: if (key.equalsIgnoreCase(property)) 198: return p.getProperty(key); 199: } 200: } 201: return null; 202: } 203: 204: /** 205: * <p>Adds a new provider, at a specified position. The position is the 206: * preference order in which providers are searched for requested algorithms. 207: * Note that it is not guaranteed that this preference will be respected. The 208: * position is 1-based, that is, <code>1</code> is most preferred, followed by 209: * <code>2</code>, and so on.</p> 210: * 211: * <p>If the given provider is installed at the requested position, the 212: * provider that used to be at that position, and all providers with a 213: * position greater than position, are shifted up one position (towards the 214: * end of the list of installed providers).</p> 215: * 216: * <p>A provider cannot be added if it is already installed.</p> 217: * 218: * <p>First, if there is a security manager, its <code>checkSecurityAccess() 219: * </code> method is called with the string <code>"insertProvider."+provider. 220: * getName()</code> to see if it's ok to add a new provider. If the default 221: * implementation of <code>checkSecurityAccess()</code> is used (i.e., that 222: * method is not overriden), then this will result in a call to the security 223: * manager's <code>checkPermission()</code> method with a 224: * <code>SecurityPermission("insertProvider."+provider.getName())</code> 225: * permission.</p> 226: * 227: * @param provider the provider to be added. 228: * @param position the preference position that the caller would like for 229: * this provider. 230: * @return the actual preference position in which the provider was added, or 231: * <code>-1</code> if the provider was not added because it is already 232: * installed. 233: * @throws SecurityException if a security manager exists and its 234: * {@link SecurityManager#checkSecurityAccess(String)} method denies access 235: * to add a new provider. 236: * @see #getProvider(String) 237: * @see #removeProvider(String) 238: * @see SecurityPermission 239: */ 240: public static int insertProviderAt(Provider provider, int position) 241: { 242: SecurityManager sm = System.getSecurityManager(); 243: if (sm != null) 244: sm.checkSecurityAccess("insertProvider." + provider.getName()); 245: 246: position--; 247: int max = providers.size (); 248: for (int i = 0; i < max; i++) 249: { 250: if (((Provider) providers.elementAt(i)).getName().equals(provider.getName())) 251: return -1; 252: } 253: 254: if (position < 0) 255: position = 0; 256: if (position > max) 257: position = max; 258: 259: providers.insertElementAt(provider, position); 260: 261: return position + 1; 262: } 263: 264: /** 265: * <p>Adds a provider to the next position available.</p> 266: * 267: * <p>First, if there is a security manager, its <code>checkSecurityAccess() 268: * </code> method is called with the string <code>"insertProvider."+provider. 269: * getName()</code> to see if it's ok to add a new provider. If the default 270: * implementation of <code>checkSecurityAccess()</code> is used (i.e., that 271: * method is not overriden), then this will result in a call to the security 272: * manager's <code>checkPermission()</code> method with a 273: * <code>SecurityPermission("insertProvider."+provider.getName())</code> 274: * permission.</p> 275: * 276: * @param provider the provider to be added. 277: * @return the preference position in which the provider was added, or 278: * <code>-1</code> if the provider was not added because it is already 279: * installed. 280: * @throws SecurityException if a security manager exists and its 281: * {@link SecurityManager#checkSecurityAccess(String)} method denies access 282: * to add a new provider. 283: * @see #getProvider(String) 284: * @see #removeProvider(String) 285: * @see SecurityPermission 286: */ 287: public static int addProvider(Provider provider) 288: { 289: return insertProviderAt (provider, providers.size () + 1); 290: } 291: 292: /** 293: * <p>Removes the provider with the specified name.</p> 294: * 295: * <p>When the specified provider is removed, all providers located at a 296: * position greater than where the specified provider was are shifted down 297: * one position (towards the head of the list of installed providers).</p> 298: * 299: * <p>This method returns silently if the provider is not installed.</p> 300: * 301: * <p>First, if there is a security manager, its <code>checkSecurityAccess() 302: * </code> method is called with the string <code>"removeProvider."+name</code> 303: * to see if it's ok to remove the provider. If the default implementation of 304: * <code>checkSecurityAccess()</code> is used (i.e., that method is not 305: * overriden), then this will result in a call to the security manager's 306: * <code>checkPermission()</code> method with a <code>SecurityPermission( 307: * "removeProvider."+name)</code> permission.</p> 308: * 309: * @param name the name of the provider to remove. 310: * @throws SecurityException if a security manager exists and its 311: * {@link SecurityManager#checkSecurityAccess(String)} method denies access 312: * to remove the provider. 313: * @see #getProvider(String) 314: * @see #addProvider(Provider) 315: */ 316: public static void removeProvider(String name) 317: { 318: SecurityManager sm = System.getSecurityManager(); 319: if (sm != null) 320: sm.checkSecurityAccess("removeProvider." + name); 321: 322: int max = providers.size (); 323: for (int i = 0; i < max; i++) 324: { 325: if (((Provider) providers.elementAt(i)).getName().equals(name)) 326: { 327: providers.remove(i); 328: break; 329: } 330: } 331: } 332: 333: /** 334: * Returns an array containing all the installed providers. The order of the 335: * providers in the array is their preference order. 336: * 337: * @return an array of all the installed providers. 338: */ 339: public static Provider[] getProviders() 340: { 341: Provider[] array = new Provider[providers.size ()]; 342: providers.copyInto (array); 343: return array; 344: } 345: 346: /** 347: * Returns the provider installed with the specified name, if any. Returns 348: * <code>null</code> if no provider with the specified name is installed. 349: * 350: * @param name the name of the provider to get. 351: * @return the provider of the specified name. 352: * @see #removeProvider(String) 353: * @see #addProvider(Provider) 354: */ 355: public static Provider getProvider(String name) 356: { 357: Provider p; 358: int max = providers.size (); 359: for (int i = 0; i < max; i++) 360: { 361: p = (Provider) providers.elementAt(i); 362: if (p.getName().equals(name)) 363: return p; 364: } 365: return null; 366: } 367: 368: /** 369: * <p>Gets a security property value.</p> 370: * 371: * <p>First, if there is a security manager, its <code>checkPermission()</code> 372: * method is called with a <code>SecurityPermission("getProperty."+key)</code> 373: * permission to see if it's ok to retrieve the specified security property 374: * value.</p> 375: * 376: * @param key the key of the property being retrieved. 377: * @return the value of the security property corresponding to key. 378: * @throws SecurityException if a security manager exists and its 379: * {@link SecurityManager#checkPermission(Permission)} method denies access 380: * to retrieve the specified security property value. 381: * @see #setProperty(String, String) 382: * @see SecurityPermission 383: */ 384: public static String getProperty(String key) 385: { 386: SecurityManager sm = System.getSecurityManager(); 387: if (sm != null) 388: sm.checkSecurityAccess("getProperty." + key); 389: 390: return secprops.getProperty(key); 391: } 392: 393: /** 394: * <p>Sets a security property value.</p> 395: * 396: * <p>First, if there is a security manager, its <code>checkPermission()</code> 397: * method is called with a <code>SecurityPermission("setProperty."+key)</code> 398: * permission to see if it's ok to set the specified security property value. 399: * </p> 400: * 401: * @param key the name of the property to be set. 402: * @param datnum the value of the property to be set. 403: * @throws SecurityException if a security manager exists and its 404: * {@link SecurityManager#checkPermission(Permission)} method denies access 405: * to set the specified security property value. 406: * @see #getProperty(String) 407: * @see SecurityPermission 408: */ 409: public static void setProperty(String key, String datnum) 410: { 411: SecurityManager sm = System.getSecurityManager(); 412: if (sm != null) 413: sm.checkSecurityAccess("setProperty." + key); 414: 415: secprops.put(key, datnum); 416: } 417: 418: /** 419: * Returns a Set of Strings containing the names of all available algorithms 420: * or types for the specified Java cryptographic service (e.g., Signature, 421: * MessageDigest, Cipher, Mac, KeyStore). Returns an empty Set if there is no 422: * provider that supports the specified service. For a complete list of Java 423: * cryptographic services, please see the Java Cryptography Architecture API 424: * Specification & Reference. Note: the returned set is immutable. 425: * 426: * @param serviceName the name of the Java cryptographic service (e.g., 427: * Signature, MessageDigest, Cipher, Mac, KeyStore). Note: this parameter is 428: * case-insensitive. 429: * @return a Set of Strings containing the names of all available algorithms 430: * or types for the specified Java cryptographic service or an empty set if 431: * no provider supports the specified service. 432: * @since 1.4 433: */ 434: public static Set getAlgorithms(String serviceName) 435: { 436: HashSet result = new HashSet(); 437: if (serviceName == null || serviceName.length() == 0) 438: return result; 439: 440: serviceName = serviceName.trim(); 441: if (serviceName.length() == 0) 442: return result; 443: 444: serviceName = serviceName.toUpperCase()+"."; 445: Provider[] providers = getProviders(); 446: int ndx; 447: for (int i = 0; i < providers.length; i++) 448: for (Enumeration e = providers[i].propertyNames(); e.hasMoreElements(); ) 449: { 450: String service = ((String) e.nextElement()).trim(); 451: if (service.toUpperCase().startsWith(serviceName)) 452: { 453: service = service.substring(serviceName.length()).trim(); 454: ndx = service.indexOf(' '); // get rid of attributes 455: if (ndx != -1) 456: service = service.substring(0, ndx); 457: result.add(service); 458: } 459: } 460: return Collections.unmodifiableSet(result); 461: } 462: 463: /** 464: * <p>Returns an array containing all installed providers that satisfy the 465: * specified selection criterion, or <code>null</code> if no such providers 466: * have been installed. The returned providers are ordered according to their 467: * preference order.</p> 468: * 469: * <p>A cryptographic service is always associated with a particular 470: * algorithm or type. For example, a digital signature service is always 471: * associated with a particular algorithm (e.g., <i>DSA</i>), and a 472: * CertificateFactory service is always associated with a particular 473: * certificate type (e.g., <i>X.509</i>).</p> 474: * 475: * <p>The selection criterion must be specified in one of the following two 476: * formats:</p> 477: * 478: * <ul> 479: * <li><p><crypto_service>.<algorithm_or_type></p> 480: * <p>The cryptographic service name must not contain any dots.</p> 481: * <p>A provider satisfies the specified selection criterion iff the 482: * provider implements the specified algorithm or type for the specified 483: * cryptographic service.</p> 484: * <p>For example, "CertificateFactory.X.509" would be satisfied by any 485: * provider that supplied a CertificateFactory implementation for X.509 486: * certificates.</p></li> 487: * 488: * <li><p><crypto_service>.<algorithm_or_type> <attribute_name>:<attribute_value></p> 489: * <p>The cryptographic service name must not contain any dots. There must 490: * be one or more space charaters between the the <algorithm_or_type> 491: * and the <attribute_name>.</p> 492: * <p>A provider satisfies this selection criterion iff the provider 493: * implements the specified algorithm or type for the specified 494: * cryptographic service and its implementation meets the constraint 495: * expressed by the specified attribute name/value pair.</p> 496: * <p>For example, "Signature.SHA1withDSA KeySize:1024" would be satisfied 497: * by any provider that implemented the SHA1withDSA signature algorithm 498: * with a keysize of 1024 (or larger).</p></li> 499: * </ul> 500: * 501: * <p>See Appendix A in the Java Cryptogaphy Architecture API Specification 502: * & Reference for information about standard cryptographic service names, 503: * standard algorithm names and standard attribute names.</p> 504: * 505: * @param filter the criterion for selecting providers. The filter is case- 506: * insensitive. 507: * @return all the installed providers that satisfy the selection criterion, 508: * or null if no such providers have been installed. 509: * @throws InvalidParameterException if the filter is not in the required 510: * format. 511: * @see #getProviders(Map) 512: */ 513: public static Provider[] getProviders(String filter) 514: { 515: if (providers == null || providers.isEmpty()) 516: return null; 517: 518: if (filter == null || filter.length() == 0) 519: return getProviders(); 520: 521: HashMap map = new HashMap(1); 522: int i = filter.indexOf(':'); 523: if (i == -1) // <service>.<algorithm> 524: map.put(filter, ""); 525: else // <service>.<algorithm> <attribute>:<value> 526: map.put(filter.substring(0, i), filter.substring(i+1)); 527: 528: return getProviders(map); 529: } 530: 531: /** 532: * <p>Returns an array containing all installed providers that satisfy the 533: * specified selection criteria, or <code>null</code> if no such providers 534: * have been installed. The returned providers are ordered according to their 535: * preference order.</p> 536: * 537: * <p>The selection criteria are represented by a map. Each map entry 538: * represents a selection criterion. A provider is selected iff it satisfies 539: * all selection criteria. The key for any entry in such a map must be in one 540: * of the following two formats:</p> 541: * 542: * <ul> 543: * <li><p><crypto_service>.<algorithm_or_type></p> 544: * <p>The cryptographic service name must not contain any dots.</p> 545: * <p>The value associated with the key must be an empty string.</p> 546: * <p>A provider satisfies this selection criterion iff the provider 547: * implements the specified algorithm or type for the specified 548: * cryptographic service.</p></li> 549: * 550: * <li><p><crypto_service>.<algorithm_or_type> <attribute_name></p> 551: * <p>The cryptographic service name must not contain any dots. There must 552: * be one or more space charaters between the <algorithm_or_type> and 553: * the <attribute_name>.</p> 554: * <p>The value associated with the key must be a non-empty string. A 555: * provider satisfies this selection criterion iff the provider implements 556: * the specified algorithm or type for the specified cryptographic service 557: * and its implementation meets the constraint expressed by the specified 558: * attribute name/value pair.</p></li> 559: * </ul> 560: * 561: * <p>See Appendix A in the Java Cryptogaphy Architecture API Specification 562: * & Reference for information about standard cryptographic service names, 563: * standard algorithm names and standard attribute names.</p> 564: * 565: * @param filter the criteria for selecting providers. The filter is case- 566: * insensitive. 567: * @return all the installed providers that satisfy the selection criteria, 568: * or <code>null</code> if no such providers have been installed. 569: * @throws InvalidParameterException if the filter is not in the required 570: * format. 571: * @see #getProviders(String) 572: */ 573: public static Provider[] getProviders(Map filter) 574: { 575: if (providers == null || providers.isEmpty()) 576: return null; 577: 578: if (filter == null) 579: return getProviders(); 580: 581: Set querries = filter.keySet(); 582: if (querries == null || querries.isEmpty()) 583: return getProviders(); 584: 585: LinkedHashSet result = new LinkedHashSet(providers); // assume all 586: int dot, ws; 587: String querry, service, algorithm, attribute, value; 588: LinkedHashSet serviceProviders = new LinkedHashSet(); // preserve insertion order 589: for (Iterator i = querries.iterator(); i.hasNext(); ) 590: { 591: querry = (String) i.next(); 592: if (querry == null) // all providers 593: continue; 594: 595: querry = querry.trim(); 596: if (querry.length() == 0) // all providers 597: continue; 598: 599: dot = querry.indexOf('.'); 600: if (dot == -1) // syntax error 601: throw new InvalidParameterException( 602: "missing dot in '" + String.valueOf(querry)+"'"); 603: 604: value = (String) filter.get(querry); 605: // deconstruct querry into [service, algorithm, attribute] 606: if (value == null || value.trim().length() == 0) // <service>.<algorithm> 607: { 608: value = null; 609: attribute = null; 610: service = querry.substring(0, dot).trim(); 611: algorithm = querry.substring(dot+1).trim(); 612: } 613: else // <service>.<algorithm> <attribute> 614: { 615: ws = querry.indexOf(' '); 616: if (ws == -1) 617: throw new InvalidParameterException( 618: "value (" + String.valueOf(value) + 619: ") is not empty, but querry (" + String.valueOf(querry) + 620: ") is missing at least one space character"); 621: value = value.trim(); 622: attribute = querry.substring(ws+1).trim(); 623: // was the dot in the attribute? 624: if (attribute.indexOf('.') != -1) 625: throw new InvalidParameterException( 626: "attribute_name (" + String.valueOf(attribute) + 627: ") in querry (" + String.valueOf(querry) + ") contains a dot"); 628: 629: querry = querry.substring(0, ws).trim(); 630: service = querry.substring(0, dot).trim(); 631: algorithm = querry.substring(dot+1).trim(); 632: } 633: 634: // service and algorithm must not be empty 635: if (service.length() == 0) 636: throw new InvalidParameterException( 637: "<crypto_service> in querry (" + String.valueOf(querry) + 638: ") is empty"); 639: 640: if (algorithm.length() == 0) 641: throw new InvalidParameterException( 642: "<algorithm_or_type> in querry (" + String.valueOf(querry) + 643: ") is empty"); 644: 645: selectProviders(service, algorithm, attribute, value, result, serviceProviders); 646: result.retainAll(serviceProviders); // eval next retaining found providers 647: if (result.isEmpty()) // no point continuing 648: break; 649: } 650: 651: if (result.isEmpty()) 652: return null; 653: 654: return (Provider[]) result.toArray(new Provider[0]); 655: } 656: 657: private static void selectProviders(String svc, String algo, String attr, 658: String val, LinkedHashSet providerSet, 659: LinkedHashSet result) 660: { 661: result.clear(); // ensure we start with an empty result set 662: for (Iterator i = providerSet.iterator(); i.hasNext(); ) 663: { 664: Provider p = (Provider) i.next(); 665: if (provides(p, svc, algo, attr, val)) 666: result.add(p); 667: } 668: } 669: 670: private static boolean provides(Provider p, String svc, String algo, 671: String attr, String val) 672: { 673: Iterator it; 674: String serviceDotAlgorithm = null; 675: String key = null; 676: String realVal; 677: boolean found = false; 678: // if <svc>.<algo> <attr> is in the set then so is <svc>.<algo> 679: // but it may be stored under an alias <algo>. resolve 680: outer: for (int r = 0; r < 3; r++) // guard against circularity 681: { 682: serviceDotAlgorithm = (svc+"."+String.valueOf(algo)).trim(); 683: for (it = p.keySet().iterator(); it.hasNext(); ) 684: { 685: key = (String) it.next(); 686: if (key.equalsIgnoreCase(serviceDotAlgorithm)) // eureka 687: { 688: found = true; 689: break outer; 690: } 691: // it may be there but as an alias 692: if (key.equalsIgnoreCase(ALG_ALIAS + serviceDotAlgorithm)) 693: { 694: algo = p.getProperty(key); 695: continue outer; 696: } 697: // else continue inner 698: } 699: } 700: 701: if (!found) 702: return false; 703: 704: // found a candidate for the querry. do we have an attr to match? 705: if (val == null) // <service>.<algorithm> querry 706: return true; 707: 708: // <service>.<algorithm> <attribute>; find the key entry that match 709: String realAttr; 710: int limit = serviceDotAlgorithm.length() + 1; 711: for (it = p.keySet().iterator(); it.hasNext(); ) 712: { 713: key = (String) it.next(); 714: if (key.length() <= limit) 715: continue; 716: 717: if (key.substring(0, limit).equalsIgnoreCase(serviceDotAlgorithm+" ")) 718: { 719: realAttr = key.substring(limit).trim(); 720: if (! realAttr.equalsIgnoreCase(attr)) 721: continue; 722: 723: // eveything matches so far. do the value 724: realVal = p.getProperty(key); 725: if (realVal == null) 726: return false; 727: 728: realVal = realVal.trim(); 729: // is it a string value? 730: if (val.equalsIgnoreCase(realVal)) 731: return true; 732: 733: // assume value is a number. cehck for greater-than-or-equal 734: return (new Integer(val).intValue() >= new Integer(realVal).intValue()); 735: } 736: } 737: 738: return false; 739: } 740: }
GNU Classpath (0.17) |