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 23package org.apache.harmony.security.fortress; 24 25import java.security.AccessController; 26import java.security.PrivilegedAction; 27import java.security.Provider; 28import java.security.Security; 29import java.util.ArrayList; 30import java.util.HashMap; 31import java.util.List; 32import java.util.Map; 33import org.apache.harmony.security.Util; 34 35 36/** 37 * This class contains information about all registered providers and preferred 38 * implementations for all "serviceName.algName". 39 * 40 */ 41 42public class Services { 43 44 // The HashMap that contains information about preferred implementations for 45 // all serviceName.algName in the registered providers 46 // BEGIN android-changed 47 // set the initial size to 600 so we don't grow to 1024 by default because 48 // initialization adds a few entries more than the growth threshold. 49 private static final Map<String, Provider.Service> services 50 = new HashMap<String, Provider.Service>(600); 51 // save default SecureRandom service as well. 52 // avoids similar provider/services iteration in SecureRandom constructor 53 private static Provider.Service secureRandom; 54 // END android-changed 55 56 // Need refresh flag 57 private static boolean needRefresh; // = false; 58 59 /** 60 * Refresh number 61 */ 62 static int refreshNumber = 1; 63 64 // Registered providers 65 private static final List<Provider> providers = new ArrayList<Provider>(20); 66 67 // Hash for quick provider access by name 68 private static final Map<String, Provider> providersNames = new HashMap<String, Provider>(20); 69 70 static { 71 AccessController.doPrivileged(new PrivilegedAction<Object>() { 72 public Object run() { 73 loadProviders(); 74 return null; 75 } 76 }); 77 } 78 79 // Load statically registered providers and init Services Info 80 private static void loadProviders() { 81 String providerClassName = null; 82 int i = 1; 83 ClassLoader cl = ClassLoader.getSystemClassLoader(); 84 Provider p; 85 86 while ((providerClassName = Security.getProperty("security.provider." 87 + i++)) != null) { 88 try { 89 p = (Provider) Class 90 .forName(providerClassName.trim(), true, cl) 91 .newInstance(); 92 providers.add(p); 93 providersNames.put(p.getName(), p); 94 initServiceInfo(p); 95 } catch (ClassNotFoundException e) { // ignore Exceptions 96 } catch (IllegalAccessException e) { 97 } catch (InstantiationException e) { 98 } 99 } 100 Engine.door.renumProviders(); 101 } 102 103 /** 104 * Returns registered providers 105 * 106 * @return 107 */ 108 public static Provider[] getProviders() { 109 return providers.toArray(new Provider[providers.size()]); 110 } 111 112 /** 113 * Returns registered providers as List 114 * 115 * @return 116 */ 117 public static List<Provider> getProvidersList() { 118 return new ArrayList<Provider>(providers); 119 } 120 121 /** 122 * Returns the provider with the specified name 123 * 124 * @param name 125 * @return 126 */ 127 public static Provider getProvider(String name) { 128 if (name == null) { 129 return null; 130 } 131 return providersNames.get(name); 132 } 133 134 /** 135 * Inserts a provider at a specified position 136 * 137 * @param provider 138 * @param position 139 * @return 140 */ 141 public static int insertProviderAt(Provider provider, int position) { 142 int size = providers.size(); 143 if ((position < 1) || (position > size)) { 144 position = size + 1; 145 } 146 providers.add(position - 1, provider); 147 providersNames.put(provider.getName(), provider); 148 setNeedRefresh(); 149 return position; 150 } 151 152 /** 153 * Removes the provider 154 * 155 * @param providerNumber 156 */ 157 public static void removeProvider(int providerNumber) { 158 Provider p = providers.remove(providerNumber - 1); 159 providersNames.remove(p.getName()); 160 setNeedRefresh(); 161 } 162 163 /** 164 * 165 * Adds information about provider services into HashMap. 166 * 167 * @param p 168 */ 169 public static void initServiceInfo(Provider p) { 170 StringBuilder sb = new StringBuilder(128); 171 172 for (Provider.Service serv : p.getServices()) { 173 String type = serv.getType(); 174 if (secureRandom == null && type.equals("SecureRandom")) { 175 secureRandom = serv; 176 } 177 sb.delete(0, sb.length()); 178 String key = sb.append(type).append(".").append( 179 Util.toUpperCase(serv.getAlgorithm())).toString(); 180 if (!services.containsKey(key)) { 181 services.put(key, serv); 182 } 183 for (String alias : Engine.door.getAliases(serv)) { 184 sb.delete(0, sb.length()); 185 key = sb.append(type).append(".").append(Util.toUpperCase(alias)) 186 .toString(); 187 if (!services.containsKey(key)) { 188 services.put(key, serv); 189 } 190 } 191 } 192 } 193 194 /** 195 * 196 * Updates services hashtable for all registered providers 197 * 198 */ 199 public static void updateServiceInfo() { 200 services.clear(); 201 secureRandom = null; 202 for (Provider p : providers) { 203 initServiceInfo(p); 204 } 205 needRefresh = false; 206 } 207 208 /** 209 * Returns true if services contain any provider information 210 * @return 211 */ 212 public static boolean isEmpty() { 213 return services.isEmpty(); 214 } 215 216 /** 217 * Returns service description. 218 * Call refresh() before. 219 * 220 * @param key in the format TYPE.ALGORITHM 221 * @return 222 */ 223 public static Provider.Service getService(String key) { 224 return services.get(key); 225 } 226 227 /** 228 * Returns the default SecureRandom service description. 229 * Call refresh() before. 230 */ 231 public static Provider.Service getSecureRandomService() { 232 return secureRandom; 233 } 234 235 /** 236 * Set flag needRefresh 237 * 238 */ 239 public static void setNeedRefresh() { 240 needRefresh = true; 241 } 242 243 /** 244 * Refresh services info 245 * 246 */ 247 public static void refresh() { 248 if (needRefresh) { 249 refreshNumber++; 250 updateServiceInfo(); 251 } 252 } 253} 254