FileDocCategorySizeDatePackage
SSLSelectorThread.javaAPI DocGlassfish v2 API22511Tue Jul 10 13:20:24 BST 2007com.sun.enterprise.web.connector.grizzly.ssl

SSLSelectorThread

public class SSLSelectorThread extends com.sun.enterprise.web.connector.grizzly.SelectorThread implements com.sun.enterprise.web.connector.grizzly.SecureSelector
SSL over NIO Selector implementation. Mainly, this class replace the clear text implementation by defining the SSL tasks counterpart: SSLReadTask, SSLProcessorTask and SSLByteBufferInputStream. The SSLPipeline is the default and must not be replace unless all its attribute properly implemented.
author
Jean-Francois Arcand

Fields Summary
private org.apache.tomcat.util.net.SSLImplementation
sslImplementation
The SSLImplementation
protected SSLContext
sslContext
The SSLContext associated with the SSL implementation we are running on.
private String[]
enabledCipherSuites
The list of cipher suite
private String[]
enabledProtocols
the list of protocols
private boolean
clientMode
Client mode when handshaking.
private boolean
needClientAuth
Require client Authentication.
private boolean
wantClientAuth
True when requesting authentication.
private static final String
EXPIRE_TIME
Session keep-alive flag.
private boolean
isProtocolConfigured
Has the enabled protocol configured.
private boolean
isCipherConfigured
Has the enabled Cipher configured.
Constructors Summary
public SSLSelectorThread()

    
    // ---------------------------------------------------------------------/.
    
    
     
        super();
        setPipelineClassName(com.sun.enterprise.web.connector.grizzly.ssl.
                SSLPipeline.class.getName());
    
Methods Summary
private static final java.lang.String[]configureEnabledCiphers(javax.net.ssl.SSLEngine sslEngine, java.lang.String[] requestedCiphers)


        String[] supportedCiphers = sslEngine.getSupportedCipherSuites();
        String[] ciphers = null;
        ArrayList<String> list = null;
        for(String supportedCipher: supportedCiphers){        
            /*
             * Check to see if the requested protocol is among the
             * supported protocols, i.e., may be enabled
             */
            for(String cipher: requestedCiphers) {
                cipher = cipher.trim();
                if (supportedCipher.equals(cipher)) {
                    if (list == null) {
                        list = new ArrayList<String>();
                    }
                    list.add(cipher);
                    break;
                }
            }
        } 

        if (list != null) {
            ciphers = list.toArray(new String[list.size()]);                
        }
 
        return ciphers;
    
private static final java.lang.String[]configureEnabledProtocols(javax.net.ssl.SSLEngine sslEngine, java.lang.String[] requestedProtocols)
Return the list of allowed protocol.

return
String[] an array of supported protocols.

        
        String[] supportedProtocols = sslEngine.getSupportedProtocols();
        String[] protocols = null;
        ArrayList<String> list = null;
        for(String supportedProtocol: supportedProtocols){        
            /*
             * Check to see if the requested protocol is among the
             * supported protocols, i.e., may be enabled
             */
            for(String protocol: requestedProtocols) {
                protocol = protocol.trim();
                if (supportedProtocol.equals(protocol)) {
                    if (list == null) {
                        list = new ArrayList<String>();
                    }
                    list.add(protocol);
                    break;
                }
            }
        } 

        if (list != null) {
            protocols = list.toArray(new String[list.size()]);                
        }
 
        return protocols;
    
public voiddisableMonitoring()
Disable gathering of monitoring datas.

        disablePipelineStats();  
        if (readThreads != null) {
            for (int i = 0; i < readThreads.length; i++) {
                ((SSLSelectorReadThread)readThreads[i]).isMonitoringEnabled = false;
            }
        }
        fileCacheFactory.setIsMonitoringEnabled(isMonitoringEnabled);        
    
public voidenableMonitoring()
Enable gathering of monitoring datas.

        isMonitoringEnabled = true;
        enablePipelineStats();      
        if (readThreads != null) {
            for (int i = 0; i < readThreads.length; i++) {
                ((SSLSelectorReadThread)readThreads[i]).isMonitoringEnabled = true;
            }
        }
        fileCacheFactory.setIsMonitoringEnabled(isMonitoringEnabled);
    
public voidenableSelectionKeys()
Enable all registered interestOps. Due a a NIO bug, all interestOps invokation needs to occurs on the same thread as the selector thread.

        SelectionKey selectionKey;
        int size = getKeysToEnable().size();
        long currentTime = System.currentTimeMillis();
        for (int i=0; i < size; i++) {
            selectionKey = (SelectionKey)getKeysToEnable().poll();

            selectionKey.interestOps(
                    selectionKey.interestOps() | SelectionKey.OP_READ);

            if ( selectionKey.attachment() != null){
                ((SSLEngine)selectionKey
                        .attachment()).getSession().putValue
                            (EXPIRE_TIME, System.currentTimeMillis());
            }
            keepAlivePipeline.trap(selectionKey);   
        } 
    
protected voidexpireIdleKeys()
Cancel keep-alive connections.

        if (keepAliveTimeoutInSeconds <= 0 || !selector.isOpen()) return;
        long current = System.currentTimeMillis();

        if (current < getNextKeysExpiration()) {
            return;
        }
        setNextKeysExpiration(current + getKaTimeout());
        
        Set<SelectionKey> readyKeys = selector.keys();
        if (readyKeys.isEmpty()){
            return;
        }
        Iterator<SelectionKey> iterator = readyKeys.iterator();
        SelectionKey key;
        while (iterator.hasNext()) {
            key = (SelectionKey)iterator.next();
            if ( !key.isValid() ) {
                keepAlivePipeline.untrap(key);
                continue;
            }  
                        
            // Keep-alive expired
            if (key.attachment() != null) {                
                SSLSession sslSession = null;
                Object attachment = key.attachment(); 
                long expire = -1L;
                if (attachment instanceof SSLEngine){
                    sslSession = ((SSLEngine)key.attachment()).getSession();
                    if (sslSession != null 
                            && sslSession.getValue(EXPIRE_TIME) != null){
                        expire = (Long)sslSession.getValue(EXPIRE_TIME); 
                    }
                } else if (attachment instanceof Long){
                    expire = (Long)attachment;
                }
                
                if (expire != -1L){
                    if (current - expire >= getKaTimeout()) {                   
                        cancelKey(key);
                    } else if (expire + getKaTimeout() < getNextKeysExpiration()){
                        setNextKeysExpiration(expire + getKaTimeout());
                    }
                }
            }
        }                    
    
public java.lang.String[]getEnabledCipherSuites()
Returns the list of cipher suites to be enabled when {@link SSLEngine} is initialized.

return
null means 'use {@link SSLEngine}'s default.'

        return enabledCipherSuites;
    
public java.lang.String[]getEnabledProtocols()
Returns the list of protocols to be enabled when {@link SSLEngine} is initialized.

return
null means 'use {@link SSLEngine}'s default.'

        return enabledProtocols;
    
public com.sun.enterprise.web.connector.grizzly.ReadTaskgetReadTask(java.nio.channels.SelectionKey key)
Return a SSLReadTask from the pool. If the pool is empty, create a new instance. Make sure the SSLEngine is reused when the SelectionKey is part of a keep-alive transaction.

        ReadTask task = super.getReadTask(key);
        
        SSLEngine sslEngine = null;
        Object attachment = key.attachment();
        if (attachment != null && attachment instanceof SSLEngine){
            sslEngine = (SSLEngine)attachment;
        } else {
            key.attach(null);
        }
        
        if (sslEngine != null) {
            ((SSLReadTask)task).setHandshake(false);
        } else {
            sslEngine = sslContext.createSSLEngine(); 
            if (enabledCipherSuites != null){                
                if (!isCipherConfigured) {
                    enabledCipherSuites = configureEnabledCiphers(sslEngine,
                            enabledCipherSuites);
                    isCipherConfigured = true;
                }                
                sslEngine.setEnabledCipherSuites(enabledCipherSuites);
            } 

            if (enabledProtocols != null){                
                if (!isProtocolConfigured) {
                    enabledProtocols = configureEnabledProtocols(sslEngine,
                                                                 enabledProtocols);
                    isProtocolConfigured = true;
                }                
                sslEngine.setEnabledProtocols(enabledProtocols);
            }       
            sslEngine.setUseClientMode(isClientMode()); 
        }
        sslEngine.setWantClientAuth(isWantClientAuth());     
        sslEngine.getSession().removeValue(EXPIRE_TIME);
        sslEngine.setNeedClientAuth(isNeedClientAuth());
        ((SSLReadTask)task).setSSLEngine(sslEngine);           
        return task;
    
public javax.net.ssl.SSLContextgetSSLContext()
Return the SSLContext required to support SSL over NIO.

        return sslContext;
    
public org.apache.tomcat.util.net.SSLImplementationgetSSLImplementation()
Return the current SSLImplementation this Thread

        return sslImplementation;
    
public org.apache.tomcat.util.net.ServerSocketFactorygetServerSocketFactory()
Return the ServerSocketFactory used when a blocking IO is enabled.

       return null;
    
protected com.sun.enterprise.web.connector.grizzly.ReadTaskhandleRead(java.nio.channels.SelectionKey key)
Handle OP_READ

                   
        // disable OP_READ on key before doing anything else 
        key.interestOps(key.interestOps() & (~SelectionKey.OP_READ));
        
        if (enableNioLogging){
            logger.log(Level.INFO,"Handling OP_READ on SocketChannel " + 
                    key.channel());
        }      
        
        return getReadTask(key);
    
protected voidinitFileCacheFactory()
Initialize the fileCacheFactory associated with this instance

        fileCacheFactory = SSLFileCacheFactory.getFactory(port);
        fileCacheFactory.setIsEnabled(isFileCacheEnabled);
        fileCacheFactory.setLargeFileCacheEnabled(isLargeFileCacheEnabled);
        fileCacheFactory.setSecondsMaxAge(secondsMaxAge);
        fileCacheFactory.setMaxCacheEntries(maxCacheEntries);
        fileCacheFactory.setMinEntrySize(minEntrySize);
        fileCacheFactory.setMaxEntrySize(maxEntrySize);
        fileCacheFactory.setMaxLargeCacheSize(maxLargeFileCacheSize);
        fileCacheFactory.setMaxSmallCacheSize(maxSmallFileCacheSize);         
        fileCacheFactory.setIsMonitoringEnabled(isMonitoringEnabled);
    
protected voidinitMultiSelectors()
Initialize SSLSelectorReadThread used to process OP_READ operations.

        for (int i = 0; i < readThreads.length; i++) {
            readThreads[i] = new SSLSelectorReadThread(){
                public ReadTask getReadTask(SelectionKey key) 
                    throws IOException{
                    
                    return SSLSelectorThread.this.getReadTask(key);
                }
            };
            ((SSLSelectorReadThread)readThreads[i]).countName = i;
            configureReadThread((SSLSelectorReadThread)readThreads[i]);
        }
    
public booleanisClientMode()
Returns true if the SSlEngine is set to use client mode when handshaking.

        return clientMode;
    
public booleanisNeedClientAuth()
Returns true if the SSLEngine will require client authentication.

        return needClientAuth;
    
public booleanisWantClientAuth()
Returns true if the engine will request client authentication.

        return wantClientAuth;
    
protected com.sun.enterprise.web.connector.grizzly.PipelinenewPipeline(int maxThreads, int minThreads, java.lang.String name, int port, int priority)
Create a new Pipeline instance using the pipelineClassName value.

        
        Class className = null;                               
        Pipeline pipeline = null;                               
        try{                              
            className = Class.forName(getPipelineClassName());
            pipeline = (Pipeline)className.newInstance();
        } catch (ClassNotFoundException ex){
            getLogger().log(Level.WARNING,
                       "Unable to load Pipeline: " + getPipelineClassName());
            pipeline = new SSLPipeline();
        } catch (InstantiationException ex){
            getLogger().log(Level.WARNING,
                       "Unable to instantiate Pipeline: "
                       + getPipelineClassName());
            pipeline = new SSLPipeline();
        } catch (IllegalAccessException ex){
            getLogger().log(Level.WARNING,
                       "Unable to instantiate Pipeline: "
                       + getPipelineClassName());
            pipeline = new SSLPipeline();
        }
        
        if (getLogger().isLoggable(Level.FINE)){
            getLogger().log(Level.FINE,
                       "http-listener " + port + " uses pipeline: "
                       + pipeline.getClass().getName());
        }
        
        pipeline.setMaxThreads(maxThreads);
        pipeline.setMinThreads(minThreads);    
        pipeline.setName(name);
        pipeline.setPort(port);
        pipeline.setPriority(priority);
        pipeline.setQueueSizeInBytes(getMaxQueueSizeInBytes());
        pipeline.setThreadsIncrement(getThreadsIncrement());
        pipeline.setThreadsTimeout(getThreadsTimeout());
        
        return pipeline;
    
    
protected com.sun.enterprise.web.connector.grizzly.ProcessorTasknewProcessorTask(boolean initialize)
Create SSLProcessorTask objects and configure it to be ready to proceed request.

                                                      
        SSLProcessorTask task = null;
        if (!asyncExecution) {
            task = new SSLProcessorTask(initialize, isBufferResponse());
        } else {
            task = new SSLAsyncProcessorTask(initialize, isBufferResponse());
        }      
        return configureProcessorTask(task);        
    
protected com.sun.enterprise.web.connector.grizzly.DefaultReadTasknewReadTask()
Return a new SSLReadTask instance

        StreamAlgorithm streamAlgorithm = new NoParsingAlgorithm();    
        streamAlgorithm.setPort(getPort());
               
        SSLReadTask task;
        if (getMaxReadWorkerThreads() > 0 || asyncExecution){
            task =  new SSLAsyncReadTask();  
        } else {
            task = new SSLReadTask();
        }
                     
        task.initialize(streamAlgorithm, isUseDirectByteBuffer(), isUseByteBufferView());
        task.setPipeline(getReadPipeline());  
        task.setSelectorThread(this);
        task.setRecycle(isRecycleTasks());
        task.setSSLImplementation(sslImplementation);
        
        return task;
    
public voidregisterKey(java.nio.channels.SelectionKey key)
Register a SelectionKey to this Selector running of this thread.

        if (key == null) return;
        
        if (keepAlivePipeline.dropConnection()) {
            cancelKey(key);
            return;
        }

        if (enableNioLogging){
            logger.log(Level.INFO,
                    "Registering SocketChannel for keep alive " +  
                    key.channel());
        }         
        getKeysToEnable().add(key);
        selector.wakeup();
    
public voidsetClientMode(boolean clientMode)
Configures the engine to use client (or server) mode when handshaking.

        this.clientMode = clientMode;
    
public voidsetEnabledCipherSuites(java.lang.String[] enabledCipherSuites)
Sets the list of cipher suites to be enabled when {@link SSLEngine} is initialized.

param
cipherSuites null means 'use {@link SSLEngine}'s default.'

        this.enabledCipherSuites = enabledCipherSuites;
    
public voidsetEnabledProtocols(java.lang.String[] enabledProtocols)
Sets the list of protocols to be enabled when {@link SSLEngine} is initialized.

param
protocols null means 'use {@link SSLEngine}'s default.'

        this.enabledProtocols = enabledProtocols;
    
public voidsetNeedClientAuth(boolean needClientAuth)
Configures the engine to require client authentication.

        this.needClientAuth = needClientAuth;
    
public voidsetSSLContext(javax.net.ssl.SSLContext sslContext)
Set the SSLContext required to support SSL over NIO.

        this.sslContext = sslContext;
    
public voidsetSSLImplementation(org.apache.tomcat.util.net.SSLImplementation sslImplementation)
Set the Coyote SSLImplementation.

        this.sslImplementation = sslImplementation;
    
public voidsetServerSocketFactory(org.apache.tomcat.util.net.ServerSocketFactory factory)
Set the ServerSocketFactory used when a blocking IO is enabled.

       ;
    
public voidsetWantClientAuth(boolean wantClientAuth)
Configures the engine to request client authentication.

        this.wantClientAuth = wantClientAuth;