/* Engine -- generic getInstance method.
   Copyright (C) 2003, 2006  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package gnu.java.security;

import gnu.java.lang.CPStringBuilder;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.util.Enumeration;

/**
 * Generic implementation of the getInstance methods in the various
 * engine classes in java.security.
 * <p>
 * These classes ({@link java.security.Signature} for example) can be
 * thought of as the "chrome, upholstery, and steering wheel", and the SPI
 * (service provider interface, e.g. {@link java.security.SignatureSpi})
 * classes can be thought of as the "engine" -- providing the actual
 * functionality of whatever cryptographic algorithm the instance
 * represents.
 *
 * @see Provider
 * @author Casey Marshall 
 */
public final class Engine
{

  // Constants.
  // ------------------------------------------------------------------------

  /** Prefix for aliases. */
  private static final String ALG_ALIAS = "Alg.Alias.";

  /** Maximum number of aliases to try. */
  private static final int MAX_ALIASES = 5;

  /** Argument list for no-argument constructors. */
  private static final Object[] NO_ARGS = new Object[0];

  // Constructor.
  // ------------------------------------------------------------------------

  /** This class cannot be instantiated. */
  private Engine() { }

  /**
   * Return the implementation for <i>algorithm</i> for service <i>service</i>
   * from <i>provider</i>. The service is e.g. "Signature", and the algorithm
   * "DSA".
   * 
   * @param service The service name.
   * @param algorithm The name of the algorithm to get.
   * @param provider The provider to get the implementation from.
   * @return The engine class for the specified algorithm; the object returned
   *         is typically a subclass of the SPI class for that service, but
   *         callers should check that this is so.
   * @throws NoSuchAlgorithmException If the implementation cannot be found or
   *           cannot be instantiated.
   * @throws InvocationTargetException If the SPI class's constructor throws an
   *           exception.
   * @throws IllegalArgumentException If any of the three arguments is null.
   */
  public static Object getInstance(String service, String algorithm,
                                   Provider provider)
      throws InvocationTargetException, NoSuchAlgorithmException
  {
    return getInstance(service, algorithm, provider, NO_ARGS);
  }

  /**
   * Return the implementation for <i>algorithm</i> for service <i>service</i>
   * from <i>provider</i>, passing <i>initArgs</i> to the SPI class's
   * constructor (which cannot be null; pass a zero-length array if the SPI
   * takes no arguments). The service is e.g. "Signature", and the algorithm
   * "DSA".
   * 
   * @param service The service name.
   * @param algorithm The name of the algorithm to get.
   * @param provider The provider to get the implementation from.
   * @param initArgs The arguments to pass to the SPI class's constructor
   *          (cannot be null).
   * @return The engine class for the specified algorithm; the object returned
   *         is typically a subclass of the SPI class for that service, but
   *         callers should check that this is so.
   * @throws NoSuchAlgorithmException If the implementation cannot be found or
   *           cannot be instantiated.
   * @throws InvocationTargetException If the SPI class's constructor throws an
   *           exception.
   * @throws IllegalArgumentException If any of the four arguments is
   *           <code>null</code> or if either <code>service</code>, or
   *           <code>algorithm</code> is an empty string.
   */
  public static Object getInstance(String service, String algorithm,
                                   Provider provider, Object[] initArgs)
      throws InvocationTargetException, NoSuchAlgorithmException
  {
    if (service == null)
      throw new IllegalArgumentException("service MUST NOT be null");
    service = service.trim();
    if (service.length() == 0)
      throw new IllegalArgumentException("service MUST NOT be empty");
    if (algorithm == null)
      throw new IllegalArgumentException("algorithm MUST NOT be null");
    algorithm = algorithm.trim();
    if (algorithm.length() == 0)
      throw new IllegalArgumentException("algorithm MUST NOT be empty");
    if (provider == null)
      throw new IllegalArgumentException("provider MUST NOT be null");
    if (initArgs == null)
      throw new IllegalArgumentException("Constructor's parameters MUST NOT be null");

    Enumeration enumer = provider.propertyNames();
    String key = null;
    String alias;
    int count = 0;
    boolean algorithmFound = false;
    CPStringBuilder sb = new CPStringBuilder();
    while (enumer.hasMoreElements())
      {
        key = (String) enumer.nextElement();
        if (key.equalsIgnoreCase(service + "." + algorithm))
          {
            // remove the service portion from the key
            algorithm = key.substring(service.length() + 1); 
            algorithmFound = true;
            break;
          }
        else if (key.equalsIgnoreCase(ALG_ALIAS + service + "." + algorithm))
          {
            alias = provider.getProperty(key);
            if (! algorithm.equalsIgnoreCase(alias)) // does not refer to itself
              {
                algorithm = alias;
                if (count++ > MAX_ALIASES)
                  {
                    sb.append("Algorithm [").append(algorithm)
                        .append("] of type [").append(service)
                        .append("] from provider [").append(provider)
                        .append("] has too many aliases");
                    throw new NoSuchAlgorithmException(sb.toString());
                  }
                // need to reset enumeration to now look for the alias
                enumer = provider.propertyNames();
              }
          }
      }

    if (! algorithmFound)
      {
        sb.append("Algorithm [").append(algorithm).append("] of type [")
            .append(service).append("] from provider [")
            .append(provider).append("] is not found");
        throw new NoSuchAlgorithmException(sb.toString());
      }

    // Find and instantiate the implementation
    Class clazz = null;
    ClassLoader loader = provider.getClass().getClassLoader();
    Constructor constructor = null;
    String className = provider.getProperty(key);
    sb.append("Class [").append(className).append("] for algorithm [")
        .append(algorithm).append("] of type [").append(service)
        .append("] from provider [").append(provider).append("] ");
    Throwable cause = null;
    try
      {
        if (loader != null)
          clazz = loader.loadClass(className);
        else
          clazz = Class.forName(className);
        constructor = getCompatibleConstructor(clazz, initArgs);
        return constructor.newInstance(initArgs);
      }
    catch (ClassNotFoundException x)
      {
        sb.append("cannot not be found");
        cause = x;
      }
    catch (IllegalAccessException x)
      {
        sb.append("cannot be accessed");
        cause = x;
      }
    catch (InstantiationException x)
      {
        sb.append("cannot be instantiated");
        cause = x;
      }
    catch (ExceptionInInitializerError x)
      {
        sb.append("cannot be initialized");
        cause = x;
      }
    catch (SecurityException x)
      {
        sb.append("caused a security violation");
        cause = x;
      }
    catch (NoSuchMethodException x)
      {
        sb.append("does not have/expose an appropriate constructor");
        cause = x;
      }

    NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
    x.initCause(cause);
    throw x;
  }

  /**
   * Find a constructor in the given class that can take the specified
   * argument list, allowing any of which to be null.
   *
   * @param clazz    The class from which to get the constructor.
   * @param initArgs The argument list to be passed to the constructor.
   * @return The constructor.
   * @throws NoSuchMethodException If no constructor of the given class
   *         can take the specified argument array.
   */
  private static Constructor getCompatibleConstructor(Class clazz,
                                                      Object[] initArgs)
    throws NoSuchMethodException
  {
    Constructor[] c = clazz.getConstructors();
    outer:for (int i = 0; i < c.length; i++)
      {
        Class[] argTypes = c[i].getParameterTypes();
        if (argTypes.length != initArgs.length)
          continue;
        for (int j = 0; j < argTypes.length; j++)
          {
            if (initArgs[j] != null &&
                !argTypes[j].isAssignableFrom(initArgs[j].getClass()))
              continue outer;
          }
        // If we reach this point, we know this constructor (c[i]) has
        // the same number of parameters as the target parameter list,
        // and all our parameters are either (1) null, or (2) assignable
        // to the target parameter type.
        return c[i];
      }
    throw new NoSuchMethodException();
  }
}
