• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
loadProviders()66         loadProviders();
67     }
68 
69     // Load statically registered providers and init Services Info
loadProviders()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      */
getProviders()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      */
getProvidersList()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      */
getProvider(String name)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      */
insertProviderAt(Provider provider, int position)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      */
removeProvider(int providerNumber)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      */
initServiceInfo(Provider p)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      */
updateServiceInfo()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      */
isEmpty()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      */
getService(String key)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      */
getSecureRandomService()215     public static Provider.Service getSecureRandomService() {
216         return secureRandom;
217     }
218 
219     /**
220      * Set flag needRefresh
221      *
222      */
setNeedRefresh()223     public static void setNeedRefresh() {
224         needRefresh = true;
225     }
226 
227     /**
228      * Refresh services info
229      *
230      */
refresh()231     public static void refresh() {
232         if (needRefresh) {
233             refreshNumber++;
234             updateServiceInfo();
235         }
236     }
237 }
238