MapBasedStoredMessageCollection.java
/* -------------------------------------------------------------------
* This software is released under the Apache license 2.0
* -------------------------------------------------------------------
*/
package com.icegreen.greenmail.store;
import com.icegreen.greenmail.foedus.util.MsgRangeFilter;
import com.icegreen.greenmail.imap.commands.IdRange;
import com.icegreen.greenmail.util.MaxSizeLinkedHashMap;
import jakarta.mail.Flags;
import java.util.*;
import static java.lang.String.format;
/**
* @author Raimund Klein <raimund.klein@gmx.de>
*/
public class MapBasedStoredMessageCollection implements StoredMessageCollection {
private final Map<Long, StoredMessage> mailMessages;
public MapBasedStoredMessageCollection(final int maximumMapSize) {
mailMessages = Collections.synchronizedMap(new MaxSizeLinkedHashMap<>(maximumMapSize));
}
@Override
public int size() {
return mailMessages.size();
}
@Override
public void add(StoredMessage storedMessage) {
mailMessages.put(storedMessage.getUid(), storedMessage);
}
@Override
public StoredMessage remove(long uid) {
final StoredMessage msg = mailMessages.remove(uid);
if (null == msg) {
throw new IllegalArgumentException("No message for uid " + uid + " exists");
}
return msg;
}
@Override
public void clear() {
mailMessages.clear();
}
@Override
public int getFirstUnseen() {
synchronized (mailMessages) {
int i = 1;
for (StoredMessage message : mailMessages.values()) {
if (!message.isSet(Flags.Flag.SEEN)) {
return i;
}
i++;
}
}
return -1;
}
@Override
public int getMsn(long uid) throws FolderException {
synchronized (mailMessages) {
if (mailMessages.containsKey(uid)) {
int i = 1;
for (Long messageUid : mailMessages.keySet()) {
if (messageUid.equals(uid)) {
return i;
}
i++;
}
}
throw new FolderException("No such message.");
}
}
@Override
public List<StoredMessage> getMessages(MsgRangeFilter range) {
final List<StoredMessage> messagesInRange = new ArrayList<>();
int i = 0;
synchronized (mailMessages) {
for (final StoredMessage message : mailMessages.values()) {
if (range.includes(i)) {
messagesInRange.add(message);
}
i++;
}
}
return messagesInRange;
}
@Override
public List<StoredMessage> getMessages() {
synchronized (mailMessages) {
return new ArrayList<>(mailMessages.values());
}
}
@Override
public long[] getMessageUids() {
synchronized (mailMessages) {
final long[] uids = new long[mailMessages.size()];
int i = 0;
for (final Long uid : mailMessages.keySet()) {
uids[i] = uid;
i++;
}
return uids;
}
}
@Override
public void expunge(List<FolderListener> mailboxListeners) {
expunge(mailboxListeners, null);
}
@Override
public void expunge(List<FolderListener> mailboxListeners, IdRange[] idRanges) {
int i = 1;
synchronized (mailMessages) {
for (final Iterator<Map.Entry<Long, StoredMessage>> messageEntryIt = mailMessages.entrySet().iterator(); messageEntryIt.hasNext(); ) {
final Map.Entry<Long, StoredMessage> messageEntry = messageEntryIt.next();
if (messageEntry.getValue().isSet(Flags.Flag.DELETED) &&
(idRanges == null || IdRange.containsUid(idRanges, messageEntry.getValue().getUid()))) {
// Notify all the listeners of the pending delete
synchronized (mailboxListeners) {
messageEntryIt.remove();
for (FolderListener expungeListener : mailboxListeners) {
expungeListener.expunged(i);
}
}
}
i++;
}
}
}
@Override
public StoredMessage get(final int messageIndex) {
synchronized (mailMessages) {
int i = 0;
for (final StoredMessage message : mailMessages.values()) {
if (messageIndex == i) {
return message;
}
i++;
}
}
throw new IllegalArgumentException(format("No message with index %d found", messageIndex));
}
@Override
public Iterator<StoredMessage> iterator() {
return mailMessages.values().iterator();
}
}