View Javadoc

1   /*
2    * Copyright (c) 2006-2007 Creative Sphere Limited.
3    * All rights reserved. This program and the accompanying materials
4    * are made available under the terms of the Eclipse Public License v1.0
5    * which accompanies this distribution, and is available at
6    * http://www.eclipse.org/legal/epl-v10.html
7    *
8    * Contributors:
9    *
10   *   Creative Sphere - initial API and implementation
11   *
12   */
13  package org.abstracthorizon.mercury.smtp;
14  
15  import java.io.BufferedInputStream;
16  import java.io.IOException;
17  import java.io.InputStream;
18  import java.io.OutputStream;
19  import java.io.PrintStream;
20  import java.text.SimpleDateFormat;
21  
22  import org.abstracthorizon.danube.connection.Connection;
23  import org.abstracthorizon.danube.connection.ConnectionException;
24  import org.abstracthorizon.danube.connection.ConnectionWrapper;
25  import org.abstracthorizon.danube.support.logging.LoggingConnection;
26  import org.abstracthorizon.mercury.common.io.TempStorage;
27  import org.abstracthorizon.mercury.smtp.command.SMTPCommandFactory;
28  import org.abstracthorizon.mercury.smtp.filter.MailSessionData;
29  import org.slf4j.Logger;
30  import org.slf4j.LoggerFactory;
31  
32  /**
33   * SMTP connection which represents SMTP session.
34   *
35   * @author Daniel Sendula
36   */
37  public class SMTPSession extends ConnectionWrapper {
38  
39      /** Human readable format */
40      public static final SimpleDateFormat USER_READABLE_FORMAT = new SimpleDateFormat("HH:mm:ss dd:MM:yyyy");
41  
42      /** Logger */
43      public static Logger logger = LoggerFactory.getLogger(SMTPConnectionHandler.class);
44  
45      /** State is not defined - UNKNOWN state */
46      public static final int STATE_UNKNOWN = 0;
47  
48      /** Session is connected - no command is received yet */
49      public static final int STATE_CONNECTED = 1;
50  
51      /** EHLO is received - waiting for MAIL FROM */
52      public static final int STATE_READY = 2;
53  
54      /** Receiving RCPT TO and DATA commands */
55      public static final int STATE_MAIL = 3;
56  
57      /** Temporary storage for receiving mail */
58      protected TempStorage mail = new TempStorage();
59  
60      /** Scanner object to be used */
61      protected SMTPScanner scanner;
62  
63      /** State of the session. Defaults to {@link SMTPSession#STATE_UNKNOWN} */
64      protected int state = STATE_UNKNOWN;
65  
66      /** Session data */
67      protected MailSessionData data = new MailSessionData();
68  
69      /** Connection handler that created this connection */
70      protected SMTPConnectionHandler parent;
71  
72      /** Cached input stream */
73      protected InputStream inputStream;
74  
75      /** Cached reference to command factory */
76      protected SMTPCommandFactory factory;
77  
78      /** When session is created */
79      protected long created;
80  
81      /** When session is accessed */
82      protected long lastAccessed;
83  
84      /**
85       * Constructor
86       * @param connection underlay connection
87       * @param parent handler that created this session
88       * @throws ConnectionException
89       */
90      public SMTPSession(Connection connection, SMTPConnectionHandler parent) throws ConnectionException {
91          super(connection);
92          this.parent = parent;
93  
94          inputStream = new BufferedInputStream((InputStream)connection.adapt(InputStream.class));
95          scanner = new SMTPScanner(inputStream);
96  
97          data.setAttribute("session", this);
98          data.setAttribute("manager", parent.getStorageManager());
99  
100         created = System.currentTimeMillis();
101         lastAccessed = created;
102     }
103 
104     /**
105      * Should we keep log after the session is finished
106      *
107      * @param keepLog keep log
108      */
109     public void setKeepLog(boolean keepLog) {
110         LoggingConnection loggingConnection = (LoggingConnection)connection.adapt(LoggingConnection.class);
111         if (loggingConnection != null) {
112             loggingConnection.setTemporaryLog(!keepLog);
113         }
114     }
115 
116     /**
117      * Returns shell logs be kept after session is finished
118      * @return keep log
119      */
120     public boolean isKeepLog() {
121         LoggingConnection loggingConnection = (LoggingConnection)connection.adapt(LoggingConnection.class);
122         if (loggingConnection != null) {
123             return !loggingConnection.isTermporaryLog();
124         } else {
125             return false;
126         }
127     }
128 
129     /**
130      * Helper function to write messaage to the log stream
131      *
132      * @param msg message to be writen to log stream
133      */
134     public void writeLogMessage(String msg) {
135         LoggingConnection loggingConnection = (LoggingConnection)connection.adapt(LoggingConnection.class);
136         if (loggingConnection != null) {
137             PrintStream out = new PrintStream(loggingConnection.getDebugOutputStream());
138             out.println(msg);
139             out.flush();
140         }
141     }
142 
143     /**
144      * Sets debug stream's logging attribute ({@link LoggingConnection#setLogging(boolean)} if any.
145      *
146      * @param debug logging should start (<code>true</code>) or stop (<code>false</code>)
147      */
148     public void setStreamDebug(boolean debug) {
149         LoggingConnection loggingConnection = (LoggingConnection)connection.adapt(LoggingConnection.class);
150         if (loggingConnection != null) {
151             loggingConnection.setLogging(debug);
152         }
153     }
154 
155     /**
156      * Returns if logging is enabled
157      * @return is logging enabled
158      */
159     public boolean isStreamDebug() {
160         LoggingConnection loggingConnection = (LoggingConnection)connection.adapt(LoggingConnection.class);
161         if (loggingConnection != null) {
162             return loggingConnection.isLogging();
163         } else {
164             return false;
165         }
166     }
167 
168     /**
169      * Returns debug output stream or <code>null</code>
170      * @return debug output stream or <code>null</code>
171      */
172     public OutputStream getDebugStream() {
173         LoggingConnection loggingConnection = (LoggingConnection)connection.adapt(LoggingConnection.class);
174         if (loggingConnection != null) {
175             return loggingConnection.getDebugOutputStream();
176         } else {
177             return null;
178         }
179     }
180 
181     /**
182      * Returns cached input stream
183      * @return cached input stream
184      */
185     public InputStream getInputStream() {
186         return inputStream;
187     }
188 
189     /**
190      * Sets session's state
191      * @param state new session's state
192      */
193     public void setState(int state) {
194         this.state = state;
195     }
196 
197     /**
198      * Returns session's state
199      * @return session's state
200      */
201     public int getState() {
202         return state;
203     }
204 
205     /**
206      * Returns scanner object
207      * @return scanner object
208      */
209     public SMTPScanner getScanner() {
210         return scanner;
211     }
212 
213     /**
214      * Returns mail session data object
215      * @return mail session data object
216      */
217     public MailSessionData getMailSessionData() {
218         return data;
219     }
220 
221     /**
222      * Returns refernece to handler that created this session
223      * @return refernece to handler that created this session
224      */
225     public SMTPConnectionHandler getConnectionHandler() {
226         return parent;
227     }
228 
229     /**
230      * Closes the session (connection)
231      */
232     public void close() {
233         super.close();
234     }
235 
236     /**
237      * Sets SMTP response back
238      * @param response response
239      * @throws IOException
240      */
241     public void sendResponse(SMTPResponse response) throws IOException {
242         data.setReturnCode(response.getCode());
243         response.submit((OutputStream)connection.adapt(OutputStream.class));
244     }
245 
246     /**
247      * Sets command factory to be used
248      * @param factory command factory to be used
249      */
250     public void setCommandFactory(SMTPCommandFactory factory) {
251         this.factory = factory;
252     }
253 
254     /**
255      * Returns command factory that is used
256      * @return command factory that is used
257      */
258     public SMTPCommandFactory getCommandFactory() {
259         return factory;
260     }
261 
262     /**
263      * Returns time when the session is created
264      * @return time when the session is created
265      */
266     public long getSessionCreated() {
267         return created;
268     }
269 
270     /**
271      * Returns time when the session is created in human readable format
272      * @return time when the session is created in human readable format
273      */
274     public String getSessionCreatedString() {
275         return USER_READABLE_FORMAT.format(created);
276     }
277 
278     /**
279      * Returns time when the session is last accessed
280      * @return time when the session is last accessed
281      */
282     public long getSessionAccessed() {
283         return lastAccessed;
284     }
285 
286     /**
287      * Returns time when the session is last accessed in the human readable format
288      * @return time when the session is last accessed
289      */
290     public String getSessionAccessedString() {
291         return USER_READABLE_FORMAT.format(lastAccessed);
292     }
293 
294     /**
295      * Resets last accessed time
296      */
297     public void resetLastAccessed() {
298         lastAccessed = System.currentTimeMillis();
299     }
300 }