/*
 * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
/*
 * $Id: TransformService.java,v 1.6.4.1 2005/09/15 12:42:11 mullan Exp $
 */
package javax.xml.crypto.dsig;

import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Provider;
import java.security.Provider.Service;
import java.security.Security;
import java.util.*;
import javax.xml.crypto.MarshalException;
import javax.xml.crypto.XMLStructure;
import javax.xml.crypto.XMLCryptoContext;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;


/**
 * A Service Provider Interface for transform and canonicalization algorithms.
 *
 * <p>Each instance of <code>TransformService</code> supports a specific
 * transform or canonicalization algorithm and XML mechanism type. To create a
 * <code>TransformService</code>, call one of the static
 * {@link #getInstance getInstance} methods, passing in the algorithm URI and
 * XML mechanism type desired, for example:
 *
 * <blockquote><code>
 * TransformService ts = TransformService.getInstance(Transform.XPATH2, "DOM");
 * </code></blockquote>
 *
 * <p><code>TransformService</code> implementations are registered and loaded
 * using the {@link java.security.Provider} mechanism.  Each
 * <code>TransformService</code> service provider implementation should include
 * a <code>MechanismType</code> service attribute that identifies the XML
 * mechanism type that it supports. If the attribute is not specified,
 * "DOM" is assumed. For example, a service provider that supports the
 * XPath Filter 2 Transform and DOM mechanism would be specified in the
 * <code>Provider</code> subclass as:
 * <pre>
 *     put("TransformService." + Transform.XPATH2,
 *         "org.example.XPath2TransformService");
 *     put("TransformService." + Transform.XPATH2 + " MechanismType", "DOM");
 * </pre>
 * <code>TransformService</code> implementations that support the DOM
 * mechanism type must abide by the DOM interoperability requirements defined
 * in the
 * {@extLink security_guide_xmldsig_rqmts DOM Mechanism Requirements} section
 * of the API overview. See the
 * {@extLink security_guide_xmldsig_provider Service Providers} section of
 * the API overview for a list of standard mechanism types.
 * <p>
 * Once a <code>TransformService</code> has been created, it can be used
 * to process <code>Transform</code> or <code>CanonicalizationMethod</code>
 * objects. If the <code>Transform</code> or <code>CanonicalizationMethod</code>
 * exists in XML form (for example, when validating an existing
 * <code>XMLSignature</code>), the {@link #init(XMLStructure, XMLCryptoContext)}
 * method must be first called to initialize the transform and provide document
 * context (even if there are no parameters). Alternatively, if the
 * <code>Transform</code> or <code>CanonicalizationMethod</code> is being
 * created from scratch, the {@link #init(TransformParameterSpec)} method
 * is called to initialize the transform with parameters and the
 * {@link #marshalParams marshalParams} method is called to marshal the
 * parameters to XML and provide the transform with document context. Finally,
 * the {@link #transform transform} method is called to perform the
 * transformation.
 * <p>
 * <b>Concurrent Access</b>
 * <p>The static methods of this class are guaranteed to be thread-safe.
 * Multiple threads may concurrently invoke the static methods defined in this
 * class with no ill effects.
 *
 * <p>However, this is not true for the non-static methods defined by this
 * class. Unless otherwise documented by a specific provider, threads that
 * need to access a single <code>TransformService</code> instance
 * concurrently should synchronize amongst themselves and provide the
 * necessary locking. Multiple threads each manipulating a different
 * <code>TransformService</code> instance need not synchronize.
 *
 * @author Sean Mullan
 * @author JSR 105 Expert Group
 * @since 1.6
 */
public abstract class TransformService implements Transform {

    private String algorithm;
    private String mechanism;
    private Provider provider;

    /**
     * Default constructor, for invocation by subclasses.
     */
    protected TransformService() {}

    /**
     * Returns a <code>TransformService</code> that supports the specified
     * algorithm URI (ex: {@link Transform#XPATH2}) and mechanism type
     * (ex: DOM).
     *
     * <p>This method uses the standard JCA provider lookup mechanism to
     * locate and instantiate a <code>TransformService</code> implementation
     * of the desired algorithm and <code>MechanismType</code> service
     * attribute. It traverses the list of registered security
     * <code>Provider</code>s, starting with the most preferred
     * <code>Provider</code>. A new <code>TransformService</code> object
     * from the first <code>Provider</code> that supports the specified
     * algorithm and mechanism type is returned.
     *
     * <p> Note that the list of registered providers may be retrieved via
     * the {@link Security#getProviders() Security.getProviders()} method.
     *
     * @implNote
     * The JDK Reference Implementation additionally uses the
     * {@code jdk.security.provider.preferred}
     * {@link Security#getProperty(String) Security} property to determine
     * the preferred provider order for the specified algorithm. This
     * may be different than the order of providers returned by
     * {@link Security#getProviders() Security.getProviders()}.
     *
     * @param algorithm the URI of the algorithm
     * @param mechanismType the type of the XML processing mechanism and
     *   representation
     * @return a new <code>TransformService</code>
     * @throws NullPointerException if <code>algorithm</code> or
     *   <code>mechanismType</code> is  <code>null</code>
     * @throws NoSuchAlgorithmException if no <code>Provider</code> supports a
     *   <code>TransformService</code> implementation for the specified
     *   algorithm and mechanism type
     * @see Provider
     */
    public static TransformService getInstance
        (String algorithm, String mechanismType)
        throws NoSuchAlgorithmException {
        if (mechanismType == null || algorithm == null) {
            throw new NullPointerException();
        }
        boolean dom = false;
        if (mechanismType.equals("DOM")) {
            dom = true;
        }

        Provider[] provs = Security.getProviders();
        for (Provider p : provs) {
            Service s = p.getService("TransformService", algorithm);
            if (s != null) {
                String value = s.getAttribute("MechanismType");
                if ((value == null && dom) ||
                    (value != null && value.equals(mechanismType))) {
                    Object obj = s.newInstance(null);
                    if (obj instanceof TransformService) {
                        TransformService ts = (TransformService) obj;
                        ts.algorithm = algorithm;
                        ts.mechanism = mechanismType;
                        ts.provider = p;
                        return ts;
                    }
                }
            }
        }
        throw new NoSuchAlgorithmException
            (algorithm + " algorithm and " + mechanismType
                 + " mechanism not available");
    }

    /**
     * Returns a <code>TransformService</code> that supports the specified
     * algorithm URI (ex: {@link Transform#XPATH2}) and mechanism type
     * (ex: DOM) as supplied by the specified provider. Note that the specified
     * <code>Provider</code> object does not have to be registered in the
     * provider list.
     *
     * @param algorithm the URI of the algorithm
     * @param mechanismType the type of the XML processing mechanism and
     *   representation
     * @param provider the <code>Provider</code> object
     * @return a new <code>TransformService</code>
     * @throws NullPointerException if <code>provider</code>,
     *   <code>algorithm</code>, or <code>mechanismType</code> is
     *   <code>null</code>
     * @throws NoSuchAlgorithmException if a <code>TransformService</code>
     *   implementation for the specified algorithm and mechanism type is not
     *   available from the specified <code>Provider</code> object
     * @see Provider
     */
    public static TransformService getInstance
        (String algorithm, String mechanismType, Provider provider)
        throws NoSuchAlgorithmException {
        if (mechanismType == null || algorithm == null || provider == null) {
            throw new NullPointerException();
        }

        boolean dom = false;
        if (mechanismType.equals("DOM")) {
            dom = true;
        }
        Service s = provider.getService("TransformService", algorithm);
        if (s != null) {
            String value = s.getAttribute("MechanismType");
            if ((value == null && dom) ||
                (value != null && value.equals(mechanismType))) {
                Object obj = s.newInstance(null);
                if (obj instanceof TransformService) {
                    TransformService ts = (TransformService) obj;
                    ts.algorithm = algorithm;
                    ts.mechanism = mechanismType;
                    ts.provider = provider;
                    return ts;
                }
            }
        }
        throw new NoSuchAlgorithmException
            (algorithm + " algorithm and " + mechanismType
                 + " mechanism not available from " + provider.getName());
    }

    /**
     * Returns a <code>TransformService</code> that supports the specified
     * algorithm URI (ex: {@link Transform#XPATH2}) and mechanism type
     * (ex: DOM) as supplied by the specified provider. The specified provider
     * must be registered in the security provider list.
     *
     * <p>Note that the list of registered providers may be retrieved via
     * the {@link Security#getProviders() Security.getProviders()} method.
     *
     * @param algorithm the URI of the algorithm
     * @param mechanismType the type of the XML processing mechanism and
     *   representation
     * @param provider the string name of the provider
     * @return a new <code>TransformService</code>
     * @throws NoSuchProviderException if the specified provider is not
     *   registered in the security provider list
     * @throws NullPointerException if <code>provider</code>,
     *   <code>mechanismType</code>, or <code>algorithm</code> is
     *   <code>null</code>
     * @throws NoSuchAlgorithmException if a <code>TransformService</code>
     *   implementation for the specified algorithm and mechanism type is not
     *   available from the specified provider
     * @see Provider
     */
    public static TransformService getInstance
        (String algorithm, String mechanismType, String provider)
        throws NoSuchAlgorithmException, NoSuchProviderException {
        if (mechanismType == null || algorithm == null || provider == null) {
            throw new NullPointerException();
        } else if (provider.length() == 0) {
            throw new NoSuchProviderException();
        }
        boolean dom = false;
        if (mechanismType.equals("DOM")) {
            dom = true;
        }
        Provider p = Security.getProvider(provider);
        if (p == null) {
            throw new NoSuchProviderException("No such provider: " +
                                              provider);
        }
        Service s = p.getService("TransformService", algorithm);
        if (s != null) {
            String value = s.getAttribute("MechanismType");
            if ((value == null && dom) ||
                (value != null && value.equals(mechanismType))) {
                Object obj = s.newInstance(null);
                if (obj instanceof TransformService) {
                    TransformService ts = (TransformService) obj;
                    ts.algorithm = algorithm;
                    ts.mechanism = mechanismType;
                    ts.provider = p;
                    return ts;
                }
            }
        }
        throw new NoSuchAlgorithmException
            (algorithm + " algorithm and " + mechanismType
                 + " mechanism not available from " + provider);
    }

    private static class MechanismMapEntry implements Map.Entry<String,String> {
        private final String mechanism;
        private final String algorithm;
        private final String key;
        MechanismMapEntry(String algorithm, String mechanism) {
            this.algorithm = algorithm;
            this.mechanism = mechanism;
            this.key = "TransformService." + algorithm + " MechanismType";
        }
        public boolean equals(Object o) {
            if (!(o instanceof Map.Entry)) {
                return false;
            }
            Map.Entry<?,?> e = (Map.Entry<?,?>) o;
            return (getKey()==null ?
                    e.getKey()==null : getKey().equals(e.getKey())) &&
                   (getValue()==null ?
                    e.getValue()==null : getValue().equals(e.getValue()));
        }
        public String getKey() {
            return key;
        }
        public String getValue() {
            return mechanism;
        }
        public String setValue(String value) {
            throw new UnsupportedOperationException();
        }
        public int hashCode() {
            return (getKey()==null ? 0 : getKey().hashCode()) ^
                   (getValue()==null ? 0 : getValue().hashCode());
        }
    }

    /**
     * Returns the mechanism type supported by this <code>TransformService</code>.
     *
     * @return the mechanism type
     */
    public final String getMechanismType() {
        return mechanism;
    }

    /**
     * Returns the URI of the algorithm supported by this
     * <code>TransformService</code>.
     *
     * @return the algorithm URI
     */
    public final String getAlgorithm() {
        return algorithm;
    }

    /**
     * Returns the provider of this <code>TransformService</code>.
     *
     * @return the provider
     */
    public final Provider getProvider() {
        return provider;
    }

    /**
     * Initializes this <code>TransformService</code> with the specified
     * parameters.
     *
     * <p>If the parameters exist in XML form, the
     * {@link #init(XMLStructure, XMLCryptoContext)} method should be used to
     * initialize the <code>TransformService</code>.
     *
     * @param params the algorithm parameters (may be <code>null</code> if
     *   not required or optional)
     * @throws InvalidAlgorithmParameterException if the specified parameters
     *   are invalid for this algorithm
     */
    public abstract void init(TransformParameterSpec params)
        throws InvalidAlgorithmParameterException;

    /**
     * Marshals the algorithm-specific parameters. If there are no parameters
     * to be marshalled, this method returns without throwing an exception.
     *
     * @param parent a mechanism-specific structure containing the parent
     *    node that the marshalled parameters should be appended to
     * @param context the <code>XMLCryptoContext</code> containing
     *    additional context (may be <code>null</code> if not applicable)
     * @throws ClassCastException if the type of <code>parent</code> or
     *    <code>context</code> is not compatible with this
     *    <code>TransformService</code>
     * @throws NullPointerException if <code>parent</code> is <code>null</code>
     * @throws MarshalException if the parameters cannot be marshalled
     */
    public abstract void marshalParams
        (XMLStructure parent, XMLCryptoContext context)
        throws MarshalException;

    /**
     * Initializes this <code>TransformService</code> with the specified
     * parameters and document context.
     *
     * @param parent a mechanism-specific structure containing the parent
     *    structure
     * @param context the <code>XMLCryptoContext</code> containing
     *    additional context (may be <code>null</code> if not applicable)
     * @throws ClassCastException if the type of <code>parent</code> or
     *    <code>context</code> is not compatible with this
     *    <code>TransformService</code>
     * @throws NullPointerException if <code>parent</code> is <code>null</code>
     * @throws InvalidAlgorithmParameterException if the specified parameters
     *   are invalid for this algorithm
     */
    public abstract void init(XMLStructure parent, XMLCryptoContext context)
        throws InvalidAlgorithmParameterException;
}
