316382: support a more strict SSL option with certificates 

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/sandbox/trunk@2782 7e9141cc-0065-0410-87d8-b60c137991c4
diff --git a/jetty-exssl/src/main/java/org/eclipse/jetty/client/HttpClient.java b/jetty-exssl/src/main/java/org/eclipse/jetty/client/HttpClient.java
index 207f6f6..c62ad5e 100644
--- a/jetty-exssl/src/main/java/org/eclipse/jetty/client/HttpClient.java
+++ b/jetty-exssl/src/main/java/org/eclipse/jetty/client/HttpClient.java
@@ -455,7 +455,8 @@
             ((LifeCycle)_threadPool).start();
         }
 
-
+        _sslContextFactory.start();
+        
         if (_connectorType == CONNECTOR_SELECT_CHANNEL)
         {
 
@@ -500,6 +501,8 @@
     {
         _connector.stop();
         _connector = null;
+        _sslContextFactory.stop();
+        
         if (_threadPool instanceof LifeCycle)
         {
             ((LifeCycle)_threadPool).stop();
@@ -528,11 +531,20 @@
      */
     protected SSLContext getSSLContext()
     {
-        return _sslContextFactory.getClientSslContext();
+        return _sslContextFactory.getSslContext();
     }
 
     /* ------------------------------------------------------------ */
     /**
+     * @return the instance of SslContextFactory associated with the client
+     */
+    public SslContextFactory getSslContextFactory()
+    {
+        return _sslContextFactory;
+    }
+    
+    /* ------------------------------------------------------------ */
+    /**
      * @return the period in milliseconds a {@link HttpConnection} can be idle for before it is closed.
      */
     public long getIdleTimeout()
@@ -670,146 +682,173 @@
     }
 
     /* ------------------------------------------------------------ */
+    @Deprecated
     public String getTrustStoreLocation()
     {
         return _sslContextFactory.getTruststore();
     }
 
     /* ------------------------------------------------------------ */
+    @Deprecated
     public void setTrustStoreLocation(String trustStoreLocation)
     {
         _sslContextFactory.setTruststore(trustStoreLocation);
     }
 
+    /* ------------------------------------------------------------ */
+    @Deprecated
     public InputStream getTrustStoreInputStream()
     {
         return _sslContextFactory.getTruststoreInputStream();
     }
 
+    /* ------------------------------------------------------------ */
+    @Deprecated
     public void setTrustStoreInputStream(InputStream trustStoreInputStream)
     {
         _sslContextFactory.setTruststoreInputStream(trustStoreInputStream);
     }
 
     /* ------------------------------------------------------------ */
+    @Deprecated
     public String getKeyStoreLocation()
     {
         return _sslContextFactory.getKeystore();
     }
 
     /* ------------------------------------------------------------ */
+    @Deprecated
     public void setKeyStoreLocation(String keyStoreLocation)
     {
         _sslContextFactory.setKeystore(keyStoreLocation);
     }
 
+    @Deprecated
     public InputStream getKeyStoreInputStream()
     {
         return _sslContextFactory.getKeystoreInputStream();
     }
 
+    @Deprecated
     public void setKeyStoreInputStream(InputStream keyStoreInputStream)
     {
         _sslContextFactory.setKeystoreInputStream(keyStoreInputStream);
     }
 
     /* ------------------------------------------------------------ */
+    @Deprecated
     public void setKeyStorePassword(String keyStorePassword)
     {
         _sslContextFactory.setKeystorePassword(keyStorePassword);
     }
 
     /* ------------------------------------------------------------ */
+    @Deprecated
     public void setKeyManagerPassword(String keyManagerPassword)
     {
         _sslContextFactory.setKeyManagerPassword(keyManagerPassword);
     }
 
     /* ------------------------------------------------------------ */
+    @Deprecated
     public void setTrustStorePassword(String trustStorePassword)
     {
         _sslContextFactory.setTruststorePassword(trustStorePassword);
     }
 
     /* ------------------------------------------------------------ */
+    @Deprecated
     public String getKeyStoreType()
     {
         return _sslContextFactory.getKeystoreType();
     }
 
     /* ------------------------------------------------------------ */
+    @Deprecated
     public void setKeyStoreType(String keyStoreType)
     {
         _sslContextFactory.setKeystoreType(keyStoreType);
     }
 
     /* ------------------------------------------------------------ */
+    @Deprecated
     public String getTrustStoreType()
     {
         return _sslContextFactory.getTruststoreType();
     }
 
     /* ------------------------------------------------------------ */
+    @Deprecated
     public void setTrustStoreType(String trustStoreType)
     {
         _sslContextFactory.setTruststoreType(trustStoreType);
     }
 
     /* ------------------------------------------------------------ */
+    @Deprecated
     public String getKeyManagerAlgorithm()
     {
         return _sslContextFactory.getSslKeyManagerFactoryAlgorithm();
     }
 
     /* ------------------------------------------------------------ */
+    @Deprecated
     public void setKeyManagerAlgorithm(String keyManagerAlgorithm)
     {
         _sslContextFactory.setSslKeyManagerFactoryAlgorithm(keyManagerAlgorithm);
     }
 
     /* ------------------------------------------------------------ */
+    @Deprecated
     public String getTrustManagerAlgorithm()
     {
         return _sslContextFactory.getTrustManagerFactoryAlgorithm();
     }
 
     /* ------------------------------------------------------------ */
+    @Deprecated
     public void setTrustManagerAlgorithm(String trustManagerAlgorithm)
     {
         _sslContextFactory.setTrustManagerFactoryAlgorithm(trustManagerAlgorithm);
     }
 
     /* ------------------------------------------------------------ */
+    @Deprecated
     public String getProtocol()
     {
         return _sslContextFactory.getProtocol();
     }
 
     /* ------------------------------------------------------------ */
+    @Deprecated
     public void setProtocol(String protocol)
     {
         _sslContextFactory.setProtocol(protocol);
     }
 
     /* ------------------------------------------------------------ */
+    @Deprecated
     public String getProvider()
     {
         return _sslContextFactory.getProvider();
     }
 
     /* ------------------------------------------------------------ */
+    @Deprecated
     public void setProvider(String provider)
     {
         setProvider(provider);
     }
 
     /* ------------------------------------------------------------ */
+    @Deprecated
     public String getSecureRandomAlgorithm()
     {
         return _sslContextFactory.getSecureRandomAlgorithm();
     }
 
     /* ------------------------------------------------------------ */
+    @Deprecated
     public void setSecureRandomAlgorithm(String secureRandomAlgorithm)
     {
         _sslContextFactory.setSecureRandomAlgorithm(secureRandomAlgorithm);
diff --git a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/AliasedX509ExtendedKeyManager.java b/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/AliasedX509ExtendedKeyManager.java
index 7bc2590..39fcaea 100644
--- a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/AliasedX509ExtendedKeyManager.java
+++ b/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/AliasedX509ExtendedKeyManager.java
@@ -29,6 +29,8 @@
 /* ------------------------------------------------------------ */
 /**
  * KeyManager to select a key with desired alias
+ * while delegating processing to specified KeyManager
+ * Can be used both with server and client sockets
  */
 public class AliasedX509ExtendedKeyManager extends X509ExtendedKeyManager
 {
@@ -36,6 +38,12 @@
     private X509KeyManager _keyManager;
 
     /* ------------------------------------------------------------ */
+    /**
+     * Construct KeyManager instance
+     * @param keyAlias Alias of the key to be selected
+     * @param keyManager Instance of KeyManager to be wrapped
+     * @throws Exception
+     */
     public AliasedX509ExtendedKeyManager(String keyAlias, X509KeyManager keyManager) throws Exception
     {
         _keyAlias = keyAlias;
diff --git a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/AliasedX509KeyManager.java b/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/AliasedX509KeyManager.java
index 48d04bc..f0ef3df 100644
--- a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/AliasedX509KeyManager.java
+++ b/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/AliasedX509KeyManager.java
@@ -27,6 +27,8 @@
 /* ------------------------------------------------------------ */
 /**
  * KeyManager to select a key with desired alias
+ * while delegating processing to specified KeyManager
+ * Can be used both with server and client sockets
  */
 public class AliasedX509KeyManager implements X509KeyManager
 {
@@ -34,6 +36,12 @@
     private X509KeyManager _keyManager;
 
     /* ------------------------------------------------------------ */
+    /**
+     * Construct KeyManager instance
+     * @param keyAlias Alias of the key to be selected
+     * @param keyManager Instance of KeyManager to be wrapped
+     * @throws Exception
+     */
     public AliasedX509KeyManager(String keyAlias, X509KeyManager keyManager) throws Exception
     {
         _keyAlias = keyAlias;
diff --git a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslConnector.java b/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslConnector.java
index 8a1ba0e..5b86cab 100644
--- a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslConnector.java
+++ b/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslConnector.java
@@ -35,6 +35,13 @@
     /** String name of keystore password property. @deprecated */
     @Deprecated
     public static final String PASSWORD_PROPERTY = "org.eclipse.jetty.ssl.password";
+    
+    
+    /* ------------------------------------------------------------ */
+    /**
+     * @return the instance of SslContextFactory associated with the connector
+     */
+    public SslContextFactory getSslContextFactory();
         
     /* ------------------------------------------------------------ */
     /**
diff --git a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSelectChannelConnector.java b/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSelectChannelConnector.java
index 42deeae..d00b351 100644
--- a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSelectChannelConnector.java
+++ b/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSelectChannelConnector.java
@@ -504,6 +504,16 @@
 
     /* ------------------------------------------------------------ */
     /**
+     * @see org.eclipse.jetty.server.ssl.SslConnector#getSslContextFactory()
+     */
+//    @Override
+    public SslContextFactory getSslContextFactory()
+    {
+        return _sslContextFactory;
+    }
+
+    /* ------------------------------------------------------------ */
+    /**
      * By default, we're confidential, given we speak SSL. But, if we've been
      * told about an confidential port, and said port is not our port, then
      * we're not. This allows separation of listeners providing INTEGRAL versus
@@ -586,7 +596,12 @@
     @Override
     protected void doStart() throws Exception
     {
-        _sslContextFactory.createSSLContext(); // called here to prevent exception wrapping 
+        if (!_sslContextFactory.checkConfig())
+        {
+            throw new IllegalStateException("SSL context is not configured correctly.");
+        }
+        
+        _sslContextFactory.start(); 
         
         SSLEngine sslEngine = _sslContextFactory.getSslContext().createSSLEngine();
 
@@ -633,7 +648,23 @@
 
         super.doStart();
     }
+    
+    /* ------------------------------------------------------------ */
+    /**
+     * @see org.eclipse.jetty.server.nio.SelectChannelConnector#doStop()
+     */
+    @Override
+    protected void doStop() throws Exception
+    {
+        _sslContextFactory.stop(); 
 
+        super.doStop();
+    }
+
+    /* ------------------------------------------------------------ */
+    /**
+     * @return SSL buffers
+     */
     public Buffers getSslBuffers()
     {
         return _sslBuffers;
diff --git a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSocketConnector.java b/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSocketConnector.java
index 6cc75b9..389beff 100644
--- a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSocketConnector.java
+++ b/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSocketConnector.java
@@ -296,6 +296,16 @@
 
     /* ------------------------------------------------------------ */
     /**
+     * @see org.eclipse.jetty.server.ssl.SslConnector#getSslContextFactory()
+     */
+//    @Override
+    public SslContextFactory getSslContextFactory()
+    {
+        return _sslContextFactory;
+    }
+
+    /* ------------------------------------------------------------ */
+    /**
      * @see org.eclipse.jetty.server.ssl.SslConnector#getTruststoreType()
      * @deprecated
      */
@@ -353,13 +363,30 @@
     @Override
     protected void doStart() throws Exception
     {
-        _sslContextFactory.createSSLContext(); // called here to prevent exception wrapping
+        if (!_sslContextFactory.checkConfig())
+        {
+            throw new IllegalStateException("SSL context is not configured correctly.");
+        }
+
+        _sslContextFactory.start();
         
         super.doStart();
     }
         
     /* ------------------------------------------------------------ */
     /**
+     * @see org.eclipse.jetty.server.bio.SocketConnector#doStop()
+     */
+    @Override
+    protected void doStop() throws Exception
+    {
+        _sslContextFactory.stop();
+
+        super.doStop();
+    }
+    
+    /* ------------------------------------------------------------ */
+    /**
      * @param host The host name that this server should listen on
      * @param port the port that this server should listen on 
      * @param backlog See {@link ServerSocket#bind(java.net.SocketAddress, int)}
diff --git a/jetty-exssl/src/main/java/org/eclipse/jetty/io/SslContextFactory.java b/jetty-exssl/src/main/java/org/eclipse/jetty/io/SslContextFactory.java
index e7b0a03..b2d2689 100644
--- a/jetty-exssl/src/main/java/org/eclipse/jetty/io/SslContextFactory.java
+++ b/jetty-exssl/src/main/java/org/eclipse/jetty/io/SslContextFactory.java
@@ -30,7 +30,6 @@
 import java.security.cert.CollectionCertStoreParameters;
 import java.security.cert.PKIXBuilderParameters;
 import java.security.cert.X509CertSelector;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -51,11 +50,19 @@
 import org.eclipse.jetty.exssl.AliasedX509ExtendedKeyManager;
 import org.eclipse.jetty.http.security.Password;
 import org.eclipse.jetty.util.IO;
+import org.eclipse.jetty.util.component.AbstractLifeCycle;
 import org.eclipse.jetty.util.resource.Resource;
 import org.eclipse.jetty.util.security.CertificateValidator;
 
 
-public class SslContextFactory
+/* ------------------------------------------------------------ */
+/**
+ * SslContextFactory is used to configure SSL connectors
+ * as well as HttpClient. It holds all SSL parameters and
+ * creates SSL context based on these parameters to be
+ * used by the SSL connectors. 
+ */
+public class SslContextFactory extends AbstractLifeCycle
 {
     public static final String DEFAULT_KEYMANAGERFACTORY_ALGORITHM = 
         (Security.getProperty("ssl.KeyManagerFactory.algorithm") == null ?
@@ -109,16 +116,16 @@
     /** Set to true if renegotiation is allowed */
     private boolean _allowRenegotiate = false;
 
-    /** KeyStore password */
+    /** Keystore password */
     private transient Password _keystorePassword;
-    /** Key password */
+    /** Key manager password */
     private transient Password _keymanagerPassword;
-    /** TrustStore password */
+    /** Truststore password */
     private transient Password _truststorePassword;
 
-    /** SSL Provider name */
+    /** SSL provider name */
     private String _sslProvider;
-    /** SSL Protocol name */
+    /** SSL protocol name */
     private String _sslProtocol = "TLS";
 
     /** SecureRandom algorithm */
@@ -135,13 +142,62 @@
 
     /** SSL context */
     private SSLContext _context;
+
+    /* ------------------------------------------------------------ */
+    /**
+     * Construct an instance of SslContextFactory
+     * Default constructor for use in XmlConfiguration files
+     */
+    public SslContextFactory()
+    {
+    }
     
-    public SslContextFactory() {}
-    
+    /* ------------------------------------------------------------ */
+    /**
+     * Construct an instance of SslContextFactory
+     * @param keystorePath default keystore location
+     */
     public SslContextFactory(String keystorePath)
     {
         _keystorePath = keystorePath;
     }
+    
+    /* ------------------------------------------------------------ */
+    /**
+     * Create the SSLContext object and start the lifecycle
+     * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
+     */
+    @Override
+    protected void doStart() throws Exception
+    {
+        if (_keystoreInputStream == null && _keystorePath == null &&
+                _truststoreInputStream == null && _truststorePath == null )
+        {
+            // Create a trust manager that does not validate certificate chains
+            TrustManager trustAllCerts = new X509TrustManager()
+            {
+                public java.security.cert.X509Certificate[] getAcceptedIssuers()
+                {
+                    return null;
+                }
+
+                public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
+                {
+                }
+
+                public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
+                {
+                }
+            };
+
+            _context = SSLContext.getInstance(_sslProtocol);
+            _context.init(null, new TrustManager[]{trustAllCerts}, null);
+        }
+        else
+        {
+            createSSLContext();
+        }
+    }
 
     /* ------------------------------------------------------------ */
     /**
@@ -161,6 +217,8 @@
      */
     public void setExcludeCipherSuites(String[] cipherSuites)
     {
+        checkStarted();
+        
         _excludeCipherSuites = new HashSet<String>(Arrays.asList(cipherSuites));
     }
 
@@ -182,6 +240,8 @@
      */
     public void setIncludeCipherSuites(String[] cipherSuites)
     {
+        checkStarted();
+        
         _includeCipherSuites = new HashSet<String>(Arrays.asList(cipherSuites));
     }
 
@@ -201,6 +261,8 @@
      */
     public void setKeystore(String keystore)
     {
+        checkStarted();
+        
         _keystorePath = keystore;
     }
 
@@ -220,6 +282,8 @@
      */
     public void setKeystoreProvider(String keystoreProvider)
     {
+        checkStarted();
+        
         _keystoreProvider = keystoreProvider;
     }
 
@@ -239,6 +303,8 @@
      */
     public void setKeystoreType(String keystoreType)
     {
+        checkStarted();
+        
         _keystoreType = keystoreType;
     }
 
@@ -259,6 +325,8 @@
      */
     public void setKeystoreInputStream(InputStream keystoreInputStream)
     {
+        checkStarted();
+        
         _keystoreInputStream = keystoreInputStream;
     }
 
@@ -278,6 +346,8 @@
      */
     public void setCertAlias(String certAlias)
     {
+        checkStarted();
+        
         _certAlias = certAlias;
     }
 
@@ -297,6 +367,8 @@
      */
     public void setTruststore(String truststore)
     {
+        checkStarted();
+        
         _truststorePath = truststore;
     }
 
@@ -316,6 +388,8 @@
      */
     public void setTruststoreProvider(String truststoreProvider)
     {
+        checkStarted();
+        
         _truststoreProvider = truststoreProvider;
     }
 
@@ -335,6 +409,8 @@
      */
     public void setTruststoreType(String truststoreType)
     {
+        checkStarted();
+        
         _truststoreType = truststoreType;
     }
 
@@ -355,6 +431,8 @@
      */
     public void setTruststoreInputStream(InputStream truststoreInputStream)
     {
+        checkStarted();
+        
         _truststoreInputStream = truststoreInputStream;
     }
 
@@ -376,6 +454,8 @@
      */
     public void setNeedClientAuth(boolean needClientAuth)
     {
+        checkStarted();
+        
         _needClientAuth = needClientAuth;
     }
 
@@ -397,6 +477,8 @@
      */
     public void setWantClientAuth(boolean wantClientAuth)
     {
+        checkStarted();
+        
         _wantClientAuth = wantClientAuth;
     }
 
@@ -416,6 +498,8 @@
      */
     public void setValidateCerts(boolean validateCerts)
     {
+        checkStarted();
+        
         _validateCerts = validateCerts;
     }
 
@@ -439,6 +523,8 @@
      */
     public void setAllowRenegotiate(boolean allowRenegotiate)
     {
+        checkStarted();
+        
         _allowRenegotiate = allowRenegotiate;
     }
 
@@ -449,6 +535,8 @@
      */
     public void setKeystorePassword(String password)
     {
+        checkStarted();
+        
         _keystorePassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
     }
 
@@ -459,6 +547,8 @@
      */
     public void setKeyManagerPassword(String password)
     {
+        checkStarted();
+        
         _keymanagerPassword = Password.getPassword(KEYPASSWORD_PROPERTY,password,null);
     }
 
@@ -469,6 +559,8 @@
      */
     public void setTruststorePassword(String password)
     {
+        checkStarted();
+        
         _truststorePassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
     }
 
@@ -490,6 +582,8 @@
      */
     public void setProvider(String provider)
     {
+        checkStarted();
+        
         _sslProvider = provider;
     }
 
@@ -511,6 +605,8 @@
      */
     public void setProtocol(String protocol)
     {
+        checkStarted();
+        
         _sslProtocol = protocol;
     }
 
@@ -534,6 +630,8 @@
      */
     public void setSecureRandomAlgorithm(String algorithm)
     {
+        checkStarted();
+        
         _secureRandomAlgorithm = algorithm;
     }
 
@@ -553,6 +651,8 @@
      */
     public void setSslKeyManagerFactoryAlgorithm(String algorithm)
     {
+        checkStarted();
+        
         _keyManagerFactoryAlgorithm = algorithm;
     }
 
@@ -572,6 +672,8 @@
      */
     public void setTrustManagerFactoryAlgorithm(String algorithm)
     {
+        checkStarted();
+        
         _trustManagerFactoryAlgorithm = algorithm;
     }
 
@@ -591,6 +693,8 @@
      */
     public void setCrlPath(String crlPath)
     {
+        checkStarted();
+        
         _crlPath = crlPath;
     }
 
@@ -612,6 +716,8 @@
      */
     public void setMaxCertPathLength(int maxCertPathLength)
     {
+        checkStarted();
+        
         _maxCertPathLength = maxCertPathLength;
     }
 
@@ -621,16 +727,6 @@
      */
     public SSLContext getSslContext()
     {
-        try
-        {
-            if (_context == null)
-                _context = createSSLContext();
-        }
-        catch (Exception e)
-        {
-            throw new RuntimeException(e);
-        }
-
         return _context;
     }
 
@@ -641,69 +737,16 @@
      */
     public void setSslContext(SSLContext sslContext)
     {
+        checkStarted();
+        
         _context = sslContext;
     }
-    
-    /* ------------------------------------------------------------ */
-    /**
-     * @return The SSLContext
-     */
-    public SSLContext getClientSslContext()
-    {
-        try
-        {
-            if (_context == null)
-                _context = createClientSSLContext();
-        }
-        catch (Exception e)
-        {
-            throw new RuntimeException(e);
-        }
-
-        return _context;
-    }
 
     /* ------------------------------------------------------------ */
     /**
-     * @return SSL context for the client code
+     * @throws Exception
      */
-    public SSLContext createClientSSLContext() throws Exception
-    {
-        SSLContext sslContext = null;
-        
-        if (_keystoreInputStream == null && _keystorePath == null &&
-                _truststoreInputStream == null && _truststorePath == null )
-        {
-            // Create a trust manager that does not validate certificate chains
-            TrustManager trustAllCerts = new X509TrustManager()
-            {
-                public java.security.cert.X509Certificate[] getAcceptedIssuers()
-                {
-                    return null;
-                }
-
-                public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
-                {
-                }
-
-                public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
-                {
-                }
-            };
-
-            sslContext = SSLContext.getInstance(_sslProtocol);
-            sslContext.init(null, new TrustManager[]{trustAllCerts}, null);
-        }
-        else
-        {
-            sslContext = createSSLContext();
-        }
-        
-        return sslContext;
-    }
-
-    /* ------------------------------------------------------------ */
-    public SSLContext createSSLContext() throws Exception
+    protected void createSSLContext() throws Exception
     {
         // verify that keystore and truststore 
         // parameters are set up correctly  
@@ -737,26 +780,29 @@
         TrustManager[] trustManagers = getTrustManagers(trustStore,crls);
 
         SecureRandom secureRandom = _secureRandomAlgorithm == null?null:SecureRandom.getInstance(_secureRandomAlgorithm);
-        SSLContext context = _sslProvider == null?SSLContext.getInstance(_sslProtocol):SSLContext.getInstance(_sslProtocol,_sslProvider);
-        context.init(keyManagers,trustManagers,secureRandom);
-
-        return context;
+        _context = _sslProvider == null?SSLContext.getInstance(_sslProtocol):SSLContext.getInstance(_sslProtocol,_sslProvider);
+        _context.init(keyManagers,trustManagers,secureRandom);
     }
 
     /* ------------------------------------------------------------ */
     protected KeyManager[] getKeyManagers(KeyStore keyStore) throws Exception
     {
-        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(_keyManagerFactoryAlgorithm);
-        keyManagerFactory.init(keyStore,_keymanagerPassword == null?(_keystorePassword == null?null:_keystorePassword.toString().toCharArray()):_keymanagerPassword.toString().toCharArray());
-        KeyManager[] managers = keyManagerFactory.getKeyManagers();
-
-        if (_certAlias != null)
+        KeyManager[] managers = null;
+        
+        if (keyStore != null)
         {
-            for (int idx = 0; idx < managers.length; idx++)
+            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(_keyManagerFactoryAlgorithm);
+            keyManagerFactory.init(keyStore,_keymanagerPassword == null?(_keystorePassword == null?null:_keystorePassword.toString().toCharArray()):_keymanagerPassword.toString().toCharArray());
+            managers = keyManagerFactory.getKeyManagers();
+    
+            if (_certAlias != null)
             {
-                if (managers[idx] instanceof X509KeyManager)
+                for (int idx = 0; idx < managers.length; idx++)
                 {
-                    managers[idx] = new AliasedX509ExtendedKeyManager(_certAlias,(X509KeyManager)managers[idx]);
+                    if (managers[idx] instanceof X509KeyManager)
+                    {
+                        managers[idx] = new AliasedX509ExtendedKeyManager(_certAlias,(X509KeyManager)managers[idx]);
+                    }
                 }
             }
         }
@@ -768,41 +814,44 @@
     protected TrustManager[] getTrustManagers(KeyStore trustStore, Collection<? extends CRL> crls) throws Exception
     {
         TrustManager[] managers = null;
-        if (trustStore != null && _validateCerts)
+        if (trustStore != null)
         {
-            // Revocation checking is only supported for PKIX algorithm
-            if (_trustManagerFactoryAlgorithm.equalsIgnoreCase("PKIX"))
+            if(_validateCerts)
             {
-                PKIXBuilderParameters pbParams = new PKIXBuilderParameters(trustStore,new X509CertSelector());
-
-                // Enable revocation checking
-                pbParams.setRevocationEnabled(true);
-
-                // Set maximum certification path length
-                pbParams.setMaxPathLength(_maxCertPathLength);
-
-                if (crls != null && !crls.isEmpty())
+                // Revocation checking is only supported for PKIX algorithm
+                if (_trustManagerFactoryAlgorithm.equalsIgnoreCase("PKIX"))
                 {
-                    pbParams.addCertStore(CertStore.getInstance("Collection",new CollectionCertStoreParameters(crls)));
+                    PKIXBuilderParameters pbParams = new PKIXBuilderParameters(trustStore,new X509CertSelector());
+    
+                    // Enable revocation checking
+                    pbParams.setRevocationEnabled(true);
+    
+                    // Set maximum certification path length
+                    pbParams.setMaxPathLength(_maxCertPathLength);
+    
+                    if (crls != null && !crls.isEmpty())
+                    {
+                        pbParams.addCertStore(CertStore.getInstance("Collection",new CollectionCertStoreParameters(crls)));
+                    }
+    
+                    // Enable On-Line Certificate Status Protocol (OCSP) support
+                    Security.setProperty("ocsp.enable","true");
+    
+                    // Enable Certificate Revocation List Distribution Points (CRLDP) support
+                    System.setProperty("com.sun.security.enableCRLDP","true");
+    
+                    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerFactoryAlgorithm);
+                    trustManagerFactory.init(new CertPathTrustManagerParameters(pbParams));
+    
+                    managers = trustManagerFactory.getTrustManagers();
                 }
-
-                // Enable On-Line Certificate Status Protocol (OCSP) support
-                Security.setProperty("ocsp.enable","true");
-
-                // Enable Certificate Revocation List Distribution Points (CRLDP) support
-                System.setProperty("com.sun.security.enableCRLDP","true");
-
-                TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerFactoryAlgorithm);
-                trustManagerFactory.init(new CertPathTrustManagerParameters(pbParams));
-
-                managers = trustManagerFactory.getTrustManagers();
-            }
-            else
-            {
-                TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerFactoryAlgorithm);
-                trustManagerFactory.init(trustStore);
-
-                managers = trustManagerFactory.getTrustManagers();
+                else
+                {
+                    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerFactoryAlgorithm);
+                    trustManagerFactory.init(trustStore);
+    
+                    managers = trustManagerFactory.getTrustManagers();
+                }
             }
         }
 
@@ -872,14 +921,25 @@
         return crlList;
     }
     
-    protected void checkConfig()
+    /* ------------------------------------------------------------ */
+    /**
+     * Check configuration. Ensures that if keystore has been
+     * configured but there's no truststore, that keystore is
+     * used as truststore.
+     * @return true SslContextFactory configuration can be used in server connector.
+     */
+    public boolean checkConfig()
     {
-        /*
-         * if the keystore exists but the trust store 
-         * does not, use the keystore as the trust store
-         */
-        if (_keystoreInputStream != null || _keystorePath != null)
+        boolean check = true;
+        if (_keystoreInputStream == null && _keystorePath == null)
         {
+            // configuration doesn't have a valid keystore
+            check = false;
+        }
+        else 
+        {
+             // if the keystore has been configured but there is no 
+             // truststore configured, use the keystore as the truststore
             if (_truststoreInputStream == null && _truststorePath == null)
             {
                 _truststorePath = _keystorePath;
@@ -908,8 +968,19 @@
                 throw new RuntimeException(ex);
             }
         }
+        
+        return check;
     }
 
+    /* ------------------------------------------------------------ */
+    /**
+     * Select cipher suites to be used by the connector
+     * based on configured inclusion and exclusion lists
+     * as well as enabled and supported cipher suite lists.
+     * @param enabledCipherSuites Array of enabled cipher suites 
+     * @param supportedCipherSuites Array of supported cipher suites  
+     * @return Array of cipher suites to enable
+     */
     public String[] selectCipherSuites(String[] enabledCipherSuites, String[] supportedCipherSuites)
     {
         Set<String> selectedCipherSuites = null;
@@ -922,13 +993,15 @@
             selectedCipherSuites = new HashSet<String>();
         }
 
-        if ((supportedCipherSuites != null && supportedCipherSuites.length > 0) && (_includeCipherSuites != null && _includeCipherSuites.size() > 0))
+        if ((supportedCipherSuites != null && supportedCipherSuites.length > 0) && 
+            (_includeCipherSuites != null && _includeCipherSuites.size() > 0))
         {
             Set<String> supportedCSList = new HashSet<String>(Arrays.asList(supportedCipherSuites));
             
             for (String cipherName : _includeCipherSuites)
             {
-                if ((!selectedCipherSuites.contains(cipherName)) && supportedCSList.contains(cipherName))
+                if ((!selectedCipherSuites.contains(cipherName)) && 
+                    supportedCSList.contains(cipherName))
                 {
                     selectedCipherSuites.add(cipherName);
                 }
@@ -948,4 +1021,16 @@
 
         return selectedCipherSuites.toArray(new String[selectedCipherSuites.size()]);
     }
+    
+    /* ------------------------------------------------------------ */
+    /**
+     * Check if the lifecycle has been started and throw runtime exception
+     */
+    protected void checkStarted()
+    {
+        if (isStarted())
+        {
+            throw new IllegalStateException("Cannot modify configuration after SslContextFactory was started");
+        }
+    }
 }
diff --git a/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/CertificateValidatorTest.java b/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/CertificateValidatorTest.java
index aa64a15..3801232 100644
--- a/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/CertificateValidatorTest.java
+++ b/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/CertificateValidatorTest.java
@@ -15,7 +15,7 @@
         String trustpath = new File(System.getProperty("java.home"),"./lib/security/cacerts").getAbsolutePath();
         String crlpath = MavenTestingUtils.getTestResourceFile("crlfile.pem").getAbsolutePath();
 
-        SslContextFactory factory = new SslContextFactory();
+        SslContextFactory factory = new SslContextFactory(null);
         factory.setValidateCerts(true);
         factory.setKeystore(keypath);
         factory.setKeystorePassword("webtide");
@@ -24,7 +24,7 @@
         factory.setTruststorePassword("changeit");
         factory.setCrlPath(crlpath);
         
-        factory.createSSLContext();
+        factory.start();
     }
     
     @Test
diff --git a/jetty-exssl/src/test/java/org/eclipse/jetty/client/ContentExchangeTest.java b/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/ContentExchangeTest.java
similarity index 98%
rename from jetty-exssl/src/test/java/org/eclipse/jetty/client/ContentExchangeTest.java
rename to jetty-exssl/src/test/java/org/eclipse/jetty/exssl/ContentExchangeTest.java
index b1321af..de58ae4 100644
--- a/jetty-exssl/src/test/java/org/eclipse/jetty/client/ContentExchangeTest.java
+++ b/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/ContentExchangeTest.java
@@ -11,7 +11,7 @@
 // You may elect to redistribute this code under either of these licenses. 
 // ========================================================================
 
-package org.eclipse.jetty.client;
+package org.eclipse.jetty.exssl;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -29,6 +29,8 @@
 
 import junit.framework.TestCase;
 
+import org.eclipse.jetty.client.ContentExchange;
+import org.eclipse.jetty.client.HttpClient;
 import org.eclipse.jetty.client.security.Realm;
 import org.eclipse.jetty.client.security.SimpleRealmResolver;
 import org.eclipse.jetty.http.HttpMethods;
diff --git a/jetty-exssl/src/test/java/org/eclipse/jetty/client/SslContentExchangeTest.java b/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/SslContentExchangeTest.java
similarity index 95%
rename from jetty-exssl/src/test/java/org/eclipse/jetty/client/SslContentExchangeTest.java
rename to jetty-exssl/src/test/java/org/eclipse/jetty/exssl/SslContentExchangeTest.java
index 7dfb21e..9f96f07 100644
--- a/jetty-exssl/src/test/java/org/eclipse/jetty/client/SslContentExchangeTest.java
+++ b/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/SslContentExchangeTest.java
@@ -11,14 +11,13 @@
 // You may elect to redistribute this code under either of these licenses. 
 // ========================================================================
 
-package org.eclipse.jetty.client;
+package org.eclipse.jetty.exssl;
 
 import java.io.File;
 
 import org.eclipse.jetty.server.Handler;
 import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.server.handler.HandlerCollection;
-import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
 import org.eclipse.jetty.servlet.DefaultServlet;
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.servlet.ServletHolder;
diff --git a/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/SslValidationTestBase.java b/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/SslValidationTestBase.java
index f835623..a04f779 100644
--- a/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/SslValidationTestBase.java
+++ b/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/SslValidationTestBase.java
@@ -4,7 +4,6 @@
 import java.lang.reflect.Constructor;
 
 import org.eclipse.jetty.client.HttpClient;
-import org.eclipse.jetty.client.SslContentExchangeTest;
 import org.eclipse.jetty.io.SslContextFactory;
 import org.eclipse.jetty.server.Handler;
 import org.eclipse.jetty.server.Server;
@@ -43,6 +42,7 @@
         
         Constructor<? extends SslConnector> constructor = __klass.getConstructor(SslContextFactory.class);
         SslConnector connector = constructor.newInstance(srvFactory);
+        connector.setMaxIdleTime(5000);
         server.addConnector(connector);
 
         Handler handler = new TestHandler(getBasePath());
@@ -59,13 +59,13 @@
         server.setHandler( handlers ); 
     }
     
-//    @Override
-//    protected void configureClient(HttpClient client)
-//        throws Exception
-//    {
-//        String trustpath = new File(System.getProperty("java.home"),"./lib/security/cacerts").getAbsolutePath();
-//        client.setTrustStoreLocation(trustpath);
-//        client.setTrustStorePassword("changeit");
-//        client.setConnectorType(__konnector);
-//    }
+    @Override
+    protected void configureClient(HttpClient client)
+        throws Exception
+    {
+        String trustpath = new File(System.getProperty("java.home"),"./lib/security/cacerts").getAbsolutePath();
+        client.setTrustStoreLocation(trustpath);
+        client.setTrustStorePassword("changeit");
+        client.setConnectorType(__konnector);
+    }
 }