/* 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();
  }
}
