1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.security;
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InputStream;
222f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughesimport java.io.NotActiveException;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.ArrayList;
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Collection;
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Collections;
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Enumeration;
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.HashMap;
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Iterator;
29fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstromimport java.util.LinkedHashMap;
30fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstromimport java.util.LinkedHashSet;
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.List;
32a695e8fafadd2591cd148e78f19bc6d7c15121bbJesse Wilsonimport java.util.Locale;
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Map;
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Properties;
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Set;
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.fortress.Services;
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code Provider} is the abstract superclass for all security providers in the
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Java security infrastructure.
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic abstract class Provider extends Properties {
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final long serialVersionUID = -4298000515446427739L;
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private String name;
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private double version;
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // String representation of the provider version number.
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient String versionString;
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private String info;
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
54f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    //The provider preference order number.
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Equals -1 for non registered provider.
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient int providerNumber = -1;
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Contains "Service.Algorithm" and Provider.Service classes added using
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // putService()
60fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom    private transient LinkedHashMap<String, Service> serviceTable;
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Contains "Service.Alias" and Provider.Service classes added using
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // putService()
64fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom    private transient LinkedHashMap<String, Service> aliasTable;
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Contains "Service.Algorithm" and Provider.Service classes added using
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // put()
68fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom    private transient LinkedHashMap<String, Service> propertyServiceTable;
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Contains "Service.Alias" and Provider.Service classes added using put()
71fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom    private transient LinkedHashMap<String, Service> propertyAliasTable;
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // The properties changed via put()
74adb4135674a4de82cabbff3b0e24f6e944ba33e3Kenny Root    private transient LinkedHashMap<Object, Object> changedProperties;
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // For getService(String type, String algorithm) optimization:
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // previous result
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient Provider.Service returnedService;
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // previous parameters
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient String lastAlgorithm;
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // last name
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient String lastServiceName;
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // For getServices() optimization:
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient Set<Service> lastServicesSet;
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // For getService(String type) optimization:
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient String lastType;
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // last Service found by type
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient Provider.Service lastServicesByType;
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new instance of {@code Provider} with its name, version and
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * description.
952f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes     *
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param name
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the name of the provider.
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param version
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the version of the provider.
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param info
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a description of the provider.
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected Provider(String name, double version, String info) {
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.name = name;
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.version = version;
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.info = info;
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        versionString = String.valueOf(version);
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        putProviderInfo();
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the name of this provider.
1132f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes     *
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the name of this provider.
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String getName() {
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return name;
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the version number for the services being provided.
1222f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes     *
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the version number for the services being provided.
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public double getVersion() {
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return version;
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a description of the services being provided.
1312f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes     *
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a description of the services being provided.
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String getInfo() {
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return info;
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a string containing a concise, human-readable description of
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * this {@code Provider} including its name and its version.
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a printable representation for this {@code Provider}.
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1442f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes    @Override
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String toString() {
146f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        return name + " version " + version;
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Clears all properties used to look up services implemented by this
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code Provider}.
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1532f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes    @Override
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized void clear() {
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super.clear();
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (serviceTable != null) {
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            serviceTable.clear();
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (propertyServiceTable != null) {
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            propertyServiceTable.clear();
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (aliasTable != null) {
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            aliasTable.clear();
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (propertyAliasTable != null) {
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            propertyAliasTable.clear();
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        changedProperties = null;
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        putProviderInfo();
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (providerNumber != -1) {
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // if registered then refresh Services
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Services.setNeedRefresh();
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        servicesChanged();
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1772f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes    @Override
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized void load(InputStream inStream) throws IOException {
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Properties tmp = new Properties();
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        tmp.load(inStream);
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        myPutAll(tmp);
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Copies all from the provided map to this {@code Provider}.
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param t
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the mappings to copy to this provider.
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1892f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes    @Override
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized void putAll(Map<?,?> t) {
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        myPutAll(t);
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void myPutAll(Map<?,?> t) {
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (changedProperties == null) {
196adb4135674a4de82cabbff3b0e24f6e944ba33e3Kenny Root            changedProperties = new LinkedHashMap<Object, Object>();
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Iterator<? extends Map.Entry<?, ?>> it = t.entrySet().iterator();
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Object key;
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Object value;
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while (it.hasNext()) {
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Map.Entry<?, ?> entry = it.next();
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            key = entry.getKey();
204f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            if (key instanceof String && ((String) key).startsWith("Provider.")) {
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // Provider service type is reserved
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                continue;
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            value = entry.getValue();
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            super.put(key, value);
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (changedProperties.remove(key) == null) {
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                removeFromPropertyServiceTable(key);
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            changedProperties.put(key, value);
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (providerNumber != -1) {
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // if registered then refresh Services
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Services.setNeedRefresh();
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
2212f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes    @Override
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized Set<Map.Entry<Object,Object>> entrySet() {
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return Collections.unmodifiableSet(super.entrySet());
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
2262f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes    @Override
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Set<Object> keySet() {
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return Collections.unmodifiableSet(super.keySet());
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
2312f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes    @Override
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Collection<Object> values() {
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return Collections.unmodifiableCollection(super.values());
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Maps the specified {@code key} property name to the specified {@code
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * value}.
2392f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes     *
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param key
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the name of the property.
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param value
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the value of the property.
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the value that was previously mapped to the specified {@code key}
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         ,or {@code null} if it did not have one.
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
2472f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes    @Override
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized Object put(Object key, Object value) {
249f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        if (key instanceof String && ((String) key).startsWith("Provider.")) {
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Provider service type is reserved
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (providerNumber != -1) {
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // if registered then refresh Services
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Services.setNeedRefresh();
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (changedProperties != null && changedProperties.remove(key) == null) {
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            removeFromPropertyServiceTable(key);
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (changedProperties == null) {
261adb4135674a4de82cabbff3b0e24f6e944ba33e3Kenny Root            changedProperties = new LinkedHashMap<Object, Object>();
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        changedProperties.put(key, value);
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return super.put(key, value);
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Removes the specified {@code key} and its associated value from this
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code Provider}.
2702f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes     *
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param key
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the name of the property
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the value that was mapped to the specified {@code key} ,or
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         {@code null} if no mapping was present
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
2762f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes    @Override
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized Object remove(Object key) {
278f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        if (key instanceof String && ((String) key).startsWith("Provider.")) {
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Provider service type is reserved
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (providerNumber != -1) {
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // if registered then refresh Services
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Services.setNeedRefresh();
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (changedProperties != null && changedProperties.remove(key) == null) {
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            removeFromPropertyServiceTable(key);
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (changedProperties.size() == 0) {
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                changedProperties = null;
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return super.remove(key);
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
2962f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes     * Returns true if this provider implements the given algorithm. Caller
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * must specify the cryptographic service and specify constraints via the
2982f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes     * attribute name and value.
299f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param serv
301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            Crypto service.
302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param alg
303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            Algorithm or type.
304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param attribute
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            The attribute name or {@code null}.
306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param val
307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            The attribute value.
308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    boolean implementsAlg(String serv, String alg, String attribute, String val) {
311f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        String servAlg = serv + "." + alg;
312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String prop = getPropertyIgnoreCase(servAlg);
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (prop == null) {
314f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            alg = getPropertyIgnoreCase("Alg.Alias." + servAlg);
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (alg != null) {
316f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                servAlg = serv + "." + alg;
3172f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes                prop = getPropertyIgnoreCase(servAlg);
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (prop != null) {
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (attribute == null) {
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return true;
323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
3242f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes            return checkAttribute(servAlg, attribute, val);
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return false;
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
329a695e8fafadd2591cd148e78f19bc6d7c15121bbJesse Wilson    /**
330a695e8fafadd2591cd148e78f19bc6d7c15121bbJesse Wilson     * Returns true if this provider has the same value as is given for the
331a695e8fafadd2591cd148e78f19bc6d7c15121bbJesse Wilson     * given attribute
332a695e8fafadd2591cd148e78f19bc6d7c15121bbJesse Wilson     */
333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean checkAttribute(String servAlg, String attribute, String val) {
334f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String attributeValue = getPropertyIgnoreCase(servAlg + ' ' + attribute);
336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (attributeValue != null) {
337a695e8fafadd2591cd148e78f19bc6d7c15121bbJesse Wilson            if (attribute.equalsIgnoreCase("KeySize")) {
338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (Integer.parseInt(attributeValue) >= Integer.parseInt(val)) {
339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return true;
340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else { // other attributes
342a695e8fafadd2591cd148e78f19bc6d7c15121bbJesse Wilson                if (attributeValue.equalsIgnoreCase(val)) {
343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return true;
344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return false;
348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
351f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Set the provider preference order number.
353f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param n
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    void setProviderNumber(int n) {
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        providerNumber = n;
358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
361f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Get the provider preference order number.
363f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return
365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    int getProviderNumber() {
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return providerNumber;
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
3718c75589cba8b490e9cbc479ce2129ccf480be8f3Kenny Root     * Get the service of the specified {@code type} (e.g. "SecureRandom",
3728c75589cba8b490e9cbc479ce2129ccf480be8f3Kenny Root     * "Signature").
373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    synchronized Provider.Service getService(String type) {
375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        updatePropertyServiceTable();
376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (lastServicesByType != null && type.equals(lastType)) {
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return lastServicesByType;
378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Provider.Service service;
380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (Iterator<Service> it = getServices().iterator(); it.hasNext();) {
381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            service = it.next();
382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (type.equals(service.type)) {
383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                lastType = type;
384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                lastServicesByType = service;
385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return service;
386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return null;
389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the service with the specified {@code type} implementing the
393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * specified {@code algorithm}, or {@code null} if no such implementation
394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * exists.
395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * If two services match the requested type and algorithm, the one added
397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * with the {@link #putService(Service)} is returned (as opposed to the one
398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * added via {@link #put(Object, Object)}.
3992f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes     *
400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param type
401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the type of the service (for example {@code KeyPairGenerator})
402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param algorithm
403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the algorithm name (case insensitive)
404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the requested service, or {@code null} if no such implementation
405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         exists
406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized Provider.Service getService(String type,
408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            String algorithm) {
40986acc043d3334651ee26c65467d78d6cefedd397Kenny Root        if (type == null) {
41086acc043d3334651ee26c65467d78d6cefedd397Kenny Root            throw new NullPointerException("type == null");
41186acc043d3334651ee26c65467d78d6cefedd397Kenny Root        } else if (algorithm == null) {
41286acc043d3334651ee26c65467d78d6cefedd397Kenny Root            throw new NullPointerException("algorithm == null");
413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
415a695e8fafadd2591cd148e78f19bc6d7c15121bbJesse Wilson        if (type.equals(lastServiceName) && algorithm.equalsIgnoreCase(lastAlgorithm)) {
416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return returnedService;
417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
419fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom        String key = key(type, algorithm);
420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Object o = null;
421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (serviceTable != null) {
422fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom            o = serviceTable.get(key);
423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (o == null && aliasTable != null) {
425fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom            o = aliasTable.get(key);
426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (o == null) {
428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            updatePropertyServiceTable();
429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (o == null && propertyServiceTable != null) {
431fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom            o = propertyServiceTable.get(key);
432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (o == null && propertyAliasTable != null) {
434fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom            o = propertyAliasTable.get(key);
435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (o != null) {
438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            lastServiceName = type;
439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            lastAlgorithm = algorithm;
440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            returnedService = (Provider.Service) o;
441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return returnedService;
442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return null;
444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns an unmodifiable {@code Set} of all services registered by this
448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * provider.
4492f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes     *
450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an unmodifiable {@code Set} of all services registered by this
451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         provider
452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized Set<Provider.Service> getServices() {
454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        updatePropertyServiceTable();
455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (lastServicesSet != null) {
456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return lastServicesSet;
457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (serviceTable != null) {
459fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom            lastServicesSet = new LinkedHashSet<Service>(serviceTable.values());
460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
461fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom            lastServicesSet = new LinkedHashSet<Service>();
462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (propertyServiceTable != null) {
464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            lastServicesSet.addAll(propertyServiceTable.values());
465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        lastServicesSet = Collections.unmodifiableSet(lastServicesSet);
467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return lastServicesSet;
468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Adds a {@code Service} to this {@code Provider}. If a service with the
472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * same name was registered via this method, it is replace.
4732f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes     *
474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param s
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code Service} to register
476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected synchronized void putService(Provider.Service s) {
478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (s == null) {
47986acc043d3334651ee26c65467d78d6cefedd397Kenny Root            throw new NullPointerException("s == null");
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
48112cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom        if ("Provider".equals(s.getType())) { // Provider service type cannot be added
482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        servicesChanged();
485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (serviceTable == null) {
486fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom            serviceTable = new LinkedHashMap<String, Service>(128);
487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
488fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom        serviceTable.put(key(s.type, s.algorithm), s);
489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (s.aliases != null) {
490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (aliasTable == null) {
491fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                aliasTable = new LinkedHashMap<String, Service>(256);
492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
49312cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom            for (String alias : s.getAliases()) {
494fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                aliasTable.put(key(s.type, alias), s);
495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        serviceInfoToProperties(s);
498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Removes a previously registered {@code Service} from this {@code
502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Provider}.
5032f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes     *
504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param s
505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code Service} to remove
506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NullPointerException
507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code s} is {@code null}
508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected synchronized void removeService(Provider.Service s) {
510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (s == null) {
51186acc043d3334651ee26c65467d78d6cefedd397Kenny Root            throw new NullPointerException("s == null");
512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        servicesChanged();
514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (serviceTable != null) {
515fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom            serviceTable.remove(key(s.type, s.algorithm));
516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (aliasTable != null && s.aliases != null) {
51812cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom            for (String alias: s.getAliases()) {
519fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                aliasTable.remove(key(s.type, alias));
520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        serviceInfoFromProperties(s);
523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
52512cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom    /**
52612cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom     * Add Service information to the provider's properties.
52712cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom     */
528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void serviceInfoToProperties(Provider.Service s) {
529f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        super.put(s.type + "." + s.algorithm, s.className);
530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (s.aliases != null) {
531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (Iterator<String> i = s.aliases.iterator(); i.hasNext();) {
532f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                super.put("Alg.Alias." + s.type + "." + i.next(), s.algorithm);
533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (s.attributes != null) {
53612cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom            for (Map.Entry<String, String> entry : s.attributes.entrySet()) {
537f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                super.put(s.type + "." + s.algorithm + " " + entry.getKey(),
538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        entry.getValue());
539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (providerNumber != -1) {
542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // if registered then refresh Services
543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Services.setNeedRefresh();
544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
54712cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom    /**
54812cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom     * Remove Service information from the provider's properties.
54912cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom     */
550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void serviceInfoFromProperties(Provider.Service s) {
551f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        super.remove(s.type + "." + s.algorithm);
552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (s.aliases != null) {
553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (Iterator<String> i = s.aliases.iterator(); i.hasNext();) {
554f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                super.remove("Alg.Alias." + s.type + "." + i.next());
555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (s.attributes != null) {
55812cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom            for (Map.Entry<String, String> entry : s.attributes.entrySet()) {
559f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                super.remove(s.type + "." + s.algorithm + " " + entry.getKey());
560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (providerNumber != -1) {
563adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // if registered then refresh Services
564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Services.setNeedRefresh();
565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Remove property information from provider Services
569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void removeFromPropertyServiceTable(Object key) {
570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (key == null || !(key instanceof String)) {
571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String k = (String) key;
574f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        if (k.startsWith("Provider.")) { // Provider service type is reserved
575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Provider.Service s;
578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String serviceName;
579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String algorithm = null;
580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String attribute = null;
581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int i;
582f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        if (k.startsWith("Alg.Alias.")) { // Alg.Alias.<crypto_service>.<aliasName>=<standardName>
583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            String aliasName;
584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            String service_alias = k.substring(10);
5852f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes            i = service_alias.indexOf('.');
586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            serviceName = service_alias.substring(0, i);
587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            aliasName = service_alias.substring(i + 1);
588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (propertyAliasTable != null) {
589fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                propertyAliasTable.remove(key(serviceName, aliasName));
590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (propertyServiceTable != null) {
592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                for (Iterator<Service> it = propertyServiceTable.values().iterator(); it
593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        .hasNext();) {
594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    s = it.next();
595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (s.aliases.contains(aliasName)) {
596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        s.aliases.remove(aliasName);
597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return;
598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
601adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
6032f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes        int j = k.indexOf('.');
604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (j == -1) { // unknown format
605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
6082f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes        i = k.indexOf(' ');
609adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (i == -1) { // <crypto_service>.<algorithm_or_type>=<className>
610adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            serviceName = k.substring(0, j);
611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            algorithm = k.substring(j + 1);
612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (propertyServiceTable != null) {
613fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                Provider.Service ser = propertyServiceTable.remove(key(serviceName, algorithm));
614adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (ser != null && propertyAliasTable != null
615adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        && ser.aliases != null) {
616a695e8fafadd2591cd148e78f19bc6d7c15121bbJesse Wilson                    for (String alias : ser.aliases) {
617fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                        propertyAliasTable.remove(key(serviceName, alias));
618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
62112cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom        } else {
62212cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom            // <crypto_service>.<algorithm_or_type>
62312cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom            // <attribute_name>=<attrValue>
624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            attribute = k.substring(i + 1);
625adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            serviceName = k.substring(0, j);
626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            algorithm = k.substring(j + 1, i);
627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (propertyServiceTable != null) {
628fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                Object o = propertyServiceTable.get(key(serviceName, algorithm));
629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (o != null) {
630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    s = (Provider.Service) o;
631adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    s.attributes.remove(attribute);
632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
633adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Update provider Services if the properties was changed
638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void updatePropertyServiceTable() {
639adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Object _key;
640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Object _value;
641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Provider.Service s;
642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String serviceName;
643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String algorithm;
644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (changedProperties == null || changedProperties.isEmpty()) {
645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (Iterator<Map.Entry<Object, Object>> it = changedProperties.entrySet().iterator(); it
648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                .hasNext();) {
649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Map.Entry<Object, Object> entry = it.next();
650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            _key = entry.getKey();
651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            _value = entry.getValue();
652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (_key == null || _value == null || !(_key instanceof String)
653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    || !(_value instanceof String)) {
654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                continue;
655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            String key = (String) _key;
657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            String value = (String) _value;
65812cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom            if (key.startsWith("Provider")) {
65912cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom                // Provider service type is reserved
660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                continue;
661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int i;
66312cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom            if (key.startsWith("Alg.Alias.")) {
66412cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom                // Alg.Alias.<crypto_service>.<aliasName>=<standardName>
665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                String aliasName;
666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                String service_alias = key.substring(10);
6672f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes                i = service_alias.indexOf('.');
668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                serviceName = service_alias.substring(0, i);
669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                aliasName = service_alias.substring(i + 1);
670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                algorithm = value;
671fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                String propertyServiceTableKey = key(serviceName, algorithm);
672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                Object o = null;
673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (propertyServiceTable == null) {
674fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                    propertyServiceTable = new LinkedHashMap<String, Service>(128);
675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
676fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                    o = propertyServiceTable.get(propertyServiceTableKey);
677adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (o != null) {
679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    s = (Provider.Service) o;
680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    s.addAlias(aliasName);
681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (propertyAliasTable == null) {
682fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                        propertyAliasTable = new LinkedHashMap<String, Service>(256);
683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
684fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                    propertyAliasTable.put(key(serviceName, aliasName), s);
685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
686adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    String className = (String) changedProperties
687f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                            .get(serviceName + "." + algorithm);
688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (className != null) {
689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        List<String> l = new ArrayList<String>();
690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        l.add(aliasName);
691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        s = new Provider.Service(this, serviceName, algorithm,
692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                className, l, new HashMap<String, String>());
693fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                        propertyServiceTable.put(propertyServiceTableKey, s);
694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (propertyAliasTable == null) {
695fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                            propertyAliasTable = new LinkedHashMap<String, Service>(256);
696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
697fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                        propertyAliasTable.put(key(serviceName, aliasName), s);
698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                continue;
701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
7022f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes            int j = key.indexOf('.');
703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (j == -1) { // unknown format
704adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                continue;
705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
7062f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes            i = key.indexOf(' ');
707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (i == -1) { // <crypto_service>.<algorithm_or_type>=<className>
708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                serviceName = key.substring(0, j);
709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                algorithm = key.substring(j + 1);
710fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                String propertyServiceTableKey = key(serviceName, algorithm);
711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                Object o = null;
712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (propertyServiceTable != null) {
713fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                    o = propertyServiceTable.get(propertyServiceTableKey);
714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (o != null) {
716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    s = (Provider.Service) o;
717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    s.className = value;
718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    s = new Provider.Service(this, serviceName, algorithm,
720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            value, Collections.<String>emptyList(),
721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            Collections.<String,String>emptyMap());
722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (propertyServiceTable == null) {
723fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                        propertyServiceTable = new LinkedHashMap<String, Service>(128);
724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
725fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                    propertyServiceTable.put(propertyServiceTableKey, s);
726adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
72812cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom            } else {
729fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                // <crypto_service>.<algorithm_or_type> <attribute_name>=<attrValue>
730adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                serviceName = key.substring(0, j);
731adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                algorithm = key.substring(j + 1, i);
732adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                String attribute = key.substring(i + 1);
733fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                String propertyServiceTableKey = key(serviceName, algorithm);
734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                Object o = null;
735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (propertyServiceTable != null) {
736fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                    o = propertyServiceTable.get(propertyServiceTableKey);
737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (o != null) {
739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    s = (Provider.Service) o;
740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    s.putAttribute(attribute, value);
741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    String className = (String) changedProperties
743f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                            .get(serviceName + "." + algorithm);
744adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (className != null) {
745adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        Map<String, String> m = new HashMap<String, String>();
746adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        m.put(attribute, value);
747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        s = new Provider.Service(this, serviceName, algorithm,
748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                className, new ArrayList<String>(), m);
749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (propertyServiceTable == null) {
750fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                            propertyServiceTable = new LinkedHashMap<String, Service>(128);
751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
752fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom                        propertyServiceTable.put(propertyServiceTableKey, s);
753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
757adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        servicesChanged();
758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        changedProperties = null;
759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void servicesChanged() {
762adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        lastServicesByType = null;
763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        lastServiceName = null;
764adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        lastServicesSet = null;
765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
766adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
76712cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom    /**
76812cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom     * These attributes should be placed in each Provider object:
76912cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom     * Provider.id name, Provider.id version, Provider.id info,
77012cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom     * Provider.id className
77112cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom     */
772adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void putProviderInfo() {
773b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes        super.put("Provider.id name", (name != null) ? name : "null");
774d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes        super.put("Provider.id version", versionString);
775b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes        super.put("Provider.id info", (info != null) ? info : "null");
7762f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes        super.put("Provider.id className", this.getClass().getName());
777adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
778adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
77912cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom    /**
780a695e8fafadd2591cd148e78f19bc6d7c15121bbJesse Wilson     * Returns the property with the specified key in the provider properties.
781a695e8fafadd2591cd148e78f19bc6d7c15121bbJesse Wilson     * The name is not case-sensitive.
78212cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom     */
783adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private String getPropertyIgnoreCase(String key) {
784adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String res = getProperty(key);
785adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (res != null) {
786adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return res;
787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
788a695e8fafadd2591cd148e78f19bc6d7c15121bbJesse Wilson        for (Enumeration<?> e = propertyNames(); e.hasMoreElements(); ) {
789a695e8fafadd2591cd148e78f19bc6d7c15121bbJesse Wilson            String propertyName = (String) e.nextElement();
790a695e8fafadd2591cd148e78f19bc6d7c15121bbJesse Wilson            if (key.equalsIgnoreCase(propertyName)) {
791a695e8fafadd2591cd148e78f19bc6d7c15121bbJesse Wilson                return getProperty(propertyName);
792adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
793adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
794adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return null;
795adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
796adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
797fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom    private static String key(String type, String algorithm) {
798fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom        return type + '.' + algorithm.toUpperCase(Locale.US);
799fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom    }
800fc7d051b4a8a79687a13228184f03a82270b262bBrian Carlstrom
801adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
802adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code Service} represents a service in the Java Security infrastructure.
803adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Each service describes its type, the algorithm it implements, to which
804adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * provider it belongs and other properties.
805adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
806adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static class Service {
8071bb8f7e39ce504504e0576dcb784406949ca506eKenny Root        /** Attribute name of supported key classes. */
8081bb8f7e39ce504504e0576dcb784406949ca506eKenny Root        private static final String ATTR_SUPPORTED_KEY_CLASSES = "SupportedKeyClasses";
8091bb8f7e39ce504504e0576dcb784406949ca506eKenny Root
8101bb8f7e39ce504504e0576dcb784406949ca506eKenny Root        /** Attribute name of supported key formats. */
8111bb8f7e39ce504504e0576dcb784406949ca506eKenny Root        private static final String ATTR_SUPPORTED_KEY_FORMATS = "SupportedKeyFormats";
8121bb8f7e39ce504504e0576dcb784406949ca506eKenny Root
813d00b7c375c1c39d113a306adc298dada35122766Kenny Root        /** Whether this type supports calls to {@link #supportsParameter(Object)}. */
8141bb8f7e39ce504504e0576dcb784406949ca506eKenny Root        private static final HashMap<String, Boolean> supportsParameterTypes
8151bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                = new HashMap<String, Boolean>();
8161bb8f7e39ce504504e0576dcb784406949ca506eKenny Root        static {
8171bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            // Does not support parameter
8181bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            supportsParameterTypes.put("AlgorithmParameterGenerator", false);
8191bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            supportsParameterTypes.put("AlgorithmParameters", false);
8201bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            supportsParameterTypes.put("CertificateFactory", false);
8211bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            supportsParameterTypes.put("CertPathBuilder", false);
8221bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            supportsParameterTypes.put("CertPathValidator", false);
8231bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            supportsParameterTypes.put("CertStore", false);
8241bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            supportsParameterTypes.put("KeyFactory", false);
8251bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            supportsParameterTypes.put("KeyGenerator", false);
8261bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            supportsParameterTypes.put("KeyManagerFactory", false);
8271bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            supportsParameterTypes.put("KeyPairGenerator", false);
8281bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            supportsParameterTypes.put("KeyStore", false);
8291bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            supportsParameterTypes.put("MessageDigest", false);
8301bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            supportsParameterTypes.put("SecretKeyFactory", false);
8311bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            supportsParameterTypes.put("SecureRandom", false);
8321bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            supportsParameterTypes.put("SSLContext", false);
8331bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            supportsParameterTypes.put("TrustManagerFactory", false);
8341bb8f7e39ce504504e0576dcb784406949ca506eKenny Root
8351bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            // Supports parameter
8361bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            supportsParameterTypes.put("Cipher", true);
8371bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            supportsParameterTypes.put("KeyAgreement", true);
8381bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            supportsParameterTypes.put("Mac", true);
8391bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            supportsParameterTypes.put("Signature", true);
8401bb8f7e39ce504504e0576dcb784406949ca506eKenny Root        }
8411bb8f7e39ce504504e0576dcb784406949ca506eKenny Root
842d00b7c375c1c39d113a306adc298dada35122766Kenny Root        /** Constructor argument classes for calls to {@link #newInstance(Object)}. */
843d00b7c375c1c39d113a306adc298dada35122766Kenny Root        private static final HashMap<String, Class<?>> constructorParameterClasses = new HashMap<String, Class<?>>();
844d00b7c375c1c39d113a306adc298dada35122766Kenny Root        static {
845d00b7c375c1c39d113a306adc298dada35122766Kenny Root            // Types that take a parameter to newInstance
846d00b7c375c1c39d113a306adc298dada35122766Kenny Root            constructorParameterClasses.put("CertStore",
847d00b7c375c1c39d113a306adc298dada35122766Kenny Root                    loadClassOrThrow("java.security.cert.CertStoreParameters"));
848d00b7c375c1c39d113a306adc298dada35122766Kenny Root
849d00b7c375c1c39d113a306adc298dada35122766Kenny Root            // Types that do not take any kind of parameter
850d00b7c375c1c39d113a306adc298dada35122766Kenny Root            constructorParameterClasses.put("AlgorithmParameterGenerator", null);
851d00b7c375c1c39d113a306adc298dada35122766Kenny Root            constructorParameterClasses.put("AlgorithmParameters", null);
852d00b7c375c1c39d113a306adc298dada35122766Kenny Root            constructorParameterClasses.put("CertificateFactory", null);
853d00b7c375c1c39d113a306adc298dada35122766Kenny Root            constructorParameterClasses.put("CertPathBuilder", null);
854d00b7c375c1c39d113a306adc298dada35122766Kenny Root            constructorParameterClasses.put("CertPathValidator", null);
855d00b7c375c1c39d113a306adc298dada35122766Kenny Root            constructorParameterClasses.put("KeyFactory", null);
856d00b7c375c1c39d113a306adc298dada35122766Kenny Root            constructorParameterClasses.put("KeyGenerator", null);
857d00b7c375c1c39d113a306adc298dada35122766Kenny Root            constructorParameterClasses.put("KeyManagerFactory", null);
858d00b7c375c1c39d113a306adc298dada35122766Kenny Root            constructorParameterClasses.put("KeyPairGenerator", null);
859d00b7c375c1c39d113a306adc298dada35122766Kenny Root            constructorParameterClasses.put("KeyStore", null);
860d00b7c375c1c39d113a306adc298dada35122766Kenny Root            constructorParameterClasses.put("MessageDigest", null);
861d00b7c375c1c39d113a306adc298dada35122766Kenny Root            constructorParameterClasses.put("SecretKeyFactory", null);
862d00b7c375c1c39d113a306adc298dada35122766Kenny Root            constructorParameterClasses.put("SecureRandom", null);
863d00b7c375c1c39d113a306adc298dada35122766Kenny Root            constructorParameterClasses.put("SSLContext", null);
864d00b7c375c1c39d113a306adc298dada35122766Kenny Root            constructorParameterClasses.put("TrustManagerFactory", null);
865d00b7c375c1c39d113a306adc298dada35122766Kenny Root            constructorParameterClasses.put("Cipher", null);
866d00b7c375c1c39d113a306adc298dada35122766Kenny Root            constructorParameterClasses.put("KeyAgreement", null);
867d00b7c375c1c39d113a306adc298dada35122766Kenny Root            constructorParameterClasses.put("Mac", null);
868d00b7c375c1c39d113a306adc298dada35122766Kenny Root            constructorParameterClasses.put("Signature", null);
869d00b7c375c1c39d113a306adc298dada35122766Kenny Root        }
870d00b7c375c1c39d113a306adc298dada35122766Kenny Root
871d00b7c375c1c39d113a306adc298dada35122766Kenny Root        /** Called to load a class if it's critical that the class exists. */
872d00b7c375c1c39d113a306adc298dada35122766Kenny Root        private static Class<?> loadClassOrThrow(String className) {
873d00b7c375c1c39d113a306adc298dada35122766Kenny Root            try {
874d00b7c375c1c39d113a306adc298dada35122766Kenny Root                return Provider.class.getClassLoader().loadClass(className);
875d00b7c375c1c39d113a306adc298dada35122766Kenny Root            } catch (Exception e) {
876d00b7c375c1c39d113a306adc298dada35122766Kenny Root                throw new AssertionError(e);
877d00b7c375c1c39d113a306adc298dada35122766Kenny Root            }
878d00b7c375c1c39d113a306adc298dada35122766Kenny Root        }
879d00b7c375c1c39d113a306adc298dada35122766Kenny Root
880adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // The provider
881adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private Provider provider;
882adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
883adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // The type of this service
884adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private String type;
885adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
886adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // The algorithm name
887adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private String algorithm;
888adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
889adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // The class implementing this service
890adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private String className;
891adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
892adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // The aliases
893adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private List<String> aliases;
894adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
895adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // The attributes
896adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private Map<String,String> attributes;
897adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
898adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Service implementation
899adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private Class<?> implementation;
900adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
901adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // For newInstance() optimization
902adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private String lastClassName;
903adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
9041bb8f7e39ce504504e0576dcb784406949ca506eKenny Root        /** Indicates whether supportedKeyClasses and supportedKeyFormats. */
9051bb8f7e39ce504504e0576dcb784406949ca506eKenny Root        private volatile boolean supportedKeysInitialized;
9061bb8f7e39ce504504e0576dcb784406949ca506eKenny Root
9071bb8f7e39ce504504e0576dcb784406949ca506eKenny Root        /** List of classes that this service supports. */
9081bb8f7e39ce504504e0576dcb784406949ca506eKenny Root        private Class<?>[] keyClasses;
9091bb8f7e39ce504504e0576dcb784406949ca506eKenny Root
9101bb8f7e39ce504504e0576dcb784406949ca506eKenny Root        /** List of key formats this service supports. */
9111bb8f7e39ce504504e0576dcb784406949ca506eKenny Root        private String[] keyFormats;
9121bb8f7e39ce504504e0576dcb784406949ca506eKenny Root
913adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
914adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Constructs a new instance of {@code Service} with the given
915adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * attributes.
9162f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes         *
917adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @param provider
918adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *            the provider to which this service belongs.
919adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @param type
920adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *            the type of this service (for example {@code
921adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *            KeyPairGenerator}).
922adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @param algorithm
923adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *            the algorithm this service implements.
924adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @param className
925adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *            the name of the class implementing this service.
926adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @param aliases
927adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *            {@code List} of aliases for the algorithm name, or {@code
928adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *            null} if the implemented algorithm has no aliases.
929adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @param attributes
930adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *            {@code Map} of additional attributes, or {@code null} if
931adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *            this {@code Service} has no attributed.
932adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @throws NullPointerException
933adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *             if {@code provider, type, algorithm} or {@code className}
934adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *             is {@code null}.
935adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
936adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public Service(Provider provider, String type, String algorithm,
937adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                String className, List<String> aliases, Map<String, String> attributes) {
93886acc043d3334651ee26c65467d78d6cefedd397Kenny Root            if (provider == null) {
93986acc043d3334651ee26c65467d78d6cefedd397Kenny Root                throw new NullPointerException("provider == null");
94086acc043d3334651ee26c65467d78d6cefedd397Kenny Root            } else if (type == null) {
94186acc043d3334651ee26c65467d78d6cefedd397Kenny Root                throw new NullPointerException("type == null");
94286acc043d3334651ee26c65467d78d6cefedd397Kenny Root            } else if (algorithm == null) {
94386acc043d3334651ee26c65467d78d6cefedd397Kenny Root                throw new NullPointerException("algorithm == null");
94486acc043d3334651ee26c65467d78d6cefedd397Kenny Root            } else if (className == null) {
94586acc043d3334651ee26c65467d78d6cefedd397Kenny Root                throw new NullPointerException("className == null");
946adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
947adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            this.provider = provider;
948adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            this.type = type;
949adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            this.algorithm = algorithm;
950adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            this.className = className;
951adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            this.aliases = ((aliases != null) && (aliases.size() == 0))
952adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    ? Collections.<String>emptyList() : aliases;
953adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            this.attributes =
954adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    ((attributes != null) && (attributes.size() == 0))
955adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    ? Collections.<String,String>emptyMap() : attributes;
956adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
957adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
958adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
959adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Adds an alias.
960f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes         *
961adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @param alias the alias to add
962adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
963adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /*package*/ void addAlias(String alias) {
964adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if ((aliases == null) || (aliases.size() == 0)) {
965adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                aliases = new ArrayList<String>();
966adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
967adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            aliases.add(alias);
968adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
969adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
970adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
971adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Puts a new attribute mapping.
972f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes         *
973adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @param name the attribute name.
974adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @param value the attribute value.
975adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
976adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /*package*/ void putAttribute(String name, String value) {
977adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if ((attributes == null) || (attributes.size() == 0)) {
978adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                attributes = new HashMap<String,String>();
979adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
980adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            attributes.put(name, value);
981adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
982adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
983adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
984adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Returns the type of this {@code Service}. For example {@code
985adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * KeyPairGenerator}.
9862f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes         *
987adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @return the type of this {@code Service}.
988adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
989adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public final String getType() {
990adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return type;
991adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
992adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
993adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
9942f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes         * Returns the name of the algorithm implemented by this {@code
9952f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes         * Service}.
9962f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes         *
9972f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes         * @return the name of the algorithm implemented by this {@code
9982f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes         *         Service}.
999adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
1000adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public final String getAlgorithm() {
1001adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return algorithm;
1002adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1003adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1004adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
1005adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Returns the {@code Provider} this {@code Service} belongs to.
10062f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes         *
1007adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @return the {@code Provider} this {@code Service} belongs to.
1008adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
1009adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public final Provider getProvider() {
1010adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return provider;
1011adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1012adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1013adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
1014adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Returns the name of the class implementing this {@code Service}.
10152f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes         *
1016adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @return the name of the class implementing this {@code Service}.
1017adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
1018adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public final String getClassName() {
1019adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return className;
1020adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1021adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1022adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
1023adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Returns the value of the attribute with the specified {@code name}.
10242f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes         *
1025adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @param name
1026adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *            the name of the attribute.
1027adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @return the value of the attribute, or {@code null} if no attribute
1028adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *         with the given name is set.
1029adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @throws NullPointerException
1030adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *             if {@code name} is {@code null}.
1031adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
1032adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public final String getAttribute(String name) {
1033adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (name == null) {
103486acc043d3334651ee26c65467d78d6cefedd397Kenny Root                throw new NullPointerException("name == null");
1035adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
1036adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (attributes == null) {
1037adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return null;
1038adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
1039adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return attributes.get(name);
1040adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1041adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
104212cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom        List<String> getAliases() {
104312cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom            if (aliases == null){
10442f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes                aliases = new ArrayList<String>(0);
10452f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes            }
104612cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom            return aliases;
1047adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1048adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1049adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
1050adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Creates and returns a new instance of the implementation described by
1051adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * this {@code Service}.
10522f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes         *
1053adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @param constructorParameter
1054adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *            the parameter that is used by the constructor, or {@code
1055adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *            null} if the implementation does not declare a constructor
1056adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *            parameter.
1057adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @return a new instance of the implementation described by this
1058adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *         {@code Service}.
1059adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @throws NoSuchAlgorithmException
1060adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *             if the instance could not be constructed.
1061adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @throws InvalidParameterException
1062adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *             if the implementation does not support the specified
1063adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *             {@code constructorParameter}.
1064adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
1065ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes        public Object newInstance(Object constructorParameter) throws NoSuchAlgorithmException {
1066adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (implementation == null || !className.equals(lastClassName)) {
1067ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes                ClassLoader cl = provider.getClass().getClassLoader();
1068ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes                if (cl == null) {
1069ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes                    cl = ClassLoader.getSystemClassLoader();
1070ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes                }
1071ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes                try {
1072ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes                    implementation = Class.forName(className, true, cl);
1073ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes                    lastClassName = className;
1074ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes                } catch (Exception e) {
1075ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes                    throw new NoSuchAlgorithmException(type + " " + algorithm + " implementation not found: " + e);
1076adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1077adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
1078d00b7c375c1c39d113a306adc298dada35122766Kenny Root
1079d00b7c375c1c39d113a306adc298dada35122766Kenny Root            // We don't know whether this takes a parameter or not.
1080d00b7c375c1c39d113a306adc298dada35122766Kenny Root            if (!constructorParameterClasses.containsKey(type)) {
1081d00b7c375c1c39d113a306adc298dada35122766Kenny Root                if (constructorParameter == null) {
1082d00b7c375c1c39d113a306adc298dada35122766Kenny Root                    return newInstanceNoParameter();
1083d00b7c375c1c39d113a306adc298dada35122766Kenny Root                } else {
1084d00b7c375c1c39d113a306adc298dada35122766Kenny Root                    return newInstanceWithParameter(constructorParameter,
1085d00b7c375c1c39d113a306adc298dada35122766Kenny Root                            constructorParameter.getClass());
1086adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
10872f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes            }
1088d00b7c375c1c39d113a306adc298dada35122766Kenny Root
1089d00b7c375c1c39d113a306adc298dada35122766Kenny Root            // A known type, but it's not required to have a parameter even if a
1090d00b7c375c1c39d113a306adc298dada35122766Kenny Root            // class is specified.
1091d00b7c375c1c39d113a306adc298dada35122766Kenny Root            if (constructorParameter == null) {
1092d00b7c375c1c39d113a306adc298dada35122766Kenny Root                return newInstanceNoParameter();
1093d00b7c375c1c39d113a306adc298dada35122766Kenny Root            }
1094d00b7c375c1c39d113a306adc298dada35122766Kenny Root
1095d00b7c375c1c39d113a306adc298dada35122766Kenny Root            // Make sure the provided constructor class is valid.
1096d00b7c375c1c39d113a306adc298dada35122766Kenny Root            final Class<?> expectedClass = constructorParameterClasses.get(type);
1097d00b7c375c1c39d113a306adc298dada35122766Kenny Root            if (expectedClass == null) {
1098d00b7c375c1c39d113a306adc298dada35122766Kenny Root                throw new IllegalArgumentException("Constructor parameter not supported for "
1099d00b7c375c1c39d113a306adc298dada35122766Kenny Root                        + type);
1100d00b7c375c1c39d113a306adc298dada35122766Kenny Root            }
1101d00b7c375c1c39d113a306adc298dada35122766Kenny Root            if (!expectedClass.isAssignableFrom(constructorParameter.getClass())) {
1102d00b7c375c1c39d113a306adc298dada35122766Kenny Root                throw new IllegalArgumentException("Expecting constructor parameter of type "
1103d00b7c375c1c39d113a306adc298dada35122766Kenny Root                        + expectedClass.getName() + " but was "
1104d00b7c375c1c39d113a306adc298dada35122766Kenny Root                        + constructorParameter.getClass().getName());
11052f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes            }
1106d00b7c375c1c39d113a306adc298dada35122766Kenny Root            return newInstanceWithParameter(constructorParameter, expectedClass);
1107d00b7c375c1c39d113a306adc298dada35122766Kenny Root        }
1108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1109d00b7c375c1c39d113a306adc298dada35122766Kenny Root        private Object newInstanceWithParameter(Object constructorParameter,
1110d00b7c375c1c39d113a306adc298dada35122766Kenny Root                Class<?> parameterClass) throws NoSuchAlgorithmException {
11112f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes            try {
1112d00b7c375c1c39d113a306adc298dada35122766Kenny Root                Class<?>[] parameterTypes = { parameterClass };
1113d00b7c375c1c39d113a306adc298dada35122766Kenny Root                Object[] initargs = { constructorParameter };
1114d00b7c375c1c39d113a306adc298dada35122766Kenny Root                return implementation.getConstructor(parameterTypes).newInstance(initargs);
1115d00b7c375c1c39d113a306adc298dada35122766Kenny Root            } catch (Exception e) {
1116d00b7c375c1c39d113a306adc298dada35122766Kenny Root                throw new NoSuchAlgorithmException(type + " " + algorithm
1117d00b7c375c1c39d113a306adc298dada35122766Kenny Root                        + " implementation not found", e);
1118d00b7c375c1c39d113a306adc298dada35122766Kenny Root            }
1119d00b7c375c1c39d113a306adc298dada35122766Kenny Root        }
1120d00b7c375c1c39d113a306adc298dada35122766Kenny Root
1121d00b7c375c1c39d113a306adc298dada35122766Kenny Root        private Object newInstanceNoParameter() throws NoSuchAlgorithmException {
1122d00b7c375c1c39d113a306adc298dada35122766Kenny Root            try {
1123d00b7c375c1c39d113a306adc298dada35122766Kenny Root                return implementation.newInstance();
11242f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes            } catch (Exception e) {
112512cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom                throw new NoSuchAlgorithmException(type + " " + algorithm
112612cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom                        + " implementation not found", e);
1127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
1128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
1131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Indicates whether this {@code Service} supports the specified
1132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * constructor parameter.
11332f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes         *
1134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @param parameter
1135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *            the parameter to test.
1136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @return {@code true} if this {@code Service} supports the specified
1137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         *         constructor parameter, {@code false} otherwise.
1138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
1139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public boolean supportsParameter(Object parameter) {
11401bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            Boolean supportsParameter = supportsParameterTypes.get(type);
11411bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            if (supportsParameter == null) {
11421bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                return true;
11431bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            }
11441bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            if (!supportsParameter) {
11451bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                throw new InvalidParameterException("Cannot use a parameter with " + type);
11461bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            }
11471bb8f7e39ce504504e0576dcb784406949ca506eKenny Root
11481bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            /*
11496d8a4f15d3dd10d2599fc9a236b5bbd8bd8f2776Kenny Root             * Only Key parameters are allowed, but allow null since there might
11506d8a4f15d3dd10d2599fc9a236b5bbd8bd8f2776Kenny Root             * not be any listed classes or formats for this instance.
11511bb8f7e39ce504504e0576dcb784406949ca506eKenny Root             */
11521bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            if (parameter != null && !(parameter instanceof Key)) {
11531bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                throw new InvalidParameterException("Parameter should be of type Key");
11541bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            }
11551bb8f7e39ce504504e0576dcb784406949ca506eKenny Root
11561bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            ensureSupportedKeysInitialized();
11571bb8f7e39ce504504e0576dcb784406949ca506eKenny Root
11581bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            // No restriction specified by Provider registration.
11591bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            if (keyClasses == null && keyFormats == null) {
11601bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                return true;
11611bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            }
11621bb8f7e39ce504504e0576dcb784406949ca506eKenny Root
11636d8a4f15d3dd10d2599fc9a236b5bbd8bd8f2776Kenny Root            // Restriction specified by registration, so null is not acceptable.
11646d8a4f15d3dd10d2599fc9a236b5bbd8bd8f2776Kenny Root            if (parameter == null) {
11656d8a4f15d3dd10d2599fc9a236b5bbd8bd8f2776Kenny Root                return false;
11666d8a4f15d3dd10d2599fc9a236b5bbd8bd8f2776Kenny Root            }
11676d8a4f15d3dd10d2599fc9a236b5bbd8bd8f2776Kenny Root
11681bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            Key keyParam = (Key) parameter;
11691bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            if (keyClasses != null && isInArray(keyClasses, keyParam.getClass())) {
11701bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                return true;
11711bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            }
11721bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            if (keyFormats != null && isInArray(keyFormats, keyParam.getFormat())) {
11731bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                return true;
11741bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            }
11751bb8f7e39ce504504e0576dcb784406949ca506eKenny Root
11761bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            return false;
11771bb8f7e39ce504504e0576dcb784406949ca506eKenny Root        }
11781bb8f7e39ce504504e0576dcb784406949ca506eKenny Root
11791bb8f7e39ce504504e0576dcb784406949ca506eKenny Root        /**
11801bb8f7e39ce504504e0576dcb784406949ca506eKenny Root         * Initialize the list of supported key classes and formats.
11811bb8f7e39ce504504e0576dcb784406949ca506eKenny Root         */
11821bb8f7e39ce504504e0576dcb784406949ca506eKenny Root        private void ensureSupportedKeysInitialized() {
11831bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            if (supportedKeysInitialized) {
11841bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                return;
11851bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            }
11861bb8f7e39ce504504e0576dcb784406949ca506eKenny Root
11871bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            final String supportedClassesString = getAttribute(ATTR_SUPPORTED_KEY_CLASSES);
11881bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            if (supportedClassesString != null) {
11891bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                String[] keyClassNames = supportedClassesString.split("\\|");
11901bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                ArrayList<Class<?>> supportedClassList = new ArrayList<Class<?>>(
11911bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                        keyClassNames.length);
11921bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                final ClassLoader classLoader = getProvider().getClass().getClassLoader();
11931bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                for (String keyClassName : keyClassNames) {
11941bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                    try {
11951bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                        Class<?> keyClass = classLoader.loadClass(keyClassName);
11961bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                        if (Key.class.isAssignableFrom(keyClass)) {
11971bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                            supportedClassList.add(keyClass);
11981bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                        }
11991bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                    } catch (ClassNotFoundException ignored) {
12001bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                    }
12011bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                }
12021bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                keyClasses = supportedClassList.toArray(new Class<?>[supportedClassList.size()]);
12031bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            }
12041bb8f7e39ce504504e0576dcb784406949ca506eKenny Root
12051bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            final String supportedFormatString = getAttribute(ATTR_SUPPORTED_KEY_FORMATS);
12061bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            if (supportedFormatString != null) {
12071bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                keyFormats = supportedFormatString.split("\\|");
12081bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            }
12091bb8f7e39ce504504e0576dcb784406949ca506eKenny Root
12101bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            supportedKeysInitialized = true;
12111bb8f7e39ce504504e0576dcb784406949ca506eKenny Root        }
12121bb8f7e39ce504504e0576dcb784406949ca506eKenny Root
12131bb8f7e39ce504504e0576dcb784406949ca506eKenny Root        /**
12141bb8f7e39ce504504e0576dcb784406949ca506eKenny Root         * Check if an item is in the array. The array of supported key classes
12151bb8f7e39ce504504e0576dcb784406949ca506eKenny Root         * and formats is usually just a length of 1, so a simple array is
12161bb8f7e39ce504504e0576dcb784406949ca506eKenny Root         * faster than a Set.
12171bb8f7e39ce504504e0576dcb784406949ca506eKenny Root         */
121885dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        private static <T> boolean isInArray(T[] itemList, T target) {
12191bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            if (target == null) {
12201bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                return false;
12211bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            }
12221bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            for (T item : itemList) {
12231bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                if (target.equals(item)) {
12241bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                    return true;
122585dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root                }
122685dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root            }
122785dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root            return false;
122885dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        }
122985dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root
123085dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        /**
123185dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root         * Check if an item is in the array. The array of supported key classes
123285dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root         * and formats is usually just a length of 1, so a simple array is
123385dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root         * faster than a Set.
123485dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root         */
123585dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        private static boolean isInArray(Class<?>[] itemList, Class<?> target) {
123685dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root            if (target == null) {
123785dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root                return false;
123885dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root            }
123985dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root            for (Class<?> item : itemList) {
124085dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root                if (item.isAssignableFrom(target)) {
124185dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root                    return true;
12421bb8f7e39ce504504e0576dcb784406949ca506eKenny Root                }
12431bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            }
12441bb8f7e39ce504504e0576dcb784406949ca506eKenny Root            return false;
1245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
1248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Returns a string containing a concise, human-readable description of
1249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * this {@code Service}.
12502f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes         *
1251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @return a printable representation for this {@code Service}.
1252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
12532f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes        @Override
1254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public String toString() {
1255f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            String result = "Provider " + provider.getName() + " Service "
1256f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                    + type + "." + algorithm + " " + className;
1257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (aliases != null) {
1258f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                result = result + "\nAliases " + aliases.toString();
1259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
1260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (attributes != null) {
1261f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                result = result + "\nAttributes " + attributes.toString();
1262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
1263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return result;
1264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1266f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
126712cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom    private void readObject(java.io.ObjectInputStream in)
126812cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom            throws NotActiveException, IOException, ClassNotFoundException {
1269d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes        in.defaultReadObject();
12702f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes        versionString = String.valueOf(version);
12712f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes        providerNumber = -1;
12722f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes    }
1273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
1274