/*
* 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();
}
}
} |