CertificateFactory.java revision f33eae7e84eb6d3b0f4e86b59605bb3de73009f3
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.cert;
19
20import java.io.InputStream;
21import java.security.NoSuchAlgorithmException;
22import java.security.NoSuchProviderException;
23import java.security.Provider;
24import java.security.Security;
25import java.util.Collection;
26import java.util.Iterator;
27import java.util.List;
28
29import org.apache.harmony.security.fortress.Engine;
30import org.apache.harmony.security.internal.nls.Messages;
31
32
33/**
34 * This class implements the functionality of a certificate factory algorithm,
35 * relying on parsing a stream of bytes.
36 * <p>
37 * It defines methods for parsing certificate chains (certificate paths) and
38 * <i>Certificate Revocation Lists</i> (CRLs).
39 */
40public class CertificateFactory {
41
42    // Store CertificateFactory service name
43    private static final String SERVICE = "CertificateFactory";
44
45    // Used to access common engine functionality
46    private static Engine engine = new Engine(SERVICE);
47
48    // Store used provider
49    private final Provider provider;
50
51    // Store used CertificateFactorySpi implementation
52    private final CertificateFactorySpi spiImpl;
53
54    // Store used type
55    private final String type;
56
57    /**
58     * Creates a new {@code CertificateFactory} instance.
59     *
60     * @param certFacSpi
61     *            the implementation delegate.
62     * @param provider
63     *            the associated provider.
64     * @param type
65     *            the certificate type.
66     */
67    protected CertificateFactory(CertificateFactorySpi certFacSpi,
68            Provider provider, String type) {
69        this.provider = provider;
70        this.type = type;
71        this.spiImpl = certFacSpi;
72    }
73
74    /**
75     * Creates a new {@code CertificateFactory} instance that provides the
76     * requested certificate type.
77     *
78     * @param type
79     *            the certificate type.
80     * @return the new {@code CertificateFactory} instance.
81     * @throws CertificateException
82     *             if the specified certificate type is not available at any
83     *             installed provider.
84     * @throws NullPointerException
85     *             if {@code type} is {@code null}.
86     */
87    public static final CertificateFactory getInstance(String type)
88            throws CertificateException {
89        if (type == null) {
90            throw new NullPointerException(Messages.getString("security.07"));
91        }
92        try {
93            synchronized (engine) {
94                engine.getInstance(type, null);
95                return new CertificateFactory((CertificateFactorySpi) engine.spi,
96                        engine.provider, type);
97            }
98        } catch (NoSuchAlgorithmException e) {
99            throw new CertificateException(e);
100        }
101    }
102
103    /**
104     * Creates a new {@code CertificateFactory} instance from the specified
105     * provider that provides the requested certificate type.
106     *
107     * @param type
108     *            the certificate type.
109     * @param provider
110     *            the name of the provider providing certificates of the
111     *            specified type.
112     * @return the new {@code CertificateFactory} instance.
113     * @throws CertificateException
114     *             if the specified certificate type is not available by the
115     *             specified provider.
116     * @throws NoSuchProviderException
117     *             if no provider with the specified name can be found.
118     * @throws IllegalArgumentException
119     *             if the specified provider name is {@code null} or empty.
120     * @throws NullPointerException
121     *             it {@code type} is {@code null}.
122     */
123    public static final CertificateFactory getInstance(String type,
124            String provider) throws CertificateException,
125            NoSuchProviderException {
126        if ((provider == null) || (provider.length() == 0)) {
127            throw new IllegalArgumentException(Messages.getString("security.02"));
128        }
129        Provider impProvider = Security.getProvider(provider);
130        if (impProvider == null) {
131            throw new NoSuchProviderException(provider);
132        }
133        return getInstance(type, impProvider);
134    }
135
136    /**
137     * Creates a new {@code CertificateFactory} instance from the specified
138     * provider that provides the requested certificate type.
139     *
140     * @param type
141     *            the certificate type.
142     * @param provider
143     *            the name of the provider providing certificates of the
144     *            specified type.
145     * @return the new {@code CertificateFactory} instance.
146     * @throws CertificateException
147     *             if the specified certificate type is not available at the
148     *             specified provider.
149     * @throws IllegalArgumentException
150     *             if the specified provider is {@code null}.
151     * @throws NullPointerException
152     *             is {@code type} is {@code null}.
153     */
154    public static final CertificateFactory getInstance(String type,
155            Provider provider) throws CertificateException {
156        if (provider == null) {
157            throw new IllegalArgumentException(Messages.getString("security.04"));
158        }
159        if (type == null) {
160            throw new NullPointerException(Messages.getString("security.07"));
161        }
162        try {
163            synchronized (engine) {
164                engine.getInstance(type, provider, null);
165                return new CertificateFactory((CertificateFactorySpi) engine.spi,
166                        provider, type);
167            }
168        } catch (NoSuchAlgorithmException e) {
169            throw new CertificateException(e.getMessage());
170        }
171    }
172
173    /**
174     * Returns the {@code Provider} of the certificate factory represented by
175     * the certificate.
176     *
177     * @return the provider of this certificate factory.
178     */
179    public final Provider getProvider() {
180        return provider;
181    }
182
183    /**
184     * Returns the Certificate type.
185     *
186     * @return type of certificate being used.
187     */
188    public final String getType() {
189        return type;
190    }
191
192    /**
193     * Generates and initializes a {@code Certificate} from the provided input
194     * stream.
195     *
196     * @param inStream
197     *            the stream from where data is read to create the {@code
198     *            Certificate}.
199     * @return an initialized Certificate.
200     * @throws CertificateException
201     *             if parsing problems are detected.
202     */
203    public final Certificate generateCertificate(InputStream inStream)
204            throws CertificateException {
205        return spiImpl.engineGenerateCertificate(inStream);
206    }
207
208    /**
209     * Returns an {@code Iterator} over the supported {@code CertPath} encodings
210     * (as Strings). The first element is the default encoding scheme to apply.
211     *
212     * @return an iterator over supported {@link CertPath} encodings (as
213     *         Strings).
214     */
215    public final Iterator<String> getCertPathEncodings() {
216        return spiImpl.engineGetCertPathEncodings();
217    }
218
219    /**
220     * Generates a {@code CertPath} (a certificate chain) from the provided
221     * {@code InputStream}. The default encoding scheme is applied.
222     *
223     * @param inStream
224     *            {@code InputStream} with encoded data.
225     * @return a {@code CertPath} initialized from the provided data.
226     * @throws CertificateException
227     *             if parsing problems are detected.
228     */
229    public final CertPath generateCertPath(InputStream inStream)
230            throws CertificateException {
231        Iterator<String> it = getCertPathEncodings();
232        if (!it.hasNext()) {
233            throw new CertificateException(Messages.getString("security.74"));
234        }
235        return spiImpl.engineGenerateCertPath(inStream, it.next());
236    }
237
238    /**
239     * Generates a {@code CertPath} (a certificate chain) from the provided
240     * {@code InputStream} and the specified encoding scheme.
241     *
242     * @param inStream
243     *            {@code InputStream} containing certificate path data in
244     *            specified encoding.
245     * @param encoding
246     *            encoding of the data in the input stream.
247     * @return a {@code CertPath} initialized from the provided data.
248     * @throws CertificateException
249     *             if parsing problems are detected.
250     * @throws UnsupportedOperationException
251     *             if the provider does not implement this method.
252     */
253    public final CertPath generateCertPath(InputStream inStream, String encoding)
254            throws CertificateException {
255        return spiImpl.engineGenerateCertPath(inStream, encoding);
256    }
257
258    /**
259     * Generates a {@code CertPath} from the provided list of certificates. The
260     * encoding is the default encoding.
261     *
262     * @param certificates
263     *            the list containing certificates in a format supported by the
264     *            {@code CertificateFactory}.
265     * @return a {@code CertPath} initialized from the provided data.
266     * @throws CertificateException
267     *             if parsing problems are detected.
268     * @throws UnsupportedOperationException
269     *             if the provider does not implement this method.
270     */
271    public final CertPath generateCertPath(List<? extends Certificate> certificates)
272            throws CertificateException {
273        return spiImpl.engineGenerateCertPath(certificates);
274    }
275
276    /**
277     * Generates and initializes a collection of (unrelated) certificates from
278     * the provided input stream.
279     *
280     * @param inStream
281     *            the stream from which the data is read to create the
282     *            collection.
283     * @return an initialized collection of certificates.
284     * @throws CertificateException
285     *             if parsing problems are detected.
286     */
287    public final Collection<? extends Certificate> generateCertificates(InputStream inStream)
288            throws CertificateException {
289        return spiImpl.engineGenerateCertificates(inStream);
290    }
291
292    /**
293     * Generates and initializes a <i>Certificate Revocation List</i> (CRL) from
294     * the provided input stream.
295     *
296     * @param inStream
297     *            the stream from where data is read to create the CRL.
298     * @return an initialized CRL.
299     * @exception CRLException
300     *                if parsing problems are detected.
301     */
302    public final CRL generateCRL(InputStream inStream) throws CRLException {
303        return spiImpl.engineGenerateCRL(inStream);
304    }
305
306    /**
307     * Generates and initializes a collection of <i>Certificate Revocation
308     * List</i> (CRL) from the provided input stream.
309     *
310     * @param inStream
311     *            the stream from which the data is read to create the CRLs.
312     * @return an initialized collection of CRLs.
313     * @exception CRLException
314     *                if parsing problems are detected.
315     */
316    public final Collection<? extends CRL> generateCRLs(InputStream inStream)
317            throws CRLException {
318        return spiImpl.engineGenerateCRLs(inStream);
319    }
320}
321