Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one *
* or more contributor license agreements. See the NOTICE file *
* distributed with this work for additional information *
* regarding copyright ownership. The ASF licenses this file *
* to you under the Apache License, Version 2.0 (the *
* "License"); you may not use this file except in compliance *
* with the License. You may obtain a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, *
* software distributed under the License is distributed on an *
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
****************************************************************/
package org.apache.james.mailbox.maildir.mail;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;
import javax.mail.Flags;
import javax.mail.Flags.Flag;
import org.apache.commons.io.FileUtils;
import org.apache.james.mailbox.MailboxSession;
import org.apache.james.mailbox.MessageUid;
import org.apache.james.mailbox.exception.MailboxException;
import org.apache.james.mailbox.maildir.MaildirFolder;
import org.apache.james.mailbox.maildir.MaildirMessageName;
import org.apache.james.mailbox.maildir.MaildirStore;
import org.apache.james.mailbox.maildir.mail.model.MaildirMailboxMessage;
import org.apache.james.mailbox.model.MessageMetaData;
import org.apache.james.mailbox.model.MessageRange;
import org.apache.james.mailbox.model.MessageRange.Type;
import org.apache.james.mailbox.model.UpdatedFlags;
import org.apache.james.mailbox.store.FlagsUpdateCalculator;
import org.apache.james.mailbox.store.SimpleMessageMetaData;
import org.apache.james.mailbox.store.mail.AbstractMessageMapper;
import org.apache.james.mailbox.store.mail.model.Mailbox;
import org.apache.james.mailbox.store.mail.model.MailboxMessage;
import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage;
public class MaildirMessageMapper extends AbstractMessageMapper {
private final MaildirStore maildirStore;
private final static int BUF_SIZE = 2048;
public MaildirMessageMapper(MailboxSession session, MaildirStore maildirStore) {
super(session, maildirStore, maildirStore);
this.maildirStore = maildirStore;
}
@Override
public long countMessagesInMailbox(Mailbox mailbox) throws MailboxException {
MaildirFolder folder = maildirStore.createMaildirFolder(mailbox);
File newFolder = folder.getNewFolder();
File curFolder = folder.getCurFolder();
File[] newFiles = newFolder.listFiles();
File[] curFiles = curFolder.listFiles();
if (newFiles == null || curFiles == null)
throw new MailboxException("Unable to count messages in Mailbox " + mailbox, new IOException(
"Not a valid Maildir folder: " + maildirStore.getFolderName(mailbox)));
return newFiles.length + curFiles.length;
}
@Override
public long countUnseenMessagesInMailbox(Mailbox mailbox) throws MailboxException {
MaildirFolder folder = maildirStore.createMaildirFolder(mailbox);
File newFolder = folder.getNewFolder();
File curFolder = folder.getCurFolder();
String[] unseenMessages = curFolder.list(MaildirMessageName.FILTER_UNSEEN_MESSAGES);
String[] newUnseenMessages = newFolder.list(MaildirMessageName.FILTER_UNSEEN_MESSAGES);
if (newUnseenMessages == null || unseenMessages == null)
throw new MailboxException("Unable to count unseen messages in Mailbox " + mailbox, new IOException(
"Not a valid Maildir folder: " + maildirStore.getFolderName(mailbox)));
return newUnseenMessages.length + unseenMessages.length;
}
@Override
public void delete(Mailbox mailbox, MailboxMessage message) throws MailboxException {
MaildirFolder folder = maildirStore.createMaildirFolder(mailbox);
try {
folder.delete(mailboxSession, message.getUid());
} catch (MailboxException e) {
throw new MailboxException("Unable to delete MailboxMessage " + message + " in Mailbox " + mailbox, e);
}
}
@Override
public Iterator findInMailbox(Mailbox mailbox, MessageRange set, FetchType fType, int max)
throws MailboxException {
final List results;
final MessageUid from = set.getUidFrom();
final MessageUid to = set.getUidTo();
final Type type = set.getType();
switch (type) {
default:
case ALL:
results = findMessagesInMailboxBetweenUIDs(mailbox, null, MessageUid.MIN_VALUE, null, max);
break;
case FROM:
results = findMessagesInMailboxBetweenUIDs(mailbox, null, from, null, max);
break;
case ONE:
results = findMessageInMailboxWithUID(mailbox, from);
break;
case RANGE:
results = findMessagesInMailboxBetweenUIDs(mailbox, null, from, to, max);
break;
}
return results.iterator();
}
@Override
public List findRecentMessageUidsInMailbox(Mailbox mailbox) throws MailboxException {
MaildirFolder folder = maildirStore.createMaildirFolder(mailbox);
SortedMap recentMessageNames = folder.getRecentMessages(mailboxSession);
return new ArrayList(recentMessageNames.keySet());
}
@Override
public MessageUid findFirstUnseenMessageUid(Mailbox mailbox) throws MailboxException {
List result = findMessagesInMailbox(mailbox, MaildirMessageName.FILTER_UNSEEN_MESSAGES, 1);
if (result.isEmpty()) {
return null;
} else {
return result.get(0).getUid();
}
}
/**
* @see org.apache.james.mailbox.store.mail.MessageMapper#updateFlags(org.apache.james.mailbox.store.mail.model.Mailbox,
* javax.mail.Flags, boolean, boolean,
* org.apache.james.mailbox.model.MessageRange)
*/
@Override
public Iterator updateFlags(Mailbox mailbox, FlagsUpdateCalculator flagsUpdateCalculator, MessageRange set) throws MailboxException {
final List updatedFlags = new ArrayList();
final MaildirFolder folder = maildirStore.createMaildirFolder(mailbox);
Iterator it = findInMailbox(mailbox, set, FetchType.Metadata, -1);
while (it.hasNext()) {
final MailboxMessage member = it.next();
Flags originalFlags = member.createFlags();
member.setFlags(flagsUpdateCalculator.buildNewFlags(originalFlags));
Flags newFlags = member.createFlags();
try {
MaildirMessageName messageName = folder.getMessageNameByUid(mailboxSession, member.getUid());
if (messageName != null) {
File messageFile = messageName.getFile();
// System.out.println("save existing " + message +
// " as " + messageFile.getName());
messageName.setFlags(member.createFlags());
// this automatically moves messages from new to cur if
// needed
String newMessageName = messageName.getFullName();
File newMessageFile;
// See MAILBOX-57
if (newFlags.contains(Flag.RECENT)) {
// message is recent so save it in the new folder
newMessageFile = new File(folder.getNewFolder(), newMessageName);
} else {
newMessageFile = new File(folder.getCurFolder(), newMessageName);
}
long modSeq;
// if the flags don't have change we should not try to move
// the file
if (newMessageFile.equals(messageFile) == false) {
FileUtils.moveFile(messageFile, newMessageFile);
modSeq = newMessageFile.lastModified();
} else {
modSeq = messageFile.lastModified();
}
member.setModSeq(modSeq);
updatedFlags.add(new UpdatedFlags(member.getUid(), modSeq, originalFlags, newFlags));
MessageUid uid = member.getUid();
folder.update(mailboxSession, uid, newMessageName);
}
} catch (IOException e) {
throw new MailboxException("Failure while save MailboxMessage " + member + " in Mailbox " + mailbox, e);
}
}
return updatedFlags.iterator();
}
@Override
public Map expungeMarkedForDeletionInMailbox(Mailbox mailbox, MessageRange set)
throws MailboxException {
List results = new ArrayList();
final MessageUid from = set.getUidFrom();
final MessageUid to = set.getUidTo();
final Type type = set.getType();
switch (type) {
default:
case ALL:
results = findMessagesInMailbox(mailbox, MaildirMessageName.FILTER_DELETED_MESSAGES, -1);
break;
case FROM:
results = findMessagesInMailboxBetweenUIDs(mailbox, MaildirMessageName.FILTER_DELETED_MESSAGES, from, null,
-1);
break;
case ONE:
results = findDeletedMessageInMailboxWithUID(mailbox, from);
break;
case RANGE:
results = findMessagesInMailboxBetweenUIDs(mailbox, MaildirMessageName.FILTER_DELETED_MESSAGES, from, to,
-1);
break;
}
Map uids = new HashMap();
for (MailboxMessage m : results) {
MessageUid uid = m.getUid();
uids.put(uid, new SimpleMessageMetaData(m));
delete(mailbox, m);
}
return uids;
}
/**
* (non-Javadoc)
*
* @see org.apache.james.mailbox.store.mail.MessageMapper#move(org.apache.james.mailbox.store.mail.model.Mailbox,
* MailboxMessage)
*/
@Override
public MessageMetaData move(Mailbox mailbox, MailboxMessage original) throws MailboxException {
throw new UnsupportedOperationException("Not implemented - see https://issues.apache.org/jira/browse/IMAP-370");
}
@Override
protected MessageMetaData copy(Mailbox mailbox, MessageUid uid, long modSeq, MailboxMessage original)
throws MailboxException {
SimpleMailboxMessage theCopy = SimpleMailboxMessage.copy(mailbox.getMailboxId(), original);
Flags flags = theCopy.createFlags();
flags.add(Flag.RECENT);
theCopy.setFlags(flags);
return save(mailbox, theCopy);
}
/**
* @see org.apache.james.mailbox.store.mail.AbstractMessageMapper#save(org.apache.james.mailbox.store.mail.model.Mailbox,
* MailboxMessage)
*/
@Override
protected MessageMetaData save(Mailbox mailbox, MailboxMessage message) throws MailboxException {
MaildirFolder folder = maildirStore.createMaildirFolder(mailbox);
MessageUid uid = MessageUid.MIN_VALUE;
// a new message
// save file to "tmp" folder
File tmpFolder = folder.getTmpFolder();
// The only case in which we could get problems with clashing names
// is if the system clock
// has been set backwards, then the server is restarted with the
// same pid, delivers the same
// number of messages since its start in the exact same millisecond
// as done before and the
// random number generator returns the same number.
// In order to prevent this case we would need to check ALL files in
// all folders and compare
// them to this message name. We rather let this happen once in a
// billion years...
MaildirMessageName messageName = MaildirMessageName.createUniqueName(folder, message.getFullContentOctets());
File messageFile = new File(tmpFolder, messageName.getFullName());
FileOutputStream fos = null;
InputStream input = null;
try {
if (!messageFile.createNewFile())
throw new IOException("Could not create file " + messageFile);
fos = new FileOutputStream(messageFile);
input = message.getFullContent();
byte[] b = new byte[BUF_SIZE];
int len = 0;
while ((len = input.read(b)) != -1)
fos.write(b, 0, len);
} catch (IOException ioe) {
throw new MailboxException("Failure while save MailboxMessage " + message + " in Mailbox " + mailbox, ioe);
} finally {
try {
if (fos != null)
fos.close();
} catch (IOException e) {
}
try {
if (input != null)
input.close();
} catch (IOException e) {
}
}
File newMessageFile = null;
// delivered via SMTP, goes to ./new without flags
if (message.isRecent()) {
messageName.setFlags(message.createFlags());
newMessageFile = new File(folder.getNewFolder(), messageName.getFullName());
// System.out.println("save new recent " + message + " as " +
// newMessageFile.getName());
}
// appended via IMAP (might already have flags etc, goes to ./cur
// directly)
else {
messageName.setFlags(message.createFlags());
newMessageFile = new File(folder.getCurFolder(), messageName.getFullName());
// System.out.println("save new not recent " + message + " as "
// + newMessageFile.getName());
}
try {
FileUtils.moveFile(messageFile, newMessageFile);
} catch (IOException e) {
// TODO: Try copy and delete
throw new MailboxException("Failure while save MailboxMessage " + message + " in Mailbox " + mailbox, e);
}
try {
uid = folder.appendMessage(mailboxSession, newMessageFile.getName());
message.setUid(uid);
message.setModSeq(newMessageFile.lastModified());
return new SimpleMessageMetaData(message);
} catch (MailboxException e) {
throw new MailboxException("Failure while save MailboxMessage " + message + " in Mailbox " + mailbox, e);
}
}
/**
* @see org.apache.james.mailbox.store.transaction.TransactionalMapper#endRequest()
*/
@Override
public void endRequest() {
// not used
}
private List findMessageInMailboxWithUID(Mailbox mailbox, MessageUid from)
throws MailboxException {
MaildirFolder folder = maildirStore.createMaildirFolder(mailbox);
try {
MaildirMessageName messageName = folder.getMessageNameByUid(mailboxSession, from);
ArrayList messages = new ArrayList();
if (messageName != null && messageName.getFile().exists()) {
messages.add(new MaildirMailboxMessage(mailbox, from, messageName));
}
return messages;
} catch (IOException e) {
throw new MailboxException("Failure while search for MailboxMessage with uid " + from + " in Mailbox " + mailbox, e);
}
}
private List findMessagesInMailboxBetweenUIDs(Mailbox mailbox, FilenameFilter filter,
MessageUid from, MessageUid to, int max) throws MailboxException {
MaildirFolder folder = maildirStore.createMaildirFolder(mailbox);
int cur = 0;
SortedMap uidMap = null;
try {
if (filter != null)
uidMap = folder.getUidMap(mailboxSession, filter, from, to);
else
uidMap = folder.getUidMap(mailboxSession, from, to);
ArrayList messages = new ArrayList();
for (Entry entry : uidMap.entrySet()) {
messages.add(new MaildirMailboxMessage(mailbox, entry.getKey(), entry.getValue()));
if (max != -1) {
cur++;
if (cur >= max)
break;
}
}
return messages;
} catch (IOException e) {
throw new MailboxException("Failure while search for Messages in Mailbox " + mailbox, e);
}
}
private List findMessagesInMailbox(Mailbox mailbox, FilenameFilter filter, int limit)
throws MailboxException {
MaildirFolder folder = maildirStore.createMaildirFolder(mailbox);
try {
SortedMap uidMap = folder.getUidMap(mailboxSession, filter, limit);
ArrayList filtered = new ArrayList(uidMap.size());
for (Entry entry : uidMap.entrySet())
filtered.add(new MaildirMailboxMessage(mailbox, entry.getKey(), entry.getValue()));
return filtered;
} catch (IOException e) {
throw new MailboxException("Failure while search for Messages in Mailbox " + mailbox, e);
}
}
private List findDeletedMessageInMailboxWithUID(Mailbox mailbox, MessageUid uid)
throws MailboxException {
MaildirFolder folder = maildirStore.createMaildirFolder(mailbox);
try {
MaildirMessageName messageName = folder.getMessageNameByUid(mailboxSession, uid);
ArrayList messages = new ArrayList();
if (MaildirMessageName.FILTER_DELETED_MESSAGES.accept(null, messageName.getFullName())) {
messages.add(new MaildirMailboxMessage(mailbox, uid, messageName));
}
return messages;
} catch (IOException e) {
throw new MailboxException("Failure while search for Messages in Mailbox " + mailbox, e);
}
}
/**
* @see org.apache.james.mailbox.store.transaction.TransactionalMapper#begin()
*/
@Override
protected void begin() throws MailboxException {
// nothing todo
}
/**
* @see org.apache.james.mailbox.store.transaction.TransactionalMapper#commit()
*/
@Override
protected void commit() throws MailboxException {
// nothing todo
}
/**
* @see org.apache.james.mailbox.store.transaction.TransactionalMapper#rollback()
*/
@Override
protected void rollback() throws MailboxException {
// nothing todo
}
}