Re-factoring in support of https://issues.apache.org/bugzilla/show_bug.cgi?id=50360
authormarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 9 Dec 2010 18:10:38 +0000 (18:10 +0000)
committermarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 9 Dec 2010 18:10:38 +0000 (18:10 +0000)
Move ad-hoc attribute handling from the ProtocolHandler to the Endpoint and expose the Endpoint to ServerSocketFactory objects so they can retrieve additional configuration if required. All default components now use explicit configuration rather than relying on the ad-hoc mechanism.
Ensure the hooks for alternative SSL implementations are in place (were partially removed).
Remove the hooks for alternative ServerSocketFactory implementations (had been hard-coded / half implemented for some time).
Make the sslEnabledProtocols attribute work with BIO as well.

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1044058 13f79535-47bb-0310-9956-ffa450edef68

18 files changed:
java/org/apache/catalina/connector/Connector.java
java/org/apache/coyote/AbstractProtocolHandler.java
java/org/apache/coyote/ProtocolHandler.java
java/org/apache/coyote/ajp/AjpProtocol.java
java/org/apache/coyote/http11/AbstractHttp11JsseProtocol.java
java/org/apache/coyote/http11/AbstractHttp11Protocol.java
java/org/apache/coyote/http11/Http11NioProtocol.java
java/org/apache/coyote/http11/Http11Protocol.java
java/org/apache/tomcat/util/net/AbstractEndpoint.java
java/org/apache/tomcat/util/net/DefaultServerSocketFactory.java
java/org/apache/tomcat/util/net/JIoEndpoint.java
java/org/apache/tomcat/util/net/NioEndpoint.java
java/org/apache/tomcat/util/net/SSLImplementation.java
java/org/apache/tomcat/util/net/ServerSocketFactory.java
java/org/apache/tomcat/util/net/jsse/JSSEFactory.java
java/org/apache/tomcat/util/net/jsse/JSSEImplementation.java
java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
webapps/docs/config/http.xml

index 4b8185b..619b28c 100644 (file)
@@ -249,7 +249,6 @@ public class Connector extends LifecycleMBeanBase  {
          replacements.put("connectionTimeout", "soTimeout");
          replacements.put("randomFile", "randomfile");
          replacements.put("rootFile", "rootfile");
-         replacements.put("sslProtocols", "protocols");
      }
 
 
index a8040eb..b7a00c4 100644 (file)
@@ -17,8 +17,6 @@
 package org.apache.coyote;
 
 import java.net.InetAddress;
-import java.util.HashMap;
-import java.util.Iterator;
 import java.util.concurrent.Executor;
 
 import javax.management.MBeanRegistration;
@@ -65,55 +63,6 @@ public abstract class AbstractProtocolHandler implements ProtocolHandler,
     // ----------------------------------------------- Generic property handling
 
     /**
-     * Attributes provide a way for configuration to be passed to sub-components
-     * without the {@link ProtocolHandler} being aware of the properties
-     * available on those sub-components. One example of such a sub-component is
-     * the {@link org.apache.tomcat.util.net.ServerSocketFactory}.
-     */
-    protected HashMap<String, Object> attributes =
-        new HashMap<String, Object>();
-
-
-    /** 
-     * Generic property setter called when a property for which a specific
-     * setter already exists within the {@link ProtocolHandler} needs to be
-     * made available to sub-components. The specific setter will call this
-     * method to populate the attributes.
-     */
-    @Override
-    public void setAttribute(String name, Object value) {
-        if (getLog().isTraceEnabled()) {
-            getLog().trace(sm.getString("abstractProtocolHandler.setAttribute",
-                    name, value));
-        }
-        attributes.put(name, value);
-    }
-
-    
-    /**
-     * Used by sub-components to retrieve configuration information.
-     */
-    @Override
-    public Object getAttribute(String key) {
-        Object value = attributes.get(key);
-        if (getLog().isTraceEnabled()) {
-            getLog().trace(sm.getString("abstractProtocolHandler.getAttribute",
-                    key, value));
-        }
-        return value;
-    }
-
-
-    /**
-     * Used by sub-components to retrieve configuration information.
-     */
-    @Override
-    public Iterator<String> getAttributeNames() {
-        return attributes.keySet().iterator();
-    }
-
-
-    /**
      * Generic property setter used by the digester. Other code should not need
      * to use this. The digester will only use this method if it can't find a
      * more specific setter. That means the property belongs to the Endpoint,
@@ -121,7 +70,6 @@ public abstract class AbstractProtocolHandler implements ProtocolHandler,
      * ensures that it is visible to both.
      */
     public boolean setProperty(String name, String value) {
-        setAttribute(name, value);
         return endpoint.setProperty(name, value);
     }
 
@@ -131,9 +79,7 @@ public abstract class AbstractProtocolHandler implements ProtocolHandler,
      * to use this.
      */
     public String getProperty(String name) {
-        // Since all calls to setProperty() will place the property in the
-        // attributes list, just retrieve it from there. 
-        return (String)getAttribute(name);
+        return endpoint.getProperty(name);
     }
 
 
@@ -217,14 +163,12 @@ public abstract class AbstractProtocolHandler implements ProtocolHandler,
     public InetAddress getAddress() { return endpoint.getAddress(); }
     public void setAddress(InetAddress ia) {
         endpoint.setAddress(ia);
-        setAttribute("address", ia.toString());
     }
 
 
     public int getPort() { return endpoint.getPort(); }
     public void setPort(int port) {
         endpoint.setPort(port);
-        setAttribute("port", Integer.toString(port));
     }
 
 
@@ -239,10 +183,6 @@ public abstract class AbstractProtocolHandler implements ProtocolHandler,
     public void setConnectionTimeout(int timeout) {
         // Note that the endpoint uses the alternative name
         endpoint.setSoTimeout(timeout);
-        String str = Integer.toString(timeout);
-        setAttribute("connectionTimeout", str);
-        // Also set the attribute for the alternative name
-        setAttribute("soTimeout", str);
     }
 
     /*
index 8b2f608..b1594c8 100644 (file)
@@ -17,7 +17,6 @@
 
 package org.apache.coyote;
 
-import java.util.Iterator;
 import java.util.concurrent.Executor;
 
 
@@ -37,14 +36,6 @@ import java.util.concurrent.Executor;
 public interface ProtocolHandler {
 
     /**
-     * Pass config info.
-     */
-    public void setAttribute(String name, Object value);
-    public Object getAttribute(String name);
-    public Iterator<String> getAttributeNames();
-
-    
-    /**
      * The adapter, used to call the connector.
      */
     public void setAdapter(Adapter adapter);
index 5ec65ca..3a4ea2c 100644 (file)
@@ -34,6 +34,7 @@ import org.apache.tomcat.util.modeler.Registry;
 import org.apache.tomcat.util.net.AbstractEndpoint;
 import org.apache.tomcat.util.net.JIoEndpoint;
 import org.apache.tomcat.util.net.JIoEndpoint.Handler;
+import org.apache.tomcat.util.net.SSLImplementation;
 import org.apache.tomcat.util.net.SocketStatus;
 import org.apache.tomcat.util.net.SocketWrapper;
 
@@ -145,6 +146,12 @@ public class AjpProtocol extends AbstractAjpProtocol {
         }
 
         @Override
+        public SSLImplementation getSslImplementation() {
+            // AJP does not support SSL
+            return null;
+        }
+
+        @Override
         public void recycle() {
             recycledProcessors.clear();
         }
@@ -251,7 +258,6 @@ public class AjpProtocol extends AbstractAjpProtocol {
                 }
             }
         }
-
     }
 
 }
index 8786fb4..2f79756 100644 (file)
@@ -17,7 +17,6 @@
 package org.apache.coyote.http11;
 
 import org.apache.tomcat.util.net.SSLImplementation;
-import org.apache.tomcat.util.net.jsse.JSSEImplementation;
 
 public abstract class AbstractHttp11JsseProtocol
         extends AbstractHttp11Protocol {
@@ -104,12 +103,19 @@ public abstract class AbstractHttp11JsseProtocol
         return endpoint.getAllowUnsafeLegacyRenegotiation();
     }
 
+    private String sslImplemenationName = null;
+    public String getSslImplemenationName() { return sslImplemenationName; }
+    public void setSslImplemenationName(String s) {
+        this.sslImplemenationName = s;
+    }
 
     // ------------------------------------------------------- Lifecycle methods
 
     @Override
     public void init() throws Exception {
+        // SSL implementation needs to be in place before end point is
+        // initialized
+        sslImplementation = SSLImplementation.getInstance(sslImplemenationName);
         super.init();
-        sslImplementation = new JSSEImplementation();
     }
 }
index 3b9748d..648409b 100644 (file)
@@ -166,7 +166,6 @@ public abstract class AbstractHttp11Protocol extends AbstractProtocolHandler {
     public boolean getSecure() { return secure; }
     public void setSecure(boolean b) { 
         secure = b;         
-        setAttribute("secure", "" + b);
     }
     
 
@@ -179,7 +178,6 @@ public abstract class AbstractHttp11Protocol extends AbstractProtocolHandler {
     }
     public void setMaxKeepAliveRequests(int mkar) {
         endpoint.setMaxKeepAliveRequests(mkar);
-        setAttribute("maxKeepAliveRequests", "" + mkar);
     }
 
     
index a0f4017..8460ae4 100644 (file)
@@ -37,6 +37,7 @@ import org.apache.tomcat.util.net.AbstractEndpoint;
 import org.apache.tomcat.util.net.NioChannel;
 import org.apache.tomcat.util.net.NioEndpoint;
 import org.apache.tomcat.util.net.NioEndpoint.Handler;
+import org.apache.tomcat.util.net.SSLImplementation;
 import org.apache.tomcat.util.net.SecureNioChannel;
 import org.apache.tomcat.util.net.SocketStatus;
 
@@ -110,12 +111,10 @@ public class Http11NioProtocol extends AbstractHttp11JsseProtocol {
     
     public void setAcceptorThreadPriority(int threadPriority) {
         ((NioEndpoint)endpoint).setAcceptorThreadPriority(threadPriority);
-      setAttribute("acceptorThreadPriority", "" + threadPriority);
     }
 
     public void setPollerThreadPriority(int threadPriority) {
         ((NioEndpoint)endpoint).setPollerThreadPriority(threadPriority);
-      setAttribute("pollerThreadPriority", "" + threadPriority);
     }
 
     public int getAcceptorThreadPriority() {
@@ -142,12 +141,10 @@ public class Http11NioProtocol extends AbstractHttp11JsseProtocol {
 
     public void setSocketCloseDelay( int d ) {
         socketCloseDelay=d;
-        setAttribute("socketCloseDelay", "" + d);
     }
 
     public void setOomParachute(int oomParachute) {
         ((NioEndpoint)endpoint).setOomParachute(oomParachute);
-        setAttribute("oomParachute", Integer.valueOf(oomParachute));
     }
 
     // --------------------  SSL related properties --------------------
@@ -217,6 +214,10 @@ public class Http11NioProtocol extends AbstractHttp11JsseProtocol {
             recycledProcessors.clear();
         }
         
+        public SSLImplementation getSslImplementation() {
+            return proto.sslImplementation;
+        }
+
         @Override
         public void release(SocketChannel socket) {
             if (log.isDebugEnabled()) 
index 00a61cf..11b5a91 100644 (file)
@@ -35,6 +35,7 @@ import org.apache.tomcat.util.modeler.Registry;
 import org.apache.tomcat.util.net.AbstractEndpoint;
 import org.apache.tomcat.util.net.JIoEndpoint;
 import org.apache.tomcat.util.net.JIoEndpoint.Handler;
+import org.apache.tomcat.util.net.SSLImplementation;
 import org.apache.tomcat.util.net.SocketStatus;
 import org.apache.tomcat.util.net.SocketWrapper;
 
@@ -142,6 +143,10 @@ public class Http11Protocol extends AbstractHttp11JsseProtocol {
             return global;
         }
 
+        public SSLImplementation getSslImplementation() {
+            return proto.sslImplementation;
+        }
+
         @Override
         public void recycle() {
             recycledProcessors.clear();
index 070ae7d..0744891 100644 (file)
@@ -20,6 +20,8 @@ import java.io.File;
 import java.io.OutputStreamWriter;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.StringTokenizer;
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
@@ -320,10 +322,44 @@ public abstract class AbstractEndpoint {
 
     protected abstract boolean getDeferAccept();
 
+
+    /**
+     * Attributes provide a way for configuration to be passed to sub-components
+     * without the {@link ProtocolHandler} being aware of the properties
+     * available on those sub-components. One example of such a sub-component is
+     * the {@link org.apache.tomcat.util.net.ServerSocketFactory}.
+     */
+    protected HashMap<String, Object> attributes =
+        new HashMap<String, Object>();
+    /** 
+     * Generic property setter called when a property for which a specific
+     * setter already exists within the {@link ProtocolHandler} needs to be
+     * made available to sub-components. The specific setter will call this
+     * method to populate the attributes.
+     */
+    public void setAttribute(String name, Object value) {
+        if (getLog().isTraceEnabled()) {
+            getLog().trace(sm.getString("abstractProtocolHandler.setAttribute",
+                    name, value));
+        }
+        attributes.put(name, value);
+    }
     /**
-     * Generic properties, introspected
+     * Used by sub-components to retrieve configuration information.
      */
+    public Object getAttribute(String key) {
+        Object value = attributes.get(key);
+        if (getLog().isTraceEnabled()) {
+            getLog().trace(sm.getString("abstractProtocolHandler.getAttribute",
+                    key, value));
+        }
+        return value;
+    }
+
+
+
     public boolean setProperty(String name, String value) {
+        setAttribute(name, value);
         final String socketName = "socket.";
         try {
             if (name.startsWith(socketName)) {
@@ -336,7 +372,10 @@ public abstract class AbstractEndpoint {
             return false;
         }
     }
-
+    public String getProperty(String name) {
+        return (String) getAttribute(name);
+    }
+    
     /**
      * Return the amount of threads that are managed by the pool.
      *
@@ -632,11 +671,24 @@ public abstract class AbstractEndpoint {
 
 
     private String[] sslEnabledProtocolsarr =  new String[0];
-    public String[] getSslEnabledProtocolsArray() { return this.sslEnabledProtocolsarr;}
+    public String[] getSslEnabledProtocolsArray() {
+        return this.sslEnabledProtocolsarr;
+    }
     public void setSslEnabledProtocols(String s) {
-        StringTokenizer t = new StringTokenizer(s,",");
-        sslEnabledProtocolsarr = new String[t.countTokens()];
-        for (int i=0; i<sslEnabledProtocolsarr.length; i++ ) sslEnabledProtocolsarr[i] = t.nextToken();
+        if (s == null) {
+            this.sslEnabledProtocolsarr = new String[0];
+        } else {
+            ArrayList<String> sslEnabledProtocols = new ArrayList<String>();
+            StringTokenizer t = new StringTokenizer(s,",");
+            while (t.hasMoreTokens()) {
+                String p = t.nextToken().trim();
+                if (p.length() > 0) {
+                    sslEnabledProtocols.add(p);
+                }
+            }
+            sslEnabledProtocolsarr = sslEnabledProtocols.toArray(
+                    new String[sslEnabledProtocols.size()]);
+        }
     }
 
 }
index 1b4c7f0..4ee222d 100644 (file)
@@ -29,48 +29,38 @@ import java.net.Socket;
  * @author db@eng.sun.com
  * @author Harish Prabandham
  */
+public class DefaultServerSocketFactory implements ServerSocketFactory {
 
-// Default implementation of server sockets.
+    private AbstractEndpoint endpoint;
 
-//
-// WARNING: Some of the APIs in this class are used by J2EE. 
-// Please talk to harishp@eng.sun.com before making any changes.
-//
-class DefaultServerSocketFactory extends ServerSocketFactory {
-
-    DefaultServerSocketFactory () {
-        /* NOTHING */
+    public DefaultServerSocketFactory(AbstractEndpoint endpoint) {
+        this.endpoint = endpoint;
     }
 
     @Override
-    public ServerSocket createSocket (int port)
-    throws IOException {
+    public ServerSocket createSocket (int port) throws IOException {
         return  new ServerSocket (port);
     }
 
     @Override
     public ServerSocket createSocket (int port, int backlog)
-    throws IOException {
+            throws IOException {
         return new ServerSocket (port, backlog);
     }
 
     @Override
     public ServerSocket createSocket (int port, int backlog,
-        InetAddress ifAddress)
-    throws IOException {
+            InetAddress ifAddress) throws IOException {
         return new ServerSocket (port, backlog, ifAddress);
     }
+
     @Override
-    public Socket acceptSocket(ServerSocket socket)
-            throws IOException {
+    public Socket acceptSocket(ServerSocket socket) throws IOException {
         return socket.accept();
     }
+
     @Override
-    public void handshake(Socket sock)
-        throws IOException {
+    public void handshake(Socket sock) throws IOException {
         // NOOP
     }
-        
 }
index 24c5e18..1ca3c92 100644 (file)
@@ -119,7 +119,9 @@ public class JIoEndpoint extends AbstractEndpoint {
      */
     public interface Handler extends AbstractEndpoint.Handler {
         public SocketState process(SocketWrapper<Socket> socket);
-        public SocketState process(SocketWrapper<Socket> socket, SocketStatus status);
+        public SocketState process(SocketWrapper<Socket> socket,
+                SocketStatus status);
+        public SSLImplementation getSslImplementation(); 
     }
 
 
@@ -333,57 +335,22 @@ public class JIoEndpoint extends AbstractEndpoint {
             acceptorThreadCount = 1;
         }
         if (serverSocketFactory == null) {
-            serverSocketFactory = ServerSocketFactory.getDefault();
-        }
-        if (isSSLEnabled()) {
-            serverSocketFactory.setAttribute(SSL_ATTR_ALGORITHM,
-                    getAlgorithm());
-            serverSocketFactory.setAttribute(SSL_ATTR_CLIENT_AUTH,
-                    getClientAuth());
-            serverSocketFactory.setAttribute(SSL_ATTR_KEYSTORE_FILE,
-                    getKeystoreFile());
-            serverSocketFactory.setAttribute(SSL_ATTR_KEYSTORE_PASS,
-                    getKeystorePass());
-            serverSocketFactory.setAttribute(SSL_ATTR_KEYSTORE_TYPE,
-                    getKeystoreType());
-            serverSocketFactory.setAttribute(SSL_ATTR_KEYSTORE_PROVIDER,
-                    getKeystoreProvider());
-            serverSocketFactory.setAttribute(SSL_ATTR_SSL_PROTOCOL,
-                    getSslProtocol());
-            serverSocketFactory.setAttribute(SSL_ATTR_CIPHERS,
-                    getCiphers());
-            serverSocketFactory.setAttribute(SSL_ATTR_KEY_ALIAS,
-                    getKeyAlias());
-            serverSocketFactory.setAttribute(SSL_ATTR_KEY_PASS,
-                    getKeyPass());
-            serverSocketFactory.setAttribute(SSL_ATTR_TRUSTSTORE_FILE,
-                    getTruststoreFile());
-            serverSocketFactory.setAttribute(SSL_ATTR_TRUSTSTORE_PASS,
-                    getTruststorePass());
-            serverSocketFactory.setAttribute(SSL_ATTR_TRUSTSTORE_TYPE,
-                    getTruststoreType());
-            serverSocketFactory.setAttribute(SSL_ATTR_TRUSTSTORE_PROVIDER,
-                    getTruststoreProvider());
-            serverSocketFactory.setAttribute(SSL_ATTR_TRUSTSTORE_ALGORITHM,
-                    getTruststoreAlgorithm());
-            serverSocketFactory.setAttribute(SSL_ATTR_CRL_FILE,
-                    getCrlFile());
-            serverSocketFactory.setAttribute(SSL_ATTR_TRUST_MAX_CERT_LENGTH,
-                    getTrustMaxCertLength());
-            serverSocketFactory.setAttribute(SSL_ATTR_SESSION_CACHE_SIZE,
-                    getSessionCacheSize());
-            serverSocketFactory.setAttribute(SSL_ATTR_SESSION_TIMEOUT,
-                    getSessionTimeout());
-            serverSocketFactory.setAttribute(SSL_ATTR_ALLOW_UNSAFE_RENEG,
-                    getAllowUnsafeLegacyRenegotiation());
+            if (isSSLEnabled()) {
+                serverSocketFactory =
+                    handler.getSslImplementation().getServerSocketFactory(this);
+            } else {
+                serverSocketFactory = new DefaultServerSocketFactory(this);
+            }
         }
 
         if (serverSocket == null) {
             try {
                 if (getAddress() == null) {
-                    serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog());
+                    serverSocket = serverSocketFactory.createSocket(getPort(),
+                            getBacklog());
                 } else {
-                    serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog(), getAddress());
+                    serverSocket = serverSocketFactory.createSocket(getPort(),
+                            getBacklog(), getAddress());
                 }
             } catch (BindException orig) {
                 String msg;
@@ -397,11 +364,8 @@ public class JIoEndpoint extends AbstractEndpoint {
                 throw be;
             }
         }
-        //if( serverTimeout >= 0 )
-        //    serverSocket.setSoTimeout( serverTimeout );
         
         initialized = true;
-        
     }
     
     @Override
@@ -475,8 +439,6 @@ public class JIoEndpoint extends AbstractEndpoint {
      * Configure the socket.
      */
     protected boolean setSocketOptions(Socket socket) {
-        serverSocketFactory.initSocket(socket);
-        
         try {
             // 1: Set socket options: timeout, linger, etc
             socketProperties.setProperties(socket);
index 2df3759..11d557a 100644 (file)
@@ -1500,6 +1500,7 @@ public class NioEndpoint extends AbstractEndpoint {
         public SocketState event(NioChannel socket, SocketStatus status);
         public void release(NioChannel socket);
         public void release(SocketChannel socket);
+        public SSLImplementation getSslImplementation();
     }
 
 
index f9a6613..a194af9 100644 (file)
@@ -80,7 +80,8 @@ public abstract class SSLImplementation {
 
     public abstract String getImplementationName();
 
-    public abstract ServerSocketFactory getServerSocketFactory();
+    public abstract ServerSocketFactory getServerSocketFactory(
+            AbstractEndpoint endpoint);
 
     public abstract SSLSupport getSSLSupport(Socket sock);
 
index d87223c..5d77925 100644 (file)
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
 package org.apache.tomcat.util.net;
 
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.ServerSocket;
 import java.net.Socket;
-import java.util.Hashtable;
 
 /**
- * This class creates server sockets. It may be subclassed by other factories,
- * which create particular types of server sockets. This provides a general
- * framework for the addition of public socket-level functionality. It it is the
- * server side analogue of a socket factory, and similarly provides a way to
- * capture a variety of policies related to the sockets being constructed.
- * <P>
- * Like socket factories, Server Socket factory instances have two categories of
- * methods. First are methods used to create sockets. Second are methods which
- * set properties used in the production of sockets, such as networking options.
- * There is also an environment specific default server socket factory;
- * frameworks will often use their own customized factory.
- * <P>
- * <hr>
- * <em> It may be desirable to move this interface into the
- * <b>java.net</b> package, so that is not an extension but the preferred
- * interface.  Should this be serializable, making it a JavaBean which can
- * be saved along with its networking configuration?
- * </em>
- * 
- * @author db@eng.sun.com
- * @author Harish Prabandham
+ * The common interface through which the {@link JIoEndpoint} interacts with
+ * both non-SSL and SSL sockets. 
  */
-public abstract class ServerSocketFactory implements Cloneable {
-
-    //
-    // NOTE: JDK 1.1 bug in class GC, this can get collected
-    // even though it's always accessible via getDefault().
-    //
-
-    private static ServerSocketFactory theFactory;
-    protected Hashtable<String, Object> attributes = new Hashtable<String, Object>();
-
-    /**
-     * Constructor is used only by subclasses.
-     */
-    protected ServerSocketFactory() {
-        /* NOTHING */
-    }
-
-    /**
-     * General mechanism to pass attributes from the ServerConnector to the
-     * socket factory. Note that the "preferred" mechanism is to use bean
-     * setters and explicit methods, but this allows easy configuration via
-     * server.xml or simple Properties
-     */
-    public void setAttribute(String name, Object value) {
-        if (name != null && value != null)
-            attributes.put(name, value);
-    }
-
-    /**
-     * Returns a copy of the environment's default socket factory.
-     */
-    public static synchronized ServerSocketFactory getDefault() {
-        //
-        // optimize typical case: no synch needed
-        //
-
-        if (theFactory == null) {
-            //
-            // Different implementations of this method could
-            // work rather differently. For example, driving
-            // this from a system property, or using a different
-            // implementation than JavaSoft's.
-            //
-
-            theFactory = new DefaultServerSocketFactory();
-        }
-
-        try {
-            return (ServerSocketFactory) theFactory.clone();
-        } catch (CloneNotSupportedException e) {
-            throw new RuntimeException(e.getMessage());
-        }
-    }
+public interface ServerSocketFactory {
 
     /**
      * Returns a server socket which uses all network interfaces on the host,
@@ -112,7 +39,7 @@ public abstract class ServerSocketFactory implements Cloneable {
      * @exception InstantiationException
      *                for construction errors
      */
-    public abstract ServerSocket createSocket(int port) throws IOException,
+    ServerSocket createSocket(int port) throws IOException,
             InstantiationException;
 
     /**
@@ -130,8 +57,8 @@ public abstract class ServerSocketFactory implements Cloneable {
      * @exception InstantiationException
      *                for construction errors
      */
-    public abstract ServerSocket createSocket(int port, int backlog)
-            throws IOException, InstantiationException;
+    ServerSocket createSocket(int port, int backlog) throws IOException,
+            InstantiationException;
 
     /**
      * Returns a server socket which uses only the specified network interface
@@ -150,26 +77,21 @@ public abstract class ServerSocketFactory implements Cloneable {
      * @exception InstantiationException
      *                for construction errors
      */
-    public abstract ServerSocket createSocket(int port, int backlog,
-            InetAddress ifAddress) throws IOException, InstantiationException;
-
-    public void initSocket(Socket s) {
-    }
+    ServerSocket createSocket(int port, int backlog, InetAddress ifAddress)
+            throws IOException, InstantiationException;
 
     /**
      * Wrapper function for accept(). This allows us to trap and translate
-     * exceptions if necessary
+     * exceptions if necessary.
      * 
      * @exception IOException
-     *                ;
      */
-    public abstract Socket acceptSocket(ServerSocket socket) throws IOException;
+    Socket acceptSocket(ServerSocket socket) throws IOException;
 
     /**
-     * Extra function to initiate the handshake. Sometimes necessary for SSL
+     * Triggers the SSL handshake. This will be a no-op for non-SSL sockets.
      * 
      * @exception IOException
-     *                ;
      */
-    public abstract void handshake(Socket sock) throws IOException;
+    void handshake(Socket sock) throws IOException;
 }
index 7745748..dcb0354 100644 (file)
@@ -22,6 +22,7 @@ import java.net.Socket;
 import javax.net.ssl.SSLSession;
 import javax.net.ssl.SSLSocket;
 
+import org.apache.tomcat.util.net.AbstractEndpoint;
 import org.apache.tomcat.util.net.SSLSupport;
 import org.apache.tomcat.util.net.ServerSocketFactory;
 
@@ -38,8 +39,8 @@ public class JSSEFactory {
     /**
      * Returns the ServerSocketFactory to use.
      */
-    public ServerSocketFactory getSocketFactory() {
-        return new JSSESocketFactory();
+    public ServerSocketFactory getSocketFactory(AbstractEndpoint endpoint) {
+        return new JSSESocketFactory(endpoint);
     }
 
     /**
index 45d3e0d..671423d 100644 (file)
@@ -21,6 +21,7 @@ import java.net.Socket;
 
 import javax.net.ssl.SSLSession;
 
+import org.apache.tomcat.util.net.AbstractEndpoint;
 import org.apache.tomcat.util.net.SSLImplementation;
 import org.apache.tomcat.util.net.SSLSupport;
 import org.apache.tomcat.util.net.ServerSocketFactory;
@@ -47,8 +48,8 @@ public class JSSEImplementation extends SSLImplementation {
     }
       
     @Override
-    public ServerSocketFactory getServerSocketFactory()  {
-        ServerSocketFactory ssf = factory.getSocketFactory();
+    public ServerSocketFactory getServerSocketFactory(AbstractEndpoint endpoint)  {
+        ServerSocketFactory ssf = factory.getSocketFactory(endpoint);
         return ssf;
     } 
 
index bf9540c..7e8ca6f 100644 (file)
@@ -60,6 +60,7 @@ import javax.net.ssl.X509KeyManager;
 
 import org.apache.catalina.Globals;
 import org.apache.tomcat.util.net.AbstractEndpoint;
+import org.apache.tomcat.util.net.ServerSocketFactory;
 import org.apache.tomcat.util.res.StringManager;
 
 /**
@@ -75,8 +76,7 @@ import org.apache.tomcat.util.res.StringManager;
  * @author Jan Luehe
  * @author Bill Barker
  */
-public class JSSESocketFactory
-    extends org.apache.tomcat.util.net.ServerSocketFactory {
+public class JSSESocketFactory implements ServerSocketFactory {
 
     private static final StringManager sm =
         StringManager.getManager("org.apache.tomcat.util.net.jsse.res");
@@ -94,6 +94,8 @@ public class JSSESocketFactory
     static final org.apache.juli.logging.Log log =
         org.apache.juli.logging.LogFactory.getLog(JSSESocketFactory.class);
 
+    private AbstractEndpoint endpoint;
+
     protected boolean initialized;
     protected SSLServerSocketFactory sslProxy = null;
     protected String[] enabledCiphers;
@@ -110,8 +112,8 @@ public class JSSESocketFactory
     protected boolean wantClientAuth    = false;
 
 
-    public JSSESocketFactory () {
-        // NOOP
+    public JSSESocketFactory (AbstractEndpoint endpoint) {
+        this.endpoint = endpoint;
     }
 
     @Override
@@ -256,13 +258,11 @@ public class JSSESocketFactory
      * Gets the SSL server's keystore password.
      */
     protected String getKeystorePassword() {
-        String keyPass = (String)attributes.get(
-                AbstractEndpoint.SSL_ATTR_KEY_PASS);
+        String keyPass = endpoint.getKeyPass();
         if (keyPass == null) {
             keyPass = DEFAULT_KEY_PASS;
         }
-        String keystorePass = (String)attributes.get(
-                AbstractEndpoint.SSL_ATTR_KEYSTORE_PASS);
+        String keystorePass = endpoint.getKeystorePass();
         if (keystorePass == null) {
             keystorePass = keyPass;
         }
@@ -275,8 +275,7 @@ public class JSSESocketFactory
     protected KeyStore getKeystore(String type, String provider, String pass)
             throws IOException {
 
-        String keystoreFile = (String)attributes.get(
-                AbstractEndpoint.SSL_ATTR_KEYSTORE_FILE);
+        String keystoreFile = endpoint.getKeystoreFile();
         if (keystoreFile == null)
             keystoreFile = defaultKeystoreFile;
 
@@ -290,8 +289,7 @@ public class JSSESocketFactory
             String keystoreProvider) throws IOException {
         KeyStore trustStore = null;
 
-        String truststoreFile = (String)attributes.get(
-                AbstractEndpoint.SSL_ATTR_TRUSTSTORE_FILE);
+        String truststoreFile = endpoint.getTruststoreFile();
         if(truststoreFile == null) {
             truststoreFile = System.getProperty("javax.net.ssl.trustStore");
         }
@@ -299,8 +297,7 @@ public class JSSESocketFactory
             log.debug("Truststore = " + truststoreFile);
         }
 
-        String truststorePassword = (String)attributes.get(
-                AbstractEndpoint.SSL_ATTR_TRUSTSTORE_PASS);
+        String truststorePassword = endpoint.getTruststorePass();
         if( truststorePassword == null) {
             truststorePassword =
                 System.getProperty("javax.net.ssl.trustStorePassword");
@@ -309,8 +306,7 @@ public class JSSESocketFactory
             log.debug("TrustPass = " + truststorePassword);
         }
 
-        String truststoreType = (String)attributes.get(
-                AbstractEndpoint.SSL_ATTR_TRUSTSTORE_TYPE);
+        String truststoreType = endpoint.getTruststoreType();
         if( truststoreType == null) {
             truststoreType = System.getProperty("javax.net.ssl.trustStoreType");
         }
@@ -321,9 +317,7 @@ public class JSSESocketFactory
             log.debug("trustType = " + truststoreType);
         }
 
-        String truststoreProvider =
-            (String)attributes.get(
-                    AbstractEndpoint.SSL_ATTR_TRUSTSTORE_PROVIDER);
+        String truststoreProvider = endpoint.getTruststoreProvider();
         if( truststoreProvider == null) {
             truststoreProvider =
                 System.getProperty("javax.net.ssl.trustStoreProvider");
@@ -419,8 +413,7 @@ public class JSSESocketFactory
     void init() throws IOException {
         try {
 
-            String clientAuthStr = (String) attributes.get(
-                    AbstractEndpoint.SSL_ATTR_CLIENT_AUTH);
+            String clientAuthStr = endpoint.getClientAuth();
             if("true".equalsIgnoreCase(clientAuthStr) ||
                "yes".equalsIgnoreCase(clientAuthStr)) {
                 requireClientAuth = true;
@@ -429,32 +422,25 @@ public class JSSESocketFactory
             }
 
             // SSL protocol variant (e.g., TLS, SSL v3, etc.)
-            String protocol = (String) attributes.get(
-                    AbstractEndpoint.SSL_ATTR_SSL_PROTOCOL);
+            String protocol = endpoint.getSslProtocol();
             if (protocol == null) {
                 protocol = defaultProtocol;
             }
 
             // Certificate encoding algorithm (e.g., SunX509)
-            String algorithm = (String) attributes.get(
-                    AbstractEndpoint.SSL_ATTR_ALGORITHM);
+            String algorithm = endpoint.getAlgorithm();
             if (algorithm == null) {
                 algorithm = KeyManagerFactory.getDefaultAlgorithm();
             }
 
-            String keystoreType = (String) attributes.get(
-                    AbstractEndpoint.SSL_ATTR_KEYSTORE_TYPE);
+            String keystoreType = endpoint.getKeystoreType();
             if (keystoreType == null) {
                 keystoreType = defaultKeystoreType;
             }
 
-            String keystoreProvider =
-                (String) attributes.get(
-                        AbstractEndpoint.SSL_ATTR_KEYSTORE_PROVIDER);
+            String keystoreProvider = endpoint.getKeystoreProvider();
 
-            String trustAlgorithm =
-                (String)attributes.get(
-                        AbstractEndpoint.SSL_ATTR_TRUSTSTORE_ALGORITHM);
+            String trustAlgorithm = endpoint.getTruststoreAlgorithm();
             if( trustAlgorithm == null ) {
                 trustAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
             }
@@ -463,27 +449,22 @@ public class JSSESocketFactory
             SSLContext context = SSLContext.getInstance(protocol); 
             context.init(getKeyManagers(keystoreType, keystoreProvider,
                     algorithm,
-                    (String) attributes.get(AbstractEndpoint.SSL_ATTR_KEY_ALIAS)),
+                    endpoint.getKeyAlias()),
                     getTrustManagers(keystoreType, keystoreProvider,
                             trustAlgorithm),
                     new SecureRandom());
 
             // Configure SSL session cache
             int sessionCacheSize;
-            if (attributes.get(
-                    AbstractEndpoint.SSL_ATTR_SESSION_CACHE_SIZE) != null) {
+            if (endpoint.getSessionCacheSize() != null) {
                 sessionCacheSize = Integer.parseInt(
-                        (String)attributes.get(
-                                AbstractEndpoint.SSL_ATTR_SESSION_CACHE_SIZE));
+                        endpoint.getSessionCacheSize());
             } else {
                 sessionCacheSize = defaultSessionCacheSize;
             }
             int sessionTimeout;
-            if (attributes.get(
-                    AbstractEndpoint.SSL_ATTR_SESSION_TIMEOUT) != null) {
-                sessionTimeout = Integer.parseInt(
-                        (String)attributes.get(
-                                AbstractEndpoint.SSL_ATTR_SESSION_TIMEOUT));
+            if (endpoint.getSessionTimeout() != null) {
+                sessionTimeout = Integer.parseInt(endpoint.getSessionTimeout());
             } else {
                 sessionTimeout = defaultSessionTimeout;
             }
@@ -498,14 +479,12 @@ public class JSSESocketFactory
             sslProxy = context.getServerSocketFactory();
 
             // Determine which cipher suites to enable
-            String requestedCiphers = (String)attributes.get(
-                    AbstractEndpoint.SSL_ATTR_CIPHERS);
+            String requestedCiphers = endpoint.getCiphers();
             enabledCiphers = getEnabledCiphers(requestedCiphers,
                     sslProxy.getSupportedCipherSuites());
 
-            allowUnsafeLegacyRenegotiation =
-                "true".equals(attributes.get(
-                        AbstractEndpoint.SSL_ATTR_ALLOW_UNSAFE_RENEG));
+            allowUnsafeLegacyRenegotiation = "true".equals(
+                    endpoint.getAllowUnsafeLegacyRenegotiation());
             
             // Check the SSL config is OK
             checkConfig();
@@ -559,8 +538,7 @@ public class JSSESocketFactory
     protected TrustManager[] getTrustManagers(String keystoreType,
             String keystoreProvider, String algorithm)
         throws Exception {
-        String crlf = (String) attributes.get(
-                AbstractEndpoint.SSL_ATTR_CRL_FILE);
+        String crlf = endpoint.getCrlFile();
         
         TrustManager[] tms = null;
         
@@ -608,8 +586,7 @@ public class JSSESocketFactory
             CertStore store = CertStore.getInstance("Collection", csp);
             xparams.addCertStore(store);
             xparams.setRevocationEnabled(true);
-            String trustLength = (String)attributes.get(
-                    AbstractEndpoint.SSL_ATTR_TRUST_MAX_CERT_LENGTH);
+            String trustLength = endpoint.getTrustMaxCertLength();
             if(trustLength != null) {
                 try {
                     xparams.setMaxPathLength(Integer.parseInt(trustLength));
@@ -677,68 +654,36 @@ public class JSSESocketFactory
      * Determines the SSL protocol variants to be enabled.
      *
      * @param socket The socket to get supported list from.
-     * @param requestedProtocols Comma-separated list of requested SSL
-     * protocol variants
+     * @param requestedProtocols Array of requested protocol names all of which
+     *                           must be non-null and non-zero length
      *
      * @return Array of SSL protocol variants to be enabled, or null if none of
      * the requested protocol variants are supported
      */
     protected String[] getEnabledProtocols(SSLServerSocket socket,
-                                           String requestedProtocols){
+                                           String[] requestedProtocols){
         String[] supportedProtocols = socket.getSupportedProtocols();
 
         String[] enabledProtocols = null;
 
-        if (requestedProtocols != null) {
+        if (requestedProtocols != null && requestedProtocols.length > 0) {
             Vector<String> vec = null;
-            String protocol = requestedProtocols;
-            int index = requestedProtocols.indexOf(',');
-            if (index != -1) {
-                int fromIndex = 0;
-                while (index != -1) {
-                    protocol =
-                        requestedProtocols.substring(fromIndex, index).trim();
-                    if (protocol.length() > 0) {
-                        /*
-                         * Check to see if the requested protocol is among the
-                         * supported protocols, i.e., may be enabled
-                         */
-                        for (int i=0; supportedProtocols != null
-                                     && i<supportedProtocols.length; i++) {
-                            if (supportedProtocols[i].equals(protocol)) {
-                                if (vec == null) {
-                                    vec = new Vector<String>();
-                                }
-                                vec.addElement(protocol);
-                                break;
-                            }
-                        }
-                    }
-                    fromIndex = index+1;
-                    index = requestedProtocols.indexOf(',', fromIndex);
-                } // while
-                protocol = requestedProtocols.substring(fromIndex);
-            }
-
-            if (protocol != null) {
-                protocol = protocol.trim();
-                if (protocol.length() > 0) {
-                    /*
-                     * Check to see if the requested protocol is among the
-                     * supported protocols, i.e., may be enabled
-                     */
-                    for (int i=0; supportedProtocols != null
-                                 && i<supportedProtocols.length; i++) {
-                        if (supportedProtocols[i].equals(protocol)) {
-                            if (vec == null) {
-                                vec = new Vector<String>();
-                            }
-                            vec.addElement(protocol);
-                            break;
+            for (String protocol : requestedProtocols) {
+                /*
+                 * Check to see if the requested protocol is among the supported
+                 * protocols, i.e., may be enabled
+                 */
+                for (int i=0; supportedProtocols != null &&
+                        i < supportedProtocols.length; i++) {
+                    if (supportedProtocols[i].equals(protocol)) {
+                        if (vec == null) {
+                            vec = new Vector<String>();
                         }
+                        vec.addElement(protocol);
+                        break;
                     }
                 }
-            }           
+            }
 
             if (vec != null) {
                 enabledProtocols = new String[vec.size()];
@@ -775,7 +720,7 @@ public class JSSESocketFactory
             socket.setEnabledCipherSuites(enabledCiphers);
         }
 
-        String requestedProtocols = (String) attributes.get("protocols");
+        String[] requestedProtocols = endpoint.getSslEnabledProtocolsArray();
         setEnabledProtocols(socket, getEnabledProtocols(socket, 
                                                          requestedProtocols));
 
index 0539267..d6ee336 100644 (file)
   connector uses OpenSSL. Therefore, in addition to using different attributes
   to configure SSL, the APR/native connector also requires keys and certificates
   to be provided in a different format.</p>
-  
+
   <p>The BIO and NIO connectors use the following attributes to configure SSL:
   </p>
 
     </attribute>
 
     <attribute name="sslEnabledProtocols" required="false">
-      <p><strong>NIO only</strong>. The version of the SSL protocols to use. If
-      not specified, the default is "<code>TLSv1,SSLv3,SSLv2Hello</code>".</p>
+      <p>The list of SSL protocols to use. If not specified, the JVM default is
+      used.</p>
+    </attribute>
+
+    <attribute name="sslImplemenationName" required="false">
+      <p>The class name of the SSL implementation to use. If not specified, the
+      default of <code>org.apache.tomcat.util.net.jsse.JSSEImplementation</code>
+      will be used which wraps JVM&apos;s default JSSE provider. Note that the
+      JVM can be configured to use a different JSSE provider as the default.</p>
     </attribute>
 
     <attribute name="sslProtocol" required="false">