001    /*
002     * Copyright 2010 the original author or authors.
003     * 
004     *  Licensed under the Apache License, Version 2.0 (the "License");
005     *  you may not use this file except in compliance with the License.
006     *  You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     *  Unless required by applicable law or agreed to in writing, software
011     *  distributed under the License is distributed on an "AS IS" BASIS,
012     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     *  See the License for the specific language governing permissions and
014     *  limitations under the License.
015     */
016    package com.hs.mail.imap.server;
017    
018    import java.nio.channels.ClosedChannelException;
019    
020    import org.apache.log4j.Level;
021    import org.apache.log4j.Logger;
022    import org.jboss.netty.channel.ChannelEvent;
023    import org.jboss.netty.channel.ChannelHandlerContext;
024    import org.jboss.netty.channel.ChannelPipelineCoverage;
025    import org.jboss.netty.channel.ChannelStateEvent;
026    import org.jboss.netty.channel.ExceptionEvent;
027    import org.jboss.netty.channel.MessageEvent;
028    import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
029    import org.jboss.netty.handler.timeout.ReadTimeoutException;
030    
031    import com.hs.mail.imap.ImapSession;
032    import com.hs.mail.imap.message.ImapRequestFactory;
033    import com.hs.mail.imap.message.request.ImapRequest;
034    import com.hs.mail.imap.message.response.HumanReadableText;
035    import com.hs.mail.imap.processor.ImapProcessor;
036    import com.hs.mail.imap.processor.ImapProcessorFactory;
037    import com.hs.mail.imap.server.codec.ImapMessage;
038    
039    /**
040     * Handles a server-side IMAP channel.
041     * 
042     * @author Won Chul Doh
043     * @since Jan 12, 2010
044     */
045    @ChannelPipelineCoverage("one")
046    public class ImapServerHandler extends SimpleChannelUpstreamHandler {
047    
048            private static Logger logger = Logger.getLogger(ImapServerHandler.class);
049    
050            public ImapServerHandler() {
051                    super();
052                    ImapProcessorFactory.registerProcessors();
053            }
054            
055            @Override
056            public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e)
057                            throws Exception {
058                    if (e != null) {
059                            if (e instanceof ChannelStateEvent) {
060                                    if (logger.isDebugEnabled()) {
061                                            logger.debug(e.toString());
062                                    }
063                            }
064                            super.handleUpstream(ctx, e);
065                    }
066            }
067    
068            @Override
069            public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
070                            throws Exception {
071                    // Send greeting for a new connection.
072                    e.getChannel().write(HumanReadableText.GREETINGS);
073                    ctx.setAttachment(new ImapSession());
074            }
075    
076            @Override
077            public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
078                    ImapSession session = (ImapSession) ctx.getAttachment();
079                    ImapMessage message = (ImapMessage) e.getMessage();
080                    ImapRequest request = ImapRequestFactory.createImapRequest(message);
081                    ImapProcessor processor = ImapProcessorFactory
082                                    .createImapProcessor(request);
083                    processor.process(session, request, e.getChannel());
084            }
085    
086            @Override
087            public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
088                    logger.log(Level.WARN, "Exception from downstream.", e.getCause());
089                    if (e.getCause() instanceof ReadTimeoutException) {
090                            e.getChannel().close();
091                    } else if (e.getCause() instanceof ClosedChannelException) {
092                            e.getChannel().close();
093                    } else {
094                            e.getChannel().write(e.getCause().getMessage() + "\r\n");
095                    }
096            }
097    
098    }