Home | History | Annotate | Download | only in fortress
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 /**
     19 * @author Boris V. Kuznetsov
     20 * @version $Revision$
     21 */
     22 
     23 package org.apache.harmony.security.fortress;
     24 
     25 import java.security.Provider;
     26 import java.security.Security;
     27 import java.util.ArrayList;
     28 import java.util.HashMap;
     29 import java.util.List;
     30 import java.util.Locale;
     31 import java.util.Map;
     32 
     33 
     34 /**
     35  * This class contains information about all registered providers and preferred
     36  * implementations for all "serviceName.algName".
     37  *
     38  */
     39 
     40 public class Services {
     41 
     42     // The HashMap that contains information about preferred implementations for
     43     // all serviceName.algName in the registered providers.
     44     // Set the initial size to 600 so we don't grow to 1024 by default because
     45     // initialization adds a few entries more than the growth threshold.
     46     private static final Map<String, Provider.Service> services
     47             = new HashMap<String, Provider.Service>(600);
     48     // Save default SecureRandom service as well.
     49     // Avoids similar provider/services iteration in SecureRandom constructor
     50     private static Provider.Service secureRandom;
     51 
     52     // Need refresh flag
     53     private static boolean needRefresh; // = false;
     54 
     55     /**
     56      * Refresh number
     57      */
     58     static int refreshNumber = 1;
     59 
     60     // Registered providers
     61     private static final List<Provider> providers = new ArrayList<Provider>(20);
     62 
     63     // Hash for quick provider access by name
     64     private static final Map<String, Provider> providersNames = new HashMap<String, Provider>(20);
     65     static {
     66         loadProviders();
     67     }
     68 
     69     // Load statically registered providers and init Services Info
     70     private static void loadProviders() {
     71         String providerClassName = null;
     72         int i = 1;
     73         ClassLoader cl = ClassLoader.getSystemClassLoader();
     74         Provider p;
     75 
     76         while ((providerClassName = Security.getProperty("security.provider."
     77                 + i++)) != null) {
     78             try {
     79                 p = (Provider) Class
     80                         .forName(providerClassName.trim(), true, cl)
     81                         .newInstance();
     82                 providers.add(p);
     83                 providersNames.put(p.getName(), p);
     84                 initServiceInfo(p);
     85             } catch (ClassNotFoundException e) { // ignore Exceptions
     86             } catch (IllegalAccessException e) {
     87             } catch (InstantiationException e) {
     88             }
     89         }
     90         Engine.door.renumProviders();
     91     }
     92 
     93     /**
     94      * Returns registered providers
     95      *
     96      * @return
     97      */
     98     public static Provider[] getProviders() {
     99         return providers.toArray(new Provider[providers.size()]);
    100     }
    101 
    102     /**
    103      * Returns registered providers as List
    104      *
    105      * @return
    106      */
    107     public static List<Provider> getProvidersList() {
    108         return new ArrayList<Provider>(providers);
    109     }
    110 
    111     /**
    112      * Returns the provider with the specified name
    113      *
    114      * @param name
    115      * @return
    116      */
    117     public static Provider getProvider(String name) {
    118         if (name == null) {
    119             return null;
    120         }
    121         return providersNames.get(name);
    122     }
    123 
    124     /**
    125      * Inserts a provider at a specified position
    126      *
    127      * @param provider
    128      * @param position
    129      * @return
    130      */
    131     public static int insertProviderAt(Provider provider, int position) {
    132         int size = providers.size();
    133         if ((position < 1) || (position > size)) {
    134             position = size + 1;
    135         }
    136         providers.add(position - 1, provider);
    137         providersNames.put(provider.getName(), provider);
    138         setNeedRefresh();
    139         return position;
    140     }
    141 
    142     /**
    143      * Removes the provider
    144      *
    145      * @param providerNumber
    146      */
    147     public static void removeProvider(int providerNumber) {
    148         Provider p = providers.remove(providerNumber - 1);
    149         providersNames.remove(p.getName());
    150         setNeedRefresh();
    151     }
    152 
    153     /**
    154      *
    155      * Adds information about provider services into HashMap.
    156      *
    157      * @param p
    158      */
    159     public static void initServiceInfo(Provider p) {
    160         for (Provider.Service serv : p.getServices()) {
    161             String type = serv.getType();
    162             if (secureRandom == null && type.equals("SecureRandom")) {
    163                 secureRandom = serv;
    164             }
    165             String key = type + "." + serv.getAlgorithm().toUpperCase(Locale.US);
    166             if (!services.containsKey(key)) {
    167                 services.put(key, serv);
    168             }
    169             for (String alias : Engine.door.getAliases(serv)) {
    170                 key = type + "." + alias.toUpperCase(Locale.US);
    171                 if (!services.containsKey(key)) {
    172                     services.put(key, serv);
    173                 }
    174             }
    175         }
    176     }
    177 
    178     /**
    179      *
    180      * Updates services hashtable for all registered providers
    181      *
    182      */
    183     public static void updateServiceInfo() {
    184         services.clear();
    185         secureRandom = null;
    186         for (Provider p : providers) {
    187             initServiceInfo(p);
    188         }
    189         needRefresh = false;
    190     }
    191 
    192     /**
    193      * Returns true if services contain any provider information
    194      * @return
    195      */
    196     public static boolean isEmpty() {
    197         return services.isEmpty();
    198     }
    199 
    200     /**
    201      * Returns service description.
    202      * Call refresh() before.
    203      *
    204      * @param key in the format TYPE.ALGORITHM
    205      * @return
    206      */
    207     public static Provider.Service getService(String key) {
    208         return services.get(key);
    209     }
    210 
    211     /**
    212      * Returns the default SecureRandom service description.
    213      * Call refresh() before.
    214      */
    215     public static Provider.Service getSecureRandomService() {
    216         return secureRandom;
    217     }
    218 
    219     /**
    220      * Set flag needRefresh
    221      *
    222      */
    223     public static void setNeedRefresh() {
    224         needRefresh = true;
    225     }
    226 
    227     /**
    228      * Refresh services info
    229      *
    230      */
    231     public static void refresh() {
    232         if (needRefresh) {
    233             refreshNumber++;
    234             updateServiceInfo();
    235         }
    236     }
    237 }
    238