Methods Summary |
---|
public void | addACL(com.sun.mail.imap.ACL acl)Add an access control list entry to the access control list
for this folder.
setACL(acl, '\0");
|
public synchronized void | addMessageCountListener(javax.mail.event.MessageCountListener l)
super.addMessageCountListener(l);
hasMessageCountListener = true;
|
public synchronized Message[] | addMessages(Message[] msgs)Append the given messages into this folder.
Return array of Message objects representing
the messages in the destination folder. Note
that the folder must be open.
Each element of the returned array corresponds to
an element of the msgs array. A null
element means the server didn't return UID information
for the appended message.
Depends on the APPENDUID response code defined by the
UIDPLUS extension -
RFC 2359.
checkOpened();
Message[] rmsgs = new MimeMessage[msgs.length];
AppendUID[] uids = appendUIDMessages(msgs);
for (int i = 0; i < uids.length; i++) {
AppendUID auid = uids[i];
if (auid != null) {
if (auid.uidvalidity == uidvalidity) {
try {
rmsgs[i] = getMessageByUID(auid.uid);
} catch (MessagingException mex) {
// ignore errors at this stage
}
}
}
}
return rmsgs;
|
public void | addRights(com.sun.mail.imap.ACL acl)Add the rights specified in the ACL to the entry for the
identifier specified in the ACL. If an entry for the identifier
doesn't already exist, add one.
setACL(acl, '+");
|
public synchronized void | appendMessages(Message[] msgs)Append the given messages into this folder.
checkExists(); // verify that self exists
// XXX - have to verify that messages are in a different
// store (if any) than target folder, otherwise could
// deadlock trying to fetch messages on the same connection
// we're using for the append.
int maxsize = ((IMAPStore)store).getAppendBufferSize();
for (int i = 0; i < msgs.length; i++) {
final Message m = msgs[i];
Date d = m.getReceivedDate(); // retain dates
if (d == null)
d = m.getSentDate();
final Date dd = d;
final Flags f = m.getFlags();
final MessageLiteral mos;
try {
// if we know the message is too big, don't buffer any of it
mos = new MessageLiteral(m,
m.getSize() > maxsize ? 0 : maxsize);
} catch (IOException ex) {
throw new MessagingException(
"IOException while appending messages", ex);
} catch (MessageRemovedException mrex) {
continue; // just skip this expunged message
}
doCommand(new ProtocolCommand() {
public Object doCommand(IMAPProtocol p)
throws ProtocolException {
p.append(fullName, f, dd, mos);
return null;
}
});
}
|
public synchronized com.sun.mail.imap.AppendUID[] | appendUIDMessages(Message[] msgs)Append the given messages into this folder.
Return array of AppendUID objects containing
UIDs of these messages in the destination folder.
Each element of the returned array corresponds to
an element of the msgs array. A null
element means the server didn't return UID information
for the appended message.
Depends on the APPENDUID response code defined by the
UIDPLUS extension -
RFC 2359.
checkExists(); // verify that self exists
// XXX - have to verify that messages are in a different
// store (if any) than target folder, otherwise could
// deadlock trying to fetch messages on the same connection
// we're using for the append.
int maxsize = ((IMAPStore)store).getAppendBufferSize();
AppendUID[] uids = new AppendUID[msgs.length];
for (int i = 0; i < msgs.length; i++) {
final Message m = msgs[i];
final MessageLiteral mos;
try {
// if we know the message is too big, don't buffer any of it
mos = new MessageLiteral(m,
m.getSize() > maxsize ? 0 : maxsize);
} catch (IOException ex) {
throw new MessagingException(
"IOException while appending messages", ex);
} catch (MessageRemovedException mrex) {
continue; // just skip this expunged message
}
Date d = m.getReceivedDate(); // retain dates
if (d == null)
d = m.getSentDate();
final Date dd = d;
final Flags f = m.getFlags();
AppendUID auid = (AppendUID)doCommand(new ProtocolCommand() {
public Object doCommand(IMAPProtocol p)
throws ProtocolException {
return p.appenduid(fullName, f, dd, mos);
}
});
uids[i] = auid;
}
return uids;
|
private void | checkClosed()
if (opened)
throw new IllegalStateException(
"This operation is not allowed on an open folder"
);
|
private void | checkExists()
// If the boolean field 'exists' is false, check with the
// server by invoking exists() ..
if (!exists && !exists())
throw new FolderNotFoundException(
this, fullName + " not found");
|
private void | checkFlags(javax.mail.Flags flags)
assert Thread.holdsLock(this);
if (mode != READ_WRITE)
throw new IllegalStateException(
"Cannot change flags on READ_ONLY folder: " + fullName
);
/*
if (!availableFlags.contains(flags))
throw new MessagingException(
"These flags are not supported by this implementation"
);
*/
|
private void | checkOpened()
assert Thread.holdsLock(this);
if (!opened) {
if (reallyClosed)
throw new IllegalStateException(
"This operation is not allowed on a closed folder"
);
else // Folder was closed "implicitly"
throw new FolderClosedException(this,
"Lost folder connection to server"
);
}
|
private void | checkRange(int msgno)
if (msgno < 1) // message-numbers start at 1
throw new IndexOutOfBoundsException("message number < 1");
if (msgno <= total)
return;
// Out of range, let's ping the server and see if
// the server has more messages for us.
synchronized(messageCacheLock) { // Acquire lock
try {
keepConnectionAlive(false);
} catch (ConnectionException cex) {
// Oops, lost connection
throw new FolderClosedException(this, cex.getMessage());
} catch (ProtocolException pex) {
throw new MessagingException(pex.getMessage(), pex);
}
} // Release lock
if (msgno > total) // Still out of range ? Throw up ...
throw new IndexOutOfBoundsException(msgno + " > " + total);
|
private void | cleanup(boolean returnToPool)
assert Thread.holdsLock(messageCacheLock);
releaseProtocol(returnToPool);
messageCache = null;
uidTable = null;
exists = false; // to force a recheck in exists().
attributes = null;
opened = false;
idleState = RUNNING; // just in case
notifyConnectionListeners(ConnectionEvent.CLOSED);
|
public synchronized void | close(boolean expunge)Close this folder.
close(expunge, false);
|
private void | close(boolean expunge, boolean force)
assert Thread.holdsLock(this);
synchronized(messageCacheLock) {
/*
* If we already know we're closed, this is illegal.
* Can't use checkOpened() because if we were forcibly
* closed asynchronously we just want to complete the
* closing here.
*/
if (!opened && reallyClosed)
throw new IllegalStateException(
"This operation is not allowed on a closed folder"
);
reallyClosed = true; // Ok, lets reset
// Maybe this folder is already closed, or maybe another
// thread which had the messageCacheLock earlier, found
// that our server connection is dead and cleaned up
// everything ..
if (!opened)
return;
try {
waitIfIdle();
if (force) {
if (debug)
out.println("DEBUG: forcing folder " + fullName +
" to close");
if (protocol != null)
protocol.disconnect();
} else if (((IMAPStore)store).isConnectionPoolFull()) {
// If the connection pool is full, logout the connection
if (debug)
out.println("DEBUG: pool is full, not adding " +
"an Authenticated connection");
// If the expunge flag is set, close the folder first.
if (expunge)
protocol.close();
if (protocol != null)
protocol.logout();
} else {
// If the expunge flag is set or we're open read-only we
// can just close the folder, otherwise open it read-only
// before closing.
if (!expunge && mode == READ_WRITE) {
try {
MailboxInfo mi = protocol.examine(fullName);
} catch (ProtocolException pex2) {
if (protocol != null)
protocol.disconnect();
}
}
if (protocol != null)
protocol.close();
}
} catch (ProtocolException pex) {
throw new MessagingException(pex.getMessage(), pex);
} finally {
// cleanup if we haven't already
if (opened)
cleanup(true);
}
}
|
public synchronized void | copyMessages(Message[] msgs, javax.mail.Folder folder)Copy the specified messages from this folder, to the
specified destination.
checkOpened();
if (msgs.length == 0) // boundary condition
return;
// If the destination belongs to our same store, optimize
if (folder.getStore() == store) {
synchronized(messageCacheLock) {
try {
IMAPProtocol p = getProtocol();
MessageSet[] ms = Utility.toMessageSet(msgs, null);
if (ms == null)
throw new MessageRemovedException(
"Messages have been removed");
p.copy(ms, folder.getFullName());
} catch (CommandFailedException cfx) {
if (cfx.getMessage().indexOf("TRYCREATE") != -1)
throw new FolderNotFoundException(
folder,
folder.getFullName() + " does not exist"
);
else
throw new MessagingException(cfx.getMessage(), cfx);
} catch (ConnectionException cex) {
throw new FolderClosedException(this, cex.getMessage());
} catch (ProtocolException pex) {
throw new MessagingException(pex.getMessage(), pex);
}
}
} else // destination is a different store.
super.copyMessages(msgs, folder);
|
public synchronized boolean | create(int type)Create this folder, with the specified type.
char c = 0;
if ((type & HOLDS_MESSAGES) == 0) // only holds folders
c = getSeparator();
final char sep = c;
Object ret = doCommandIgnoreFailure(new ProtocolCommand() {
public Object doCommand(IMAPProtocol p)
throws ProtocolException {
if ((type & HOLDS_MESSAGES) == 0) // only holds folders
p.create(fullName + sep);
else {
p.create(fullName);
// Certain IMAP servers do not allow creation of folders
// that can contain messages *and* subfolders. So, if we
// were asked to create such a folder, we should verify
// that we could indeed do so.
if ((type & HOLDS_FOLDERS) != 0) {
// we want to hold subfolders and messages. Check
// whether we could create such a folder.
ListInfo[] li = p.list("", fullName);
if (li != null && !li[0].hasInferiors) {
// Hmm ..the new folder
// doesn't support Inferiors ? Fail
p.delete(fullName);
throw new ProtocolException("Unsupported type");
}
}
}
return Boolean.TRUE;
}
});
if (ret == null)
return false; // CREATE failure, maybe this
// folder already exists ?
// exists = true;
// this.type = type;
boolean retb = exists(); // set exists, type, and attributes
if (retb) // Notify listeners on self and our Store
notifyFolderListeners(FolderEvent.CREATED);
return retb;
|
public synchronized boolean | delete(boolean recurse)Delete this folder.
checkClosed(); // insure that this folder is closed.
if (recurse) {
// Delete all subfolders.
Folder[] f = list();
for (int i = 0; i < f.length; i++)
f[i].delete(recurse); // ignore intermediate failures
}
// Attempt to delete this folder
Object ret = doCommandIgnoreFailure(new ProtocolCommand() {
public Object doCommand(IMAPProtocol p) throws ProtocolException {
p.delete(fullName);
return Boolean.TRUE;
}
});
if (ret == null)
// Non-existent folder/No permission ??
return false;
// DELETE succeeded.
exists = false;
attributes = null;
// Notify listeners on self and our Store
notifyFolderListeners(FolderEvent.DELETED);
return true;
|
public java.lang.Object | doCommand(com.sun.mail.imap.IMAPFolder$ProtocolCommand cmd)Execute a user-supplied IMAP command. The command is executed
in the appropriate context with the necessary locks held and
using the appropriate IMAPProtocol object.
This method returns whatever the ProtocolCommand
object's doCommand method returns. If the
doCommand method throws a ConnectionException
it is translated into a StoreClosedException or
FolderClosedException as appropriate. If the
doCommand method throws a ProtocolException
it is translated into a MessagingException .
The following example shows how to execute the IMAP NOOP command.
Executing more complex IMAP commands requires intimate knowledge
of the com.sun.mail.iap and
com.sun.mail.imap.protocol packages, best acquired by
reading the source code.
import com.sun.mail.iap.*;
import com.sun.mail.imap.*;
import com.sun.mail.imap.protocol.*;
...
IMAPFolder f = (IMAPFolder)folder;
Object val = f.doCommand(new IMAPFolder.ProtocolCommand() {
public Object doCommand(IMAPProtocol p)
throws ProtocolException {
p.simpleCommand("NOOP", null);
return null;
}
});
Here's a more complex example showing how to use the proposed
IMAP SORT extension:
import com.sun.mail.iap.*;
import com.sun.mail.imap.*;
import com.sun.mail.imap.protocol.*;
...
IMAPFolder f = (IMAPFolder)folder;
Object val = f.doCommand(new IMAPFolder.ProtocolCommand() {
public Object doCommand(IMAPProtocol p)
throws ProtocolException {
// Issue command
Argument args = new Argument();
Argument list = new Argument();
list.writeString("SUBJECT");
args.writeArgument(list);
args.writeString("UTF-8");
args.writeString("ALL");
Response[] r = p.command("SORT", args);
Response response = r[r.length-1];
// Grab response
Vector v = new Vector();
if (response.isOK()) { // command succesful
for (int i = 0, len = r.length; i < len; i++) {
if (!(r[i] instanceof IMAPResponse))
continue;
IMAPResponse ir = (IMAPResponse)r[i];
if (ir.keyEquals("SORT")) {
String num;
while ((num = ir.readAtomString()) != null)
System.out.println(num);
r[i] = null;
}
}
}
// dispatch remaining untagged responses
p.notifyResponseHandlers(r);
p.handleResult(response);
return null;
}
});
try {
return doProtocolCommand(cmd);
} catch (ConnectionException cex) {
// Oops, the store or folder died on us.
throwClosedException(cex);
} catch (ProtocolException pex) {
throw new MessagingException(pex.getMessage(), pex);
}
return null;
|
public java.lang.Object | doCommandIgnoreFailure(com.sun.mail.imap.IMAPFolder$ProtocolCommand cmd)
try {
return doProtocolCommand(cmd);
} catch (CommandFailedException cfx) {
return null;
} catch (ConnectionException cex) {
// Oops, the store or folder died on us.
throwClosedException(cex);
} catch (ProtocolException pex) {
throw new MessagingException(pex.getMessage(), pex);
}
return null;
|
private synchronized javax.mail.Folder[] | doList(java.lang.String pattern, boolean subscribed)
checkExists(); // insure that this folder does exist.
// Why waste a roundtrip to the server?
if (attributes != null && !isDirectory())
return new Folder[0];
final char c = getSeparator();
ListInfo[] li = (ListInfo[])doCommandIgnoreFailure(
new ProtocolCommand() {
public Object doCommand(IMAPProtocol p)
throws ProtocolException {
if (subscribed)
return p.lsub("", fullName + c + pattern);
else
return p.list("", fullName + c + pattern);
}
});
if (li == null)
return new Folder[0];
/*
* The UW based IMAP4 servers (e.g. SIMS2.0) include
* current folder (terminated with the separator), when
* the LIST pattern is '%' or '*'. i.e, <LIST "" mail/%>
* returns "mail/" as the first LIST response.
*
* Doesn't make sense to include the current folder in this
* case, so we filter it out. Note that I'm assuming that
* the offending response is the *first* one, my experiments
* with the UW & SIMS2.0 servers indicate that ..
*/
int start = 0;
// Check the first LIST response.
if (li.length > 0 && li[0].name.equals(fullName + c))
start = 1; // start from index = 1
IMAPFolder[] folders = new IMAPFolder[li.length - start];
for (int i = start; i < li.length; i++)
folders[i-start] = new IMAPFolder(li[i], (IMAPStore)store);
return folders;
|
public java.lang.Object | doOptionalCommand(java.lang.String err, com.sun.mail.imap.IMAPFolder$ProtocolCommand cmd)
try {
return doProtocolCommand(cmd);
} catch (BadCommandException bex) {
throw new MessagingException(err, bex);
} catch (ConnectionException cex) {
// Oops, the store or folder died on us.
throwClosedException(cex);
} catch (ProtocolException pex) {
throw new MessagingException(pex.getMessage(), pex);
}
return null;
|
protected java.lang.Object | doProtocolCommand(com.sun.mail.imap.IMAPFolder$ProtocolCommand cmd)
synchronized (this) {
/*
* Check whether we have a protocol object, not whether we're
* opened, to allow use of the exsting protocol object in the
* open method before the state is changed to "opened".
*/
if (protocol != null) {
synchronized (messageCacheLock) {
return cmd.doCommand(getProtocol());
}
}
}
// only get here if using store's connection
IMAPProtocol p = null;
try {
p = getStoreProtocol();
return cmd.doCommand(p);
} finally {
releaseStoreProtocol(p);
}
|
public synchronized boolean | exists()Check whether this folder really exists on the server.
// Check whether this folder exists ..
ListInfo[] li = null;
final String lname;
if (isNamespace && separator != '\0")
lname = fullName + separator;
else
lname = fullName;
li = (ListInfo[])doCommand(new ProtocolCommand() {
public Object doCommand(IMAPProtocol p) throws ProtocolException {
return p.list("", lname);
}
});
if (li != null) {
int i = findName(li, lname);
fullName = li[i].name;
separator = li[i].separator;
int len = fullName.length();
if (separator != '\0" && len > 0 &&
fullName.charAt(len - 1) == separator) {
fullName = fullName.substring(0, len - 1);
}
type = 0;
if (li[i].hasInferiors)
type |= HOLDS_FOLDERS;
if (li[i].canOpen)
type |= HOLDS_MESSAGES;
exists = true;
attributes = li[i].attrs;
} else {
exists = opened;
attributes = null;
}
return exists;
|
public synchronized Message[] | expunge()Expunge all messages marked as DELETED.
return expunge(null);
|
public synchronized Message[] | expunge(Message[] msgs)Expunge the indicated messages, which must have been marked as DELETED.
checkOpened();
if (msgs != null) {
// call fetch to make sure we have all the UIDs
FetchProfile fp = new FetchProfile();
fp.add(UIDFolder.FetchProfileItem.UID);
fetch(msgs, fp);
}
IMAPMessage[] rmsgs;
synchronized(messageCacheLock) {
doExpungeNotification = false; // We do this ourselves later
try {
IMAPProtocol p = getProtocol();
if (msgs != null)
p.uidexpunge(Utility.toUIDSet(msgs));
else
p.expunge();
} catch (CommandFailedException cfx) {
// expunge not allowed, perhaps due to a permission problem?
if (mode != READ_WRITE)
throw new IllegalStateException(
"Cannot expunge READ_ONLY folder: " + fullName);
else
throw new MessagingException(cfx.getMessage(), cfx);
} catch (ConnectionException cex) {
throw new FolderClosedException(this, cex.getMessage());
} catch (ProtocolException pex) {
// Bad bad server ..
throw new MessagingException(pex.getMessage(), pex);
} finally {
doExpungeNotification = true;
}
// Cleanup expunged messages and sync messageCache with reality.
if (msgs != null)
rmsgs = messageCache.removeExpungedMessages(msgs);
else
rmsgs = messageCache.removeExpungedMessages();
if (uidTable != null) {
for (int i = 0; i < rmsgs.length; i++) {
IMAPMessage m = rmsgs[i];
/* remove this message from the UIDTable */
long uid = m.getUID();
if (uid != -1)
uidTable.remove(new Long(uid));
}
}
// Update 'total'
total = messageCache.size();
}
// Notify listeners. This time its for real, guys.
if (rmsgs.length > 0)
notifyMessageRemovedListeners(true, rmsgs);
return rmsgs;
|
public synchronized void | fetch(Message[] msgs, javax.mail.FetchProfile fp)Prefetch attributes, based on the given FetchProfile.
checkOpened();
IMAPMessage.fetch(this, msgs, fp);
|
private int | findName(com.sun.mail.imap.protocol.ListInfo[] li, java.lang.String lname)Which entry in li matches lname ?
If the name contains wildcards, more than one entry may be
returned.
int i;
// if the name contains a wildcard, there might be more than one
for (i = 0; i < li.length; i++) {
if (li[i].name.equals(lname))
break;
}
if (i >= li.length) { // nothing matched exactly
// XXX - possibly should fail? But what if server
// is case insensitive and returns the preferred
// case of the name here?
i = 0; // use first one
}
return i;
|
public synchronized void | forceClose()Close this folder without waiting for the server.
close(false, true);
|
public com.sun.mail.imap.ACL[] | getACL()Get the access control list entries for this folder.
return (ACL[])doOptionalCommand("ACL not supported",
new ProtocolCommand() {
public Object doCommand(IMAPProtocol p)
throws ProtocolException {
return p.getACL(fullName);
}
});
|
public synchronized java.lang.String[] | getAttributes()Get the attributes that the IMAP server returns with the
LIST response.
checkExists();
if (attributes == null)
exists(); // do a LIST to set the attributes
return attributes == null ? new String[0] :
(String[])(attributes.clone());
|
public synchronized int | getDeletedMessageCount()Get the deleted message count.
if (!opened) {
checkExists();
// no way to do this on closed folders
return -1;
}
// if opened, issue server-side search for messages that do
// have the DELETED flag.
Flags f = new Flags();
f.add(Flags.Flag.DELETED);
try {
synchronized(messageCacheLock) {
int[] matches = getProtocol().search(new FlagTerm(f, true));
return matches.length; // NOTE: 'matches' is never null
}
} catch (ConnectionException cex) {
throw new FolderClosedException(this, cex.getMessage());
} catch (ProtocolException pex) {
// Shouldn't happen
throw new MessagingException(pex.getMessage(), pex);
}
|
public synchronized javax.mail.Folder | getFolder(java.lang.String name)Get the named subfolder.
// If we know that this folder is *not* a directory, don't
// send the request to the server at all ...
if (attributes != null && !isDirectory())
throw new MessagingException("Cannot contain subfolders");
char c = getSeparator();
return new IMAPFolder(fullName + c + name, c, (IMAPStore)store);
|
public synchronized java.lang.String | getFullName()Get the fullname of this folder.
return fullName;
|
public synchronized Message | getMessage(int msgnum)Get the specified message.
checkOpened();
checkRange(msgnum);
return messageCache.getMessage(msgnum);
|
com.sun.mail.imap.IMAPMessage | getMessageBySeqNumber(int seqnum)Get the message object for the given sequence number. If
none found, null is returned.
ASSERT: This method must be called only when holding the
messageCacheLock
return messageCache.getMessageBySeqnum(seqnum);
|
public synchronized Message | getMessageByUID(long uid)Get the Message corresponding to the given UID.
If no such message exists, null is returned.
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;
|
public synchronized int | getMessageCount()Get the total message count.
if (!opened) {
checkExists();
// If this folder is not yet open, we use STATUS to
// get the total message count
try {
Status status = getStatus();
return status.total;
} catch (BadCommandException bex) {
// doesn't support STATUS, probably vanilla IMAP4 ..
// lets try EXAMINE
IMAPProtocol p = null;
try {
p = getStoreProtocol(); // XXX
MailboxInfo minfo = p.examine(fullName);
p.close();
return minfo.total;
} catch (ProtocolException pex) {
// Give up.
throw new MessagingException(pex.getMessage(), pex);
} finally {
releaseStoreProtocol(p);
}
} catch (ConnectionException cex) {
throw new StoreClosedException(store, cex.getMessage());
} catch (ProtocolException pex) {
throw new MessagingException(pex.getMessage(), pex);
}
}
// Folder is open, we know what the total message count is ..
synchronized(messageCacheLock) {
// tickle the folder and store connections.
try {
keepConnectionAlive(true);
return total;
} catch (ConnectionException cex) {
throw new FolderClosedException(this, cex.getMessage());
} catch (ProtocolException pex) {
throw new MessagingException(pex.getMessage(), pex);
}
}
|
public synchronized Message[] | getMessagesByUID(long start, long end)Get the Messages specified by the given range.
Returns Message objects for all valid messages in this range.
Returns an empty array if no messages are found.
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;
|
public synchronized Message[] | getMessagesByUID(long[] uids)Get the Messages specified by the given array.
uids.length() elements are returned.
If any UID in the array is invalid, a null entry
is returned for that element.
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);
}
|
public synchronized java.lang.String | getName()Get the name of this folder.
/* Return the last component of this Folder's full name.
* Folder components are delimited by the separator character.
*/
if (name == null) {
try {
name = fullName.substring(
fullName.lastIndexOf(getSeparator()) + 1
);
} catch (MessagingException mex) { }
}
return name;
|
public synchronized int | getNewMessageCount()Get the new message count.
if (!opened) {
checkExists();
// If this folder is not yet open, we use STATUS to
// get the new message count
try {
Status status = getStatus();
return status.recent;
} catch (BadCommandException bex) {
// doesn't support STATUS, probably vanilla IMAP4 ..
// lets try EXAMINE
IMAPProtocol p = null;
try {
p = getStoreProtocol(); // XXX
MailboxInfo minfo = p.examine(fullName);
p.close();
return minfo.recent;
} catch (ProtocolException pex) {
// Give up.
throw new MessagingException(pex.getMessage(), pex);
} finally {
releaseStoreProtocol(p);
}
} catch (ConnectionException cex) {
throw new StoreClosedException(store, cex.getMessage());
} catch (ProtocolException pex) {
throw new MessagingException(pex.getMessage(), pex);
}
}
// Folder is open, we know what the new message count is ..
synchronized(messageCacheLock) {
// tickle the folder and store connections.
try {
keepConnectionAlive(true);
return recent;
} catch (ConnectionException cex) {
throw new FolderClosedException(this, cex.getMessage());
} catch (ProtocolException pex) {
throw new MessagingException(pex.getMessage(), pex);
}
}
|
public synchronized javax.mail.Folder | getParent()Get this folder's parent.
char c = getSeparator();
int index;
if ((index = fullName.lastIndexOf(c)) != -1)
return new IMAPFolder(fullName.substring(0, index),
c, (IMAPStore)store);
else
return new DefaultFolder((IMAPStore)store);
|
public synchronized javax.mail.Flags | getPermanentFlags()Return the permanent flags supported by the server.
return (Flags)(permanentFlags.clone());
|
private com.sun.mail.imap.protocol.IMAPProtocol | getProtocol()Return the IMAPProtocol object for this folder.
This method will block if necessary to wait for an IDLE
command to finish.
assert Thread.holdsLock(messageCacheLock);
waitIfIdle();
return protocol;
|
public javax.mail.Quota[] | getQuota()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 (Quota[])doOptionalCommand("QUOTA not supported",
new ProtocolCommand() {
public Object doCommand(IMAPProtocol p)
throws ProtocolException {
return p.getQuotaRoot(fullName);
}
});
|
public synchronized char | getSeparator()Get the separator character.
if (separator == UNKNOWN_SEPARATOR) {
ListInfo[] li = null;
li = (ListInfo[])doCommand(new ProtocolCommand() {
public Object doCommand(IMAPProtocol p)
throws ProtocolException {
// REV1 allows the following LIST format to obtain
// the hierarchy delimiter of non-existent folders
if (p.isREV1()) // IMAP4rev1
return p.list(fullName, "");
else // IMAP4, note that this folder must exist for this
// to work :(
return p.list("", fullName);
}
});
if (li != null)
separator = li[0].separator;
else
separator = '/"; // punt !
}
return separator;
|
private com.sun.mail.imap.protocol.Status | getStatus()
int statusCacheTimeout = ((IMAPStore)store).getStatusCacheTimeout();
// if allowed to cache and our cache is still valid, return it
if (statusCacheTimeout > 0 && cachedStatus != null &&
System.currentTimeMillis() - cachedStatusTime < statusCacheTimeout)
return cachedStatus;
IMAPProtocol p = null;
try {
p = getStoreProtocol(); // XXX
Status s = p.status(fullName, null);
// if allowed to cache, do so
if (statusCacheTimeout > 0) {
cachedStatus = s;
cachedStatusTime = System.currentTimeMillis();
}
return s;
} finally {
releaseStoreProtocol(p);
}
|
protected synchronized com.sun.mail.imap.protocol.IMAPProtocol | getStoreProtocol()Get this folder's Store's protocol connection.
When acquiring a store protocol object, it is important to
use the following steps:
IMAPProtocol p = null;
try {
p = getStoreProtocol();
// perform the command
} catch (WhateverException ex) {
// handle it
} finally {
releaseStoreProtocol(p);
}
if (connectionPoolDebug) {
out.println("DEBUG: getStoreProtocol() - " +
"borrowing a connection");
}
return ((IMAPStore)store).getFolderStoreProtocol();
|
public synchronized int | getType()Get the type of this folder.
if (opened) {
// never throw FolderNotFoundException if folder is open
if (attributes == null)
exists(); // try to fetch attributes
} else {
checkExists();
}
return type;
|
public synchronized long | getUID(Message message)Get the UID for the specified message.
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;
|
public synchronized long | getUIDNext()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.
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.
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;
|
public synchronized long | getUIDValidity()Returns the UIDValidity for this folder.
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;
|
public synchronized int | getUnreadMessageCount()Get the unread message count.
if (!opened) {
checkExists();
// If this folder is not yet open, we use STATUS to
// get the unseen message count
try {
Status status = getStatus();
return status.unseen;
} catch (BadCommandException bex) {
// doesn't support STATUS, probably vanilla IMAP4 ..
// Could EXAMINE, SEARCH for UNREAD messages and
// return the count .. bah, not worth it.
return -1;
} catch (ConnectionException cex) {
throw new StoreClosedException(store, cex.getMessage());
} catch (ProtocolException pex) {
throw new MessagingException(pex.getMessage(), pex);
}
}
// if opened, issue server-side search for messages that do
// *not* have the SEEN flag.
Flags f = new Flags();
f.add(Flags.Flag.SEEN);
try {
synchronized(messageCacheLock) {
int[] matches = getProtocol().search(new FlagTerm(f, false));
return matches.length; // NOTE: 'matches' is never null
}
} catch (ConnectionException cex) {
throw new FolderClosedException(this, cex.getMessage());
} catch (ProtocolException pex) {
// Shouldn't happen
throw new MessagingException(pex.getMessage(), pex);
}
|
public void | handleResponse(com.sun.mail.iap.Response r)The response handler. This is the callback routine that is
invoked by the protocol layer.
assert Thread.holdsLock(messageCacheLock);
/*
* First, delegate possible ALERT or notification to the Store.
*/
if (r.isOK() || r.isNO() || r.isBAD() || r.isBYE())
((IMAPStore)store).handleResponseCode(r);
/*
* Now check whether this is a BYE or OK response and
* handle appropriately.
*/
if (r.isBYE()) {
if (opened) // XXX - accessed without holding folder lock
cleanup(false);
return;
} else if (r.isOK()) {
return;
} else if (!r.isUnTagged()) {
return; // XXX - should never happen
}
/* Now check whether this is an IMAP specific response */
if (!(r instanceof IMAPResponse)) {
// Probably a bug in our code !
// XXX - should be an assert
out.println("UNEXPECTED RESPONSE : " + r.toString());
out.println("CONTACT javamail@sun.com");
return;
}
IMAPResponse ir = (IMAPResponse)r;
if (ir.keyEquals("EXISTS")) { // EXISTS
int exists = ir.getNumber();
if (exists <= realTotal)
// Could be the EXISTS following EXPUNGE, ignore 'em
return;
int count = exists - realTotal; // number of new messages
Message[] msgs = new Message[count];
// Add 'count' new IMAPMessage objects into the messageCache
messageCache.addMessages(count);
int oldtotal = total; // used in loop below
realTotal += count;
total += count;
// avoid instantiating Message objects if no listeners.
if (hasMessageCountListener) {
for (int i = 0; i < count; i++)
msgs[i] = messageCache.getMessage(++oldtotal);
// Notify listeners.
notifyMessageAddedListeners(msgs);
}
} else if (ir.keyEquals("EXPUNGE")) {
// EXPUNGE response.
int seqnum = ir.getNumber();
Message[] msgs = null;
if (doExpungeNotification && hasMessageCountListener) {
// save the Message object first; can't look it
// up after it's expunged
msgs = new Message[] { getMessageBySeqNumber(seqnum) };
}
messageCache.expungeMessage(seqnum);
// decrement 'realTotal'; but leave 'total' unchanged
realTotal--;
if (msgs != null) // Do the notification here.
notifyMessageRemovedListeners(false, msgs);
} else if (ir.keyEquals("FETCH")) {
// The only unsolicited FETCH response that makes sense
// to me (for now) is FLAGS updates. Ignore any other junk.
assert ir instanceof FetchResponse : "!ir instanceof FetchResponse";
FetchResponse f = (FetchResponse)ir;
// Get FLAGS response, if present
Flags flags = (Flags)f.getItem(Flags.class);
if (flags != null) {
IMAPMessage msg = getMessageBySeqNumber(f.getNumber());
if (msg != null) { // should always be true
msg._setFlags(flags);
notifyMessageChangedListeners(
MessageChangedEvent.FLAGS_CHANGED, msg);
}
}
} else if (ir.keyEquals("RECENT")) {
// update 'recent'
recent = ir.getNumber();
}
|
void | handleResponses(com.sun.mail.iap.Response[] r)Handle the given array of Responses.
ASSERT: This method must be called only when holding the
messageCacheLock
for (int i = 0; i < r.length; i++) {
if (r[i] != null)
handleResponse(r[i]);
}
|
public synchronized boolean | hasNewMessages()Check whether this folder has new messages.
if (opened) { // If we are open, we already have this information
// Folder is open, make sure information is up to date
synchronized(messageCacheLock) {
// tickle the folder and store connections.
try {
keepConnectionAlive(true);
} catch (ConnectionException cex) {
throw new FolderClosedException(this, cex.getMessage());
} catch (ProtocolException pex) {
throw new MessagingException(pex.getMessage(), pex);
}
return recent > 0 ? true : false;
}
}
// First, the cheap way - use LIST and look for the \Marked
// or \Unmarked tag
ListInfo[] li = null;
final String lname;
if (isNamespace && separator != '\0")
lname = fullName + separator;
else
lname = fullName;
li = (ListInfo[])doCommandIgnoreFailure(new ProtocolCommand() {
public Object doCommand(IMAPProtocol p) throws ProtocolException {
return p.list("", lname);
}
});
// if folder doesn't exist, throw exception
if (li == null)
throw new FolderNotFoundException(this, fullName + " not found");
int i = findName(li, lname);
if (li[i].changeState == ListInfo.CHANGED)
return true;
else if (li[i].changeState == ListInfo.UNCHANGED)
return false;
// LIST didn't work. Try the hard way, using STATUS
try {
Status status = getStatus();
if (status.recent > 0)
return true;
else
return false;
} catch (BadCommandException bex) {
// Probably doesn't support STATUS, tough luck.
return false;
} catch (ConnectionException cex) {
throw new StoreClosedException(store, cex.getMessage());
} catch (ProtocolException pex) {
throw new MessagingException(pex.getMessage(), pex);
}
|
public void | idle()Use the IMAP IDLE command (see
RFC 2177),
if supported by the server, to enter idle mode so that the server
can send unsolicited notifications of new messages arriving, etc.
without the need for the client to constantly poll the server.
Use an appropriate listener to be notified of new messages or
other events. When another thread (e.g., the listener thread)
needs to issue an IMAP comand for this folder, the idle mode will
be terminated and this method will return. Typically the caller
will invoke this method in a loop.
The mail.imap.minidletime property enforces a minimum delay
before returning from this method, to ensure that other threads
have a chance to issue commands before the caller invokes this
method again. The default delay is 10 milliseconds.
idle(false);
|
public void | idle(boolean once)Like {@link #idle}, but if once is true, abort the
IDLE command after the first notification, to allow the caller
to process any notification synchronously.
// ASSERT: Must NOT be called with this folder's
// synchronization lock held.
assert !Thread.holdsLock(this);
synchronized(this) {
checkOpened();
Boolean started = (Boolean)doOptionalCommand("IDLE not supported",
new ProtocolCommand() {
public Object doCommand(IMAPProtocol p)
throws ProtocolException {
if (idleState == RUNNING) {
p.idleStart();
idleState = IDLE;
return Boolean.TRUE;
} else {
// some other thread must be running the IDLE
// command, we'll just wait for it to finish
// without aborting it ourselves
try {
// give up lock and wait to be not idle
messageCacheLock.wait();
} catch (InterruptedException ex) { }
return Boolean.FALSE;
}
}
});
if (!started.booleanValue())
return;
}
/*
* We gave up the folder lock so that other threads
* can get into the folder far enough to see that we're
* in IDLE and abort the IDLE.
*
* Now we read responses from the IDLE command, especially
* including unsolicited notifications from the server.
* We don't hold the messageCacheLock while reading because
* it protects the idleState and other threads need to be
* able to examine the state.
*
* We hold the messageCacheLock while processing the
* responses so that we can update the number of messages
* in the folder (for example).
*/
for (;;) {
Response r = protocol.readIdleResponse();
try {
synchronized (messageCacheLock) {
try {
if (r == null || protocol == null ||
!protocol.processIdleResponse(r)) {
idleState = RUNNING;
messageCacheLock.notifyAll();
break;
}
} catch (ProtocolException pex) {
idleState = RUNNING;
messageCacheLock.notifyAll();
throw pex;
}
if (once) {
if (idleState == IDLE) {
protocol.idleAbort();
idleState = ABORTING;
}
}
}
} catch (ConnectionException cex) {
// Oops, the store or folder died on us.
throwClosedException(cex);
} catch (ProtocolException pex) {
throw new MessagingException(pex.getMessage(), pex);
}
}
/*
* Enforce a minimum delay to give time to threads
* processing the responses that came in while we
* were idle.
*/
int minidle = ((IMAPStore)store).getMinIdleTime();
if (minidle > 0) {
try {
Thread.sleep(minidle);
} catch (InterruptedException ex) { }
}
|
private boolean | isDirectory()
return ((type & HOLDS_FOLDERS) != 0);
|
public synchronized boolean | isOpen()Check whether this connection is really open.
synchronized(messageCacheLock) {
// Probe the connection to make sure its really open.
if (opened) {
try {
keepConnectionAlive(false);
} catch (ProtocolException pex) { }
}
}
return opened;
|
public synchronized boolean | isSubscribed()Check whether this folder is subscribed.
ListInfo[] li = null;
final String lname;
if (isNamespace && separator != '\0")
lname = fullName + separator;
else
lname = fullName;
try {
li = (ListInfo[])doProtocolCommand(new ProtocolCommand() {
public Object doCommand(IMAPProtocol p)
throws ProtocolException {
return p.lsub("", lname);
}
});
} catch (ProtocolException pex) {
}
if (li != null) {
int i = findName(li, lname);
return li[i].canOpen;
} else
return false;
|
private void | keepConnectionAlive(boolean keepStoreAlive)Issue a noop command for the connection if the connection has not been
used in more than a second. If keepStoreAlive is true,
also issue a noop over the store's connection.
ASSERT: This method must be called only when holding the
messageCacheLock
if (System.currentTimeMillis() - protocol.getTimestamp() > 1000) {
waitIfIdle();
if (protocol != null)
protocol.noop();
}
if (keepStoreAlive && ((IMAPStore)store).hasSeparateStoreConnection()) {
IMAPProtocol p = null;
try {
p = ((IMAPStore)store).getFolderStoreProtocol();
if (System.currentTimeMillis() - p.getTimestamp() > 1000)
p.noop();
} finally {
((IMAPStore)store).releaseFolderStoreProtocol(p);
}
}
|
public javax.mail.Folder[] | list(java.lang.String pattern)List all subfolders matching the specified pattern.
return doList(pattern, false);
|
public com.sun.mail.imap.Rights[] | listRights(java.lang.String name)Get all the rights that may be allowed to the given identifier.
Rights are grouped per RFC 2086 and each group is returned as an
element of the array. The first element of the array is the set
of rights that are always granted to the identifier. Later
elements are rights that may be optionally granted to the
identifier.
Note that this method lists the rights that it is possible to
assign to the given identifier, not the rights that are
actually granted to the given identifier. For the latter, see
the getACL method.
return (Rights[])doOptionalCommand("ACL not supported",
new ProtocolCommand() {
public Object doCommand(IMAPProtocol p)
throws ProtocolException {
return p.listRights(fullName, name);
}
});
|
public javax.mail.Folder[] | listSubscribed(java.lang.String pattern)List all subscribed subfolders matching the specified pattern.
return doList(pattern, true);
|
public com.sun.mail.imap.Rights | myRights()Get the rights allowed to the currently authenticated user.
return (Rights)doOptionalCommand("ACL not supported",
new ProtocolCommand() {
public Object doCommand(IMAPProtocol p)
throws ProtocolException {
return p.myRights(fullName);
}
});
|
public synchronized void | open(int mode)Open this folder in the given mode.
checkClosed(); // insure that we are not already open
MailboxInfo mi = null;
// Request store for our own protocol connection.
protocol = ((IMAPStore)store).getProtocol(this);
synchronized(messageCacheLock) { // Acquire messageCacheLock
/*
* Add response handler right away so we get any alerts or
* notifications that occur during the SELECT or EXAMINE.
* Have to be sure to remove it if we fail to open the
* folder.
*/
protocol.addResponseHandler(this);
try {
if (mode == READ_ONLY)
mi = protocol.examine(fullName);
else
mi = protocol.select(fullName);
} catch (CommandFailedException cex) {
/*
* Handle SELECT or EXAMINE failure.
* Try to figure out why the operation failed so we can
* report a more reasonable exception.
*
* Will use our existing protocol object.
*/
try {
checkExists(); // throw exception if folder doesn't exist
if ((type & HOLDS_MESSAGES) == 0)
throw new MessagingException(
"folder cannot contain messages");
throw new MessagingException(cex.getMessage(), cex);
} finally {
// folder not open, don't keep this information
exists = false;
attributes = null;
type = 0;
// connection still good, return it
releaseProtocol(true);
}
// NOTREACHED
} catch (ProtocolException pex) {
// got a BAD or a BYE; connection may be bad, close it
try {
protocol.logout();
} catch (ProtocolException pex2) {
// ignore
} finally {
releaseProtocol(false);
throw new MessagingException(pex.getMessage(), pex);
}
}
if (mi.mode != mode) {
if (mode == READ_WRITE && mi.mode == READ_ONLY &&
((IMAPStore)store).allowReadOnlySelect()) {
; // all ok, allow it
} else { // otherwise, it's an error
try {
// close mailbox and return connection
protocol.close();
releaseProtocol(true);
} catch (ProtocolException pex) {
// something went wrong, close connection
try {
protocol.logout();
} catch (ProtocolException pex2) {
// ignore
} finally {
releaseProtocol(false);
}
} finally {
throw new ReadOnlyFolderException(this,
"Cannot open in desired mode");
}
}
}
// Initialize stuff.
opened = true;
reallyClosed = false;
this.mode = mi.mode;
availableFlags = mi.availableFlags;
permanentFlags = mi.permanentFlags;
total = realTotal = mi.total;
recent = mi.recent;
uidvalidity = mi.uidvalidity;
uidnext = mi.uidnext;
// Create the message cache of appropriate size
messageCache = new MessageCache(this, (IMAPStore)store, total);
} // Release lock
exists = true; // if we opened it, it must exist
attributes = null; // but we don't yet know its attributes
type = HOLDS_MESSAGES; // lacking more info, we know at least this much
// notify listeners
notifyConnectionListeners(ConnectionEvent.OPENED);
|
private void | releaseProtocol(boolean returnToPool)Release the protocol object.
ASSERT: This method must be called only when holding the
messageCacheLock
if (protocol != null) {
protocol.removeResponseHandler(this);
if (returnToPool)
((IMAPStore)store).releaseProtocol(this, protocol);
else {
protocol.disconnect(); // make sure it's disconnected
((IMAPStore)store).releaseProtocol(this, null);
}
protocol = null;
}
|
protected synchronized void | releaseStoreProtocol(com.sun.mail.imap.protocol.IMAPProtocol p)Release the store protocol object. If we borrowed a protocol
object from the connection pool, give it back. If we used our
own protocol object, nothing to do.
if (p != protocol)
((IMAPStore)store).releaseFolderStoreProtocol(p);
else {
// XXX - should never happen
if (debug)
out.println("DEBUG: releasing our protocol as store protocol?");
}
|
public void | removeACL(java.lang.String name)Remove any access control list entry for the given identifier
from the access control list for this folder.
doOptionalCommand("ACL not supported",
new ProtocolCommand() {
public Object doCommand(IMAPProtocol p)
throws ProtocolException {
p.deleteACL(fullName, name);
return null;
}
});
|
public void | removeRights(com.sun.mail.imap.ACL acl)Remove the rights specified in the ACL from the entry for the
identifier specified in the ACL.
setACL(acl, '-");
|
public synchronized boolean | renameTo(javax.mail.Folder f)Rename this folder.
checkClosed(); // insure that we are closed.
checkExists();
if (f.getStore() != store)
throw new MessagingException("Can't rename across Stores");
Object ret = doCommandIgnoreFailure(new ProtocolCommand() {
public Object doCommand(IMAPProtocol p) throws ProtocolException {
p.rename(fullName, f.getFullName());
return Boolean.TRUE;
}
});
if (ret == null)
return false;
exists = false;
attributes = null;
notifyFolderRenamedListeners(f);
return true;
|
public synchronized Message[] | search(javax.mail.search.SearchTerm term)Search whole folder for messages matching the given term.
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);
}
|
public synchronized Message[] | search(javax.mail.search.SearchTerm term, Message[] msgs)Search the folder for messages matching the given term. Returns
array of matching messages. Returns an empty array if no matching
messages are found.
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);
}
|
private void | setACL(com.sun.mail.imap.ACL acl, char mod)
doOptionalCommand("ACL not supported",
new ProtocolCommand() {
public Object doCommand(IMAPProtocol p)
throws ProtocolException {
p.setACL(fullName, mod, acl);
return null;
}
});
|
public synchronized void | setFlags(Message[] msgs, javax.mail.Flags flag, boolean value)Set the specified flags for the given array of messages.
checkOpened();
checkFlags(flag); // validate flags
if (msgs.length == 0) // boundary condition
return;
synchronized(messageCacheLock) {
try {
IMAPProtocol p = getProtocol();
MessageSet[] ms = Utility.toMessageSet(msgs, null);
if (ms == null)
throw new MessageRemovedException(
"Messages have been removed");
p.storeFlags(ms, flag, value);
} catch (ConnectionException cex) {
throw new FolderClosedException(this, cex.getMessage());
} catch (ProtocolException pex) {
throw new MessagingException(pex.getMessage(), pex);
}
}
|
public void | setQuota(javax.mail.Quota quota)Set the quotas for the quotaroot specified in the quota argument.
Typically this will be one of the quotaroots associated with this
folder, as obtained from the getQuota method, but it
need not be.
doOptionalCommand("QUOTA not supported",
new ProtocolCommand() {
public Object doCommand(IMAPProtocol p)
throws ProtocolException {
p.setQuota(quota);
return null;
}
});
|
public synchronized void | setSubscribed(boolean subscribe)Subscribe/Unsubscribe this folder.
doCommandIgnoreFailure(new ProtocolCommand() {
public Object doCommand(IMAPProtocol p) throws ProtocolException {
if (subscribe)
p.subscribe(fullName);
else
p.unsubscribe(fullName);
return null;
}
});
|
private synchronized void | throwClosedException(com.sun.mail.iap.ConnectionException cex)Throw the appropriate 'closed' exception.
// If it's the folder's protocol object, throw a FolderClosedException;
// otherwise, throw a StoreClosedException.
// If a command has failed because the connection is closed,
// the folder will have already been forced closed by the
// time we get here and our protocol object will have been
// released, so if we no longer have a protocol object we base
// this decision on whether we *think* the folder is open.
if ((protocol != null && cex.getProtocol() == protocol) ||
(protocol == null && !reallyClosed))
throw new FolderClosedException(this, cex.getMessage());
else
throw new StoreClosedException(store, cex.getMessage());
|
void | waitIfIdle()
assert Thread.holdsLock(messageCacheLock);
while (idleState != RUNNING) {
if (idleState == IDLE) {
protocol.idleAbort();
idleState = ABORTING;
}
try {
// give up lock and wait to be not idle
messageCacheLock.wait();
} catch (InterruptedException ex) { }
}
|