Merge "Clean up ImapStore and related classes."

This commit is contained in:
Makoto Onuki 2010-05-20 15:17:57 -07:00 committed by Android (Google) Code Review
commit 12e64b09d8
5 changed files with 93 additions and 90 deletions

View File

@ -28,15 +28,15 @@ import java.util.ArrayList;
* Part: Indicates that the given Part should be fetched. The provider
* is expected have previously created the given BodyPart and stored
* any information it needs to download the content.
* </pre>
* </pre>
*/
public class FetchProfile extends ArrayList {
public class FetchProfile extends ArrayList<Fetchable> {
/**
* Default items available for pre-fetching. It should be expected that any
* item fetched by using these items could potentially include all of the
* previous items.
*/
public enum Item {
public enum Item implements Fetchable {
/**
* Download the flags of the message.
*/
@ -54,7 +54,7 @@ public class FetchProfile extends ArrayList {
* The provider should, if possible, fill in a properly formatted MIME structure in
* the message without actually downloading any message data. If the provider is not
* capable of this operation it should specifically set the body of the message to null
* so that upper levels can detect that a full body download is needed.
* so that upper levels can detect that a full body download is needed.
*/
STRUCTURE,
@ -63,7 +63,7 @@ public class FetchProfile extends ArrayList {
* This should generaly be around 50kB.
*/
BODY_SANE,
/**
* The entire message.
*/

View File

@ -0,0 +1,24 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.email.mail;
/**
* Interface for classes that can be added to {@link FetchProfile}.
* i.e. {@link Part} and its subclasses, and {@link FetchProfile.Item}.
*/
public interface Fetchable {
}

View File

@ -19,7 +19,7 @@ package com.android.email.mail;
import java.io.IOException;
import java.io.OutputStream;
public interface Part {
public interface Part extends Fetchable {
public void addHeader(String name, String value) throws MessagingException;
public void removeHeader(String name) throws MessagingException;
@ -31,17 +31,17 @@ public interface Part {
public String getContentType() throws MessagingException;
public String getDisposition() throws MessagingException;
public String getContentId() throws MessagingException;
public String[] getHeader(String name) throws MessagingException;
public void setExtendedHeader(String name, String value) throws MessagingException;
public String getExtendedHeader(String name) throws MessagingException;
public int getSize() throws MessagingException;
public boolean isMimeType(String mimeType) throws MessagingException;
public String getMimeType() throws MessagingException;

View File

@ -44,6 +44,7 @@ import java.util.regex.Pattern;
public class MimeUtility {
public static final String MIME_TYPE_RFC822 = "message/rfc822";
private final static Pattern PATTERN_CR_OR_LF = Pattern.compile("\r|\n");
/**
@ -179,6 +180,8 @@ public class MimeUtility {
* TODO: Also has a latent bug: uses "startsWith" to match the name, which can false-positive.
* TODO: The doc says that for a null name you get the first param, but you get the header.
* Should probably just fix the doc, but if other code assumes that behavior, fix the code.
* TODO: Need to decode %-escaped strings, as in: filename="ab%22d".
* ('+' -> ' ' conversion too? check RFC)
*
* @param header
* @param name

View File

@ -77,6 +77,7 @@ import javax.net.ssl.SSLException;
* TODO Need to start keeping track of UIDVALIDITY
* TODO Need a default response handler for things like folder updates
* TODO In fetch(), if we need a ImapMessage and were given
* TODO Collect ALERT messages and show them to users.
* something else we can try to do a pre-fetch first.
*
* ftp://ftp.isi.edu/in-notes/rfc2683.txt When a client asks for
@ -230,7 +231,8 @@ public class ImapStore extends Store {
* @param capability the capabilities string from the server
* @return a String for use in an IMAP ID message.
*/
public String getImapId(Context context, String userName, String host, String capability) {
public static String getImapId(Context context, String userName, String host,
String capability) {
// The first section is global to all IMAP connections, and generates the fixed
// values in any IMAP ID message
synchronized (ImapStore.class) {
@ -290,7 +292,7 @@ public class ImapStore extends Store {
* @param networkOperator TelephonyManager.getNetworkOperatorName()
* @return the static (never changes) portion of the IMAP ID
*/
/* package */ String makeCommonImapId(String packageName, String version,
/* package */ static String makeCommonImapId(String packageName, String version,
String codeName, String model, String id, String vendor, String networkOperator) {
// Before building up IMAP ID string, pre-filter the input strings for "legal" chars
@ -363,7 +365,7 @@ public class ImapStore extends Store {
synchronized (mFolderCache) {
folder = mFolderCache.get(name);
if (folder == null) {
folder = new ImapFolder(name);
folder = new ImapFolder(this, name);
mFolderCache.put(name, folder);
}
}
@ -413,8 +415,7 @@ public class ImapStore extends Store {
ImapConnection connection = new ImapConnection();
connection.open();
connection.close();
}
catch (IOException ioe) {
} catch (IOException ioe) {
throw new MessagingException(MessagingException.IOERROR, ioe.toString());
}
}
@ -457,8 +458,7 @@ public class ImapStore extends Store {
byte[] b = new byte[bb.limit()];
bb.get(b);
return new String(b, "US-ASCII");
}
catch (UnsupportedEncodingException uee) {
} catch (UnsupportedEncodingException uee) {
/*
* The only thing that can throw this is getBytes("US-ASCII") and if US-ASCII doesn't
* exist we're totally screwed.
@ -476,8 +476,7 @@ public class ImapStore extends Store {
byte[] encoded = name.getBytes("US-ASCII");
CharBuffer cb = MODIFIED_UTF_7_CHARSET.decode(ByteBuffer.wrap(encoded));
return cb.toString();
}
catch (UnsupportedEncodingException uee) {
} catch (UnsupportedEncodingException uee) {
/*
* The only thing that can throw this is getBytes("US-ASCII") and if US-ASCII doesn't
* exist we're totally screwed.
@ -486,15 +485,17 @@ public class ImapStore extends Store {
}
}
class ImapFolder extends Folder {
static class ImapFolder extends Folder {
private final ImapStore mStore;
private final String mName;
private int mMessageCount = -1;
private ImapConnection mConnection;
private OpenMode mMode;
private boolean mExists;
public ImapFolder(String name) {
this.mName = name;
public ImapFolder(ImapStore store, String name) {
mStore = store;
mName = name;
}
@Override
@ -512,7 +513,7 @@ public class ImapStore extends Store {
}
}
synchronized (this) {
mConnection = getConnection();
mConnection = mStore.getConnection();
}
// * FLAGS (\Answered \Flagged \Deleted \Seen \Draft NonJunk
// $MDNSent)
@ -578,7 +579,7 @@ public class ImapStore extends Store {
// TODO implement expunge
mMessageCount = -1;
synchronized (this) {
poolConnection(mConnection);
mStore.poolConnection(mConnection);
mConnection = null;
}
}
@ -601,9 +602,8 @@ public class ImapStore extends Store {
ImapConnection connection = null;
synchronized(this) {
if (mConnection == null) {
connection = getConnection();
}
else {
connection = mStore.getConnection();
} else {
connection = mConnection;
}
}
@ -612,16 +612,16 @@ public class ImapStore extends Store {
encodeFolderName(mName)));
mExists = true;
return true;
}
catch (MessagingException me) {
} catch (MessagingException me) {
return false;
}
catch (IOException ioe) {
} catch (IOException ioe) {
throw ioExceptionHandler(connection, ioe);
}
finally {
} finally {
if (mConnection == null) {
poolConnection(connection);
mStore.poolConnection(connection);
}
}
}
@ -642,9 +642,8 @@ public class ImapStore extends Store {
ImapConnection connection = null;
synchronized(this) {
if (mConnection == null) {
connection = getConnection();
}
else {
connection = mStore.getConnection();
} else {
connection = mConnection;
}
}
@ -652,16 +651,16 @@ public class ImapStore extends Store {
connection.executeSimpleCommand(String.format("CREATE \"%s\"",
encodeFolderName(mName)));
return true;
}
catch (MessagingException me) {
} catch (MessagingException me) {
return false;
}
catch (IOException ioe) {
} catch (IOException ioe) {
throw ioExceptionHandler(connection, ioe);
}
finally {
} finally {
if (mConnection == null) {
poolConnection(connection);
mStore.poolConnection(connection);
}
}
}
@ -678,8 +677,7 @@ public class ImapStore extends Store {
mConnection.executeSimpleCommand(String.format("UID COPY %s \"%s\"",
Utility.combine(uids, ','),
encodeFolderName(folder.getName())));
}
catch (IOException ioe) {
} catch (IOException ioe) {
throw ioExceptionHandler(mConnection, ioe);
}
}
@ -704,8 +702,7 @@ public class ImapStore extends Store {
}
}
return unreadMessageCount;
}
catch (IOException ioe) {
} catch (IOException ioe) {
throw ioExceptionHandler(mConnection, ioe);
}
}
@ -1007,7 +1004,7 @@ public class ImapStore extends Store {
}
}
private void parseBodyStructure(ImapList bs, Part part, String id)
private static void parseBodyStructure(ImapList bs, Part part, String id)
throws MessagingException {
if (bs.get(0) instanceof ImapList) {
/*
@ -1020,7 +1017,7 @@ public class ImapStore extends Store {
* For each part in the message we're going to add a new BodyPart and parse
* into it.
*/
ImapBodyPart bp = new ImapBodyPart();
MimeBodyPart bp = new MimeBodyPart();
if (id.equals("TEXT")) {
parseBodyStructure(bs.getList(i), bp, Integer.toString(i + 1));
}
@ -1040,8 +1037,7 @@ public class ImapStore extends Store {
}
}
part.setBody(mp);
}
else{
} else {
/*
* This is a body. We need to add as much information as we can find out about
* it to the Part.
@ -1070,16 +1066,18 @@ public class ImapStore extends Store {
String encoding = bs.getString(5);
int size = bs.getNumber(6);
if (MimeUtility.mimeTypeMatches(mimeType, "message/rfc822")) {
// A body type of type MESSAGE and subtype RFC822
// contains, immediately after the basic fields, the
// envelope structure, body structure, and size in
// text lines of the encapsulated message.
// [MESSAGE, RFC822, [NAME, Fwd: [#HTR-517941]: update plans at 1am Friday - Memory allocation - displayware.eml], NIL, NIL, 7BIT, 5974, NIL, [INLINE, [FILENAME*0, Fwd: [#HTR-517941]: update plans at 1am Friday - Memory all, FILENAME*1, ocation - displayware.eml]], NIL]
if (MimeUtility.mimeTypeMatches(mimeType, MimeUtility.MIME_TYPE_RFC822)) {
// A body type of type MESSAGE and subtype RFC822
// contains, immediately after the basic fields, the
// envelope structure, body structure, and size in
// text lines of the encapsulated message.
// [MESSAGE, RFC822, [NAME, filename.eml], NIL, NIL, 7BIT, 5974, NIL,
// [INLINE, [FILENAME*0, Fwd: Xxx..., FILENAME*1, filename.eml]], NIL]
/*
* This will be caught by fetch and handled appropriately.
*/
throw new MessagingException("BODYSTRUCTURE message/rfc822 not yet supported.");
throw new MessagingException("BODYSTRUCTURE " + MimeUtility.MIME_TYPE_RFC822
+ " not yet supported.");
}
/*
@ -1161,11 +1159,9 @@ public class ImapStore extends Store {
if (part instanceof ImapMessage) {
((ImapMessage) part).setSize(size);
}
else if (part instanceof ImapBodyPart) {
((ImapBodyPart) part).setSize(size);
}
else {
} else if (part instanceof MimeBodyPart) {
((MimeBodyPart) part).setSize(size);
} else {
throw new MessagingException("Unknown part type " + part.toString());
}
part.setHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA, id);
@ -1220,8 +1216,7 @@ public class ImapStore extends Store {
eolOut.write('\r');
eolOut.write('\n');
eolOut.flush();
}
else if (response.mTag == null) {
} else if (response.mTag == null) {
handleUntaggedResponse(response);
}
while (response.more());
@ -1256,10 +1251,8 @@ public class ImapStore extends Store {
message.setUid(response1.getString(response1.size()-1));
}
}
}
}
catch (IOException ioe) {
} catch (IOException ioe) {
throw ioExceptionHandler(mConnection, ioe);
}
}
@ -1305,8 +1298,8 @@ public class ImapStore extends Store {
uidList,
value ? "+" : "-",
allFlags));
}
catch (IOException ioe) {
} catch (IOException ioe) {
throw ioExceptionHandler(mConnection, ioe);
}
}
@ -1448,13 +1441,6 @@ public class ImapStore extends Store {
}
public void close() {
// if (isOpen()) {
// try {
// executeSimpleCommand("LOGOUT");
// } catch (Exception e) {
//
// }
// }
if (mTransport != null) {
mTransport.close();
mTransport = null;
@ -1529,7 +1515,7 @@ public class ImapStore extends Store {
}
}
class ImapMessage extends MimeMessage {
static class ImapMessage extends MimeMessage {
ImapMessage(String uid, Folder folder) throws MessagingException {
this.mUid = uid;
this.mFolder = folder;
@ -1555,17 +1541,7 @@ public class ImapStore extends Store {
}
}
class ImapBodyPart extends MimeBodyPart {
public ImapBodyPart() throws MessagingException {
super();
}
// public void setSize(int size) {
// this.mSize = size;
// }
}
class ImapException extends MessagingException {
static class ImapException extends MessagingException {
String mAlertText;
public ImapException(String message, String alertText, Throwable throwable) {