001 package org.rakeshv.mail;
002
003 import java.io.*;
004 import java.util.*;
005
006 import org.jdom.*;
007 import org.jdom.input.*;
008 import org.jdom.output.*;
009
010 /**
011 * This class stores the mail account preferences for the user(s)
012 * currently logged on to the application. This class populates the
013 * <code>class fields</code> from the information stored in the
014 * underlying <code>preferences XML file</code> that conforms to the
015 * <a href='http://src.rakeshv.org/xml/schema/mailPreferences.xsd'>mail
016 * preferences</a> <code>XML schema</code> using <a
017 * href='http://www.jdom.org/'>JDOM</a>.
018 *
019 * <p>You can use the {@link #createMailPreferences( String )} method
020 * to create a default mail preferences file.</p>
021 *
022 * <p>Modifiying the class fields do not modify the contents of the
023 * preferences file. Use {@link #saveMailPreferences()} to write the
024 * modified XML data back to the preferences {@link #fileName file}.</p>
025 *
026 * <p>Copyright 2003, Rakesh Vidyadharan</p>
027 *
028 * @author Rakesh Vidyadharan
029 * @version $Id: MailPreferences.java,v 1.9 2005/09/17 11:13:49 rakesh Exp $
030 */
031 public class MailPreferences extends Object
032 {
033 /**
034 * A constant that is used to indicate that messages being deleted
035 * should be moved to the {@link WebMailBean#trashFolderName} folder.
036 * This constant is currently defined as <code>0</code>.
037 */
038 public static final int MOVE_TO_TRASH = 0;
039
040 /**
041 * A constant that is used to indicate that message being deleted
042 * should be deleted permanently from the store. This constant is
043 * currently defined as <code>1</code>.
044 */
045 public static final int DELETE_PERMANENTLY = 1;
046
047 /**
048 * A constant that is used to indicate that the message being deleted
049 * should be marked as deleted (while left in the current folder).
050 * This constant is currently defined as <code>2</code>.
051 */
052 public static final int MARK_AS_DELETED = 2;
053
054 /**
055 * A flag that is used to indicate that messages being sent <b>should</b>
056 * be copied to the {@link WebMailBean#sentFolderName}. At present
057 * a value of <code>true</code> indicates that messages should be
058 * copied to the folder.
059 */
060 public static final boolean COPY_SENT_MESSAGES = true;
061
062 /**
063 * A flag that is used to indicate that messages being sent should
064 * <b>not</b> be copied to the {@link WebMailBean#sentFolderName}.
065 * At present a value of <code>true</code> indicates that messages
066 * should not be copied to the folder.
067 */
068 public static final boolean DO_NOT_COPY_SENT_MESSAGES = false;
069
070 /**
071 * A constant that is used to indicate that all available messages
072 * for the chosen folder should be displayed on the page.
073 */
074 public static final int DISPLAY_ALL_MESSAGES = 1000;
075
076 /**
077 * The fully qualified name of the file that contains the mail
078 * preferences.
079 */
080 private String fileName = "";
081
082 /**
083 * This field is used to indicate the type of action the user desires
084 * when deleting a mail message. Valid values for this variable are
085 * defined by the fields {@link #MOVE_TO_TRASH}, {@link
086 * #DELETE_PERMANENTLY}, and {@link #MARK_AS_DELETED}. Setting this
087 * field to other values will cause undefined behaviour. This field
088 * maps to the <code>deleteAction</code> element in the schema.
089 */
090 private int deleteAction = 0;
091
092 /**
093 * This field is used to indicate whether message being sent by the
094 * user are to be copied to the {@link WebMailBean#sentFolderName}
095 * folder or not. This field maps to the <code>copySentMessages</code>
096 * element in the schema.
097 */
098 private boolean copySentMessages = false;
099
100 /**
101 * This field is used to indicate the number of days until which
102 * deleted messages in the {@link WebMailBean#trashFolderName} folder
103 * should be kept. Message older than the configured number of days
104 * will be automatically deleted when the user logs out of the
105 * web-mail application. This value will by default be 30 days.
106 */
107 private int daysToKeepDeletedMessages = 30;
108
109 /**
110 * This field is used to store the user preference for the number of
111 * messages to be displayed on a page. This field maps to the
112 * <code>messagesPerPage</code> element. This field is set by default
113 * to {@link #DISPLAY_ALL_MESSAGES}. This field maps to the
114 * <code>messagesPerPage</code> element in the schema.
115 */
116 private int messagesPerPage = MailPreferences.DISPLAY_ALL_MESSAGES;
117
118 /**
119 * The JDOM XML document representation.
120 */
121 private Document document = null;
122
123 /**
124 * The target namespace for the mail preferences XML data.
125 */
126 private Namespace namespace = null;
127
128 /**
129 * Default constructor. Cannot be directly invoked.
130 */
131 protected MailPreferences()
132 {
133 super();
134 }
135
136 /**
137 * Just invoke {@link #MailPreferences( String, String )} with a value
138 * of <code>null</code> for the preferred SAX Parser to use.
139 *
140 * @param fileName - The fully qualified name of the address
141 * book XML file.
142 * @throws MailException - If any JDOM/IOExceptions are encountered
143 * while processing the address book XML file.
144 */
145 public MailPreferences( String fileName ) throws MailException
146 {
147 this( fileName, null );
148 }
149
150 /**
151 * Load the specified address book XML file using the specified
152 * SAX Parser.
153 *
154 * @see #loadMailPreferences( String )
155 *
156 * @param fileName - The fully qualified name of the address
157 * book XML file.
158 * @param saxParser - The full class name of the preferred
159 * SAX Parser to use.
160 * @throws MailException - If any JDOM/IOExceptions are encountered
161 * while processing the address book XML file.
162 */
163 public MailPreferences( String fileName, String saxParser )
164 throws MailException
165 {
166 this.fileName = fileName;
167 loadMailPreferences( saxParser );
168 }
169
170 /**
171 * Load the address book XML file ({@link #fileName}) using JDOM,
172 * and populate the instance variables.
173 *
174 * @param saxParser - The full class name of the SAX Parser
175 * to use. If this is <code>null</code> the default JAXP SAX
176 * Parser will be used.
177 * @throws MailException - If any JDOM/IOExceptions are encountered
178 * while processing the address book XML file.
179 */
180 private void loadMailPreferences( String saxParser )
181 throws MailException
182 {
183 SAXBuilder builder = null;
184
185 if ( saxParser == null )
186 {
187 builder = new SAXBuilder();
188 }
189 else
190 {
191 builder = new SAXBuilder( saxParser );
192 }
193
194 try
195 {
196 document = builder.build( new File( fileName ) );
197 }
198 catch ( Exception ex )
199 {
200 throw new MailException( true, "Error accessing mail preferences file.", ex );
201 }
202
203 Element rootElement = document.getRootElement();
204 namespace = rootElement.getNamespace( rootElement.getNamespacePrefix() );
205
206 // Get the delete action preference
207 String value = rootElement.getChildTextTrim( "deleteAction", namespace );
208 if ( value != null && ! value.equals( "" ) )
209 {
210 deleteAction = Integer.parseInt( value );
211 }
212
213 // Get the sent messages preference
214 value = rootElement.getChildTextTrim( "copySentMessage", namespace );
215 if ( value != null && ! value.equals( "" ) )
216 {
217 if ( value.equals( "true" ) )
218 {
219 copySentMessages = MailPreferences.COPY_SENT_MESSAGES;
220 }
221 else if ( value.equals( "false" ) )
222 {
223 copySentMessages = MailPreferences.DO_NOT_COPY_SENT_MESSAGES;
224 }
225 }
226
227 // Get the number of days to keep deleted mail preference
228 value = rootElement.getChildTextTrim( "daysToKeepDeletedMessages", namespace );
229 if ( value != null && ! value.equals( "" ) )
230 {
231 try
232 {
233 daysToKeepDeletedMessages = Integer.parseInt( value );
234 }
235 catch ( NumberFormatException nfex )
236 {
237 // Do nothing. Just ignore it.
238 nfex.printStackTrace();
239 }
240 }
241
242 // Get the number of messages per page preference
243 value = rootElement.getChildTextTrim( "messagesPerPage", namespace );
244 if ( value != null && ! value.equals( "" ) )
245 {
246 if ( value.equals( "all" ) )
247 {
248 messagesPerPage = MailPreferences.DISPLAY_ALL_MESSAGES;
249 }
250 else
251 {
252 try
253 {
254 messagesPerPage = Integer.parseInt( value );
255 }
256 catch ( NumberFormatException nfex )
257 {
258 // Do nothing. Just ignore it.
259 nfex.printStackTrace();
260 }
261 }
262 }
263 }
264
265 /**
266 * Just invokes {@link #createMailPreferences( String, String )} with
267 * a <code>null</code> value for the default SAX Parser.
268 *
269 * @param file - The fully qualified name of the file ie. the
270 * full path and name of file to use as the address book.
271 * @throws MailException - If any exceptions are encountered while
272 * creating or writing to the specified file.
273 */
274 public static MailPreferences createMailPreferences( String file )
275 throws MailException
276 {
277 return createMailPreferences( file, null );
278 }
279
280 /**
281 * Write the JDOM tree back to the address book file.
282 *
283 * @throws MailException - If any exceptions are encountered while
284 * serialising the JDOM tree to the mail preferences file.
285 */
286 public void saveMailPreferences() throws MailException
287 {
288 FileOutputStream out = null;
289 try
290 {
291 out = new FileOutputStream( fileName );
292 }
293 catch ( FileNotFoundException fnfex )
294 {
295 throw new MailException( true, "The mail preferences file could not be found.", fnfex );
296 }
297
298 XMLOutputter outputter = new XMLOutputter();
299 outputter.getFormat().setLineSeparator( "\n" );
300 outputter.getFormat().setIndent( " " );
301 try
302 {
303 outputter.output( document, out );
304 out.close();
305 }
306 catch ( IOException ioex )
307 {
308 throw new MailException( true, "Error while writing to mail preferences file.", ioex );
309 }
310 }
311
312 /**
313 * Create a new mail preferences file using the fully qualified file
314 * name specified, and using the specified SAX Parser to load the XML
315 * file that has been created.
316 *
317 * @param file - The fully qualified name of the file ie. the
318 * full path and name of file to use as the address book.
319 * @param saxParser - The full class name of the preferred
320 * SAX Parser. If this is <code>null</code> the default JAXP
321 * SAX Parser will be used.
322 * @throws MailException - If any exceptions are encountered while
323 * creating or writing to the specified file.
324 */
325 public static MailPreferences createMailPreferences( String file,
326 String saxParser ) throws MailException
327 {
328 MailPreferences mailPreferences = new MailPreferences();
329 mailPreferences.setFileName( file );
330
331 try
332 {
333 PrintWriter out = new PrintWriter(
334 new BufferedWriter( new FileWriter( file ) )
335 );
336 out.println( "<?xml version='1.0' encoding='UTF-8'?>" );
337 out.println( "<mailPreferences xmlns='http://src.rakeshv.org/xml/schema/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://src.rakeshv.org/xml/schema/ http://src.rakeshv.org/xml/schema/mailPreferences.xsd'>" );
338 out.println( " <deleteAction>0</deleteAction>" );
339 out.println( " <copySentMessage>true</copySentMessage>" );
340 out.println( " <daysToKeepDeletedMessages>30</daysToKeepDeletedMessages>" );
341 out.println( " <messagesPerPage>10</messagesPerPage>" );
342 out.println( "</mailPreferences>" );
343 out.flush();
344 out.close();
345 }
346 catch ( IOException iex )
347 {
348 throw new MailException( true, "Error creating/writing new address book " + file + ".", iex );
349 }
350
351 mailPreferences.loadMailPreferences( saxParser );
352
353 return mailPreferences;
354 }
355
356 /**
357 * Set the value of {@link #fileName}.
358 *
359 * @param fileName - The value to set.
360 */
361 public final void setFileName( String fileName )
362 {
363 this.fileName = fileName;
364 }
365
366 /**
367 * Return the value/reference of the {@link #deleteAction}.
368 *
369 * @return int - The value/reference of deleteAction.
370 */
371 public final int getDeleteAction()
372 {
373 return deleteAction;
374 }
375
376 /**
377 * Set the value of {@link #deleteAction}. Also updates the
378 * underlying JDOM tree with the new value. Use {@link
379 * #saveMailPreferences()} to actually write the modified XML data
380 * back to the mail preferences {@link #fileName file}.
381 *
382 * @param deleteAction - The value to set.
383 */
384 public final void setDeleteAction( int deleteAction )
385 {
386 this.deleteAction = deleteAction;
387
388 document.getRootElement().getChild( "deleteAction", namespace ).setText( String.valueOf( deleteAction ) );
389 }
390
391 /**
392 * Return the value/reference of the {@link #copySentMessages}.
393 *
394 * @return boolean - The value/reference of copySentMessages.
395 */
396 public final boolean getCopySentMessages()
397 {
398 return copySentMessages;
399 }
400
401 /**
402 * Set the value of {@link #copySentMessages}. Also updates the
403 * underlying JDOM tree with the new value. Use {@link
404 * #saveMailPreferences()}, to actually write the modified XML back
405 * to the mail preferences {@link #fileName file}.
406 *
407 * @param copySentMessages - The value to set.
408 */
409 public final void setCopySentMessages( boolean copySentMessages )
410 {
411 this.copySentMessages = copySentMessages;
412
413 document.getRootElement().getChild( "copySentMessage", namespace ).setText( String.valueOf( copySentMessages ) );
414 }
415
416 /**
417 * Return the value/reference of the {@link #messagesPerPage}.
418 *
419 * @return int - The value/reference of messagesPerPage.
420 */
421 public final int getMessagesPerPage()
422 {
423 return messagesPerPage;
424 }
425
426 /**
427 * Set the value of {@link #messagesPerPage}. Use {@link
428 * #DISPLAY_ALL_MESSAGES} if you wish to display all the messages on
429 * one page. This method also updates the underlying JDOM tree with
430 * the new value. Use {@link #saveMailPreferences()} to actually
431 * write the modified XML back to the mail preferences {@link
432 * #fileName file}.
433 *
434 * @param messagesPerPage - The value to set.
435 */
436 public final void setMessagesPerPage( int messagesPerPage )
437 {
438 this.messagesPerPage = messagesPerPage;
439
440 document.getRootElement().getChild( "messagesPerPage", namespace ).setText( String.valueOf( messagesPerPage ) );
441 }
442
443 /**
444 * Return the value/reference of the {@link #daysToKeepDeletedMessages}.
445 *
446 * @return int - The value/reference of daysToKeepDeletedMessages.
447 */
448 public final int getDaysToKeepDeletedMessages()
449 {
450 return daysToKeepDeletedMessages;
451 }
452
453 /**
454 * Set the value of {@link #daysToKeepDeletedMessages}. This method
455 * also updates the underlying JDOM tree with the new value. Use
456 * {@link #saveMailPreferences()} to actually write the modified
457 * XML back to the mail preferences {@link #fileName file}.
458 *
459 * @param daysToKeepDeletedMessages - The value to set.
460 */
461 public final void setDaysToKeepDeletedMessages( int daysToKeepDeletedMessages )
462 {
463 this.daysToKeepDeletedMessages = daysToKeepDeletedMessages;
464
465 document.getRootElement().getChild( "daysToKeepDeletedMessages", namespace ).setText( String.valueOf( daysToKeepDeletedMessages ) );
466 }
467 }