1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package javax.net.ssl;
19
20import java.security.InvalidAlgorithmParameterException;
21import java.security.KeyStore;
22import java.security.KeyStoreException;
23import java.security.NoSuchAlgorithmException;
24import java.security.NoSuchProviderException;
25import java.security.Provider;
26import java.security.Security;
27import java.security.UnrecoverableKeyException;
28import org.apache.harmony.security.fortress.Engine;
29
30/**
31 * The public API for {@code KeyManagerFactory} implementations.
32 */
33public class KeyManagerFactory {
34    // Store KeyManagerFactory service name
35    private static final String SERVICE = "KeyManagerFactory";
36
37    // Used to access common engine functionality
38    private static final Engine ENGINE = new Engine(SERVICE);
39
40    // Store default property name
41    private static final String PROPERTY_NAME = "ssl.KeyManagerFactory.algorithm";
42
43    /**
44     * Returns the default key manager factory algorithm name.
45     * <p>
46     * The default algorithm name is specified by the security property:
47     * {@code 'ssl.KeyManagerFactory.algorithm'}.
48     *
49     * @return the default algorithm name.
50     */
51    public static final String getDefaultAlgorithm() {
52        return Security.getProperty(PROPERTY_NAME);
53    }
54
55    /**
56     * Creates a new {@code KeyManagerFactory} instance for the specified key
57     * management algorithm.
58     *
59     * @param algorithm
60     *            the name of the requested key management algorithm.
61     * @return a key manager factory for the requested algorithm.
62     * @throws NoSuchAlgorithmException
63     *             if no installed provider can provide the requested algorithm.
64     * @throws NullPointerException
65     *             if {@code algorithm} is {@code null} (instead of
66     *             NoSuchAlgorithmException as in 1.4 release)
67     */
68    public static final KeyManagerFactory getInstance(String algorithm)
69            throws NoSuchAlgorithmException {
70        if (algorithm == null) {
71            throw new NullPointerException("algorithm == null");
72        }
73        Engine.SpiAndProvider sap = ENGINE.getInstance(algorithm, null);
74        return new KeyManagerFactory((KeyManagerFactorySpi) sap.spi, sap.provider, algorithm);
75    }
76
77    /**
78     * Creates a new {@code KeyManagerFactory} instance for the specified key
79     * management algorithm from the specified provider.
80     *
81     * @param algorithm
82     *            the name of the requested key management algorithm name.
83     * @param provider
84     *            the name of the provider that provides the requested
85     *            algorithm.
86     * @return a key manager factory for the requested algorithm.
87     * @throws NoSuchAlgorithmException
88     *             if the specified provider cannot provide the requested
89     *             algorithm.
90     * @throws NoSuchProviderException
91     *             if the specified provider does not exist.
92     * @throws NullPointerException
93     *             if {@code algorithm} is {@code null} (instead of
94     *             NoSuchAlgorithmException as in 1.4 release)
95     */
96    public static final KeyManagerFactory getInstance(String algorithm, String provider)
97            throws NoSuchAlgorithmException, NoSuchProviderException {
98        if ((provider == null) || (provider.length() == 0)) {
99            throw new IllegalArgumentException("Provider is null or empty");
100        }
101        Provider impProvider = Security.getProvider(provider);
102        if (impProvider == null) {
103            throw new NoSuchProviderException(provider);
104        }
105        return getInstance(algorithm, impProvider);
106    }
107
108    /**
109     * Creates a new {@code KeyManagerFactory} instance for the specified key
110     * management algorithm from the specified provider.
111     *
112     * @param algorithm
113     *            the name of the requested key management algorithm name.
114     * @param provider
115     *            the provider that provides the requested algorithm.
116     * @return a key manager factory for the requested algorithm.
117     * @throws NoSuchAlgorithmException
118     *             if the specified provider cannot provide the requested
119     *             algorithm.
120     * @throws NullPointerException
121     *             if {@code algorithm} is {@code null} (instead of
122     *             NoSuchAlgorithmException as in 1.4 release)
123     */
124    public static final KeyManagerFactory getInstance(String algorithm, Provider provider)
125            throws NoSuchAlgorithmException {
126        if (provider == null) {
127            throw new IllegalArgumentException("Provider is null");
128        }
129        if (algorithm == null) {
130            throw new NullPointerException("algorithm == null");
131        }
132        Object spi = ENGINE.getInstance(algorithm, provider, null);
133        return new KeyManagerFactory((KeyManagerFactorySpi) spi, provider, algorithm);
134    }
135
136    // Store used provider
137    private final Provider provider;
138
139    // Store used KeyManagerFactorySpi implementation
140    private final KeyManagerFactorySpi spiImpl;
141
142    // Store used algorithm
143    private final String algorithm;
144
145    /**
146     * Creates a new {@code KeyManagerFactory}.
147     *
148     * @param factorySpi
149     *            the implementation delegate.
150     * @param provider
151     *            the provider.
152     * @param algorithm
153     *            the key management algorithm name.
154     */
155    protected KeyManagerFactory(KeyManagerFactorySpi factorySpi, Provider provider,
156                                String algorithm) {
157        this.provider = provider;
158        this.algorithm = algorithm;
159        this.spiImpl = factorySpi;
160    }
161
162    /**
163     * Returns the name of the key management algorithm.
164     *
165     * @return the name of the key management algorithm.
166     */
167    public final String getAlgorithm() {
168        return algorithm;
169    }
170
171    /**
172     * Returns the provider for this {@code KeyManagerFactory} instance.
173     *
174     * @return the provider for this {@code KeyManagerFactory} instance.
175     */
176    public final Provider getProvider() {
177        return provider;
178    }
179
180    /**
181     * Initializes this instance with the specified key store and password.
182     *
183     * @param ks
184     *            the key store or {@code null} to use the default key store.
185     * @param password
186     *            the password for the specified key store or {@code null} if no
187     *            key store is provided.
188     * @throws KeyStoreException
189     *             if initializing this key manager factory fails.
190     * @throws NoSuchAlgorithmException
191     *             if a required algorithm is not available.
192     * @throws UnrecoverableKeyException
193     *             if a key cannot be recovered.
194     */
195    public final void init(KeyStore ks, char[] password) throws KeyStoreException,
196            NoSuchAlgorithmException, UnrecoverableKeyException {
197        spiImpl.engineInit(ks, password);
198    }
199
200    /**
201     * Initializes this instance with the specified factory parameters.
202     *
203     * @param spec
204     *            the factory parameters.
205     * @throws InvalidAlgorithmParameterException
206     *             if an error occurs.
207     */
208    public final void init(ManagerFactoryParameters spec)
209            throws InvalidAlgorithmParameterException {
210        spiImpl.engineInit(spec);
211    }
212
213    /**
214     * Returns a list of key managers, one instance for each type of key in the
215     * key store.
216     *
217     * @return a list of key managers.
218     */
219    public final KeyManager[] getKeyManagers() {
220        return spiImpl.engineGetKeyManagers();
221    }
222}
223