null if none
   *         found.
   * @deprecated Use the provider-based and algorithm-independent
   *             {@link AlgorithmParameters} and {@link KeyFactory} engine
   *             classes instead.
   */
  public static String getAlgorithmProperty(String algName, String propName)
  {
    if (algName == null || propName == null)
      return null;
    String property = String.valueOf(propName) + "." + String.valueOf(algName);
    Provider p;
    for (Iterator i = providers.iterator(); i.hasNext(); )
      {
        p = (Provider) i.next();
        for (Iterator j = p.keySet().iterator(); j.hasNext(); )
          {
            String key = (String) j.next();
            if (key.equalsIgnoreCase(property))
              return p.getProperty(key);
          }
      }
    return null;
  }
  /**
   * Inserts a new designated {@link Provider} at a designated (1-based)
   * position in the current list of installed {@link Provider}s,
   * 
   * @param provider
   *          the new {@link Provider} to add.
   * @param position
   *          the position (starting from 1) of where to install
   *          provider.
   * @return the actual position, in the list of installed Providers. Returns
   *         -1 if provider was laready in the
   *         list. The actual position may be different than the desired
   *         position.
   * @throws SecurityException
   *           if a {@link SecurityManager} is installed and it disallows this
   *           operation.
   * @see #getProvider(String)
   * @see #removeProvider(String)
   * @see SecurityPermission
   */
  public static int insertProviderAt(Provider provider, int position)
  {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null)
      sm.checkSecurityAccess("insertProvider." + provider.getName());
    position--;
    int max = providers.size ();
    for (int i = 0; i < max; i++)
      {
	if (((Provider) providers.elementAt(i)).getName().equals(provider.getName()))
	  return -1;
      }
    if (position < 0)
      position = 0;
    if (position > max)
      position = max;
    providers.insertElementAt(provider, position);
    return position + 1;
  }
  /**
   * Appends the designated new {@link Provider} to the current list of
   * installed {@link Provider}s.
   * 
   * @param provider
   *          the new {@link Provider} to append.
   * @return the position (starting from 1) of provider in the
   *         current list of {@link Provider}s, or -1 if
   *         provider was already there.
   * @throws SecurityException
   *           if a {@link SecurityManager} is installed and it disallows this
   *           operation.
   * @see #getProvider(String)
   * @see #removeProvider(String)
   * @see SecurityPermission
   */
  public static int addProvider(Provider provider)
  {
    return insertProviderAt (provider, providers.size () + 1);
  }
  /**
   * Removes an already installed {@link Provider}, given its name, from the
   * current list of installed {@link Provider}s.
   * 
   * @param name
   *          the name of an already installed {@link Provider} to remove.
   * @throws SecurityException
   *           if a {@link SecurityManager} is installed and it disallows this
   *           operation.
   * @see #getProvider(String)
   * @see #addProvider(Provider)
   */
  public static void removeProvider(String name)
  {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null)
      sm.checkSecurityAccess("removeProvider." + name);
    int max = providers.size ();
    for (int i = 0; i < max; i++)
      {
	if (((Provider) providers.elementAt(i)).getName().equals(name))
	  {
	    providers.remove(i);
	    break;
	  }
      }
  }
  /**
   * Returns the current list of installed {@link Provider}s as an array
   * ordered according to their installation preference order.
   * 
   * @return an array of all the installed providers.
   */
  public static Provider[] getProviders()
  {
    Provider[] array = new Provider[providers.size ()];
    providers.copyInto (array);
    return array;
  }
  /**
   * Returns an already installed {@link Provider} given its name.
   * 
   * @param name
   *          the name of an already installed {@link Provider}.
   * @return the {@link Provider} known by name. Returns
   *         null if the current list of {@link Provider}s does
   *         not include one named name.
   * @see #removeProvider(String)
   * @see #addProvider(Provider)
   */
  public static Provider getProvider(String name)
  {
    if (name == null)
      return null;
    else
      {
        name = name.trim();
        if (name.length() == 0)
          return null;
      }
    Provider p;
    int max = providers.size ();
    for (int i = 0; i < max; i++)
      {
	p = (Provider) providers.elementAt(i);
	if (p.getName().equals(name))
	  return p;
      }
    return null;
  }
  /**
   * Returns the value associated with a Security propery.
   * 
   * @param key
   *          the key of the property to fetch.
   * @return the value of the Security property associated with
   *         key. Returns null if no such property
   *         was found.
   * @throws SecurityException
   *           if a {@link SecurityManager} is installed and it disallows this
   *           operation.
   * @see #setProperty(String, String)
   * @see SecurityPermission
   */
  public static String getProperty(String key)
  {
    // XXX To prevent infinite recursion when the SecurityManager calls us,
    // don't do a security check if the caller is trusted (by virtue of having
    // been loaded by the bootstrap class loader).
    SecurityManager sm = System.getSecurityManager();
    if (sm != null && VMStackWalker.getCallingClassLoader() != null)
      sm.checkSecurityAccess("getProperty." + key);
    return secprops.getProperty(key);
  }
  /**
   * Sets or changes a designated Security property to a designated value.
   * 
   * @param key
   *          the name of the property to set.
   * @param datum
   *          the new value of the property.
   * @throws SecurityException
   *           if a {@link SecurityManager} is installed and it disallows this
   *           operation.
   * @see #getProperty(String)
   * @see SecurityPermission
   */
  public static void setProperty(String key, String datum)
  {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null)
      sm.checkSecurityAccess("setProperty." + key);
    if (datum == null)
      secprops.remove(key);
    else
      secprops.put(key, datum);
  }
  /**
   * For a given service (e.g. Signature, MessageDigest, etc...) this
   * method returns the {@link Set} of all available algorithm names (instances
   * of {@link String}, from all currently installed {@link Provider}s.
   * 
   * @param serviceName
   *          the case-insensitive name of a service (e.g. Signature,
   *          MessageDigest, etc).
   * @return a {@link Set} of {@link String}s containing the names of all
   *         algorithm names provided by all of the currently installed
   *         {@link Provider}s.
   * @since 1.4
   */
  public static SetThis implementation recognizes a selection criterion written in * one of two following forms:
* *For example, "CertificateFactory.X.509" would return all the installed * {@link Provider}s which provide a CertificateFactory * implementation of X.509.
For example, "Signature.Sha1WithDSS KeySize:1024" would return all the * installed {@link Provider}s which declared their ability to provide * Signature services, using the Sha1WithDSS algorithm with * key sizes of 1024.
null if no installed
   *         {@link Provider}s were found which satisfy the selection
   *         criterion. Returns ALL installed {@link Provider}s if
   *         filter is null or is an empty string.
   * @throws InvalidParameterException
   *           if an exception occurs while parsing the filter.
   * @see #getProviders(Map)
   */
  public static Provider[] getProviders(String filter)
  {
    if (providers == null || providers.isEmpty())
      return null;
    if (filter == null || filter.length() == 0)
      return getProviders();
    HashMap map = new HashMap(1);
    int i = filter.indexOf(':');
    if (i == -1) // The selection criteria are defined in a {@link Map} where each * element specifies a selection querry. The Keys in this * {@link Map} must be in one of the two following forms:
* *null or an empty string. {@link Provider}s which
   *   declare the designated attribute_name and value for the
   *   designated service algorithm are included in the result.filter.
   *         Returns ALL installed {@link Provider}s if filter
   *         is null or empty.
   * @throws InvalidParameterException
   *           if an exception is encountered while parsing the syntax of the
   *           {@link Map}'s keys.
   * @see #getProviders(String)
   */
  public static Provider[] getProviders(Map