/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package java.security;

import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import org.apache.harmony.security.fortress.Engine;
import org.apache.harmony.security.fortress.SecurityAccess;
import org.apache.harmony.security.fortress.Services;

/**
 * {@code Security} is the central class in the Java Security API. It manages
 * the list of security {@code Provider} that have been installed into this
 * runtime environment.
 */
public final class Security {

    // Security properties
    private static final Properties secprops = new Properties();

    // static initialization
    // - load security properties files
    // - load statically registered providers
    // - if no provider description file found then load default providers
    // Note: Getting the input stream for the security.properties file is factored into its own
    //       function, which will be intercepted during boot image creation.
    static {
        boolean loaded = false;
        Reader input = null;
        try {
            input = getSecurityPropertiesReader();
            secprops.load(input);
            loaded = true;
        } catch (Exception ex) {
            System.logE("Could not load 'security.properties'", ex);
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (Exception ex) {
                    System.logW("Could not close 'security.properties'", ex);
                }
            }
        }
        if (!loaded) {
            registerDefaultProviders();
        }
        Engine.door = new SecurityDoor();
    }

    private static Reader getSecurityPropertiesReader() throws Exception {
        InputStream configStream = Security.class.getResourceAsStream("security.properties");
        return new InputStreamReader(new BufferedInputStream(configStream), "ISO-8859-1");
    }

    /**
     * This class can't be instantiated.
     */
    private Security() {
    }

    // Register default providers
    private static void registerDefaultProviders() {
        secprops.put("security.provider.1", "com.android.org.conscrypt.OpenSSLProvider");
        secprops.put("security.provider.2", "com.android.org.bouncycastle.jce.provider.BouncyCastleProvider");
        secprops.put("security.provider.3", "org.apache.harmony.security.provider.crypto.CryptoProvider");
        secprops.put("security.provider.4", "com.android.org.conscrypt.JSSEProvider");
    }

    /**
     * Returns value for the specified algorithm with the specified name.
     *
     * @param algName
     *            the name of the algorithm.
     * @param propName
     *            the name of the property.
     * @return value of the property.
     * @deprecated Use {@link AlgorithmParameters} and {@link KeyFactory} instead.
     */
    @Deprecated
    public static String getAlgorithmProperty(String algName, String propName) {
        if (algName == null || propName == null) {
            return null;
        }
        String prop = "Alg." + propName + "." + algName;
        Provider[] providers = getProviders();
        for (Provider provider : providers) {
            for (Enumeration<?> e = provider.propertyNames(); e.hasMoreElements();) {
                String propertyName = (String) e.nextElement();
                if (propertyName.equalsIgnoreCase(prop)) {
                    return provider.getProperty(propertyName);
                }
            }
        }
        return null;
    }

    /**
     * Insert the given {@code Provider} at the specified {@code position}. The
     * positions define the preference order in which providers are searched for
     * requested algorithms.
     *
     * @param provider
     *            the provider to insert.
     * @param position
     *            the position (starting from 1).
     * @return the actual position or {@code -1} if the given {@code provider}
     *         was already in the list. The actual position may be different
     *         from the desired position.
     */
    public static synchronized int insertProviderAt(Provider provider, int position) {
        // check that provider is not already
        // installed, else return -1; if (position <1) or (position > max
        // position) position = max position + 1; insert provider, shift up
        // one position for next providers; Note: The position is 1-based
        if (getProvider(provider.getName()) != null) {
            return -1;
        }
        int result = Services.insertProviderAt(provider, position);
        renumProviders();
        return result;
    }

    /**
     * Adds the given {@code provider} to the collection of providers at the
     * next available position.
     *
     * @param provider
     *            the provider to be added.
     * @return the actual position or {@code -1} if the given {@code provider}
     *         was already in the list.
     */
    public static int addProvider(Provider provider) {
        return insertProviderAt(provider, 0);
    }

    /**
     * Removes the {@code Provider} with the specified name form the collection
     * of providers. If the the {@code Provider} with the specified name is
     * removed, all provider at a greater position are shifted down one
     * position.
     *
     * <p>Returns silently if {@code name} is {@code null} or no provider with the
     * specified name is installed.
     *
     * @param name
     *            the name of the provider to remove.
     */
    public static synchronized void removeProvider(String name) {
        // It is not clear from spec.:
        // 1. if name is null, should we checkSecurityAccess or not?
        //    throw SecurityException or not?
        // 2. as 1 but provider is not installed
        // 3. behavior if name is empty string?

        Provider p;
        if ((name == null) || (name.length() == 0)) {
            return;
        }
        p = getProvider(name);
        if (p == null) {
            return;
        }
        Services.removeProvider(p.getProviderNumber());
        renumProviders();
        p.setProviderNumber(-1);
    }

    /**
     * Returns an array containing all installed providers. The providers are
     * ordered according their preference order.
     *
     * @return an array containing all installed providers.
     */
    public static synchronized Provider[] getProviders() {
        ArrayList<Provider> providers = Services.getProviders();
        return providers.toArray(new Provider[providers.size()]);
    }

    /**
     * Returns the {@code Provider} with the specified name. Returns {@code
     * null} if name is {@code null} or no provider with the specified name is
     * installed.
     *
     * @param name
     *            the name of the requested provider.
     * @return the provider with the specified name, maybe {@code null}.
     */
    public static synchronized Provider getProvider(String name) {
        return Services.getProvider(name);
    }

    /**
     * Returns the array of providers which meet the user supplied string
     * filter. The specified filter must be supplied in one of two formats:
     * <nl>
     * <li> CRYPTO_SERVICE_NAME.ALGORITHM_OR_TYPE
     * <p>
     * (for example: "MessageDigest.SHA")
     * <li> CRYPTO_SERVICE_NAME.ALGORITHM_OR_TYPE
     * ATTR_NAME:ATTR_VALUE
     * <p>
     * (for example: "Signature.MD2withRSA KeySize:512")
     * </nl>
     *
     * @param filter
     *            case-insensitive filter.
     * @return the providers which meet the user supplied string filter {@code
     *         filter}. A {@code null} value signifies that none of the
     *         installed providers meets the filter specification.
     * @throws InvalidParameterException
     *             if an unusable filter is supplied.
     * @throws NullPointerException
     *             if {@code filter} is {@code null}.
     */
    public static Provider[] getProviders(String filter) {
        if (filter == null) {
            throw new NullPointerException("filter == null");
        }
        if (filter.length() == 0) {
            throw new InvalidParameterException();
        }
        HashMap<String, String> hm = new HashMap<String, String>();
        int i = filter.indexOf(':');
        if ((i == filter.length() - 1) || (i == 0)) {
            throw new InvalidParameterException();
        }
        if (i < 1) {
            hm.put(filter, "");
        } else {
            hm.put(filter.substring(0, i), filter.substring(i + 1));
        }
        return getProviders(hm);
    }

    /**
     * Returns the array of providers which meet the user supplied set of
     * filters. The filter must be supplied in one of two formats:
     * <nl>
     * <li> CRYPTO_SERVICE_NAME.ALGORITHM_OR_TYPE
     * <p>
     * for example: "MessageDigest.SHA" The value associated with the key must
     * be an empty string. <li> CRYPTO_SERVICE_NAME.ALGORITHM_OR_TYPE
     * ATTR_NAME:ATTR_VALUE
     * <p>
     * for example: "Signature.MD2withRSA KeySize:512" where "KeySize:512" is
     * the value of the filter map entry.
     * </nl>
     *
     * @param filter
     *            case-insensitive filter.
     * @return the providers which meet the user supplied string filter {@code
     *         filter}. A {@code null} value signifies that none of the
     *         installed providers meets the filter specification.
     * @throws InvalidParameterException
     *             if an unusable filter is supplied.
     * @throws NullPointerException
     *             if {@code filter} is {@code null}.
     */
    public static synchronized Provider[] getProviders(Map<String,String> filter) {
        if (filter == null) {
            throw new NullPointerException("filter == null");
        }
        if (filter.isEmpty()) {
            return null;
        }
        ArrayList<Provider> result = new ArrayList<Provider>(Services.getProviders());
        Set<Entry<String, String>> keys = filter.entrySet();
        Map.Entry<String, String> entry;
        for (Iterator<Entry<String, String>> it = keys.iterator(); it.hasNext();) {
            entry = it.next();
            String key = entry.getKey();
            String val = entry.getValue();
            String attribute = null;
            int i = key.indexOf(' ');
            int j = key.indexOf('.');
            if (j == -1) {
                throw new InvalidParameterException();
            }
            if (i == -1) { // <crypto_service>.<algorithm_or_type>
                if (val.length() != 0) {
                    throw new InvalidParameterException();
                }
            } else { // <crypto_service>.<algorithm_or_type> <attribute_name>
                if (val.length() == 0) {
                    throw new InvalidParameterException();
                }
                attribute = key.substring(i + 1);
                if (attribute.trim().length() == 0) {
                    throw new InvalidParameterException();
                }
                key = key.substring(0, i);
            }
            String serv = key.substring(0, j);
            String alg = key.substring(j + 1);
            if (serv.length() == 0 || alg.length() == 0) {
                throw new InvalidParameterException();
            }
            filterProviders(result, serv, alg, attribute, val);
        }
        if (result.size() > 0) {
            return result.toArray(new Provider[result.size()]);
        }
        return null;
    }

    private static void filterProviders(ArrayList<Provider> providers, String service,
            String algorithm, String attribute, String attrValue) {
        Iterator<Provider> it = providers.iterator();
        while (it.hasNext()) {
            Provider p = it.next();
            if (!p.implementsAlg(service, algorithm, attribute, attrValue)) {
                it.remove();
            }
        }
    }

    /**
     * Returns the value of the security property named by the argument.
     *
     * @param key
     *            the name of the requested security property.
     * @return the value of the security property.
     */
    public static String getProperty(String key) {
        if (key == null) {
            throw new NullPointerException("key == null");
        }
        String property = secprops.getProperty(key);
        if (property != null) {
            property = property.trim();
        }
        return property;
    }

    /**
     * Sets the value of the specified security property.
     */
    public static void setProperty(String key, String value) {
        Services.setNeedRefresh();
        secprops.put(key, value);
    }

    /**
     * Returns a {@code Set} of all registered algorithms for the specified
     * cryptographic service. {@code "Signature"}, {@code "Cipher"} and {@code
     * "KeyStore"} are examples for such kind of services.
     *
     * @param serviceName
     *            the case-insensitive name of the service.
     * @return a {@code Set} of all registered algorithms for the specified
     *         cryptographic service, or an empty {@code Set} if {@code
     *         serviceName} is {@code null} or if no registered provider
     *         provides the requested service.
     */
    public static Set<String> getAlgorithms(String serviceName) {
        Set<String> result = new HashSet<String>();
        // compatibility with RI
        if (serviceName == null) {
            return result;
        }
        for (Provider provider : getProviders()) {
            for (Provider.Service service: provider.getServices()) {
                if (service.getType().equalsIgnoreCase(serviceName)) {
                    result.add(service.getAlgorithm());
                }
            }
        }
        return result;
    }

    /**
     *
     * Update sequence numbers of all providers.
     *
     */
    private static void renumProviders() {
        ArrayList<Provider> providers = Services.getProviders();
        for (int i = 0; i < providers.size(); i++) {
            providers.get(i).setProviderNumber(i + 1);
        }
    }

    private static class SecurityDoor implements SecurityAccess {
        // Access to Security.renumProviders()
        public void renumProviders() {
            Security.renumProviders();
        }

        //  Access to Security.getAliases()
        public List<String> getAliases(Provider.Service s) {
            return s.getAliases();
        }

        // Access to Provider.getService()
        public Provider.Service getService(Provider p, String type) {
            return p.getService(type);
        }
    }
}
