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  import java.io.RandomAccessFile;
18  
19  import javax.mail.MessagingException;
20  import javax.mail.internet.MimeMessage;
21  
22  import org.abstracthorizon.mercury.maildir.MaildirFolderData;
23  import org.abstracthorizon.mercury.maildir.MaildirMessage;
24  import org.abstracthorizon.mercury.maildir.MaildirStore;
25  
26  /**
27   * UID implementation of maildir folder model.
28   *
29   * @author Daniel Sendula
30   */
31  public class UIDMaildirFolderData extends MaildirFolderData /* implements UIDFolder TODO: nice to have */{
32  
33  
34      /** Number of retries for .nextuid file to be read */
35      public static final int MAX_RETRIES = 30;
36  
37  
38      /** Current maxUID (last read) */
39      protected long maxUid = -1;
40  
41      /** UID validity of this folder */
42      protected long uidValidity = -1;
43  
44      /**
45       * Constructor.
46       * @param store store
47       * @param file file
48       */
49      protected UIDMaildirFolderData(MaildirStore store, File file) {
50          super(store, file);
51      }
52  
53      /**
54       * Returns max uid value
55       * @return max uid value
56       */
57      public long getMaxUID() {
58          return maxUid;
59      }
60  
61      /**
62       * This method creates new maildir message for folder data (not folder). It is expected
63       * for this method to create appropriate file in proper directory based on flags in
64       * supplied message (cur or new).
65       * @param message message whose content will be copied to new message
66       * @param num message number
67       * @return new maildir message this folder will keep for its folder data
68       * @throws IOException
69       * @throws MessagingException
70       */
71      protected synchronized MaildirMessage createNewMaildirMessage(MimeMessage message, int num) throws IOException, MessagingException {
72          UIDMaildirMessage msg = new UIDMaildirMessage(this, message, num);
73          return msg;
74      }
75  
76      /**
77       * This method creates new maildir message object for existing file in folder data's directory.
78       * @param file file message object is going to be created
79       * @param num message number
80       * @return new maildir message this folder will keep for its folder data
81       * @throws IOException
82       * @throws MessagingException
83       */
84      protected MaildirMessage createExistingMaildirMessage(File file, int num) throws IOException, MessagingException {
85          UIDMaildirMessage msg = new UIDMaildirMessage(this, file, num);
86          return msg;
87      }
88  
89  
90      /**
91       * This method obtains next UID
92       * @return next UID number
93       * @throws MessagingException
94       */
95      protected synchronized UID getNextUID() throws MessagingException {
96          RandomAccessFile uidFile = null;
97          File file = new File(getFolderFile(), UIDMaildirStore.NEXT_UID_FILE);
98          int retry = 0;
99          while ((uidFile == null) && (retry < MAX_RETRIES)) {
100             try {
101                 uidFile = new RandomAccessFile(file, "rw");
102             } catch (IOException ignore) {
103             }
104             if (uidFile == null) {
105                 try {
106                     Thread.sleep(100);
107                 } catch (InterruptedException ignore) {
108                 }
109                 retry = retry + 1;
110             }
111         }
112         try {
113             String old = uidFile.readLine();
114             long uid = 0;
115             try {
116                 uid = Long.parseLong(old);
117             } catch (NumberFormatException ignore) {
118             }
119             uid = uid + 1;
120             uidFile.seek(0);
121             uidFile.writeBytes(Long.toString(uid));
122             uidFile.close();
123             maxUid = uid;
124             return new UID(uid);
125         } catch (IOException e) {
126             throw new MessagingException("Cannot obtain next uid", e);
127         } finally {
128             try {
129                 uidFile.close();
130             } catch (IOException ignore) {
131             }
132         }
133     }
134 
135     /**
136      * This method returns folder's uid validity. It is read from &quot;.uidvalidity&quot;
137      * @return uid validity
138      */
139     public long getUIDValidity() {
140         if (uidValidity != -1) {
141             return uidValidity;
142         }
143         File file = new File(getFolderFile(), UIDMaildirStore.UID_VALIDITY_FILE);
144         if (file.exists()) {
145             try {
146                 RandomAccessFile uidFile = new RandomAccessFile(file, "r");
147                 try {
148                     String line = uidFile.readLine();
149                     try {
150                         uidValidity = Long.parseLong(line);
151                     } catch (NumberFormatException ignore) {
152                     }
153                 } finally {
154                     uidFile.close();
155                 }
156             } catch (IOException ignore) {
157             }
158         }
159         if (uidValidity == -1) {
160             uidValidity = System.currentTimeMillis();
161             try {
162                 RandomAccessFile uidFile = new RandomAccessFile(file, "rw");
163                 try {
164                     uidFile.writeBytes(Long.toString(uidValidity));
165                 } finally {
166                     uidFile.close();
167                 }
168             } catch (IOException ignore) {
169             }
170         }
171         return uidValidity;
172     }
173 
174     /**
175      * Returns folder's uid validity as integer - hash code
176      * @return folder's uid validity
177      */
178     public int hashCode() {
179         return (int)getUIDValidity();
180     }
181 }