Convert RealImapStore
to Kotlin
This commit is contained in:
parent
33fa9d2b7c
commit
a57f127a11
2 changed files with 230 additions and 319 deletions
|
@ -1,411 +1,322 @@
|
||||||
package com.fsck.k9.mail.store.imap;
|
package com.fsck.k9.mail.store.imap
|
||||||
|
|
||||||
|
import com.fsck.k9.logging.Timber
|
||||||
|
import com.fsck.k9.mail.AuthType
|
||||||
|
import com.fsck.k9.mail.AuthenticationFailedException
|
||||||
|
import com.fsck.k9.mail.ConnectionSecurity
|
||||||
|
import com.fsck.k9.mail.Flag
|
||||||
|
import com.fsck.k9.mail.FolderType
|
||||||
|
import com.fsck.k9.mail.MessagingException
|
||||||
|
import com.fsck.k9.mail.ServerSettings
|
||||||
|
import com.fsck.k9.mail.oauth.OAuth2TokenProvider
|
||||||
|
import com.fsck.k9.mail.ssl.TrustedSocketFactory
|
||||||
|
import com.fsck.k9.mail.store.imap.ImapStoreSettings.autoDetectNamespace
|
||||||
|
import com.fsck.k9.mail.store.imap.ImapStoreSettings.pathPrefix
|
||||||
|
import java.io.IOException
|
||||||
|
import java.util.Deque
|
||||||
|
import java.util.LinkedList
|
||||||
|
|
||||||
import java.io.IOException;
|
internal open class RealImapStore(
|
||||||
import java.nio.charset.CharacterCodingException;
|
private val serverSettings: ServerSettings,
|
||||||
import java.util.ArrayList;
|
private val config: ImapStoreConfig,
|
||||||
import java.util.Deque;
|
private val trustedSocketFactory: TrustedSocketFactory,
|
||||||
import java.util.EnumSet;
|
private val oauthTokenProvider: OAuth2TokenProvider?
|
||||||
import java.util.HashMap;
|
) : ImapStore, ImapConnectionManager, InternalImapStore {
|
||||||
import java.util.HashSet;
|
private val folderNameCodec: FolderNameCodec = FolderNameCodec.newInstance()
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import com.fsck.k9.logging.Timber;
|
private val host: String = checkNotNull(serverSettings.host)
|
||||||
import com.fsck.k9.mail.AuthType;
|
|
||||||
import com.fsck.k9.mail.AuthenticationFailedException;
|
|
||||||
import com.fsck.k9.mail.ConnectionSecurity;
|
|
||||||
import com.fsck.k9.mail.Flag;
|
|
||||||
import com.fsck.k9.mail.FolderType;
|
|
||||||
import com.fsck.k9.mail.MessagingException;
|
|
||||||
import com.fsck.k9.mail.ServerSettings;
|
|
||||||
import com.fsck.k9.mail.oauth.OAuth2TokenProvider;
|
|
||||||
import com.fsck.k9.mail.ssl.TrustedSocketFactory;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
|
private var pathPrefix: String?
|
||||||
|
private var combinedPrefix: String? = null
|
||||||
|
private var pathDelimiter: String? = null
|
||||||
|
|
||||||
/**
|
private val permanentFlagsIndex: MutableSet<Flag> = mutableSetOf()
|
||||||
* <pre>
|
private val connections: Deque<ImapConnection> = LinkedList()
|
||||||
* TODO Need a default response handler for things like folder updates
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
class RealImapStore implements ImapStore, ImapConnectionManager, InternalImapStore {
|
|
||||||
private final ImapStoreConfig config;
|
|
||||||
private final TrustedSocketFactory trustedSocketFactory;
|
|
||||||
private Set<Flag> permanentFlagsIndex = EnumSet.noneOf(Flag.class);
|
|
||||||
private OAuth2TokenProvider oauthTokenProvider;
|
|
||||||
|
|
||||||
private String host;
|
@Volatile
|
||||||
private int port;
|
private var connectionGeneration = 1
|
||||||
private String username;
|
|
||||||
private String password;
|
|
||||||
private String clientCertificateAlias;
|
|
||||||
private ConnectionSecurity connectionSecurity;
|
|
||||||
private AuthType authType;
|
|
||||||
private String pathPrefix;
|
|
||||||
private String combinedPrefix = null;
|
|
||||||
private String pathDelimiter = null;
|
|
||||||
private final Deque<ImapConnection> connections = new LinkedList<>();
|
|
||||||
private FolderNameCodec folderNameCodec;
|
|
||||||
private volatile int connectionGeneration = 1;
|
|
||||||
|
|
||||||
|
init {
|
||||||
public RealImapStore(ServerSettings serverSettings, ImapStoreConfig config,
|
val autoDetectNamespace = serverSettings.autoDetectNamespace
|
||||||
TrustedSocketFactory trustedSocketFactory, OAuth2TokenProvider oauthTokenProvider) {
|
val pathPrefixSetting = serverSettings.pathPrefix
|
||||||
this.config = config;
|
|
||||||
this.trustedSocketFactory = trustedSocketFactory;
|
|
||||||
|
|
||||||
host = serverSettings.host;
|
|
||||||
port = serverSettings.port;
|
|
||||||
|
|
||||||
connectionSecurity = serverSettings.connectionSecurity;
|
|
||||||
this.oauthTokenProvider = oauthTokenProvider;
|
|
||||||
|
|
||||||
authType = serverSettings.authenticationType;
|
|
||||||
username = serverSettings.username;
|
|
||||||
password = serverSettings.password;
|
|
||||||
clientCertificateAlias = serverSettings.clientCertificateAlias;
|
|
||||||
|
|
||||||
boolean autoDetectNamespace = ImapStoreSettings.getAutoDetectNamespace(serverSettings);
|
|
||||||
String pathPrefixSetting = ImapStoreSettings.getPathPrefix(serverSettings);
|
|
||||||
|
|
||||||
// Make extra sure pathPrefix is null if "auto-detect namespace" is configured
|
// Make extra sure pathPrefix is null if "auto-detect namespace" is configured
|
||||||
pathPrefix = autoDetectNamespace ? null : pathPrefixSetting;
|
pathPrefix = if (autoDetectNamespace) null else pathPrefixSetting
|
||||||
|
|
||||||
folderNameCodec = FolderNameCodec.newInstance();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImapFolder getFolder(String name) {
|
override fun getFolder(name: String): ImapFolder {
|
||||||
return new RealImapFolder(this, this, name, folderNameCodec);
|
return RealImapFolder(
|
||||||
|
internalImapStore = this,
|
||||||
|
connectionManager = this,
|
||||||
|
serverId = name,
|
||||||
|
folderNameCodec = folderNameCodec
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun getCombinedPrefix(): String {
|
||||||
@NotNull
|
return combinedPrefix ?: buildCombinedPrefix().also { combinedPrefix = it }
|
||||||
public String getCombinedPrefix() {
|
|
||||||
if (combinedPrefix == null) {
|
|
||||||
if (pathPrefix != null) {
|
|
||||||
String tmpPrefix = pathPrefix.trim();
|
|
||||||
String tmpDelim = (pathDelimiter != null ? pathDelimiter.trim() : "");
|
|
||||||
if (tmpPrefix.endsWith(tmpDelim)) {
|
|
||||||
combinedPrefix = tmpPrefix;
|
|
||||||
} else if (tmpPrefix.length() > 0) {
|
|
||||||
combinedPrefix = tmpPrefix + tmpDelim;
|
|
||||||
} else {
|
|
||||||
combinedPrefix = "";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
combinedPrefix = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return combinedPrefix;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<FolderListItem> getFolders() throws MessagingException {
|
private fun buildCombinedPrefix(): String {
|
||||||
ImapConnection connection = getConnection();
|
val pathPrefix = pathPrefix ?: return ""
|
||||||
|
|
||||||
try {
|
val trimmedPathPrefix = pathPrefix.trim { it <= ' ' }
|
||||||
List<FolderListItem> folders = listFolders(connection, false);
|
val trimmedPathDelimiter = pathDelimiter?.trim { it <= ' ' }.orEmpty()
|
||||||
|
|
||||||
if (!config.isSubscribedFoldersOnly()) {
|
return if (trimmedPathPrefix.endsWith(trimmedPathDelimiter)) {
|
||||||
return folders;
|
trimmedPathPrefix
|
||||||
}
|
} else if (trimmedPathPrefix.isNotEmpty()) {
|
||||||
|
trimmedPathPrefix + trimmedPathDelimiter
|
||||||
List<FolderListItem> subscribedFolders = listFolders(connection, true);
|
|
||||||
return limitToSubscribedFolders(folders, subscribedFolders);
|
|
||||||
} catch (AuthenticationFailedException e) {
|
|
||||||
connection.close();
|
|
||||||
throw e;
|
|
||||||
} catch (IOException | MessagingException ioe) {
|
|
||||||
connection.close();
|
|
||||||
throw new MessagingException("Unable to get folder list.", ioe);
|
|
||||||
} finally {
|
|
||||||
releaseConnection(connection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<FolderListItem> limitToSubscribedFolders(List<FolderListItem> folders,
|
|
||||||
List<FolderListItem> subscribedFolders) {
|
|
||||||
Set<String> subscribedFolderNames = new HashSet<>(subscribedFolders.size());
|
|
||||||
for (FolderListItem subscribedFolder : subscribedFolders) {
|
|
||||||
subscribedFolderNames.add(subscribedFolder.getServerId());
|
|
||||||
}
|
|
||||||
|
|
||||||
List<FolderListItem> filteredFolders = new ArrayList<>();
|
|
||||||
for (FolderListItem folder : folders) {
|
|
||||||
if (subscribedFolderNames.contains(folder.getServerId())) {
|
|
||||||
filteredFolders.add(folder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return filteredFolders;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<FolderListItem> listFolders(ImapConnection connection, boolean subscribedOnly) throws IOException,
|
|
||||||
MessagingException {
|
|
||||||
|
|
||||||
String commandFormat;
|
|
||||||
if (subscribedOnly) {
|
|
||||||
commandFormat = "LSUB \"\" %s";
|
|
||||||
} else if (connection.hasCapability(Capabilities.SPECIAL_USE) &&
|
|
||||||
connection.hasCapability(Capabilities.LIST_EXTENDED)) {
|
|
||||||
commandFormat = "LIST \"\" %s RETURN (SPECIAL-USE)";
|
|
||||||
} else {
|
} else {
|
||||||
commandFormat = "LIST \"\" %s";
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(MessagingException::class)
|
||||||
|
override fun getFolders(): List<FolderListItem> {
|
||||||
|
val connection = getConnection()
|
||||||
|
|
||||||
|
return try {
|
||||||
|
val folders = listFolders(connection, false)
|
||||||
|
if (!config.isSubscribedFoldersOnly()) {
|
||||||
|
return folders
|
||||||
|
}
|
||||||
|
|
||||||
|
val subscribedFolders = listFolders(connection, true)
|
||||||
|
limitToSubscribedFolders(folders, subscribedFolders)
|
||||||
|
} catch (e: AuthenticationFailedException) {
|
||||||
|
connection.close()
|
||||||
|
throw e
|
||||||
|
} catch (e: IOException) {
|
||||||
|
connection.close()
|
||||||
|
throw MessagingException("Unable to get folder list.", e)
|
||||||
|
} catch (e: MessagingException) {
|
||||||
|
connection.close()
|
||||||
|
throw MessagingException("Unable to get folder list.", e)
|
||||||
|
} finally {
|
||||||
|
releaseConnection(connection)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun limitToSubscribedFolders(
|
||||||
|
folders: List<FolderListItem>,
|
||||||
|
subscribedFolders: List<FolderListItem>
|
||||||
|
): List<FolderListItem> {
|
||||||
|
val subscribedFolderServerIds = subscribedFolders.map { it.serverId }.toSet()
|
||||||
|
return folders.filter { it.serverId in subscribedFolderServerIds }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class, MessagingException::class)
|
||||||
|
private fun listFolders(connection: ImapConnection, subscribedOnly: Boolean): List<FolderListItem> {
|
||||||
|
val commandFormat = when {
|
||||||
|
subscribedOnly -> {
|
||||||
|
"LSUB \"\" %s"
|
||||||
|
}
|
||||||
|
connection.supportsListExtended -> {
|
||||||
|
"LIST \"\" %s RETURN (SPECIAL-USE)"
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
"LIST \"\" %s"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String encodedListPrefix = ImapUtility.encodeString(getCombinedPrefix() + "*");
|
val encodedListPrefix = ImapUtility.encodeString(getCombinedPrefix() + "*")
|
||||||
List<ImapResponse> responses = connection.executeSimpleCommand(String.format(commandFormat, encodedListPrefix));
|
val responses = connection.executeSimpleCommand(String.format(commandFormat, encodedListPrefix))
|
||||||
|
|
||||||
List<ListResponse> listResponses = (subscribedOnly) ?
|
val listResponses = if (subscribedOnly) {
|
||||||
ListResponse.parseLsub(responses) :
|
ListResponse.parseLsub(responses)
|
||||||
ListResponse.parseList(responses);
|
} else {
|
||||||
|
ListResponse.parseList(responses)
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, FolderListItem> folderMap = new HashMap<>(listResponses.size());
|
val folderMap = mutableMapOf<String, FolderListItem>()
|
||||||
for (ListResponse listResponse : listResponses) {
|
for (listResponse in listResponses) {
|
||||||
String serverId = listResponse.getName();
|
val serverId = listResponse.name
|
||||||
|
|
||||||
if (pathDelimiter == null) {
|
if (pathDelimiter == null) {
|
||||||
pathDelimiter = listResponse.getHierarchyDelimiter();
|
pathDelimiter = listResponse.hierarchyDelimiter
|
||||||
combinedPrefix = null;
|
combinedPrefix = null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RealImapFolder.INBOX.equalsIgnoreCase(serverId)) {
|
if (RealImapFolder.INBOX.equals(serverId, ignoreCase = true)) {
|
||||||
continue;
|
continue
|
||||||
} else if (listResponse.hasAttribute("\\NoSelect")) {
|
} else if (listResponse.hasAttribute("\\NoSelect")) {
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
String name = getFolderDisplayName(serverId);
|
val name = getFolderDisplayName(serverId)
|
||||||
String oldServerId = getOldServerId(serverId);
|
val oldServerId = getOldServerId(serverId)
|
||||||
|
|
||||||
FolderType type;
|
val type = when {
|
||||||
if (listResponse.hasAttribute("\\Archive") || listResponse.hasAttribute("\\All")) {
|
listResponse.hasAttribute("\\Archive") -> FolderType.ARCHIVE
|
||||||
type = FolderType.ARCHIVE;
|
listResponse.hasAttribute("\\All") -> FolderType.ARCHIVE
|
||||||
} else if (listResponse.hasAttribute("\\Drafts")) {
|
listResponse.hasAttribute("\\Drafts") -> FolderType.DRAFTS
|
||||||
type = FolderType.DRAFTS;
|
listResponse.hasAttribute("\\Sent") -> FolderType.SENT
|
||||||
} else if (listResponse.hasAttribute("\\Sent")) {
|
listResponse.hasAttribute("\\Junk") -> FolderType.SPAM
|
||||||
type = FolderType.SENT;
|
listResponse.hasAttribute("\\Trash") -> FolderType.TRASH
|
||||||
} else if (listResponse.hasAttribute("\\Junk")) {
|
else -> FolderType.REGULAR
|
||||||
type = FolderType.SPAM;
|
|
||||||
} else if (listResponse.hasAttribute("\\Trash")) {
|
|
||||||
type = FolderType.TRASH;
|
|
||||||
} else {
|
|
||||||
type = FolderType.REGULAR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FolderListItem existingItem = folderMap.get(serverId);
|
val existingItem = folderMap[serverId]
|
||||||
if (existingItem == null || existingItem.getType() == FolderType.REGULAR) {
|
if (existingItem == null || existingItem.type == FolderType.REGULAR) {
|
||||||
folderMap.put(serverId, new FolderListItem(serverId, name, type, oldServerId));
|
folderMap[serverId] = FolderListItem(serverId, name, type, oldServerId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<FolderListItem> folders = new ArrayList<>(folderMap.size() + 1);
|
return buildList {
|
||||||
folders.add(new FolderListItem(RealImapFolder.INBOX, RealImapFolder.INBOX, FolderType.INBOX, RealImapFolder.INBOX));
|
add(FolderListItem(RealImapFolder.INBOX, RealImapFolder.INBOX, FolderType.INBOX, RealImapFolder.INBOX))
|
||||||
folders.addAll(folderMap.values());
|
addAll(folderMap.values)
|
||||||
|
}
|
||||||
return folders;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getFolderDisplayName(String serverId) {
|
private fun getFolderDisplayName(serverId: String): String {
|
||||||
String decodedFolderName;
|
val decodedFolderName = try {
|
||||||
try {
|
folderNameCodec.decode(serverId)
|
||||||
decodedFolderName = folderNameCodec.decode(serverId);
|
} catch (e: CharacterCodingException) {
|
||||||
} catch (CharacterCodingException e) {
|
Timber.w(e, "Folder name not correctly encoded with the UTF-7 variant as defined by RFC 3501: %s", serverId)
|
||||||
Timber.w(e, "Folder name not correctly encoded with the UTF-7 variant as defined by RFC 3501: %s",
|
serverId
|
||||||
serverId);
|
|
||||||
|
|
||||||
decodedFolderName = serverId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String folderNameWithoutPrefix = removePrefixFromFolderName(decodedFolderName);
|
val folderNameWithoutPrefix = removePrefixFromFolderName(decodedFolderName)
|
||||||
return folderNameWithoutPrefix != null ? folderNameWithoutPrefix : decodedFolderName;
|
return folderNameWithoutPrefix ?: decodedFolderName
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
private fun getOldServerId(serverId: String): String? {
|
||||||
private String getOldServerId(String serverId) {
|
val decodedFolderName = try {
|
||||||
String decodedFolderName;
|
folderNameCodec.decode(serverId)
|
||||||
try {
|
} catch (e: CharacterCodingException) {
|
||||||
decodedFolderName = folderNameCodec.decode(serverId);
|
|
||||||
} catch (CharacterCodingException e) {
|
|
||||||
// Previous versions of K-9 Mail ignored folders with invalid UTF-7 encoding
|
// Previous versions of K-9 Mail ignored folders with invalid UTF-7 encoding
|
||||||
return null;
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return removePrefixFromFolderName(decodedFolderName);
|
return removePrefixFromFolderName(decodedFolderName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
private fun removePrefixFromFolderName(folderName: String): String? {
|
||||||
private String removePrefixFromFolderName(String folderName) {
|
val prefix = getCombinedPrefix()
|
||||||
String prefix = getCombinedPrefix();
|
val prefixLength = prefix.length
|
||||||
int prefixLength = prefix.length();
|
|
||||||
if (prefixLength == 0) {
|
if (prefixLength == 0) {
|
||||||
return folderName;
|
return folderName
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!folderName.startsWith(prefix)) {
|
if (!folderName.startsWith(prefix)) {
|
||||||
// Folder name doesn't start with our configured prefix. But right now when building commands we prefix all
|
// Folder name doesn't start with our configured prefix. But right now when building commands we prefix all
|
||||||
// folders except the INBOX with the prefix. So we won't be able to use this folder.
|
// folders except the INBOX with the prefix. So we won't be able to use this folder.
|
||||||
return null;
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return folderName.substring(prefixLength);
|
return folderName.substring(prefixLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkSettings() throws MessagingException {
|
@Throws(MessagingException::class)
|
||||||
|
override fun checkSettings() {
|
||||||
try {
|
try {
|
||||||
ImapConnection connection = createImapConnection();
|
val connection = createImapConnection()
|
||||||
|
|
||||||
connection.open();
|
connection.open()
|
||||||
connection.close();
|
connection.close()
|
||||||
} catch (IOException ioe) {
|
} catch (e: IOException) {
|
||||||
throw new MessagingException("Unable to connect", ioe);
|
throw MessagingException("Unable to connect", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Throws(MessagingException::class)
|
||||||
@NotNull
|
override fun getConnection(): ImapConnection {
|
||||||
public ImapConnection getConnection() throws MessagingException {
|
while (true) {
|
||||||
ImapConnection connection;
|
val connection = pollConnection() ?: return createImapConnection()
|
||||||
while ((connection = pollConnection()) != null) {
|
|
||||||
try {
|
try {
|
||||||
connection.executeSimpleCommand(Commands.NOOP);
|
connection.executeSimpleCommand(Commands.NOOP)
|
||||||
break;
|
|
||||||
} catch (IOException ioe) {
|
// If the command completes without an error this connection is still usable.
|
||||||
connection.close();
|
return connection
|
||||||
|
} catch (ioe: IOException) {
|
||||||
|
connection.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection == null) {
|
|
||||||
connection = createImapConnection();
|
|
||||||
}
|
|
||||||
|
|
||||||
return connection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImapConnection pollConnection() {
|
private fun pollConnection(): ImapConnection? {
|
||||||
synchronized (connections) {
|
return synchronized(connections) {
|
||||||
return connections.poll();
|
connections.poll()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun releaseConnection(connection: ImapConnection?) {
|
||||||
public void releaseConnection(ImapConnection connection) {
|
if (connection != null && connection.isConnected) {
|
||||||
if (connection != null && connection.isConnected()) {
|
if (connection.connectionGeneration == connectionGeneration) {
|
||||||
if (connection.getConnectionGeneration() == connectionGeneration) {
|
synchronized(connections) {
|
||||||
synchronized (connections) {
|
connections.offer(connection)
|
||||||
connections.offer(connection);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
connection.close();
|
connection.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun closeAllConnections() {
|
||||||
public void closeAllConnections() {
|
Timber.v("ImapStore.closeAllConnections()")
|
||||||
Timber.v("ImapStore.closeAllConnections()");
|
|
||||||
|
|
||||||
List<ImapConnection> connectionsToClose;
|
val connectionsToClose = synchronized(connections) {
|
||||||
synchronized (connections) {
|
val connectionsToClose = connections.toList()
|
||||||
connectionGeneration++;
|
|
||||||
connectionsToClose = new ArrayList<>(connections);
|
connectionGeneration++
|
||||||
connections.clear();
|
connections.clear()
|
||||||
|
|
||||||
|
connectionsToClose
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ImapConnection connection : connectionsToClose) {
|
for (connection in connectionsToClose) {
|
||||||
connection.close();
|
connection.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImapConnection createImapConnection() {
|
open fun createImapConnection(): ImapConnection {
|
||||||
return new RealImapConnection(
|
return RealImapConnection(
|
||||||
new StoreImapSettings(),
|
StoreImapSettings(),
|
||||||
trustedSocketFactory,
|
trustedSocketFactory,
|
||||||
oauthTokenProvider,
|
oauthTokenProvider,
|
||||||
connectionGeneration);
|
connectionGeneration
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override val logLabel: String
|
||||||
@NotNull
|
get() = config.logLabel
|
||||||
public String getLogLabel() {
|
|
||||||
return config.getLogLabel();
|
override fun getPermanentFlagsIndex(): MutableSet<Flag> {
|
||||||
|
return permanentFlagsIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private inner class StoreImapSettings : ImapSettings {
|
||||||
@NotNull
|
override val host: String = this@RealImapStore.host
|
||||||
public Set<Flag> getPermanentFlagsIndex() {
|
override val port: Int = serverSettings.port
|
||||||
return permanentFlagsIndex;
|
override val connectionSecurity: ConnectionSecurity = serverSettings.connectionSecurity
|
||||||
}
|
override val authType: AuthType = serverSettings.authenticationType
|
||||||
|
override val username: String = serverSettings.username
|
||||||
|
override val password: String? = serverSettings.password
|
||||||
|
override val clientCertificateAlias: String? = serverSettings.clientCertificateAlias
|
||||||
|
|
||||||
|
override fun useCompression(): Boolean {
|
||||||
private class StoreImapSettings implements ImapSettings {
|
return this@RealImapStore.config.useCompression()
|
||||||
@Override
|
|
||||||
public String getHost() {
|
|
||||||
return host;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override var pathPrefix: String?
|
||||||
public int getPort() {
|
get() = this@RealImapStore.pathPrefix
|
||||||
return port;
|
set(value) {
|
||||||
}
|
this@RealImapStore.pathPrefix = value
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
override var pathDelimiter: String?
|
||||||
public ConnectionSecurity getConnectionSecurity() {
|
get() = this@RealImapStore.pathDelimiter
|
||||||
return connectionSecurity;
|
set(value) {
|
||||||
}
|
this@RealImapStore.pathDelimiter = value
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
override fun setCombinedPrefix(prefix: String?) {
|
||||||
public AuthType getAuthType() {
|
combinedPrefix = prefix
|
||||||
return authType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUsername() {
|
|
||||||
return username;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getPassword() {
|
|
||||||
return password;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getClientCertificateAlias() {
|
|
||||||
return clientCertificateAlias;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean useCompression() {
|
|
||||||
return config.useCompression();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getPathPrefix() {
|
|
||||||
return pathPrefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setPathPrefix(String prefix) {
|
|
||||||
pathPrefix = prefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getPathDelimiter() {
|
|
||||||
return pathDelimiter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setPathDelimiter(String delimiter) {
|
|
||||||
pathDelimiter = delimiter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCombinedPrefix(String prefix) {
|
|
||||||
combinedPrefix = prefix;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val ImapConnection.supportsListExtended: Boolean
|
||||||
|
get() = hasCapability(Capabilities.SPECIAL_USE) && hasCapability(Capabilities.LIST_EXTENDED)
|
||||||
|
|
|
@ -465,7 +465,7 @@ public class RealImapStoreTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
ImapConnection createImapConnection() {
|
public ImapConnection createImapConnection() {
|
||||||
if (imapConnections.isEmpty()) {
|
if (imapConnections.isEmpty()) {
|
||||||
throw new AssertionError("Unexpectedly tried to create an ImapConnection instance");
|
throw new AssertionError("Unexpectedly tried to create an ImapConnection instance");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue