You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by "Robin Bankhead (JIRA)" <ji...@apache.org> on 2013/09/24 15:53:03 UTC

[jira] [Updated] (MAILBOX-199) Maildir support for Windows

     [ https://issues.apache.org/jira/browse/MAILBOX-199?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Robin Bankhead updated MAILBOX-199:
-----------------------------------

    Description: 
Propose that Maildir be supported under the Windows platform. To my knowledge, the only technical bar to this is that maildir uses the colon (":") character, which is an illegal character on the NTFS (and I believe also FAT*) filesystem.

The Maildir standard document[1] that this project refers to, specifies a colon (although quite obliquely). The "standard" clearly was never aimed at use on Windows, but its benefits as a format strike me as sufficiently great that a small deviation is justifiable in order to include it with James and thus increase platform-portability.

The below patch alters message-naming so that, instead of a literal colon, the local system's path separator character (java.io.File.pathSeparator) is used in each case, giving a colon on *NIX and a semicolon (";") on Windows. (Critique of this particular methodology is welcome.)

It also includes a quick fix for an issue encountered with file locking on Windows, which calls System.gc() on that platform. There may be other issues like this; I'm searching for them currently.

[1] http://cr.yp.to/proto/maildir.html



  was:
Propose that Maildir be supported under the Windows platform. To my knowledge, the only technical bar to this is that maildir uses the colon (":") character, which is an illegal character on the NTFS (and I believe also FAT*) filesystem.

The Maildir standard document[1] that this project refers to, specifies a colon (although quite obliquely). The "standard" clearly was never aimed at use on Windows, but its benefits as a format strike me as sufficiently great that a small deviation is justifiable in order to include it with James and thus increase platform-portability.

The below patch alters message-naming so that, instead of a literal colon, the local system's path separator character (java.io.File.pathSeparator) is used in each case, giving a colon on *NIX and a semicolon (";") on Windows. (Critique of this particular methodology is welcome.)

It also includes a quick fix for an issue encountered with file locking on Windows, which calls System.gc() so should be made OS-specific. There may be other issues like this; I'm searching for them currently.

[1] http://cr.yp.to/proto/maildir.html

# This patch file was generated by NetBeans IDE
# Following Index: paths are relative to: /home/robin/backups/app-dev/Java/apache-james-mailbox-api/maildir
# This patch can be applied using context Tools: Patch action on respective folder.
# It uses platform neutral UTF-8 encoding and \n newlines.
# Above lines and this line are ignored by the patching process.
Index: src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java
--- src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java Base (BASE)
+++ src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java Locally Modified (Based On LOCAL)
@@ -729,7 +729,7 @@
     public static String stripMetaFromName(String fileName) {
         int end = fileName.indexOf(",S="); // the size
         if (end == -1)
-            end = fileName.indexOf(":2,"); // the flags
+            end = fileName.indexOf(MaildirMessageName.FLAG_PREFIX + "2,"); // the flags
         if (end == -1)
             return fileName; // there is no meta data to strip
         return fileName.substring(0, end);
Index: src/main/java/org/apache/james/mailbox/maildir/MaildirMessageName.java
--- src/main/java/org/apache/james/mailbox/maildir/MaildirMessageName.java Base (BASE)
+++ src/main/java/org/apache/james/mailbox/maildir/MaildirMessageName.java Locally Modified (Based On LOCAL)
@@ -41,20 +41,25 @@
     public static final String FLAG_SEEN = "S";
     public static final String FLAG_DELETED = "T";
 
+	// Character used instead of ":" for Windows filesystems.
+	// Using java.io.File.pathSeparator which = ":" on *NIX
+	// and ";" on Windows.
+	public static final String FLAG_PREFIX = File.pathSeparator;//";";
+
     // patterns
     public static final String PATTERN_STRING_MESSAGE_NAME = "\\d+\\.\\w+\\..+?";
-    public static final String PATTERN_STRING_FLAGS = ":2,[DFRST]*";
+    public static final String PATTERN_STRING_FLAGS = FLAG_PREFIX + "2,[DFRST]*";
     public static final String PATTERN_STRING_SIZE = ",S=\\d+";
     public static final Pattern PATTERN_MESSAGE =
         Pattern.compile(PATTERN_STRING_MESSAGE_NAME + optional(PATTERN_STRING_SIZE) + optional(PATTERN_STRING_FLAGS));
     
     public static final Pattern PATTERN_UNSEEN_MESSAGES =
-        Pattern.compile(PATTERN_STRING_MESSAGE_NAME + PATTERN_STRING_SIZE + optional(":2,[^S]*"));
+        Pattern.compile(PATTERN_STRING_MESSAGE_NAME + PATTERN_STRING_SIZE + optional(FLAG_PREFIX + "2,[^S]*"));
     
     public static final FilenameFilter FILTER_UNSEEN_MESSAGES = createRegexFilter(PATTERN_UNSEEN_MESSAGES);
     
     public static final Pattern PATTERN_DELETED_MESSAGES =
-        Pattern.compile(PATTERN_STRING_MESSAGE_NAME + PATTERN_STRING_SIZE + ":2,.*" + FLAG_DELETED);
+        Pattern.compile(PATTERN_STRING_MESSAGE_NAME + PATTERN_STRING_SIZE + FLAG_PREFIX + "2,.*" + FLAG_DELETED);
     
     public static final FilenameFilter FILTER_DELETED_MESSAGES = createRegexFilter(PATTERN_DELETED_MESSAGES);
     
@@ -250,7 +255,7 @@
      * into its components hostname, size and flags and fills the respective variables.
      */
     private void splitHostNameAndMeta() {
-        String[] hostnamemetaFlags = hostnameAndMeta.split(":", 2);
+        String[] hostnamemetaFlags = hostnameAndMeta.split(FLAG_PREFIX, 2);
         if (hostnamemetaFlags.length >= 1) {
           this.hostnameAndMeta = hostnamemetaFlags[0];
           int firstEnd = hostnameAndMeta.indexOf(',');
@@ -272,7 +277,7 @@
         }
 
         if (hostnamemetaFlags.length >= 2) {
-            this.flagsString = ":" + hostnamemetaFlags[1];
+            this.flagsString = FLAG_PREFIX + hostnamemetaFlags[1];
         }
         if (isMessageNameStrictParse()) {
             if (sizeString == null) {
@@ -364,7 +369,7 @@
      * @return A String valid for Maildir
      */
     public String encodeFlags(Flags flags) {
-        StringBuilder localFlagsString = new StringBuilder(":2,");
+        StringBuilder localFlagsString = new StringBuilder(FLAG_PREFIX + "2,");
         if (flags.contains(Flags.Flag.DRAFT))
             localFlagsString.append(FLAG_DRAFT);
         if (flags.contains(Flags.Flag.FLAGGED))
Index: src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMessageMapper.java
--- src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMessageMapper.java Base (BASE)
+++ src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMessageMapper.java Locally Modified (Based On LOCAL)
@@ -216,7 +216,18 @@
                     // if the flags don't have change we should not try to move
                     // the file
                     if (newMessageFile.equals(messageFile) == false) {
+						byte tries = 0;
+						while (true) {
+							try {
                         FileUtils.moveFile(messageFile, newMessageFile);
+								break;
+							} catch(IOException e) {
+								if(File.pathSeparator.equals(":") || ++tries >= 5) {
+									throw e;
+								}
+								System.gc();
+							}
+						}
                         modSeq = newMessageFile.lastModified();
 
                     } else {
Index: src/test/java/org/apache/james/mailbox/maildir/MailderMessageNameTest.java
--- src/test/java/org/apache/james/mailbox/maildir/MailderMessageNameTest.java Base (BASE)
+++ src/test/java/org/apache/james/mailbox/maildir/MailderMessageNameTest.java Locally Modified (Based On LOCAL)
@@ -48,34 +48,34 @@
     public static List<Object[]> testData() {
         List<Object[]> args = new ArrayList<Object[]>();
         // no size, two flags
-        Parts parts = Parts.fullName("1328026049.19146_0.km1111:2,RS").timeSeconds(1328026049)
+        Parts parts = Parts.fullName("1328026049.19146_0.km1111;2,RS").timeSeconds(1328026049)
                 .baseName("1328026049.19146_0.km1111").flagAnswered().flagSeen();
         args.add(valid(parts));
 
         // size and flag
-        parts = Parts.fullName("1328613172.M569643P1862V0000000000000902I00EE42CE_0.km1111,S=13103:2,S")
+        parts = Parts.fullName("1328613172.M569643P1862V0000000000000902I00EE42CE_0.km1111,S=13103;2,S")
                 .timeSeconds(1328613172).size(13103L)
                 .baseName("1328613172.M569643P1862V0000000000000902I00EE42CE_0.km1111").flagSeen();
         args.add(valid(parts));
 
         // size, no flags
-        parts = Parts.fullName("1340124194.M723289P3184V0000000000000902I006780E9_6.km1111,S=1344:2,")
+        parts = Parts.fullName("1340124194.M723289P3184V0000000000000902I006780E9_6.km1111,S=1344;2,")
                 .baseName("1340124194.M723289P3184V0000000000000902I006780E9_6.km1111").timeSeconds(1340124194)
                 .size(1344L);
         args.add(valid(parts));
 
         // three flags, no size
-        parts = Parts.fullName("1106685752.12132_0.km1111:2,FRS").baseName("1106685752.12132_0.km1111")
+        parts = Parts.fullName("1106685752.12132_0.km1111;2,FRS").baseName("1106685752.12132_0.km1111")
                 .timeSeconds(1106685752).flagFlagged().flagAnswered().flagSeen();
         args.add(valid(parts));
 
         // with dovecot attributes
-        parts = Parts.fullName("1035478339.27041_118.foo.org,S=1000,W=1030:2,S")
+        parts = Parts.fullName("1035478339.27041_118.foo.org,S=1000,W=1030;2,S")
                 .baseName("1035478339.27041_118.foo.org").timeSeconds(1035478339).size(1000L).flagSeen();
         args.add(valid(parts));
 
         parts = parts.copy();
-        parts.fullName = "1035478339.27041_118.foo.org,W=1030,S=1000:2,S";
+        parts.fullName = "1035478339.27041_118.foo.org,W=1030,S=1000;2,S";
         args.add(valid(parts));
 
         // new mail, no info part at all. found in courier maildirs
@@ -84,15 +84,15 @@
         args.add(valid(parts));
 
         // new mail, generated by james
-        parts = Parts.fullName("1356001301.e563087e30181513.foohost,S=629:2,")
+        parts = Parts.fullName("1356001301.e563087e30181513.foohost,S=629;2,")
                 .baseName("1356001301.e563087e30181513.foohost").timeSeconds(1356001301).size(629L);
         args.add(valid(parts));
 
-        parts = Parts.fullName("1355675588.5c7e107958851103.foohost,S=654:2,S").timeSeconds(1355675588)
+        parts = Parts.fullName("1355675588.5c7e107958851103.foohost,S=654;2,S").timeSeconds(1355675588)
                 .baseName("1355675588.5c7e107958851103.foohost").size(654L).flagSeen();
         args.add(valid(parts));
 
-        parts = Parts.fullName("1355675651.f3dd564265174501.foohost,S=661:2,")
+        parts = Parts.fullName("1355675651.f3dd564265174501.foohost,S=661;2,")
                 .baseName("1355675651.f3dd564265174501.foohost").timeSeconds(1355675651).size(661L);
         args.add(valid(parts));
 


    
> Maildir support for Windows
> ---------------------------
>
>                 Key: MAILBOX-199
>                 URL: https://issues.apache.org/jira/browse/MAILBOX-199
>             Project: James Mailbox
>          Issue Type: New Feature
>          Components: maildir
>         Environment: Windows 7 Professional
>            Reporter: Robin Bankhead
>
> Propose that Maildir be supported under the Windows platform. To my knowledge, the only technical bar to this is that maildir uses the colon (":") character, which is an illegal character on the NTFS (and I believe also FAT*) filesystem.
> The Maildir standard document[1] that this project refers to, specifies a colon (although quite obliquely). The "standard" clearly was never aimed at use on Windows, but its benefits as a format strike me as sufficiently great that a small deviation is justifiable in order to include it with James and thus increase platform-portability.
> The below patch alters message-naming so that, instead of a literal colon, the local system's path separator character (java.io.File.pathSeparator) is used in each case, giving a colon on *NIX and a semicolon (";") on Windows. (Critique of this particular methodology is welcome.)
> It also includes a quick fix for an issue encountered with file locking on Windows, which calls System.gc() on that platform. There may be other issues like this; I'm searching for them currently.
> [1] http://cr.yp.to/proto/maildir.html

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org