/****************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one   *
 * or more contributor license agreements.  See the NOTICE file *
 * distributed with this work for additional information        *
 * regarding copyright ownership.  The ASF licenses this file   *
 * to you under the Apache License, Version 2.0 (the            *
 * "License"); you may not use this file except in compliance   *
 * with the License.  You may obtain a copy of the License at   *
 *                                                              *
 *   http://www.apache.org/licenses/LICENSE-2.0                 *
 *                                                              *
 * Unless required by applicable law or agreed to in writing,   *
 * software distributed under the License is distributed on an  *
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
 * KIND, either express or implied.  See the License for the    *
 * specific language governing permissions and limitations      *
 * under the License.                                           *
 ****************************************************************/
package org.apache.james.imapserver.netty;

import static org.jboss.netty.channel.Channels.pipeline;

import javax.annotation.Resource;
import javax.net.ssl.SSLEngine;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.james.imap.api.ImapConstants;
import org.apache.james.imap.api.process.ImapProcessor;
import org.apache.james.imap.decode.ImapDecoder;
import org.apache.james.imap.encode.ImapEncoder;
import org.apache.james.imap.main.ImapRequestStreamHandler;
import org.apache.james.protocols.impl.ChannelGroupHandler;
import org.apache.james.socket.netty.AbstractConfigurableAsyncServer;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.handler.connection.ConnectionLimitUpstreamHandler;
import org.jboss.netty.handler.connection.ConnectionPerIpLimitUpstreamHandler;
import org.jboss.netty.handler.ssl.SslHandler;

/**
 * NIO IMAP Server which use Netty
 *
 */
public class NioImapServer extends AbstractConfigurableAsyncServer implements ImapConstants{

    private static final String softwaretype = "JAMES "+VERSION+" Server "; //+ Constants.SOFTWARE_VERSION;

    private String hello;
    private ImapProcessor processor;
    private ImapEncoder encoder;

    private ImapDecoder decoder;

    @Resource(name="imapDecoder")
    public void setImapDecoder(ImapDecoder decoder) {
        this.decoder = decoder;
    }
    
    @Resource(name="imapEncoder")
    public void setImapEncoder(ImapEncoder encoder) {
        this.encoder = encoder;
    }
    
    @Resource(name="imapProcessor")
    public void setImapProcessor(ImapProcessor processor) {
        this.processor = processor;
    }
    
    @Override
    public void doConfigure( final HierarchicalConfiguration configuration ) throws ConfigurationException {
        super.doConfigure(configuration);
        hello  = softwaretype + " Server " + getHelloName() + " is ready.";
    }
    
    
    /*
     * (non-Javadoc)
     * @see org.apache.james.socket.mina.AbstractAsyncServer#getDefaultPort()
     */
    public int getDefaultPort() {
        return 143;
    }

 
    /*
     * (non-Javadoc)
     * @see org.apache.james.socket.mina.AbstractAsyncServer#getServiceType()
     */
    public String getServiceType() {
        return "IMAP Service";
    }

    @Override
    protected ChannelPipelineFactory createPipelineFactory(final ChannelGroup group) {
        return new ChannelPipelineFactory() {
            private ChannelGroupHandler groupHandler = new ChannelGroupHandler(group);

            public ChannelPipeline getPipeline() throws Exception {
                ChannelPipeline pipeline = pipeline();
                pipeline.addLast("groupHandler", groupHandler);

                pipeline.addLast("connectionLimit", new ConnectionLimitUpstreamHandler(NioImapServer.this.connectionLimit));

                pipeline.addLast("connectionPerIpLimit", new ConnectionPerIpLimitUpstreamHandler(NioImapServer.this.connPerIP));

                if (isSSLSocket()) {
                    // We need to set clientMode to false.
                    // See https://issues.apache.org/jira/browse/JAMES-1025
                    SSLEngine engine = getSSLContext().createSSLEngine();
                    engine.setUseClientMode(false);
                    pipeline.addFirst("sslHandler", new SslHandler(engine));
                    
                }
                final ImapRequestStreamHandler handler = new ImapRequestStreamHandler(decoder, processor, encoder);
                
                if (isStartTLSSupported())  {
                    pipeline.addLast("coreHandler",  new ImapStreamChannelUpstreamHandler(hello, handler, getLogger(), NioImapServer.this.getTimeout(), getSSLContext().createSSLEngine()));
                } else {
                    pipeline.addLast("coreHandler",  new ImapStreamChannelUpstreamHandler(hello, handler, getLogger(), NioImapServer.this.getTimeout()));
                }
                
                return pipeline;
            }
           
        };
    }



}

@@ -1829,32 +1829,88 @@
 lGroupHandler;%0D%0A
+import org.apache.james.protocols.impl.TimeoutHandler;%0D%0A
 import org.apach
@@ -2323,16 +2323,63 @@
 andler;%0D
+%0Aimport org.jboss.netty.util.HashedWheelTimer;%0D
 %0A%0D%0A/**%0D%0A
@@ -4004,16 +4004,22 @@
 private 
+final 
 ChannelG
@@ -4074,24 +4074,249 @@
 er(group);%0D%0A
+            private final HashedWheelTimer timer = new HashedWheelTimer();%0D%0A            %0D%0A            // Timeout of 30 minutes See rfc2060 5.4 for details%0D%0A            private final static int TIMEOUT = 30 * 60;%0D%0A            
 %0D%0A          
@@ -4491,24 +4491,124 @@
 pHandler);%0D%0A
+                pipeline.addLast(%22timeoutHandler%22, new TimeoutHandler(timer, TIMEOUT , TIMEOUT, 0));
 %0D%0A          

Use timeout of 30 minutes for IMAP (JAMES-1033)