Security.java 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  1. /* Security.java --- Java base security class implementation
  2. Copyright (C) 1999, 2001, 2002, 2003, 2004, 2005, 2006
  3. Free Software Foundation, Inc.
  4. This file is part of GNU Classpath.
  5. GNU Classpath is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9. GNU Classpath is distributed in the hope that it will be useful, but
  10. WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with GNU Classpath; see the file COPYING. If not, write to the
  15. Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  16. 02110-1301 USA.
  17. Linking this library statically or dynamically with other modules is
  18. making a combined work based on this library. Thus, the terms and
  19. conditions of the GNU General Public License cover the whole
  20. combination.
  21. As a special exception, the copyright holders of this library give you
  22. permission to link this library with independent modules to produce an
  23. executable, regardless of the license terms of these independent
  24. modules, and to copy and distribute the resulting executable under
  25. terms of your choice, provided that you also meet, for each linked
  26. independent module, the terms and conditions of the license of that
  27. module. An independent module is a module which is not derived from
  28. or based on this library. If you modify this library, you may extend
  29. this exception to your version of the library, but you are not
  30. obligated to do so. If you do not wish to do so, delete this
  31. exception statement from your version. */
  32. package java.security;
  33. import gnu.classpath.SystemProperties;
  34. import gnu.classpath.Configuration;
  35. import gnu.classpath.VMStackWalker;
  36. import java.io.IOException;
  37. import java.io.InputStream;
  38. import java.net.URL;
  39. import java.util.Collections;
  40. import java.util.Enumeration;
  41. import java.util.HashMap;
  42. import java.util.HashSet;
  43. import java.util.Iterator;
  44. import java.util.LinkedHashSet;
  45. import java.util.Map;
  46. import java.util.Properties;
  47. import java.util.Set;
  48. import java.util.Vector;
  49. /**
  50. * This class centralizes all security properties and common security methods.
  51. * One of its primary uses is to manage security providers.
  52. *
  53. * @author Mark Benvenuto (ivymccough@worldnet.att.net)
  54. */
  55. public final class Security
  56. {
  57. private static final String ALG_ALIAS = "Alg.Alias.";
  58. private static Vector providers = new Vector();
  59. private static Properties secprops = new Properties();
  60. static
  61. {
  62. String base = SystemProperties.getProperty("gnu.classpath.home.url");
  63. String vendor = SystemProperties.getProperty("gnu.classpath.vm.shortname");
  64. // Try VM specific security file
  65. boolean loaded = loadProviders (base, vendor);
  66. // Append classpath standard provider if possible
  67. if (!loadProviders (base, "classpath")
  68. && !loaded
  69. && providers.size() == 0)
  70. {
  71. if (Configuration.DEBUG)
  72. {
  73. /* No providers found and both security files failed to
  74. * load properly. Give a warning in case of DEBUG is
  75. * enabled. Could be done with java.util.logging later.
  76. */
  77. System.err.println
  78. ("WARNING: could not properly read security provider files:");
  79. System.err.println
  80. (" " + base + "/security/" + vendor
  81. + ".security");
  82. System.err.println
  83. (" " + base + "/security/" + "classpath"
  84. + ".security");
  85. System.err.println
  86. (" Falling back to standard GNU security provider");
  87. }
  88. // Note that this matches our classpath.security file.
  89. providers.addElement (new gnu.java.security.provider.Gnu());
  90. providers.addElement(new gnu.javax.crypto.jce.GnuCrypto());
  91. providers.addElement(new gnu.javax.crypto.jce.GnuSasl());
  92. providers.addElement(new gnu.javax.net.ssl.provider.Jessie());
  93. providers.addElement(new gnu.javax.security.auth.callback.GnuCallbacks());
  94. }
  95. }
  96. // This class can't be instantiated.
  97. private Security()
  98. {
  99. }
  100. /**
  101. * Tries to load the vender specific security providers from the given base
  102. * URL. Returns true if the resource could be read and completely parsed
  103. * successfully, false otherwise.
  104. */
  105. private static boolean loadProviders(String baseUrl, String vendor)
  106. {
  107. if (baseUrl == null || vendor == null)
  108. return false;
  109. boolean result = true;
  110. String secfilestr = baseUrl + "/security/" + vendor + ".security";
  111. try
  112. {
  113. InputStream fin = new URL(secfilestr).openStream();
  114. secprops.load(fin);
  115. int i = 1;
  116. String name;
  117. while ((name = secprops.getProperty("security.provider." + i)) != null)
  118. {
  119. Exception exception = null;
  120. try
  121. {
  122. ClassLoader sys = ClassLoader.getSystemClassLoader();
  123. providers.addElement(Class.forName(name, true, sys).newInstance());
  124. }
  125. catch (ClassNotFoundException x)
  126. {
  127. exception = x;
  128. }
  129. catch (InstantiationException x)
  130. {
  131. exception = x;
  132. }
  133. catch (IllegalAccessException x)
  134. {
  135. exception = x;
  136. }
  137. if (exception != null)
  138. {
  139. System.err.println ("WARNING: Error loading security provider "
  140. + name + ": " + exception);
  141. result = false;
  142. }
  143. i++;
  144. }
  145. }
  146. catch (IOException ignored)
  147. {
  148. result = false;
  149. }
  150. return result;
  151. }
  152. /**
  153. * Returns the value associated to a designated property name for a given
  154. * algorithm.
  155. *
  156. * @param algName
  157. * the algorithm name.
  158. * @param propName
  159. * the name of the property to return.
  160. * @return the value of the specified property or <code>null</code> if none
  161. * found.
  162. * @deprecated Use the provider-based and algorithm-independent
  163. * {@link AlgorithmParameters} and {@link KeyFactory} engine
  164. * classes instead.
  165. */
  166. public static String getAlgorithmProperty(String algName, String propName)
  167. {
  168. if (algName == null || propName == null)
  169. return null;
  170. String property = String.valueOf(propName) + "." + String.valueOf(algName);
  171. Provider p;
  172. for (Iterator i = providers.iterator(); i.hasNext(); )
  173. {
  174. p = (Provider) i.next();
  175. for (Iterator j = p.keySet().iterator(); j.hasNext(); )
  176. {
  177. String key = (String) j.next();
  178. if (key.equalsIgnoreCase(property))
  179. return p.getProperty(key);
  180. }
  181. }
  182. return null;
  183. }
  184. /**
  185. * Inserts a new designated {@link Provider} at a designated (1-based)
  186. * position in the current list of installed {@link Provider}s,
  187. *
  188. * @param provider
  189. * the new {@link Provider} to add.
  190. * @param position
  191. * the position (starting from 1) of where to install
  192. * <code>provider</code>.
  193. * @return the actual position, in the list of installed Providers. Returns
  194. * <code>-1</code> if <code>provider</code> was laready in the
  195. * list. The actual position may be different than the desired
  196. * <code>position</code>.
  197. * @throws SecurityException
  198. * if a {@link SecurityManager} is installed and it disallows this
  199. * operation.
  200. * @see #getProvider(String)
  201. * @see #removeProvider(String)
  202. * @see SecurityPermission
  203. */
  204. public static int insertProviderAt(Provider provider, int position)
  205. {
  206. SecurityManager sm = System.getSecurityManager();
  207. if (sm != null)
  208. sm.checkSecurityAccess("insertProvider." + provider.getName());
  209. position--;
  210. int max = providers.size ();
  211. for (int i = 0; i < max; i++)
  212. {
  213. if (((Provider) providers.elementAt(i)).getName().equals(provider.getName()))
  214. return -1;
  215. }
  216. if (position < 0)
  217. position = 0;
  218. if (position > max)
  219. position = max;
  220. providers.insertElementAt(provider, position);
  221. return position + 1;
  222. }
  223. /**
  224. * Appends the designated new {@link Provider} to the current list of
  225. * installed {@link Provider}s.
  226. *
  227. * @param provider
  228. * the new {@link Provider} to append.
  229. * @return the position (starting from 1) of <code>provider</code> in the
  230. * current list of {@link Provider}s, or <code>-1</code> if
  231. * <code>provider</code> was already there.
  232. * @throws SecurityException
  233. * if a {@link SecurityManager} is installed and it disallows this
  234. * operation.
  235. * @see #getProvider(String)
  236. * @see #removeProvider(String)
  237. * @see SecurityPermission
  238. */
  239. public static int addProvider(Provider provider)
  240. {
  241. return insertProviderAt (provider, providers.size () + 1);
  242. }
  243. /**
  244. * Removes an already installed {@link Provider}, given its name, from the
  245. * current list of installed {@link Provider}s.
  246. *
  247. * @param name
  248. * the name of an already installed {@link Provider} to remove.
  249. * @throws SecurityException
  250. * if a {@link SecurityManager} is installed and it disallows this
  251. * operation.
  252. * @see #getProvider(String)
  253. * @see #addProvider(Provider)
  254. */
  255. public static void removeProvider(String name)
  256. {
  257. SecurityManager sm = System.getSecurityManager();
  258. if (sm != null)
  259. sm.checkSecurityAccess("removeProvider." + name);
  260. int max = providers.size ();
  261. for (int i = 0; i < max; i++)
  262. {
  263. if (((Provider) providers.elementAt(i)).getName().equals(name))
  264. {
  265. providers.remove(i);
  266. break;
  267. }
  268. }
  269. }
  270. /**
  271. * Returns the current list of installed {@link Provider}s as an array
  272. * ordered according to their installation preference order.
  273. *
  274. * @return an array of all the installed providers.
  275. */
  276. public static Provider[] getProviders()
  277. {
  278. Provider[] array = new Provider[providers.size ()];
  279. providers.copyInto (array);
  280. return array;
  281. }
  282. /**
  283. * Returns an already installed {@link Provider} given its name.
  284. *
  285. * @param name
  286. * the name of an already installed {@link Provider}.
  287. * @return the {@link Provider} known by <code>name</code>. Returns
  288. * <code>null</code> if the current list of {@link Provider}s does
  289. * not include one named <code>name</code>.
  290. * @see #removeProvider(String)
  291. * @see #addProvider(Provider)
  292. */
  293. public static Provider getProvider(String name)
  294. {
  295. if (name == null)
  296. return null;
  297. else
  298. {
  299. name = name.trim();
  300. if (name.length() == 0)
  301. return null;
  302. }
  303. Provider p;
  304. int max = providers.size ();
  305. for (int i = 0; i < max; i++)
  306. {
  307. p = (Provider) providers.elementAt(i);
  308. if (p.getName().equals(name))
  309. return p;
  310. }
  311. return null;
  312. }
  313. /**
  314. * Returns the value associated with a Security propery.
  315. *
  316. * @param key
  317. * the key of the property to fetch.
  318. * @return the value of the Security property associated with
  319. * <code>key</code>. Returns <code>null</code> if no such property
  320. * was found.
  321. * @throws SecurityException
  322. * if a {@link SecurityManager} is installed and it disallows this
  323. * operation.
  324. * @see #setProperty(String, String)
  325. * @see SecurityPermission
  326. */
  327. public static String getProperty(String key)
  328. {
  329. // XXX To prevent infinite recursion when the SecurityManager calls us,
  330. // don't do a security check if the caller is trusted (by virtue of having
  331. // been loaded by the bootstrap class loader).
  332. SecurityManager sm = System.getSecurityManager();
  333. if (sm != null && VMStackWalker.getCallingClassLoader() != null)
  334. sm.checkSecurityAccess("getProperty." + key);
  335. return secprops.getProperty(key);
  336. }
  337. /**
  338. * Sets or changes a designated Security property to a designated value.
  339. *
  340. * @param key
  341. * the name of the property to set.
  342. * @param datum
  343. * the new value of the property.
  344. * @throws SecurityException
  345. * if a {@link SecurityManager} is installed and it disallows this
  346. * operation.
  347. * @see #getProperty(String)
  348. * @see SecurityPermission
  349. */
  350. public static void setProperty(String key, String datum)
  351. {
  352. SecurityManager sm = System.getSecurityManager();
  353. if (sm != null)
  354. sm.checkSecurityAccess("setProperty." + key);
  355. if (datum == null)
  356. secprops.remove(key);
  357. else
  358. secprops.put(key, datum);
  359. }
  360. /**
  361. * For a given <i>service</i> (e.g. Signature, MessageDigest, etc...) this
  362. * method returns the {@link Set} of all available algorithm names (instances
  363. * of {@link String}, from all currently installed {@link Provider}s.
  364. *
  365. * @param serviceName
  366. * the case-insensitive name of a service (e.g. Signature,
  367. * MessageDigest, etc).
  368. * @return a {@link Set} of {@link String}s containing the names of all
  369. * algorithm names provided by all of the currently installed
  370. * {@link Provider}s.
  371. * @since 1.4
  372. */
  373. public static Set<String> getAlgorithms(String serviceName)
  374. {
  375. HashSet<String> result = new HashSet<String>();
  376. if (serviceName == null || serviceName.length() == 0)
  377. return result;
  378. serviceName = serviceName.trim();
  379. if (serviceName.length() == 0)
  380. return result;
  381. serviceName = serviceName.toUpperCase()+".";
  382. Provider[] providers = getProviders();
  383. int ndx;
  384. for (int i = 0; i < providers.length; i++)
  385. for (Enumeration e = providers[i].propertyNames(); e.hasMoreElements(); )
  386. {
  387. String service = ((String) e.nextElement()).trim();
  388. if (service.toUpperCase().startsWith(serviceName))
  389. {
  390. service = service.substring(serviceName.length()).trim();
  391. ndx = service.indexOf(' '); // get rid of attributes
  392. if (ndx != -1)
  393. service = service.substring(0, ndx);
  394. result.add(service);
  395. }
  396. }
  397. return Collections.unmodifiableSet(result);
  398. }
  399. /**
  400. * Returns an array of currently installed {@link Provider}s, ordered
  401. * according to their installation preference order, which satisfy a given
  402. * <i>selection</i> criterion.
  403. *
  404. * <p>This implementation recognizes a <i>selection</i> criterion written in
  405. * one of two following forms:</p>
  406. *
  407. * <ul>
  408. * <li>&lt;crypto_service&gt;.&lt;algorithm_or_type&gt;: Where
  409. * <i>crypto_service</i> is a case-insensitive string, similar to what has
  410. * been described in the {@link #getAlgorithms(String)} method, and
  411. * <i>algorithm_or_type</i> is a known case-insensitive name of an
  412. * Algorithm, or one of its aliases.
  413. *
  414. * <p>For example, "CertificateFactory.X.509" would return all the installed
  415. * {@link Provider}s which provide a <i>CertificateFactory</i>
  416. * implementation of <i>X.509</i>.</p></li>
  417. *
  418. * <li>&lt;crypto_service&gt;.&lt;algorithm_or_type&gt; &lt;attribute_name&gt;:&lt;value&gt;:
  419. * Where <i>crypto_service</i> is a case-insensitive string, similar to what
  420. * has been described in the {@link #getAlgorithms(String)} method,
  421. * <i>algorithm_or_type</i> is a case-insensitive known name of an Algorithm
  422. * or one of its aliases, <i>attribute_name</i> is a case-insensitive
  423. * property name with no whitespace characters, and no dots, in-between, and
  424. * <i>value</i> is a {@link String} with no whitespace characters in-between.
  425. *
  426. * <p>For example, "Signature.Sha1WithDSS KeySize:1024" would return all the
  427. * installed {@link Provider}s which declared their ability to provide
  428. * <i>Signature</i> services, using the <i>Sha1WithDSS</i> algorithm with
  429. * key sizes of <i>1024</i>.</p></li>
  430. * </ul>
  431. *
  432. * @param filter
  433. * the <i>selection</i> criterion for selecting among the installed
  434. * {@link Provider}s.
  435. * @return all the installed {@link Provider}s which satisfy the <i>selection</i>
  436. * criterion. Returns <code>null</code> if no installed
  437. * {@link Provider}s were found which satisfy the <i>selection</i>
  438. * criterion. Returns ALL installed {@link Provider}s if
  439. * <code>filter</code> is <code>null</code> or is an empty string.
  440. * @throws InvalidParameterException
  441. * if an exception occurs while parsing the <code>filter</code>.
  442. * @see #getProviders(Map)
  443. */
  444. public static Provider[] getProviders(String filter)
  445. {
  446. if (providers == null || providers.isEmpty())
  447. return null;
  448. if (filter == null || filter.length() == 0)
  449. return getProviders();
  450. HashMap map = new HashMap(1);
  451. int i = filter.indexOf(':');
  452. if (i == -1) // <service>.<algorithm>
  453. map.put(filter, "");
  454. else // <service>.<algorithm> <attribute>:<value>
  455. map.put(filter.substring(0, i), filter.substring(i+1));
  456. return getProviders(map);
  457. }
  458. /**
  459. * Returns an array of currently installed {@link Provider}s which satisfy a
  460. * set of <i>selection</i> criteria.
  461. *
  462. * <p>The <i>selection</i> criteria are defined in a {@link Map} where each
  463. * element specifies a <i>selection</i> querry. The <i>Keys</i> in this
  464. * {@link Map} must be in one of the two following forms:</p>
  465. *
  466. * <ul>
  467. * <li>&lt;crypto_service&gt;.&lt;algorithm_or_type&gt;: Where
  468. * <i>crypto_service</i> is a case-insensitive string, similar to what has
  469. * been described in the {@link #getAlgorithms(String)} method, and
  470. * <i>algorithm_or_type</i> is a case-insensitive known name of an
  471. * Algorithm, or one of its aliases. The <i>value</i> of the entry in the
  472. * {@link Map} for such a <i>Key</i> MUST be the empty string.
  473. * {@link Provider}s which provide an implementation for the designated
  474. * <i>service algorithm</i> are included in the result.</li>
  475. *
  476. * <li>&lt;crypto_service&gt;.&lt;algorithm_or_type&gt; &lt;attribute_name&gt;:
  477. * Where <i>crypto_service</i> is a case-insensitive string, similar to what
  478. * has been described in the {@link #getAlgorithms(String)} method,
  479. * <i>algorithm_or_type</i> is a case-insensitive known name of an Algorithm
  480. * or one of its aliases, and <i>attribute_name</i> is a case-insensitive
  481. * property name with no whitespace characters, and no dots, in-between. The
  482. * <i>value</i> of the entry in this {@link Map} for such a <i>Key</i> MUST
  483. * NOT be <code>null</code> or an empty string. {@link Provider}s which
  484. * declare the designated <i>attribute_name</i> and <i>value</i> for the
  485. * designated <i>service algorithm</i> are included in the result.</li>
  486. * </ul>
  487. *
  488. * @param filter
  489. * a {@link Map} of <i>selection querries</i>.
  490. * @return all currently installed {@link Provider}s which satisfy ALL the
  491. * <i>selection</i> criteria defined in <code>filter</code>.
  492. * Returns ALL installed {@link Provider}s if <code>filter</code>
  493. * is <code>null</code> or empty.
  494. * @throws InvalidParameterException
  495. * if an exception is encountered while parsing the syntax of the
  496. * {@link Map}'s <i>keys</i>.
  497. * @see #getProviders(String)
  498. */
  499. public static Provider[] getProviders(Map<String,String> filter)
  500. {
  501. if (providers == null || providers.isEmpty())
  502. return null;
  503. if (filter == null)
  504. return getProviders();
  505. Set<String> querries = filter.keySet();
  506. if (querries == null || querries.isEmpty())
  507. return getProviders();
  508. LinkedHashSet result = new LinkedHashSet(providers); // assume all
  509. int dot, ws;
  510. String querry, service, algorithm, attribute, value;
  511. LinkedHashSet serviceProviders = new LinkedHashSet(); // preserve insertion order
  512. for (Iterator i = querries.iterator(); i.hasNext(); )
  513. {
  514. querry = (String) i.next();
  515. if (querry == null) // all providers
  516. continue;
  517. querry = querry.trim();
  518. if (querry.length() == 0) // all providers
  519. continue;
  520. dot = querry.indexOf('.');
  521. if (dot == -1) // syntax error
  522. throw new InvalidParameterException(
  523. "missing dot in '" + String.valueOf(querry)+"'");
  524. value = filter.get(querry);
  525. // deconstruct querry into [service, algorithm, attribute]
  526. if (value == null || value.trim().length() == 0) // <service>.<algorithm>
  527. {
  528. value = null;
  529. attribute = null;
  530. service = querry.substring(0, dot).trim();
  531. algorithm = querry.substring(dot+1).trim();
  532. }
  533. else // <service>.<algorithm> <attribute>
  534. {
  535. ws = querry.indexOf(' ');
  536. if (ws == -1)
  537. throw new InvalidParameterException(
  538. "value (" + String.valueOf(value) +
  539. ") is not empty, but querry (" + String.valueOf(querry) +
  540. ") is missing at least one space character");
  541. value = value.trim();
  542. attribute = querry.substring(ws+1).trim();
  543. // was the dot in the attribute?
  544. if (attribute.indexOf('.') != -1)
  545. throw new InvalidParameterException(
  546. "attribute_name (" + String.valueOf(attribute) +
  547. ") in querry (" + String.valueOf(querry) + ") contains a dot");
  548. querry = querry.substring(0, ws).trim();
  549. service = querry.substring(0, dot).trim();
  550. algorithm = querry.substring(dot+1).trim();
  551. }
  552. // service and algorithm must not be empty
  553. if (service.length() == 0)
  554. throw new InvalidParameterException(
  555. "<crypto_service> in querry (" + String.valueOf(querry) +
  556. ") is empty");
  557. if (algorithm.length() == 0)
  558. throw new InvalidParameterException(
  559. "<algorithm_or_type> in querry (" + String.valueOf(querry) +
  560. ") is empty");
  561. selectProviders(service, algorithm, attribute, value, result, serviceProviders);
  562. result.retainAll(serviceProviders); // eval next retaining found providers
  563. if (result.isEmpty()) // no point continuing
  564. break;
  565. }
  566. if (result.isEmpty())
  567. return null;
  568. return (Provider[]) result.toArray(new Provider[result.size()]);
  569. }
  570. private static void selectProviders(String svc, String algo, String attr,
  571. String val, LinkedHashSet providerSet,
  572. LinkedHashSet result)
  573. {
  574. result.clear(); // ensure we start with an empty result set
  575. for (Iterator i = providerSet.iterator(); i.hasNext(); )
  576. {
  577. Provider p = (Provider) i.next();
  578. if (provides(p, svc, algo, attr, val))
  579. result.add(p);
  580. }
  581. }
  582. private static boolean provides(Provider p, String svc, String algo,
  583. String attr, String val)
  584. {
  585. Iterator it;
  586. String serviceDotAlgorithm = null;
  587. String key = null;
  588. String realVal;
  589. boolean found = false;
  590. // if <svc>.<algo> <attr> is in the set then so is <svc>.<algo>
  591. // but it may be stored under an alias <algo>. resolve
  592. outer: for (int r = 0; r < 3; r++) // guard against circularity
  593. {
  594. serviceDotAlgorithm = (svc+"."+String.valueOf(algo)).trim();
  595. for (it = p.keySet().iterator(); it.hasNext(); )
  596. {
  597. key = (String) it.next();
  598. if (key.equalsIgnoreCase(serviceDotAlgorithm)) // eureka
  599. {
  600. found = true;
  601. break outer;
  602. }
  603. // it may be there but as an alias
  604. if (key.equalsIgnoreCase(ALG_ALIAS + serviceDotAlgorithm))
  605. {
  606. algo = p.getProperty(key);
  607. continue outer;
  608. }
  609. // else continue inner
  610. }
  611. }
  612. if (!found)
  613. return false;
  614. // found a candidate for the querry. do we have an attr to match?
  615. if (val == null) // <service>.<algorithm> querry
  616. return true;
  617. // <service>.<algorithm> <attribute>; find the key entry that match
  618. String realAttr;
  619. int limit = serviceDotAlgorithm.length() + 1;
  620. for (it = p.keySet().iterator(); it.hasNext(); )
  621. {
  622. key = (String) it.next();
  623. if (key.length() <= limit)
  624. continue;
  625. if (key.substring(0, limit).equalsIgnoreCase(serviceDotAlgorithm+" "))
  626. {
  627. realAttr = key.substring(limit).trim();
  628. if (! realAttr.equalsIgnoreCase(attr))
  629. continue;
  630. // eveything matches so far. do the value
  631. realVal = p.getProperty(key);
  632. if (realVal == null)
  633. return false;
  634. realVal = realVal.trim();
  635. // is it a string value?
  636. if (val.equalsIgnoreCase(realVal))
  637. return true;
  638. // assume value is a number. cehck for greater-than-or-equal
  639. return (Integer.parseInt(val) >= Integer.parseInt(realVal));
  640. }
  641. }
  642. return false;
  643. }
  644. }