View Javadoc

1   /****************************************************************
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   ****************************************************************/
19  
20  package org.apache.james.imapserver;
21  
22  import java.io.IOException;
23  import java.net.Socket;
24  
25  import org.apache.avalon.cornerstone.services.connection.ConnectionHandler;
26  import org.apache.avalon.framework.container.ContainerUtil;
27  import org.apache.avalon.framework.logger.Logger;
28  import org.apache.james.imap.api.process.ImapSession;
29  import org.apache.james.imap.main.ContextualLog;
30  import org.apache.james.imap.main.ImapRequestHandler;
31  import org.apache.james.imap.main.ImapSessionImpl;
32  import org.apache.james.imap.main.OutputStreamImapResponseWriter;
33  import org.apache.james.imap.encode.ImapResponseComposer;
34  import org.apache.james.imap.encode.base.ImapResponseComposerImpl;
35  import org.apache.james.socket.ProtocolHandler;
36  import org.apache.james.socket.ProtocolHandlerHelper;
37  import org.apache.commons.logging.impl.AvalonLogger;
38  
39  /**
40   * Handles IMAP connections.
41   */
42  public class ImapHandler implements ProtocolHandler
43  {
44      
45      private ProtocolHandlerHelper helper;
46  
47      private static final byte[] EMERGENCY_SIGNOFF = {'*',' ', 'B', 'Y', 'E', ' ', 
48          'S', 'e', 'r', 'v', 'e', 'r', ' ', 'f', 'a', 'u', 'l', 't', '\r', '\n'};
49  
50      private final String hello;
51      private final ImapRequestHandler requestHandler;
52      private ImapSession session;
53  
54      public ImapHandler(final ImapRequestHandler requestHandler, final String hello) {
55          super();
56          this.requestHandler = requestHandler;
57          this.hello = hello;
58      }
59      
60      // TODO: this shouldn't be necessary
61      public void setConfigurationData( Object theData )
62      {
63      }
64  
65      /**
66       * Resets the handler data to a basic state.
67       */
68      public void resetHandler() {
69          
70          // Clear user data
71          try {
72              if (session != null) {
73                  session.logout();
74              }
75          } catch (Exception e) {
76              getLogger().warn("Failed to close mailbox: " + e.getMessage());
77              getLogger().debug(e.getMessage(), e);
78          }
79          session = null;
80      }
81  
82      /**
83       * @see ConnectionHandler#handleConnection(Socket)
84       */
85      public void handleProtocol() throws IOException {
86              getLogger().debug(
87                  "Connection from " + helper.getRemoteHost() + " (" + helper.getRemoteIP()
88                          + ") opened.");
89              final OutputStreamImapResponseWriter writer = new OutputStreamImapResponseWriter( helper.getOutputStream() );
90              ImapResponseComposer response = new ImapResponseComposerImpl( writer);
91  
92              // Write welcome message
93                   
94              response.hello(hello);
95  
96              setUpSession();
97              
98              helper.getWatchdog().start();
99              while ( handleRequest() ) {
100                 helper.getWatchdog().reset();
101             }
102             helper.getWatchdog().stop();
103             if (session != null) {
104                 session.logout();
105             }
106             
107             getLogger().info(
108                     "Connection from " + helper.getRemoteHost() + " (" + helper.getRemoteIP()
109                             + ") closed.");
110     }
111 
112     /**
113      * Sets up a session.
114      */
115     private void setUpSession() {
116         final ImapSessionImpl session = new ImapSessionImpl();
117         session.setLog(new ContextualLog("[" + helper.getName() + "]", new AvalonLogger(getLogger())));
118         this.session = session;
119     }
120 
121     private boolean handleRequest() {
122         final boolean result = requestHandler.handleRequest( helper.getInputStream(), helper.getOutputStream(), session );
123         return result;
124     }
125     
126     /**
127      * Method which will be called on error
128      *  
129      * @param e the RuntimeException
130      */
131     public void errorHandler(RuntimeException e) {
132         try {
133             helper.getOutputStream().write(EMERGENCY_SIGNOFF);
134         } catch (Throwable t) {
135             getLogger().debug("Write emergency signoff failed.", t);
136         }
137         helper.defaultErrorHandler(e);
138     }
139     
140     public Logger getLogger() {
141         return helper.getAvalonLogger();
142     }
143 
144     public void setProtocolHandlerHelper(ProtocolHandlerHelper phh) {
145         this.helper = phh;
146     }
147 
148 }
149