📄 imapfolder.java
字号:
// Bad bad server ..
throw new MessagingException(pex.getMessage(), pex);
} finally {
doExpungeNotification = true;
}
// Cleanup expunged messages and sync messageCache with
// reality.
for (int i = 0; i < messageCache.size(); ) {
IMAPMessage m = (IMAPMessage)messageCache.elementAt(i);
if (m.isExpunged()) {
v.addElement(m); // add into vector of expunged messages
/* remove this message from the messageCache.
*
* Note that this also causes all succeeding messages
* in the cache to shifted downward in the vector,
* therby decrementing the vector's size. (and hence
* we need to do messageCache.size() at the top of
* this loop.
*/
messageCache.removeElementAt(i);
/* remove this message from the UIDTable */
if (uidTable != null) {
long uid = m.getUID();
if (uid != -1)
uidTable.remove(new Long(uid));
}
} else {
/* Valid message, sync its message number with
* its sequence number.
*/
m.setMessageNumber(m.getSequenceNumber());
i++; // done; increment index, go check next message
}
}
}
// Update 'total'
total = messageCache.size();
// Notify listeners. This time its for real, guys.
Message[] rmsgs = new Message[v.size()];
v.copyInto(rmsgs);
if (rmsgs.length > 0)
notifyMessageRemovedListeners(true, rmsgs);
return rmsgs;
}
/**
* Search whole folder for messages matching the given term.
*/
public synchronized Message[] search(SearchTerm term)
throws MessagingException {
checkOpened();
try {
Message[] matchMsgs = null;
synchronized(messageCacheLock) {
int[] matches = getProtocol().search(term);
if (matches != null) {
matchMsgs = new IMAPMessage[matches.length];
// Map seq-numbers into actual Messages.
for (int i = 0; i < matches.length; i++)
matchMsgs[i] = getMessageBySeqNumber(matches[i]);
}
}
return matchMsgs;
} catch (CommandFailedException cfx) {
// unsupported charset or search criterion
return super.search(term);
} catch (SearchException sex) {
// too complex for IMAP
return super.search(term);
} catch (ConnectionException cex) {
throw new FolderClosedException(this, cex.getMessage());
} catch (ProtocolException pex) {
// bug in our IMAP layer ?
throw new MessagingException(pex.getMessage(), pex);
}
}
/**
* Search the folder for messages matching the given term. Returns
* array of matching messages. Returns an empty array if no matching
* messages are found.
*/
public synchronized Message[] search(SearchTerm term, Message[] msgs)
throws MessagingException {
checkOpened();
if (msgs.length == 0)
// need to return an empty array (not null!)
return msgs;
try {
Message[] matchMsgs = null;
synchronized(messageCacheLock) {
IMAPProtocol p = getProtocol();
MessageSet[] ms = Utility.toMessageSet(msgs, null);
if (ms == null)
throw new MessageRemovedException(
"Messages have been removed");
int[] matches = p.search(ms, term);
if (matches != null) {
matchMsgs = new IMAPMessage[matches.length];
for (int i = 0; i < matches.length; i++)
matchMsgs[i] = getMessageBySeqNumber(matches[i]);
}
}
return matchMsgs;
} catch (CommandFailedException cfx) {
// unsupported charset or search criterion
return super.search(term, msgs);
} catch (SearchException sex) {
// too complex for IMAP
return super.search(term, msgs);
} catch (ConnectionException cex) {
throw new FolderClosedException(this, cex.getMessage());
} catch (ProtocolException pex) {
// bug in our IMAP layer ?
throw new MessagingException(pex.getMessage(), pex);
}
}
/***********************************************************
* UIDFolder interface methods
**********************************************************/
/**
* Returns the UIDValidity for this folder.
*/
public synchronized long getUIDValidity() throws MessagingException {
if (opened) // we already have this information
return uidvalidity;
IMAPProtocol p = null;
Status status = null;
try {
p = getStoreProtocol(); // XXX
String[] item = { "UIDVALIDITY" };
status = p.status(fullName, item);
} catch (BadCommandException bex) {
// Probably a RFC1730 server
throw new MessagingException("Cannot obtain UIDValidity", bex);
} catch (ConnectionException cex) {
// Oops, the store or folder died on us.
throwClosedException(cex);
} catch (ProtocolException pex) {
throw new MessagingException(pex.getMessage(), pex);
} finally {
releaseStoreProtocol(p);
}
return status.uidvalidity;
}
/**
* Returns the predicted UID that will be assigned to the
* next message that is appended to this folder.
* If the folder is closed, the STATUS command is used to
* retrieve this value. If the folder is open, the value
* returned from the SELECT or EXAMINE command is returned.
* Note that messages may have been appended to the folder
* while it was open and thus this value may be out of
* date. <p>
*
* Servers implementing RFC2060 likely won't return this value
* when a folder is opened. Servers implementing RFC3501
* should return this value when a folder is opened. <p>
*
* @return the UIDNEXT value, or -1 if unknown
* @since JavaMail 1.3.3
*/
// Not a UIDFolder method, but still useful
public synchronized long getUIDNext() throws MessagingException {
if (opened) // we already have this information
return uidnext;
IMAPProtocol p = null;
Status status = null;
try {
p = getStoreProtocol(); // XXX
String[] item = { "UIDNEXT" };
status = p.status(fullName, item);
} catch (BadCommandException bex) {
// Probably a RFC1730 server
throw new MessagingException("Cannot obtain UIDNext", bex);
} catch (ConnectionException cex) {
// Oops, the store or folder died on us.
throwClosedException(cex);
} catch (ProtocolException pex) {
throw new MessagingException(pex.getMessage(), pex);
} finally {
releaseStoreProtocol(p);
}
return status.uidnext;
}
/**
* Get the Message corresponding to the given UID.
* If no such message exists, <code> null </code> is returned.
*/
public synchronized Message getMessageByUID(long uid)
throws MessagingException {
checkOpened(); // insure folder is open
IMAPMessage m = null;
try {
synchronized(messageCacheLock) {
Long l = new Long(uid);
if (uidTable != null) {
// Check in uidTable
m = (IMAPMessage)uidTable.get(l);
if (m != null) // found it
return m;
} else
uidTable = new Hashtable();
// Check with the server
// Issue UID FETCH command
UID u = getProtocol().fetchSequenceNumber(uid);
if (u != null && u.seqnum <= total) { // Valid UID
m = getMessageBySeqNumber(u.seqnum);
m.setUID(u.uid); // set this message's UID ..
// .. and put this into the hashtable
uidTable.put(l, m);
}
}
} catch(ConnectionException cex) {
throw new FolderClosedException(this, cex.getMessage());
} catch (ProtocolException pex) {
throw new MessagingException(pex.getMessage(), pex);
}
return m;
}
/**
* Get the Messages specified by the given range. <p>
* Returns Message objects for all valid messages in this range.
* Returns an empty array if no messages are found.
*/
public synchronized Message[] getMessagesByUID(long start, long end)
throws MessagingException {
checkOpened(); // insure that folder is open
Message[] msgs; // array of messages to be returned
try {
synchronized(messageCacheLock) {
if (uidTable == null)
uidTable = new Hashtable();
// Issue UID FETCH for given range
UID[] ua = getProtocol().fetchSequenceNumbers(start, end);
msgs = new Message[ua.length];
IMAPMessage m;
// NOTE: Below must be within messageCacheLock region
for (int i = 0; i < ua.length; i++) {
m = getMessageBySeqNumber(ua[i].seqnum);
m.setUID(ua[i].uid);
msgs[i] = m;
uidTable.put(new Long(ua[i].uid), m);
}
}
} catch(ConnectionException cex) {
throw new FolderClosedException(this, cex.getMessage());
} catch (ProtocolException pex) {
throw new MessagingException(pex.getMessage(), pex);
}
return msgs;
}
/**
* Get the Messages specified by the given array. <p>
*
* <code>uids.length()</code> elements are returned.
* If any UID in the array is invalid, a <code>null</code> entry
* is returned for that element.
*/
public synchronized Message[] getMessagesByUID(long[] uids)
throws MessagingException {
checkOpened(); // insure that folder is open
try {
synchronized(messageCacheLock) {
long[] unavailUids = uids;
if (uidTable != null) {
Vector v = new Vector(); // to collect unavailable UIDs
Long l;
for (int i = 0; i < uids.length; i++) {
if (!uidTable.containsKey(l = new Long(uids[i])))
// This UID has not been loaded yet.
v.addElement(l);
}
int vsize = v.size();
unavailUids = new long[vsize];
for (int i = 0; i < vsize; i++)
unavailUids[i] = ((Long)v.elementAt(i)).longValue();
} else
uidTable = new Hashtable();
if (unavailUids.length > 0) {
// Issue UID FETCH request for given uids
UID[] ua = getProtocol().fetchSequenceNumbers(unavailUids);
IMAPMessage m;
for (int i = 0; i < ua.length; i++) {
m = getMessageBySeqNumber(ua[i].seqnum);
m.setUID(ua[i].uid);
uidTable.put(new Long(ua[i].uid), m);
}
}
// Return array of size = uids.length
Message[] msgs = new Message[uids.length];
for (int i = 0; i < uids.length; i++)
msgs[i] = (Message)uidTable.get(new Long(uids[i]));
return msgs;
}
} catch(ConnectionException cex) {
throw new FolderClosedException(this, cex.getMessage());
} catch (ProtocolException pex) {
throw new MessagingException(pex.getMessage(), pex);
}
}
/**
* Get the UID for the specified message.
*/
public synchronized long getUID(Message message)
throws MessagingException {
if (message.getFolder() != this)
throw new NoSuchElementException(
"Message does not belong to this folder");
checkOpened(); // insure that folder is open
IMAPMessage m = (IMAPMessage)message;
// If the message already knows its UID, great ..
long uid;
if ((uid = m.getUID()) != -1)
return uid;
synchronized(messageCacheLock) { // Acquire Lock
try {
IMAPProtocol p = getProtocol();
m.checkExpunged(); // insure that message is not expunged
UID u = p.fetchUID(m.getSequenceNumber());
if (u != null) {
uid = u.uid;
m.setUID(uid); // set message's UID
// insert this message into uidTable
if (uidTable == null)
uidTable = new Hashtable();
uidTable.put(new Long(uid), m);
}
} catch (ConnectionException cex) {
throw new FolderClosedException(this, cex.getMessage());
} catch (ProtocolException pex) {
throw new MessagingException(pex.getMessage(), pex);
}
}
return uid;
}
/**
* Get the quotas for the quotaroot associated with this
* folder. Note that many folders may have the same quotaroot.
* Quotas are controlled on the basis of a quotaroot, not
* (necessarily) a folder. The relationship between folders
* and quotaroots depends on the IMAP server. Some servers
* might implement a single quotaroot for all folders owned by
* a user. Other servers might implement a separate quotaroot
* for each folder. A single folder can even have multiple
* quotaroots, perhaps controlling quotas for different
* resources.
*
* @return array of Quota objects for the quotaroots associated with
* this folder
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -