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.KeyManagementException;
21import java.security.NoSuchAlgorithmException;
22import java.security.NoSuchProviderException;
23import java.security.Provider;
24import java.security.SecureRandom;
25import java.security.Security;
26
27import org.apache.harmony.security.fortress.Engine;
28
29
30/**
31 * The public API for secure socket protocol implementations. It acts as factory
32 * for {@code SSLSocketFactory}'s and {@code SSLEngine}s.
33 */
34public class SSLContext {
35    // StoreSSLContext service name
36    private static final String SERVICE = "SSLContext";
37
38    // Used to access common engine functionality
39    private static Engine engine = new Engine(SERVICE);
40
41    /**
42     * Creates a new {@code SSLContext} instance for the specified protocol.
43     *
44     * @param protocol
45     *            the requested protocol to create a context for.
46     * @return the created {@code SSLContext} instance.
47     * @throws NoSuchAlgorithmException
48     *             if no installed provider can provide the requested protocol
49     * @throws NullPointerException
50     *             if {@code protocol} is {@code null} (instead of
51     *             NoSuchAlgorithmException as in 1.4 release)
52     */
53    public static SSLContext getInstance(String protocol) throws NoSuchAlgorithmException {
54        if (protocol == null) {
55            throw new NullPointerException("protocol is null");
56        }
57        synchronized (engine) {
58            engine.getInstance(protocol, null);
59            return new SSLContext((SSLContextSpi) engine.spi, engine.provider, protocol);
60        }
61    }
62
63    /**
64     * Creates a new {@code SSLContext} instance for the specified protocol from
65     * the specified provider.
66     *
67     * @param protocol
68     *            the requested protocol to create a context for.
69     * @param provider
70     *            the name of the provider that provides the requested protocol.
71     * @return an {@code SSLContext} for the requested protocol.
72     * @throws NoSuchAlgorithmException
73     *             if the specified provider cannot provider the requested
74     *             protocol.
75     * @throws NoSuchProviderException
76     *             if the specified provider does not exits.
77     * @throws NullPointerException
78     *             if {@code protocol} is {@code null} (instead of
79     *             NoSuchAlgorithmException as in 1.4 release)
80     */
81    public static SSLContext getInstance(String protocol, String provider)
82            throws NoSuchAlgorithmException, NoSuchProviderException {
83        if (provider == null) {
84            throw new IllegalArgumentException("Provider is null");
85        }
86        if (provider.length() == 0) {
87            throw new IllegalArgumentException("Provider is empty");
88        }
89        Provider impProvider = Security.getProvider(provider);
90        if (impProvider == null) {
91            throw new NoSuchProviderException(provider);
92        }
93        return getInstance(protocol, impProvider);
94    }
95
96    /**
97     * Creates a new {@code SSLContext} instance for the specified protocol from
98     * the specified provider.
99     *
100     * @param protocol
101     *            the requested protocol to create a context for
102     * @param provider
103     *            the provider that provides the requested protocol.
104     * @return an {@code SSLContext} for the requested protocol.
105     * @throws NoSuchAlgorithmException
106     *             if the specified provider cannot provide the requested
107     *             protocol.
108     * @throws NullPointerException
109     *             if {@code protocol} is {@code null} (instead of
110     *             NoSuchAlgorithmException as in 1.4 release)
111     */
112    public static SSLContext getInstance(String protocol, Provider provider)
113            throws NoSuchAlgorithmException {
114        if (provider == null) {
115            throw new IllegalArgumentException("provider is null");
116        }
117        if (protocol == null) {
118            throw new NullPointerException("protocol is null");
119        }
120        synchronized (engine) {
121            engine.getInstance(protocol, provider, null);
122            return new SSLContext((SSLContextSpi) engine.spi, provider, protocol);
123        }
124    }
125
126    private final Provider provider;
127
128    private final SSLContextSpi spiImpl;
129
130    private final String protocol;
131
132    /**
133     * Creates a new {@code SSLContext}.
134     *
135     * @param contextSpi
136     *            the implementation delegate.
137     * @param provider
138     *            the provider.
139     * @param protocol
140     *            the protocol name.
141     */
142    protected SSLContext(SSLContextSpi contextSpi, Provider provider, String protocol) {
143        this.provider = provider;
144        this.protocol = protocol;
145        this.spiImpl = contextSpi;
146    }
147
148    /**
149     * Returns the name of the secure socket protocol of this instance.
150     *
151     * @return the name of the secure socket protocol of this instance.
152     */
153    public final String getProtocol() {
154        return protocol;
155    }
156
157    /**
158     * Returns the provider of this {@code SSLContext} instance.
159     *
160     * @return the provider of this {@code SSLContext} instance.
161     */
162    public final Provider getProvider() {
163        return provider;
164    }
165
166    /**
167     * Initializes this {@code SSLContext} instance. All of the arguments are
168     * optional, and the security providers will be searched for the required
169     * implementations of the needed algorithms.
170     *
171     * @param km
172     *            the key sources or {@code null}.
173     * @param tm
174     *            the trust decision sources or {@code null}.
175     * @param sr
176     *            the randomness source or {@code null.}
177     * @throws KeyManagementException
178     *             if initializing this instance fails.
179     */
180    public final void init(KeyManager[] km, TrustManager[] tm, SecureRandom sr)
181            throws KeyManagementException {
182        spiImpl.engineInit(km, tm, sr);
183    }
184
185    /**
186     * Returns a socket factory for this instance.
187     *
188     * @return a socket factory for this instance.
189     */
190    public final SSLSocketFactory getSocketFactory() {
191        return spiImpl.engineGetSocketFactory();
192    }
193
194    /**
195     * Returns a server socket factory for this instance.
196     *
197     * @return a server socket factory for this instance.
198     */
199    public final SSLServerSocketFactory getServerSocketFactory() {
200        return spiImpl.engineGetServerSocketFactory();
201    }
202
203    /**
204     * Creates an {@code SSLEngine} instance from this context.
205     *
206     * @return an {@code SSLEngine} instance from this context.
207     * @throws UnsupportedOperationException
208     *             if the provider does not support the operation.
209     */
210    public final SSLEngine createSSLEngine() {
211        return spiImpl.engineCreateSSLEngine();
212    }
213
214    /**
215     * Creates an {@code SSLEngine} instance from this context with the
216     * specified hostname and port.
217     *
218     * @param peerHost
219     *            the name of the host
220     * @param peerPort
221     *            the port
222     * @return an {@code SSLEngine} instance from this context.
223     * @throws UnsupportedOperationException
224     *             if the provider does not support the operation.
225     */
226    public final SSLEngine createSSLEngine(String peerHost, int peerPort) {
227        return spiImpl.engineCreateSSLEngine(peerHost, peerPort);
228    }
229
230    /**
231     * Returns the SSL session context that encapsulates the set of SSL sessions
232     * that can be used for handshake of server-side SSL sockets.
233     *
234     * @return the SSL server session context for this context or {@code null}
235     *         if the underlying provider does not provide an implementation of
236     *         the {@code SSLSessionContext} interface.
237     */
238    public final SSLSessionContext getServerSessionContext() {
239        return spiImpl.engineGetServerSessionContext();
240    }
241
242    /**
243     * Returns the SSL session context that encapsulates the set of SSL sessions
244     * that can be used for handshake of client-side SSL sockets.
245     *
246     * @return the SSL client session context for this context or {@code null}
247     *         if the underlying provider does not provide an implementation of
248     *         the {@code SSLSessionContext} interface.
249     */
250    public final SSLSessionContext getClientSessionContext() {
251        return spiImpl.engineGetClientSessionContext();
252    }
253}
254