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 }