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 java.security;
19
20import java.security.spec.InvalidKeySpecException;
21import java.security.spec.KeySpec;
22
23import org.apache.harmony.security.fortress.Engine;
24import org.apache.harmony.security.internal.nls.Messages;
25
26/**
27 * {@code KeyFactory} is an engine class that can be used to translate between
28 * public and private key objects and convert keys between their external
29 * representation, that can be easily transported and their internal
30 * representation.
31 */
32public class KeyFactory {
33    // The service name.
34    private static final String SERVICE = "KeyFactory"; //$NON-NLS-1$
35
36    // The provider
37    private Provider provider;
38
39
40    // Used to access common engine functionality
41    static private Engine engine = new Engine(SERVICE);
42
43    // The SPI implementation.
44    private KeyFactorySpi spiImpl;
45
46    // The algorithm.
47    private String algorithm;
48
49    /**
50     * Constructs a new instance of {@code KeyFactory} with the specified
51     * arguments.
52     *
53     * @param keyFacSpi
54     *            the concrete key factory service.
55     * @param provider
56     *            the provider.
57     * @param algorithm
58     *            the algorithm to use.
59     */
60    protected KeyFactory(KeyFactorySpi keyFacSpi,
61                         Provider provider,
62                         String algorithm) {
63        this.provider = provider;
64        this. algorithm = algorithm;
65        this.spiImpl = keyFacSpi;
66    }
67
68    /**
69     * Returns a new instance of {@code KeyFactory} that utilizes the specified
70     * algorithm.
71     *
72     * @param algorithm
73     *            the name of the algorithm.
74     * @return a new instance of {@code KeyFactory} that utilizes the specified
75     *         algorithm.
76     * @throws NoSuchAlgorithmException
77     *             if no provider provides the requested algorithm.
78     */
79    public static KeyFactory getInstance(String algorithm)
80                                throws NoSuchAlgorithmException {
81        if (algorithm == null) {
82            throw new NullPointerException(Messages.getString("security.01")); //$NON-NLS-1$
83        }
84        synchronized (engine) {
85            engine.getInstance(algorithm, null);
86            return new KeyFactory((KeyFactorySpi)engine.spi, engine.provider, algorithm);
87        }
88    }
89
90    /**
91     * Returns a new instance of {@code KeyFactory} that utilizes the specified
92     * algorithm from the specified provider.
93     *
94     * @param algorithm
95     *            the name of the algorithm.
96     * @param provider
97     *            the name of the provider.
98     * @return a new instance of {@code KeyFactory} that utilizes the specified
99     *         algorithm from the specified provider.
100     * @throws NoSuchAlgorithmException
101     *             if the provider does not provide the requested algorithm.
102     * @throws NoSuchProviderException
103     *             if the requested provider is not available.
104     * @throws IllegalArgumentException
105     *             if {@code provider} is {@code null} or empty.
106     */
107    @SuppressWarnings("nls")
108    public static KeyFactory getInstance(String algorithm, String provider)
109                                throws NoSuchAlgorithmException, NoSuchProviderException {
110        if ((provider == null) || (provider.length() == 0)) {
111            throw new IllegalArgumentException(Messages.getString("security.02"));
112        }
113        Provider p = Security.getProvider(provider);
114        if (p == null) {
115            throw new NoSuchProviderException(Messages.getString("security.03", provider));
116        }
117        return getInstance(algorithm, p);
118    }
119
120    /**
121     * Returns a new instance of {@code KeyFactory} that utilizes the specified
122     * algorithm from the specified provider.
123     *
124     * @param algorithm
125     *            the name of the algorithm.
126     * @param provider
127     *            the security provider.
128     * @return a new instance of {@code KeyFactory} that utilizes the specified
129     *         algorithm from the specified provider.
130     * @throws NoSuchAlgorithmException
131     *             if the provider does not provide the requested algorithm.
132     */
133    public static KeyFactory getInstance(String algorithm, Provider provider)
134                                 throws NoSuchAlgorithmException {
135        if (provider == null) {
136            throw new IllegalArgumentException(Messages.getString("security.04")); //$NON-NLS-1$
137        }
138        if (algorithm == null) {
139            throw new NullPointerException(Messages.getString("security.01")); //$NON-NLS-1$
140        }
141        synchronized (engine) {
142            engine.getInstance(algorithm, provider, null);
143            return new KeyFactory((KeyFactorySpi)engine.spi, provider, algorithm);
144        }
145    }
146
147    /**
148     * Returns the provider associated with this {@code KeyFactory}.
149     *
150     * @return the provider associated with this {@code KeyFactory}.
151     */
152    public final Provider getProvider() {
153        return provider;
154    }
155
156    /**
157     * Returns the name of the algorithm associated with this {@code
158     * KeyFactory}.
159     *
160     * @return the name of the algorithm associated with this {@code
161     *         KeyFactory}.
162     */
163    public final String getAlgorithm() {
164        return algorithm;
165    }
166
167    /**
168     * Generates a instance of {@code PublicKey} from the given key
169     * specification.
170     *
171     * @param keySpec
172     *            the specification of the public key
173     * @return the public key
174     * @throws InvalidKeySpecException
175     *             if the specified {@code keySpec} is invalid
176     */
177    public final PublicKey generatePublic(KeySpec keySpec)
178                                throws InvalidKeySpecException {
179        return spiImpl.engineGeneratePublic(keySpec);
180    }
181
182    /**
183     * Generates a instance of {@code PrivateKey} from the given key
184     * specification.
185     *
186     * @param keySpec
187     *            the specification of the private key.
188     * @return the private key.
189     * @throws InvalidKeySpecException
190     *             if the specified {@code keySpec} is invalid.
191     */
192    public final PrivateKey generatePrivate(KeySpec keySpec)
193                                throws InvalidKeySpecException {
194        return spiImpl.engineGeneratePrivate(keySpec);
195    }
196
197    /**
198     * Returns the key specification for the specified key.
199     *
200     * @param key
201     *            the key from which the specification is requested.
202     * @param keySpec
203     *            the type of the requested {@code KeySpec}.
204     * @return the key specification for the specified key.
205     * @throws InvalidKeySpecException
206     *             if the key can not be processed, or the requested requested
207     *             {@code KeySpec} is inappropriate for the given key.
208     */
209    public final <T extends KeySpec> T getKeySpec(Key key,
210                                    Class<T> keySpec)
211                            throws InvalidKeySpecException {
212        return spiImpl.engineGetKeySpec(key, keySpec);
213    }
214
215    /**
216     * Translates the given key into a key from this key factory.
217     *
218     * @param key
219     *            the key to translate.
220     * @return the translated key.
221     * @throws InvalidKeyException
222     *             if the specified key can not be translated by this key
223     *             factory.
224     */
225    public final Key translateKey(Key key)
226                        throws InvalidKeyException {
227        return spiImpl.engineTranslateKey(key);
228    }
229}
230