📄 imapfolder.java
字号:
}
/*
* Ensure the folder is open.
* ASSERT: Must be called with this folder's synchronization lock held.
*/
private void checkOpened() throws FolderClosedException {
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"
);
}
}
/*
* Check that the given message number is within the range
* of messages present in this folder. If the message
* number is out of range, we ping the server to obtain any
* pending new message notifications from the server.
*/
private void checkRange(int msgno) throws MessagingException {
if (msgno < 1) // message-numbers start at 1
throw new IndexOutOfBoundsException();
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();
}
/*
* Check whether the given flags are supported by this server,
* and also verify that the folder allows setting flags.
*/
private void checkFlags(Flags flags) throws MessagingException {
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"
);
*/
}
/**
* Get the name of this folder.
*/
public synchronized String getName() {
/* 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;
}
/**
* Get the fullname of this folder.
*/
public synchronized String getFullName() {
return fullName;
}
/**
* Get this folder's parent.
*/
public synchronized Folder getParent() throws MessagingException {
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);
}
/**
* Check whether this folder really exists on the server.
*/
public synchronized boolean exists() throws MessagingException {
// 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;
}
/**
* Which entry in <code>li</code> matches <code>lname</code>?
* If the name contains wildcards, more than one entry may be
* returned.
*/
private int findName(ListInfo[] li, String lname) {
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;
}
/**
* List all subfolders matching the specified pattern.
*/
public Folder[] list(String pattern) throws MessagingException {
return doList(pattern, false);
}
/**
* List all subscribed subfolders matching the specified pattern.
*/
public Folder[] listSubscribed(String pattern) throws MessagingException {
return doList(pattern, true);
}
private synchronized Folder[] doList(final String pattern,
final boolean subscribed) throws MessagingException {
checkExists(); // insure that this folder does exist.
if (!isDirectory()) // Why waste a roundtrip to the server ?
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;
}
/**
* Get the separator character.
*/
public synchronized char getSeparator() throws MessagingException {
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;
}
/**
* Get the type of this folder.
*/
public synchronized int getType() throws MessagingException {
if (opened) {
// never throw FolderNotFoundException if folder is open
if (attributes == null)
exists(); // try to fetch attributes
} else {
checkExists();
}
return type;
}
/**
* Check whether this folder is subscribed. <p>
*/
public synchronized boolean isSubscribed() {
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;
}
/**
* Subscribe/Unsubscribe this folder.
*/
public synchronized void setSubscribed(final boolean subscribe)
throws MessagingException {
doCommandIgnoreFailure(new ProtocolCommand() {
public Object doCommand(IMAPProtocol p) throws ProtocolException {
if (subscribe)
p.subscribe(fullName);
else
p.unsubscribe(fullName);
return null;
}
});
}
/**
* Create this folder, with the specified type.
*/
public synchronized boolean create(final int type)
throws MessagingException {
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;
}
/**
* Check whether this folder has new messages.
*/
public synchronized boolean hasNewMessages() throws MessagingException {
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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -