OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [java/] [security/] [Security.java] - Blame information for rev 14

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.