diff -r bc39523cca98 -r abe1b4c57038 mail/src/main/java/com/sun/mail/imap/IMAPMessage.java
--- a/mail/src/main/java/com/sun/mail/imap/IMAPMessage.java Mon Jul 02 11:50:56 2012 -0700
+++ b/mail/src/main/java/com/sun/mail/imap/IMAPMessage.java Wed Jul 25 00:49:07 2012 +0200
@@ -40,20 +40,56 @@
package com.sun.mail.imap;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
import java.util.Date;
-import java.io.*;
import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
import java.util.Vector;
-import java.util.Hashtable;
-import java.util.Locale;
-import javax.mail.*;
-import javax.mail.internet.*;
-import javax.activation.*;
+import javax.activation.DataHandler;
+import javax.mail.Address;
+import javax.mail.FetchProfile;
+import javax.mail.Flags;
+import javax.mail.FolderClosedException;
+import javax.mail.Header;
+import javax.mail.IllegalWriteException;
+import javax.mail.Message;
+import javax.mail.MessageRemovedException;
+import javax.mail.MessagingException;
+import javax.mail.Session;
+import javax.mail.UIDFolder;
+import javax.mail.internet.ContentType;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.InternetHeaders;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeUtility;
-import com.sun.mail.util.*;
-import com.sun.mail.iap.*;
-import com.sun.mail.imap.protocol.*;
+import com.sun.mail.iap.CommandFailedException;
+import com.sun.mail.iap.ConnectionException;
+import com.sun.mail.iap.ProtocolException;
+import com.sun.mail.iap.Response;
+import com.sun.mail.imap.protocol.BODY;
+import com.sun.mail.imap.protocol.BODYSTRUCTURE;
+import com.sun.mail.imap.protocol.ENVELOPE;
+import com.sun.mail.imap.protocol.FetchCommandBuilder;
+import com.sun.mail.imap.protocol.FetchExtensions;
+import com.sun.mail.imap.protocol.FetchResponse;
+import com.sun.mail.imap.protocol.IMAPProtocol;
+import com.sun.mail.imap.protocol.INTERNALDATE;
+import com.sun.mail.imap.protocol.Item;
+import com.sun.mail.imap.protocol.MessageSet;
+import com.sun.mail.imap.protocol.RFC822DATA;
+import com.sun.mail.imap.protocol.RFC822SIZE;
+import com.sun.mail.imap.protocol.UID;
+import com.sun.mail.util.ReadableMime;
/**
* This class implements an IMAPMessage object.
@@ -115,6 +151,8 @@
// This is our Envelope
private static String EnvelopeCmd = "ENVELOPE INTERNALDATE RFC822.SIZE";
+ private Map customItems = new HashMap();
+
/**
* Constructor.
*/
@@ -974,8 +1012,9 @@
private boolean needHeaders = false;
private boolean needSize = false;
private String[] hdrs = null;
+ private List neededBuilders;
- public FetchProfileCondition(FetchProfile fp) {
+ public FetchProfileCondition(FetchProfile fp, List neededBuilders) {
if (fp.contains(FetchProfile.Item.ENVELOPE))
needEnvelope = true;
if (fp.contains(FetchProfile.Item.FLAGS))
@@ -989,6 +1028,7 @@
if (fp.contains(IMAPFolder.FetchProfileItem.SIZE))
needSize = true;
hdrs = fp.getHeaderNames();
+ this.neededBuilders = neededBuilders;
}
// The actual test.
@@ -1011,43 +1051,40 @@
if (!m.isHeaderLoaded(hdrs[i]))
return true; // Nope, return
}
+ for (FetchCommandBuilder builder: neededBuilders) {
+ if (builder.needFetch(m)) {
+ return true;
+ }
+ }
return false;
}
}
- StringBuffer command = new StringBuffer();
- boolean first = true;
+ DelimitedStringBuilder command = new DelimitedStringBuilder();
boolean allHeaders = false;
if (fp.contains(FetchProfile.Item.ENVELOPE)) {
command.append(EnvelopeCmd);
- first = false;
}
if (fp.contains(FetchProfile.Item.FLAGS)) {
- command.append(first ? "FLAGS" : " FLAGS");
- first = false;
+ command.append("FLAGS");
}
if (fp.contains(FetchProfile.Item.CONTENT_INFO)) {
- command.append(first ? "BODYSTRUCTURE" : " BODYSTRUCTURE");
- first = false;
+ command.append("BODYSTRUCTURE");
}
if (fp.contains(UIDFolder.FetchProfileItem.UID)) {
- command.append(first ? "UID" : " UID");
- first = false;
+ command.append("UID");
}
if (fp.contains(IMAPFolder.FetchProfileItem.HEADERS)) {
allHeaders = true;
if (folder.protocol.isREV1())
- command.append(first ?
- "BODY.PEEK[HEADER]" : " BODY.PEEK[HEADER]");
+ command.append("BODY.PEEK[HEADER]");
else
- command.append(first ? "RFC822.HEADER" : " RFC822.HEADER");
- first = false;
+ command.append("RFC822.HEADER");
}
if (fp.contains(IMAPFolder.FetchProfileItem.SIZE)) {
- command.append(first ? "RFC822.SIZE" : " RFC822.SIZE");
- first = false;
+ command.append("RFC822.SIZE");
}
// if we're not fetching all headers, fetch individual headers
@@ -1055,13 +1092,26 @@
if (!allHeaders) {
hdrs = fp.getHeaderNames();
if (hdrs.length > 0) {
- if (!first)
- command.append(" ");
command.append(craftHeaderCmd(folder.protocol, hdrs));
}
}
-
- Utility.Condition condition = new FetchProfileCondition(fp);
+ FetchExtensions ext = FetchExtensions.getInstance();
+ for (FetchCommandBuilder b : ext.getCommandBuilders()) {
+ String contrib = b.getCommandFragment(fp);
+ if (contrib != null) {
+ command.append(contrib);
+ }
+ }
+ javax.mail.FetchProfile.Item[] items = fp.getItems();
+ List neededBuilders = new ArrayList ();
+ for (FetchProfile.Item item: items) {
+ FetchCommandBuilder builder = ext.getCommandBuilder(item);
+ if (builder != null) {
+ neededBuilders.add(builder);
+ }
+ }
+
+ Utility.Condition condition = new FetchProfileCondition(fp, neededBuilders);
// Acquire the Folder's MessageCacheLock.
synchronized(folder.messageCacheLock) {
@@ -1192,6 +1242,8 @@
for (int k = 0; k < hdrs.length; k++)
msg.setHeaderLoaded(hdrs[k]);
}
+ } else {
+ msg.customItems.put(item.getClass().getName(), item);
}
}
@@ -1211,6 +1263,30 @@
} // Release messageCacheLock
}
+
+ static class DelimitedStringBuilder {
+ StringBuilder builder = new StringBuilder();
+ boolean first = true;
+
+ public void append(String str) {
+ if (first) {
+ first = false;
+ } else {
+ builder.append(' ');
+ }
+ builder.append(str);
+ }
+
+ @Override
+ public String toString() {
+ return builder.toString();
+ }
+ }
+
+ public Item getCustomItem(Class> cls) {
+ return customItems.get(cls.getName());
+ }
+
/*
* Load the Envelope for this message.
diff -r bc39523cca98 -r abe1b4c57038 mail/src/main/java/com/sun/mail/imap/protocol/FetchCommandBuilder.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mail/src/main/java/com/sun/mail/imap/protocol/FetchCommandBuilder.java Wed Jul 25 00:49:07 2012 +0200
@@ -0,0 +1,15 @@
+package com.sun.mail.imap.protocol;
+
+import javax.mail.FetchProfile;
+
+import com.sun.mail.imap.IMAPMessage;
+
+public interface FetchCommandBuilder {
+
+ FetchProfile.Item getResponsibleFor();
+
+ String getCommandFragment(FetchProfile profile);
+
+ boolean needFetch(IMAPMessage alreadyLoaded);
+
+}
diff -r bc39523cca98 -r abe1b4c57038 mail/src/main/java/com/sun/mail/imap/protocol/FetchExtensions.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mail/src/main/java/com/sun/mail/imap/protocol/FetchExtensions.java Wed Jul 25 00:49:07 2012 +0200
@@ -0,0 +1,151 @@
+package com.sun.mail.imap.protocol;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+
+import javax.mail.FetchProfile;
+
+import com.sun.mail.iap.ParsingException;
+
+public class FetchExtensions {
+
+ private static FetchExtensions instance;
+
+ private final static char[] RFC822DATA_HEADER = (new String(RFC822DATA.name) + ".HEADER").toCharArray();
+ private final static char[] RFC822DATA_TEXT = (new String(RFC822DATA.name) + ".TEXT").toCharArray();
+
+
+ final List itemBuilders = new ArrayList();
+ final Map> firstCharLists = new HashMap>();
+ final Map commandBuilders = new HashMap();
+ final List commandBuilderList = new ArrayList();
+
+ static abstract class BaseItemBuilder implements ItemBuilder {
+ final char[] name;
+
+ BaseItemBuilder(char[] nm) {
+ this.name = nm;
+ }
+ BaseItemBuilder(String nm) {
+ this.name = nm.toCharArray();
+ }
+
+ @Override
+ public char[] getName() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ return "ItemBuilder[ " + String.valueOf(name)+ ']';
+ }
+ }
+
+
+
+ protected FetchExtensions() {
+ itemBuilders.add(new BaseItemBuilder(BODY.name) {
+ @Override
+ public Item build(FetchResponse response) throws ParsingException {
+ return new BODY(response);
+ }
+ });
+ itemBuilders.add(new BaseItemBuilder(ENVELOPE.name) {
+ @Override
+ public Item build(FetchResponse response) throws ParsingException {
+ return new ENVELOPE(response);
+ }
+ });
+ itemBuilders.add(new BaseItemBuilder(FLAGS.name) {
+ @Override
+ public Item build(FetchResponse response) throws ParsingException {
+ return new FLAGS(response);
+ }
+ });
+ itemBuilders.add(new BaseItemBuilder(INTERNALDATE.name) {
+ @Override
+ public Item build(FetchResponse response) throws ParsingException {
+ return new INTERNALDATE(response);
+ }
+ });
+ itemBuilders.add(new BaseItemBuilder(BODYSTRUCTURE.name) {
+ @Override
+ public Item build(FetchResponse response) throws ParsingException {
+ return new BODYSTRUCTURE(response);
+ }
+ });
+ itemBuilders.add(new BaseItemBuilder(RFC822SIZE.name) {
+ @Override
+ public Item build(FetchResponse response) throws ParsingException {
+ return new RFC822SIZE(response);
+ }
+ });
+ itemBuilders.add(new BaseItemBuilder(RFC822DATA_HEADER) {
+ @Override
+ public Item build(FetchResponse response) throws ParsingException {
+ return new RFC822DATA(response);
+ }
+ });
+ itemBuilders.add(new BaseItemBuilder(RFC822DATA_TEXT) {
+ @Override
+ public Item build(FetchResponse response) throws ParsingException {
+ return new RFC822DATA(response);
+ }
+ });
+ itemBuilders.add(new BaseItemBuilder(UID.name) {
+ @Override
+ public Item build(FetchResponse response) throws ParsingException {
+ return new UID(response);
+ }
+ });
+ ServiceLoader loader = ServiceLoader.load(ItemBuilder.class);
+ for (ItemBuilder additional : loader) {
+ itemBuilders.add(additional);
+ }
+ for (ItemBuilder b : itemBuilders) {
+ Character firstCharacter = Character.valueOf(b.getName()[0]);
+ List list = firstCharLists.get(firstCharacter);
+ if (list == null) {
+ list = new ArrayList();
+ firstCharLists.put(firstCharacter, list);
+ }
+ list.add(b);
+ }
+ ServiceLoader loader2 = ServiceLoader.load(FetchCommandBuilder.class);
+ for (FetchCommandBuilder b : loader2) {
+ commandBuilders.put(b.getResponsibleFor(), b);
+ commandBuilderList.add(b);
+ }
+ }
+
+
+ public List getItemBuilders() {
+ return itemBuilders;
+ }
+
+ public List getItemBuildersStartsWith(Character ch) {
+ List list = firstCharLists.get(ch);
+ return list != null ? list : Collections.emptyList();
+ }
+
+ public List getCommandBuilders() {
+ return commandBuilderList;
+ }
+
+ public FetchCommandBuilder getCommandBuilder(FetchProfile.Item item) {
+ return commandBuilders.get(item);
+ }
+
+
+ public static synchronized FetchExtensions getInstance() {
+ if (instance == null) {
+ instance = new FetchExtensions();
+ }
+ return instance;
+ }
+
+}
diff -r bc39523cca98 -r abe1b4c57038 mail/src/main/java/com/sun/mail/imap/protocol/FetchResponse.java
--- a/mail/src/main/java/com/sun/mail/imap/protocol/FetchResponse.java Mon Jul 02 11:50:56 2012 -0700
+++ b/mail/src/main/java/com/sun/mail/imap/protocol/FetchResponse.java Wed Jul 25 00:49:07 2012 +0200
@@ -42,6 +42,7 @@
import java.io.*;
import java.util.*;
+
import com.sun.mail.util.*;
import com.sun.mail.iap.*;
@@ -105,84 +106,34 @@
return null;
}
- private final static char[] HEADER = {'.','H','E','A','D','E','R'};
- private final static char[] TEXT = {'.','T','E','X','T'};
-
-
private void parse() throws ParsingException {
skipSpaces();
if (buffer[index] != '(')
throw new ParsingException(
"error in FETCH parsing, missing '(' at index " + index);
+ FetchExtensions itemBuilders = FetchExtensions.getInstance();
Vector v = new Vector();
- Item i = null;
+ Item i = null;
do {
index++; // skip '(', or SPACE
if (index >= size)
throw new ParsingException(
"error in FETCH parsing, ran off end of buffer, size " + size);
+ i = null;
- switch(buffer[index]) {
- case 'E': case 'e':
- if (match(ENVELOPE.name)) {
- index += ENVELOPE.name.length; // skip "ENVELOPE"
- i = new ENVELOPE(this);
- }
- break;
- case 'F': case 'f':
- if (match(FLAGS.name)) {
- index += FLAGS.name.length; // skip "FLAGS"
- i = new FLAGS((IMAPResponse)this);
- }
- break;
- case 'I': case 'i':
- if (match(INTERNALDATE.name)) {
- index += INTERNALDATE.name.length; // skip "INTERNALDATE"
- i = new INTERNALDATE(this);
- }
- break;
- case 'B': case 'b':
- if (match(BODY.name)) {
- if (buffer[index+4] == '[') {
- index += BODY.name.length; // skip "BODY"
- i = new BODY(this);
- }
- else {
- if (match(BODYSTRUCTURE.name))
- index += BODYSTRUCTURE.name.length;
- // skip "BODYSTRUCTURE"
- else
- index += BODY.name.length; // skip "BODY"
- i = new BODYSTRUCTURE(this);
- }
- }
- break;
- case 'R': case 'r':
- if (match(RFC822SIZE.name)) {
- index += RFC822SIZE.name.length; // skip "RFC822.SIZE"
- i = new RFC822SIZE(this);
- }
- else {
- if (match(RFC822DATA.name)) {
- index += RFC822DATA.name.length;
- if (match(HEADER))
- index += HEADER.length; // skip ".HEADER"
- else if (match(TEXT))
- index += TEXT.length; // skip ".TEXT"
- i = new RFC822DATA(this);
- }
- }
- break;
- case 'U': case 'u':
- if (match(UID.name)) {
- index += UID.name.length;
- i = new UID(this);
- }
- break;
- default:
+ byte current = buffer[index];
+ Character upperCase = Character.toUpperCase((char) current);
+ List itemBuildersStartsWith = itemBuilders.getItemBuildersStartsWith(upperCase);
+ for (Iterator iter = itemBuildersStartsWith.iterator(); iter.hasNext() && i == null;) {
+ ItemBuilder builder = iter.next();
+ if (match(builder.getName())) {
+ index += builder.getName().length;
+ i = builder.build(this);
+ }
}
+
if (i != null)
v.addElement(i);
} while (buffer[index] != ')');
@@ -203,6 +154,6 @@
// uppercase, so convert operand to uppercase before comparing.
if (Character.toUpperCase((char)buffer[j++]) != itemName[i++])
return false;
- return true;
+ return index + len >= buffer.length || !Character.isLetter(buffer[index + len]);
}
}
diff -r bc39523cca98 -r abe1b4c57038 mail/src/main/java/com/sun/mail/imap/protocol/ItemBuilder.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mail/src/main/java/com/sun/mail/imap/protocol/ItemBuilder.java Wed Jul 25 00:49:07 2012 +0200
@@ -0,0 +1,10 @@
+package com.sun.mail.imap.protocol;
+
+import com.sun.mail.iap.ParsingException;
+
+public interface ItemBuilder {
+
+ char[] getName();
+
+ Item build(FetchResponse response) throws ParsingException;
+}