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 }