001    /* SSLContext.java -- an SSL protocol context.
002       Copyright (C) 2004 Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package javax.net.ssl;
040    
041    import gnu.java.security.Engine;
042    
043    import java.lang.reflect.InvocationTargetException;
044    import java.security.KeyManagementException;
045    import java.security.NoSuchAlgorithmException;
046    import java.security.NoSuchProviderException;
047    import java.security.Provider;
048    import java.security.SecureRandom;
049    import java.security.Security;
050    
051    /**
052     * A "meta-factory" for protocol-specific socket and server socket
053     * factories. This class serves as a clearinghouse for socket
054     * factories and cached session contexts for a particular protocol,
055     * such as SSLv3.
056     *
057     * @author Casey Marshall (rsdio@metastatic.org)
058     */
059    public class SSLContext
060    {
061      // Constants and fields.
062      // ------------------------------------------------------------------
063    
064      /** Service name for SSL contexts. */
065      private static final String SSL_CONTEXT = "SSLContext";
066    
067      /** The underlying engine. */
068      private final SSLContextSpi ctxSpi;
069    
070      /** The provider of the engine class. */
071      private final Provider provider;
072    
073      /** The protocal name. */
074      private final String protocol;
075    
076      // Constructor.
077      // ------------------------------------------------------------------
078    
079      /**
080       * Create a new SSL context.
081       *
082       * @param ctxSpi The context engine.
083       * @param provider The provider of the implementation.
084       * @param protocol The name of the SSL protocol.
085       */
086      protected SSLContext(SSLContextSpi ctxSpi, Provider provider,
087                           String protocol)
088      {
089        this.ctxSpi = ctxSpi;
090        this.provider = provider;
091        this.protocol = protocol;
092      }
093    
094      /**
095       * Get an instance of a context for the specified protocol from the first
096       * provider that implements it.
097       *
098       * @param protocol The name of the protocol to get a context for.
099       * @return The new context.
100       * @throws NoSuchAlgorithmException If no provider implements the given
101       *           protocol.
102       * @throws IllegalArgumentException if <code>protocol</code> is
103       *           <code>null</code> or is an empty string.
104       */
105      public static final SSLContext getInstance(String protocol)
106          throws NoSuchAlgorithmException
107      {
108        Provider[] p = Security.getProviders();
109        NoSuchAlgorithmException lastException = null;
110        for (int i = 0; i < p.length; i++)
111          try
112            {
113              return getInstance(protocol, p[i]);
114            }
115          catch (NoSuchAlgorithmException x)
116            {
117              lastException = x;
118            }
119        if (lastException != null)
120          throw lastException;
121        throw new NoSuchAlgorithmException(protocol);
122      }
123    
124      /**
125       * Get an instance of a context for the specified protocol from the named
126       * provider.
127       *
128       * @param protocol The name of the protocol to get a context for.
129       * @param provider The name of the provider to get the implementation from.
130       * @return The new context.
131       * @throws NoSuchAlgorithmException If the provider does not implement the
132       *           given protocol.
133       * @throws NoSuchProviderException If the named provider does not exist.
134       * @throws IllegalArgumentException if either <code>protocol</code> or
135       *           <code>provider</code> is <code>null</code>, or if
136       *           <code>protocol</code> is an empty string.
137       */
138      public static final SSLContext getInstance(String protocol, String provider)
139          throws NoSuchAlgorithmException, NoSuchProviderException
140      {
141        if (provider == null)
142          throw new IllegalArgumentException("provider MUST NOT be null");
143        Provider p = Security.getProvider(provider);
144        if (p == null)
145          throw new NoSuchProviderException(provider);
146        return getInstance(protocol, p);
147      }
148    
149      /**
150       * Get an instance of a context for the specified protocol from the specified
151       * provider.
152       *
153       * @param protocol The name of the protocol to get a context for.
154       * @param provider The name of the provider to get the implementation from.
155       * @return The new context.
156       * @throws NoSuchAlgorithmException If the provider does not implement the
157       *           given protocol.
158       * @throws IllegalArgumentException if either <code>protocol</code> or
159       *           <code>provider</code> is <code>null</code>, or if
160       *           <code>protocol</code> is an empty string.
161       */
162      public static final SSLContext getInstance(String protocol, Provider provider)
163          throws NoSuchAlgorithmException
164      {
165        StringBuilder sb = new StringBuilder("SSLContext for protocol [")
166            .append(protocol).append("] from provider[")
167            .append(provider).append("] could not be created");
168        Throwable cause;
169        try
170          {
171            Object spi = Engine.getInstance(SSL_CONTEXT, protocol, provider);
172            return new SSLContext((SSLContextSpi) spi, provider, protocol);
173          }
174        catch (InvocationTargetException x)
175          {
176            cause = x.getCause();
177            if (cause instanceof NoSuchAlgorithmException)
178              throw (NoSuchAlgorithmException) cause;
179            if (cause == null)
180              cause = x;
181          }
182        catch (ClassCastException x)
183          {
184            cause = x;
185          }
186        NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
187        x.initCause(cause);
188        throw x;
189      }
190    
191      /**
192       * Creates a new {@link SSLEngine} for this context.
193       *
194       * @return The new SSLEngine.
195       * @since 1.5
196       */
197      public final SSLEngine createSSLEngine ()
198      {
199        return ctxSpi.engineCreateSSLEngine ();
200      }
201    
202      /**
203       * Creates a new {@link SSLEngine} for this context, with a given
204       * host name and port number.
205       *
206       * @param host The local host name.
207       * @param port The local port number.
208       * @return The new SSLEngine.
209       * @since 1.5
210       */
211      public final SSLEngine createSSLEngine (final String host, final int port)
212      {
213        return ctxSpi.engineCreateSSLEngine (host, port);
214      }
215    
216      /**
217       * Returns the set of SSL contexts available for client connections.
218       *
219       * @return The set of SSL contexts available for client connections.
220       */
221      public final SSLSessionContext getClientSessionContext()
222      {
223        return ctxSpi.engineGetClientSessionContext();
224      }
225    
226      /**
227       * Returns the protocol name of this context.
228       *
229       * @return The protocol name of this context.
230       */
231      public final String getProtocol()
232      {
233        return protocol;
234      }
235    
236      /**
237       * Returns the provider of this implementation.
238       *
239       * @return The provider of this implementation.
240       */
241      public final Provider getProvider()
242      {
243        return provider;
244      }
245    
246      /**
247       * Returns the set of SSL contexts available for server connections.
248       *
249       * @return The set of SSL contexts available for server connections.
250       */
251      public final SSLSessionContext getServerSessionContext()
252      {
253        return ctxSpi.engineGetServerSessionContext();
254      }
255    
256      /**
257       * Returns the factory for server SSL sockets.
258       *
259       * @return The factory for server SSL sockets.
260       */
261      public final SSLServerSocketFactory getServerSocketFactory()
262      {
263        return ctxSpi.engineGetServerSocketFactory();
264      }
265    
266      /**
267       * Returns the factory for client SSL sockets.
268       *
269       * @return The factory for client SSL sockets.
270       */
271      public final SSLSocketFactory getSocketFactory()
272      {
273        return ctxSpi.engineGetSocketFactory();
274      }
275    
276      /**
277       * Initializes this context and prepares it for producing socket
278       * factories. All of the parameters are optional; default values are
279       * used if left unspecified.
280       *
281       * @param keyManagers The set of key managers to use.
282       * @param trustManagers The set of trust managers to use.
283       * @param random A source of random bits to use.
284       * @throws KeyManagementException If initialization fails.
285       */
286      public final void init(KeyManager[] keyManagers,
287                             TrustManager[] trustManagers,
288                             SecureRandom random)
289        throws KeyManagementException
290      {
291        ctxSpi.engineInit(keyManagers, trustManagers, random);
292      }
293    }