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.processor;
017    
018    import org.apache.log4j.Logger;
019    import org.jboss.netty.channel.Channel;
020    import org.jboss.netty.channel.ChannelFuture;
021    import org.jboss.netty.channel.ChannelFutureListener;
022    
023    import com.hs.mail.container.config.ComponentManager;
024    import com.hs.mail.imap.ImapSession;
025    import com.hs.mail.imap.event.EventTracker;
026    import com.hs.mail.imap.mailbox.MailboxManager;
027    import com.hs.mail.imap.mailbox.SelectedMailbox;
028    import com.hs.mail.imap.message.request.ImapRequest;
029    import com.hs.mail.imap.message.responder.DefaultImapResponder;
030    import com.hs.mail.imap.message.responder.Responder;
031    import com.hs.mail.imap.message.responder.UnsolicitedResponder;
032    import com.hs.mail.imap.message.response.HumanReadableText;
033    import com.hs.mail.imap.message.response.UnsolicitedResponse;
034    import com.hs.mail.imap.message.response.UnsolicitedResponseBuilder;
035    import com.hs.mail.imap.user.UserManager;
036    
037    /**
038     * 
039     * @author Won Chul Doh
040     * @since Jan 31, 2010
041     *
042     */
043    public abstract class AbstractImapProcessor implements ImapProcessor {
044            
045            static Logger logger = Logger.getLogger(AbstractImapProcessor.class);
046    
047            protected AbstractImapProcessor() {
048                    super();
049            }
050            
051            public void process(ImapSession session, ImapRequest request,
052                            Channel channel) {
053                    if (!request.validForState(session.getState())) {
054                            channel.write(request.getTag() + " NO " + request.getCommand()
055                                            + " " + HumanReadableText.INVALID_COMMAND + "\r\n");
056                    } else {
057                            Responder responder = createResponder(channel, request);
058                            if (isSelectedMailboxDeleted(session)) {
059                                    writeSignOff(session, responder);
060                            } else {
061                                    try {
062                                            doProcess(session, request, responder);
063                                    } catch (Exception ex) {
064                                            logger.error(ex.getMessage(), ex);
065                                            responder.taggedNo(request, ex.getMessage());
066                                    }
067                            }
068                    }
069            }
070            
071            abstract protected void doProcess(ImapSession session, ImapRequest request,
072                            Responder responder) throws Exception;
073    
074            protected MailboxManager getMailboxManager() {
075                    return (MailboxManager) ComponentManager
076                                    .getBeanOfType(MailboxManager.class);
077            }
078            
079            protected UserManager getUserManager() {
080                    return (UserManager) ComponentManager.getBeanOfType(UserManager.class);
081            }
082            
083            protected Responder createResponder(Channel channel, ImapRequest request) {
084                    return new DefaultImapResponder(channel, request);
085            }
086            
087            protected void unsolicitedResponse(ImapSession session, Responder responder) {
088                    SelectedMailbox selected = session.getSelectedMailbox();
089                    if (selected != null) {
090                            EventTracker tracker = selected.getEventTracker();
091                            if (tracker != null) {
092                                    UnsolicitedResponse response = new UnsolicitedResponseBuilder()
093                                                    .build(selected, tracker);
094                                    if (response != null) {
095                                            new UnsolicitedResponder(responder).respond(response);
096                                    }
097                                    selected.resetEvents();
098                            }
099                    }
100            }
101            
102            private boolean isSelectedMailboxDeleted(ImapSession session) {
103                    SelectedMailbox selected = session.getSelectedMailbox();
104                    return (selected != null) ? selected.isDeletedMailbox() : false;
105            }
106            
107            private void writeSignOff(ImapSession session, Responder responder) {
108                    getMailboxManager().removeEventListener(session.getSelectedMailbox());
109                    // Is this necessary?
110                    session.logout();
111                    // RFC2180 3.3 The server MAY allow the DELETE/RENAME of a
112                    // multi-accessed mailbox, but disconnect all other clients who
113                    // have the mailbox accessed by sending a untagged BYE response.
114                    ChannelFuture future = responder
115                                    .bye(HumanReadableText.MAILBOX_DELETED_SIGN_OFF);
116                    future.addListener(ChannelFutureListener.CLOSE);
117            }
118            
119    }