View Javadoc

1   /*
2    * Copyright (c) 2005-2006 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.maildir.uid;
14  
15  import java.io.File;
16  import java.io.IOException;
17  
18  import javax.mail.MessagingException;
19  import javax.mail.internet.MimeMessage;
20  
21  import org.abstracthorizon.mercury.maildir.MaildirFolderData;
22  import org.abstracthorizon.mercury.maildir.MaildirMessage;
23  
24  
25  /**
26   * <p>UID Maildir message representation.</p>
27   * <p>Messages file name is defined in the following way:
28   * <ul>
29   * <li>time of creation in seconds</li>
30   * <li>&quot;.&quot; (dot)</li>
31   * <li>&quot;V&quot; followed with last 9 bits of folder's hash code as an integer</li>
32   * <li>&quot;U&quot; message's uid</li>
33   * <li>&quot;.&quot; (dot)</li>
34   * <li>host name</li>
35   * <li>optional &quot;:&quot;, &quot;.&quot; or value from stores info separator attibute
36   * followed by &quot;2,&quot; followed by flags</li>
37   * </ul>
38   * Flags are defined on the way explained in {@link org.abstracthorizon.mercury.maildir.FlagUtilities}
39   * </p>
40   * <p>Note: If file supplied in one of the constructors doesn't match this file name pattern file is then
41   * renamed to match it. Also, if file name matches that pattern but folder's hash code is different
42   * (folder's hash code represents UID validity) file is again renamed to proper one.
43   * </p>
44   *
45   * @author Daniel Sendula
46   */
47  public class UIDMaildirMessage extends MaildirMessage implements UIDMessage {
48  
49      /** Messages uid object */
50      private UID uid;
51  
52      /**
53       * Creates new message based on another message. It will create new file for this message in supplied folder.
54       * @param folder folder this message belongs to
55       * @param message message
56       * @param msgnum message number
57       * @throws MessagingException
58       * @throws IOException
59       */
60      protected UIDMaildirMessage(MaildirFolderData folder, MimeMessage message, int msgnum) throws MessagingException, IOException {
61          super(folder, message, msgnum);
62      }
63  
64      /**
65       * This constructor creates new message from supplied file. If supplied file doesn't
66       * match appropriate format than it is renamed.
67       * @param folder folder this message belongs to
68       * @param file file
69       * @param msgnum message number
70       * @throws MessagingException
71       */
72      public UIDMaildirMessage(MaildirFolderData folder, File file, int msgnum) throws MessagingException {
73          super(folder, file, msgnum, false);
74  
75          String name = file.getName();
76  
77          int i = name.indexOf('.');
78          if (i > 0) {
79              int j = name.indexOf('.', i+1);
80              if (name.charAt(i+1) == 'V') {
81                  int k = name.indexOf('U', i+1);
82                  if ((k > 0) && (k < j)) {
83                      try {
84                          int folderHash = Integer.parseInt(name.substring(i+2, k));
85                          long uidx = Long.parseLong(name.substring(k+1, j));
86                          if ((getFolder().hashCode() & 511) == folderHash) {
87                              uid = new UID(uidx);
88                          }
89                      } catch (NumberFormatException ignore) {
90                      }
91                  }
92              }
93          }
94  
95          if (uid == null) {
96              File oldFile = file;
97              String filename = file.getName();
98              String flags = null;
99  
100             int j = filename.lastIndexOf(FLAGS_SEPERATOR);
101             if (j >= 0) {
102                 flags = filename.substring(j+2);
103             }
104 
105             this.file = new File(file.getParentFile(), createFileName(flags));
106             long oldDate = oldFile.lastModified();
107             if (!oldFile.renameTo(this.file)) {
108                 throw new MessagingException("Cannot rename "+oldFile.getAbsolutePath()+" to "+this.file.getAbsolutePath());
109             } else {
110                 this.file.setLastModified(oldDate);
111             }
112         }
113         initialise();
114     }
115 
116     /**
117      * Creates file name using supplied flags.
118      * @param flags flags
119      * @return file name for this message
120      * @throws MessagingException
121      */
122     protected String createFileName(String flags) throws MessagingException {
123         String time = Long.toString(System.currentTimeMillis());
124 
125         uid = ((UIDMaildirFolderData)folder).getNextUID();
126 
127          String folderHash = Integer.toString(getFolder().hashCode() & 511);
128 
129         baseName = time + ".V" + folderHash + 'U' + uid.getUID() + '.' + host;
130 
131         if ((flags == null) || (flags.length() == 0)) {
132             return baseName;
133         } else {
134             return baseName + infoSeparator + FLAGS_SEPERATOR + flags;
135         }
136     }
137 
138     /**
139      * Returns message's UID object.
140      * @return message's UID object.
141      */
142     public UID getUID() {
143         return uid;
144     }
145 
146     /**
147      * This object compares two messages based on UID value.
148      * @param o message to be compared
149      * @return <code>true</code> if both messages have same UID. <code>False</code> is returned if
150      * UIDs are different or supplied object is not UID message
151      */
152     public boolean equals(Object o) {
153         if (o instanceof UIDMaildirMessage) {
154             long u1 = uid.getUID();
155             long u2 = ((UIDMaildirMessage)o).getUID().getUID();
156             if ((u1 == u2) && (getFolder().getFullName().equals(((UIDMaildirMessage)o).getFolder().getFullName()))) {
157                 return true;
158             }
159         }
160         return false;
161     }
162 
163     /**
164      * This method compares two messages' uids.
165      * @param o message to be compared with
166      * @return -1, 0, 1 depending if this message has less, equal or greater UID then supplied.
167      * If supplied object is not UID message then -1 is returned.
168      */
169     public int compareTo(MaildirMessage o) {
170         if (o instanceof UIDMaildirMessage) {
171             long u1 = uid.getUID();
172             long u2 = ((UIDMaildirMessage)o).getUID().getUID();
173             if (u1 == u2) {
174                 return 0;
175             } else if (u1 < u2) {
176                 return -1;
177             } else {
178                 return 1;
179             }
180         }
181         return -1;
182     }
183 }