FileDocCategorySizeDatePackage
Services.javaAPI DocAndroid 1.5 API7312Wed May 06 22:41:06 BST 2009org.apache.harmony.security.fortress

Services.java

/*
 *  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.
 */

/**
* @author Boris V. Kuznetsov
* @version $Revision$
*/

package org.apache.harmony.security.fortress;

import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.Provider;
import java.security.Security;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * This class contains information about all registered providers and preferred
 * implementations for all "serviceName.algName".
 * 
 */

public class Services {

    // The HashMap that contains information about preferred implementations for
    // all serviceName.algName in the registered providers
    // BEGIN android-changed
    // set the initial size to 600 so we don't grow to 1024 by default because
    // initialization adds a few entries more than the growth threshold.
    private static final Map<String, Provider.Service> services = new HashMap<String, Provider.Service>(600);
    // END android-changed

    // Need refresh flag
    private static boolean needRefresh; // = false;

    /**
     * Refresh number
     */
    public static int refreshNumber = 1;

    // Registered providers
    private static final List<Provider> providers = new ArrayList<Provider>(20);

    // Hash for quick provider access by name
    private static final Map<String, Provider> providersNames = new HashMap<String, Provider>(20);

    static {
        AccessController.doPrivileged(new PrivilegedAction<Object>() {
            public Object run() {
                loadProviders();
                return null;
            }
        });
    }

    // Load statically registered providers and init Services Info
    private static void loadProviders() {
        String providerClassName = null;
        int i = 1;
        ClassLoader cl = ClassLoader.getSystemClassLoader();
        Provider p;

        while ((providerClassName = Security.getProperty("security.provider." //$NON-NLS-1$
                + i++)) != null) {
            try {
                p = (Provider) Class
                        .forName(providerClassName.trim(), true, cl)
                        .newInstance();
                providers.add(p);
                providersNames.put(p.getName(), p);
                initServiceInfo(p);
            } catch (Exception e) { // ignore
            }
        }
        Engine.door.renumProviders();
    }

    /**
     * Returns registered providers
     * 
     * @return
     */
    public static Provider[] getProviders() {
        return providers.toArray(new Provider[providers.size()]);
    }

    /**
     * Returns registered providers as List
     * 
     * @return
     */
    public static List<Provider> getProvidersList() {
        return new ArrayList<Provider>(providers);
    }

    /**
     * Returns the provider with the specified name
     * 
     * @param name
     * @return
     */
    public static Provider getProvider(String name) {
        if (name == null) {
            return null;
        }
        return providersNames.get(name);
    }

    /**
     * Inserts a provider at a specified position
     * 
     * @param provider
     * @param position
     * @return
     */
    public static int insertProviderAt(Provider provider, int position) {
        int size = providers.size();
        if ((position < 1) || (position > size)) {
            position = size + 1;
        }
        providers.add(position - 1, provider);
        providersNames.put(provider.getName(), provider);
        setNeedRefresh();
        return position;
    }

    /**
     * Removes the provider
     * 
     * @param providerNumber
     */
    public static void removeProvider(int providerNumber) {
        Provider p = providers.remove(providerNumber - 1);
        providersNames.remove(p.getName());
        setNeedRefresh();
    }

    /**
     * 
     * Adds information about provider services into HashMap.
     * 
     * @param p
     */
    public static void initServiceInfo(Provider p) {
        Provider.Service serv;
        String key;
        String type;
        String alias;
        StringBuffer sb = new StringBuffer(128);

        for (Iterator<Provider.Service> it1 = p.getServices().iterator(); it1.hasNext();) {
            serv = it1.next();
            type = serv.getType();
            sb.delete(0, sb.length());
            key = sb.append(type).append(".").append( //$NON-NLS-1$
                    serv.getAlgorithm().toUpperCase()).toString();
            if (!services.containsKey(key)) {
                services.put(key, serv);
            }
            for (Iterator<String> it2 = Engine.door.getAliases(serv); it2.hasNext();) {
                alias = it2.next();
                sb.delete(0, sb.length());
                key = sb.append(type).append(".").append(alias.toUpperCase()) //$NON-NLS-1$
                        .toString();
                if (!services.containsKey(key)) {
                    services.put(key, serv);
                }
            }
        }
    }

    /**
     * 
     * Updates services hashtable for all registered providers
     *  
     */
    public static void updateServiceInfo() {
        services.clear();
        for (Iterator<Provider> it = providers.iterator(); it.hasNext();) {
            initServiceInfo(it.next());
        }
        needRefresh = false;
    }

    /**
     * Returns true if services contain any provider information  
     * @return
     */
    public static boolean isEmpty() {
        return services.isEmpty();
    }
    
    /**
     * 
     * Returns service description.
     * Call refresh() before.
     * 
     * @param key
     * @return
     */
    public static Provider.Service getService(String key) {
        return services.get(key);
    }

    /**
     * Prints Services content  
     */
    // FIXME remove debug function
    public static void printServices() {
        refresh();
        Set<String> s = services.keySet();
        for (Iterator<String> i = s.iterator(); i.hasNext();) {
            String key = i.next();
            System.out.println(key + "=" + services.get(key)); //$NON-NLS-1$
        }
    }

    /**
     * Set flag needRefresh 
     *
     */
    public static void setNeedRefresh() {
        needRefresh = true;
    }

    /**
     * Refresh services info
     *
     */
    public static void refresh() {
        if (needRefresh) {
            refreshNumber++;
            updateServiceInfo();
        }
    }
}