Methods Summary |
---|
public void | configure(org.apache.avalon.framework.configuration.Configuration conf)Configure the component
String destination;
this.mList = null;
BUFFERING = conf.getAttributeAsBoolean("BUFFERING", true);
destination = conf.getAttribute("destinationURL");
if (destination.charAt(destination.length() - 1) == '/") {
// Remove the trailing / as well as the protocol marker
mboxFile = destination.substring("mbox://".length(), destination.lastIndexOf("/"));
} else {
mboxFile = destination.substring("mbox://".length());
}
if (getLogger().isDebugEnabled()) {
getLogger().debug("MBoxMailRepository.destinationURL: " + destination);
}
String checkType = conf.getAttribute("type");
if (!(checkType.equals("MAIL") || checkType.equals("SPOOL"))) {
String exceptionString = "Attempt to configure MboxMailRepository as " + checkType;
if (getLogger().isWarnEnabled()) {
getLogger().warn(exceptionString);
}
throw new ConfigurationException(exceptionString);
}
|
private javax.mail.internet.MimeMessage | convertTextToMimeMessage(java.lang.String emailBody)Parse a text block as an email and convert it into a mime message
//this.emailBody = emailBody;
MimeMessage mimeMessage = null;
// Parse the mime message as we have the full message now (in string format)
ByteArrayInputStream mb = new ByteArrayInputStream(emailBody.getBytes());
Properties props = System.getProperties();
Session session = Session.getDefaultInstance(props);
try {
mimeMessage = new MimeMessage(session, mb);
} catch (MessagingException e) {
getLogger().error("Unable to parse mime message!", e);
}
if (mimeMessage == null && getLogger().isDebugEnabled()) {
StringBuffer logBuffer =
new StringBuffer(128)
.append(this.getClass().getName())
.append(" Mime message is null");
getLogger().debug(logBuffer.toString());
}
/*
String toAddr = null;
try {
// Attempt to read the TO field and see if it errors
toAddr = mimeMessage.getRecipients(javax.mail.Message.RecipientType.TO).toString();
} catch (Exception e) {
// It has errored, so time for plan B
// use the from field I suppose
try {
mimeMessage.setRecipients(javax.mail.Message.RecipientType.TO, mimeMessage.getFrom());
if (getLogger().isDebugEnabled()) {
StringBuffer logBuffer =
new StringBuffer(128)
.append(this.getClass().getName())
.append(" Patching To: field for message ")
.append(" with From: field");
getLogger().debug(logBuffer.toString());
}
} catch (MessagingException e1) {
getLogger().error("Unable to set to: field to from: field", e);
}
} */
return mimeMessage;
|
private javax.mail.internet.MimeMessage | findMessage(java.lang.String key)Find a given message
This method will first use selectMessage(key) to see if the key/offset combination allows us to skip
parts of the file and only load the message we are interested in
MimeMessage foundMessage = null;
// See if we can get the message by using the cache position first
foundMessage = selectMessage(key);
if (foundMessage == null) {
// If the message is not found something has changed from
// the cache. The cache may have been invalidated by
// another method, or the file may have been replaced from
// underneath us. Reload the cache, and try again.
mList = null;
loadKeys();
foundMessage = selectMessage(key);
}
return foundMessage;
|
private java.lang.String | generateKeyValue(java.lang.String emailBody)Generate a hex representation of an MD5 checksum on the emailbody
// MD5 the email body for a reilable (ha ha) key
byte[] digArray = MessageDigest.getInstance("MD5").digest(emailBody.getBytes());
StringBuffer digest = new StringBuffer();
for (int i = 0; i < digArray.length; i++) {
digest.append(Integer.toString(digArray[i], Character.MAX_RADIX).toUpperCase(Locale.US));
}
return digest.toString();
|
private java.lang.String | getRawMessage(javax.mail.internet.MimeMessage mc)Convert a MimeMessage into raw text
// *** Not valid until AFTER each call to messageAction(...)!
ByteArrayOutputStream rawMessage = new ByteArrayOutputStream();
mc.writeTo(rawMessage);
return rawMessage.toString();
|
public void | initialize()Initialise the component
|
public java.util.Iterator | list()Return the list of the current messages' keys
loadKeys();
if (mList.keySet().isEmpty() == false) {
// find the first message. This is a trick to make sure that if
// the file is changed out from under us, we will detect it and
// correct for it BEFORE we return the iterator.
findMessage((String) mList.keySet().iterator().next());
}
if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
StringBuffer logBuffer =
new StringBuffer(128)
.append(this.getClass().getName())
.append(" ")
.append(mList.size())
.append(" keys to be iterated over.");
getLogger().debug(logBuffer.toString());
}
return mList.keySet().iterator();
|
private synchronized void | loadKeys()Load the message keys and file pointer offsets from disk
if (mList!=null) {
return;
}
RandomAccessFile ins = null;
try {
ins = new RandomAccessFile(mboxFile, "r");
long initialCapacity = (ins.length() > MLISTPRESIZEFACTOR ? ins.length() /MLISTPRESIZEFACTOR : 0);
if (initialCapacity < DEFAULTMLISTCAPACITY ) {
initialCapacity = DEFAULTMLISTCAPACITY;
}
if (initialCapacity > Integer.MAX_VALUE) {
initialCapacity = Integer.MAX_VALUE - 1;
}
this.mList = new Hashtable((int)initialCapacity);
this.parseMboxFile(ins, new MessageAction() {
public boolean isComplete() { return false; }
public MimeMessage messageAction(String messageSeparator, String bodyText, long messageStart) {
try {
String key = generateKeyValue(bodyText);
mList.put(key, new Long(messageStart));
if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
getLogger().debug(this.getClass().getName() + " Key " + key + " at " + messageStart);
}
} catch (NoSuchAlgorithmException e) {
getLogger().error("MD5 not supported! ",e);
}
return null;
}
});
//System.out.println("Done Load keys!");
} catch (FileNotFoundException e) {
getLogger().error("Unable to save(open) file (File not found) " + mboxFile, e);
this.mList = new Hashtable((int)DEFAULTMLISTCAPACITY);
} catch (IOException e) {
getLogger().error("Unable to write file (General I/O problem) " + mboxFile, e);
} finally {
if (ins != null) try { ins.close(); } catch (IOException e) { getLogger().error("Unable to close file (General I/O problem) " + mboxFile, e); }
}
|
public boolean | lock(java.lang.String key)Not implemented
return false;
|
private void | lockMBox()Attempt to get a lock on the mbox by creating
the file mboxname.lock
// Create the lock file (if possible)
String lockFileName = mboxFile + LOCKEXT;
int sleepCount = 0;
File mBoxLock = new File(lockFileName);
if (!mBoxLock.createNewFile()) {
// This is not good, somebody got the lock before me
// So wait for a file
while (!mBoxLock.createNewFile() && sleepCount < MAXSLEEPTIMES) {
try {
if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
StringBuffer logBuffer =
new StringBuffer(128)
.append(this.getClass().getName())
.append(" Waiting for lock on file ")
.append(mboxFile);
getLogger().debug(logBuffer.toString());
}
Thread.sleep(LOCKSLEEPDELAY);
sleepCount++;
} catch (InterruptedException e) {
getLogger().error("File lock wait for " + mboxFile + " interrupted!",e);
}
}
if (sleepCount >= MAXSLEEPTIMES) {
throw new Exception("Unable to get lock on file " + mboxFile);
}
}
|
public static void | main(java.lang.String[] args)
// Test invocation
MBoxMailRepository mbx = new MBoxMailRepository();
mbx.mboxFile = "C:\\java\\test\\1998-05.txt";
Iterator mList = mbx.list();
while (mList.hasNext()) {
//String key = (String) mList.next();
//System.out.println("key=" + key);
/*MailImpl mi = mbx.retrieve(key);
try
{
System.out.println("Subject : " + (mi.getMessage()).getSubject());
}
catch (MessagingException e)
{
e.printStackTrace(); //To change body of catch statement use Options | File Templates.
} */
}
/* MailImpl mi = mbx.retrieve("ffffffb4ffffffe2f59fffffff291dffffffde4366243ffffff971d1f24");
try {
System.out.println("Subject : " + (mi.getMessage()).getSubject());
} catch (MessagingException e) {
e.printStackTrace(); //To change body of catch statement use Options | File Templates.
}
mbx.remove("ffffffb4ffffffe2f59fffffff291dffffffde4366243ffffff971d1f24");*/
|
private javax.mail.internet.MimeMessage | parseMboxFile(java.io.RandomAccessFile ins, org.apache.james.mailrepository.MBoxMailRepository$MessageAction messAct)Parse the mbox file.
if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
StringBuffer logBuffer =
new StringBuffer(128)
.append(this.getClass().getName())
.append(" Start parsing ")
.append(mboxFile);
getLogger().debug(logBuffer.toString());
}
try {
Perl5Compiler sepMatchCompiler = new Perl5Compiler();
Pattern sepMatchPattern = sepMatchCompiler.compile("^From (.*) (.*):(.*):(.*)$");
Perl5Matcher sepMatch = new Perl5Matcher();
int c;
boolean inMessage = false;
StringBuffer messageBuffer = new StringBuffer();
String previousMessageSeparator = null;
boolean foundSep = false;
long prevMessageStart = ins.getFilePointer();
if (BUFFERING) {
String line = null;
while ((line = ins.readLine()) != null) {
foundSep = sepMatch.contains(line + "\n", sepMatchPattern);
if (foundSep && inMessage) {
// if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
// getLogger().debug(this.getClass().getName() + " Invoking " + messAct.getClass() + " at " + prevMessageStart);
// }
MimeMessage endResult = messAct.messageAction(previousMessageSeparator, messageBuffer.toString(), prevMessageStart);
if (messAct.isComplete()) {
// I've got what I want so just exit
return endResult;
}
previousMessageSeparator = line;
prevMessageStart = ins.getFilePointer() - line.length();
messageBuffer = new StringBuffer();
inMessage = true;
}
// Only done at the start (first header)
if (foundSep && !inMessage) {
previousMessageSeparator = line.toString();
inMessage = true;
}
if (!foundSep && inMessage) {
messageBuffer.append(line).append("\n");
}
}
} else {
StringBuffer line = new StringBuffer();
while ((c = ins.read()) != -1) {
if (c == 10) {
foundSep = sepMatch.contains(line.toString(), sepMatchPattern);
if (foundSep && inMessage) {
// if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
// getLogger().debug(this.getClass().getName() + " Invoking " + messAct.getClass() + " at " + prevMessageStart);
// }
MimeMessage endResult = messAct.messageAction(previousMessageSeparator, messageBuffer.toString(), prevMessageStart);
if (messAct.isComplete()) {
// I've got what I want so just exit
return endResult;
}
previousMessageSeparator = line.toString();
prevMessageStart = ins.getFilePointer() - line.length();
messageBuffer = new StringBuffer();
inMessage = true;
}
// Only done at the start (first header)
if (foundSep && inMessage == false) {
previousMessageSeparator = line.toString();
inMessage = true;
}
if (!foundSep) {
messageBuffer.append(line).append((char) c);
}
line = new StringBuffer(); // Reset buffer
} else {
line.append((char) c);
}
}
}
if (messageBuffer.length() != 0) {
// process last message
return messAct.messageAction(previousMessageSeparator, messageBuffer.toString(), prevMessageStart);
}
} catch (IOException ioEx) {
getLogger().error("Unable to write file (General I/O problem) " + mboxFile, ioEx);
} catch (MalformedPatternException e) {
getLogger().error("Bad regex passed " + mboxFile, e);
} finally {
if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
StringBuffer logBuffer =
new StringBuffer(128)
.append(this.getClass().getName())
.append(" Finished parsing ")
.append(mboxFile);
getLogger().debug(logBuffer.toString());
}
}
return null;
|
public void | remove(org.apache.mailet.Mail mail)Remove an existing message
ArrayList remArray = new ArrayList();
remArray.add(mail);
remove(remArray);
|
public void | remove(java.util.Collection mails)Remove a list of messages from disk
The collection is simply a list of mails to delete
if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
StringBuffer logBuffer =
new StringBuffer(128)
.append(this.getClass().getName())
.append(" Removing entry for key ")
.append(mails);
getLogger().debug(logBuffer.toString());
}
// The plan is as follows:
// Attempt to locate the message in the file
// by reading through the
// once we've done that then seek to the file
try {
RandomAccessFile ins = new RandomAccessFile(mboxFile, "r"); // The source
final RandomAccessFile outputFile = new RandomAccessFile(mboxFile + WORKEXT, "rw"); // The destination
parseMboxFile(ins, new MessageAction() {
public boolean isComplete() { return false; }
public MimeMessage messageAction(String messageSeparator, String bodyText, long messageStart) {
// Write out the messages as we go, until we reach the key we want
try {
String currentKey=generateKeyValue(bodyText);
boolean foundKey=false;
Iterator mailList = mails.iterator();
String key;
while (mailList.hasNext()) {
// Attempt to find the current key in the array
key = ((Mail)mailList.next()).getName();
if (key.equals(currentKey)) {
// Don't write the message to disk
foundKey = true;
break;
}
}
if (foundKey == false)
{
// We didn't find the key in the array so we will keep it
outputFile.writeBytes(messageSeparator + "\n");
outputFile.writeBytes(bodyText);
}
} catch (NoSuchAlgorithmException e) {
getLogger().error("MD5 not supported! ",e);
} catch (IOException e) {
getLogger().error("Unable to write file (General I/O problem) " + mboxFile, e);
}
return null;
}
});
ins.close();
outputFile.close();
// Delete the old mbox file
File mbox = new File(mboxFile);
mbox.delete();
// And rename the lock file to be the new mbox
mbox = new File(mboxFile + WORKEXT);
if (!mbox.renameTo(new File(mboxFile)))
{
System.out.println("Failed to rename file!");
}
// Now delete the keys in mails from the main hash
Iterator mailList = mails.iterator();
String key;
while (mailList.hasNext()) {
// Attempt to find the current key in the array
key = ((Mail)mailList.next()).getName();
mList.remove(key);
}
} catch (FileNotFoundException e) {
getLogger().error("Unable to save(open) file (File not found) " + mboxFile, e);
} catch (IOException e) {
getLogger().error("Unable to write file (General I/O problem) " + mboxFile, e);
}
|
public void | remove(java.lang.String key)Remove a mail from the mbox file
loadKeys();
try {
lockMBox();
} catch (Exception e) {
getLogger().error("Lock failed!",e);
return; // No lock, so exit
}
ArrayList keys = new ArrayList();
keys.add(retrieve(key));
this.remove(keys);
unlockMBox();
|
public org.apache.mailet.Mail | retrieve(java.lang.String key)Get a message from the backing store (disk)
loadKeys();
MailImpl res = null;
try {
MimeMessage foundMessage = findMessage(key);
if (foundMessage == null) {
getLogger().error("found message is null!");
return null;
}
res = new MailImpl(foundMessage);
res.setName(key);
if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
StringBuffer logBuffer =
new StringBuffer(128)
.append(this.getClass().getName())
.append(" Retrieving entry for key ")
.append(key);
getLogger().debug(logBuffer.toString());
}
} catch (MessagingException e) {
getLogger().error("Unable to parse mime message for " + mboxFile + "\n" + e.getMessage(), e);
}
return res;
|
private javax.mail.internet.MimeMessage | selectMessage(java.lang.String key)Quickly find a message by using the stored message offsets
MimeMessage foundMessage = null;
// Can we find the key first
if (mList == null || !mList.containsKey(key)) {
// Not initiailised so no point looking
if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
StringBuffer logBuffer =
new StringBuffer(128)
.append(this.getClass().getName())
.append(" mList - key not found ")
.append(mboxFile);
getLogger().debug(logBuffer.toString());
}
return foundMessage;
}
long messageStart = ((Long) mList.get(key)).longValue();
if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
StringBuffer logBuffer =
new StringBuffer(128)
.append(this.getClass().getName())
.append(" Load message starting at offset ")
.append(messageStart)
.append(" from file ")
.append(mboxFile);
getLogger().debug(logBuffer.toString());
}
// Now try and find the position in the file
RandomAccessFile ins = null;
try {
ins = new RandomAccessFile(mboxFile, "r");
if (messageStart != 0) {
ins.seek(messageStart - 1);
}
MessageAction op = new MessageAction() {
public boolean isComplete() { return true; }
public MimeMessage messageAction(String messageSeparator, String bodyText, long messageStart) {
try {
if (key.equals(generateKeyValue(bodyText))) {
getLogger().debug(this.getClass().getName() + " Located message. Returning MIME message");
return convertTextToMimeMessage(bodyText);
}
} catch (NoSuchAlgorithmException e) {
getLogger().error("MD5 not supported! ",e);
}
return null;
}
};
foundMessage = this.parseMboxFile(ins, op);
} catch (FileNotFoundException e) {
getLogger().error("Unable to save(open) file (File not found) " + mboxFile, e);
} catch (IOException e) {
getLogger().error("Unable to write file (General I/O problem) " + mboxFile, e);
} finally {
if (foundMessage == null) {
if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
StringBuffer logBuffer =
new StringBuffer(128)
.append(this.getClass().getName())
.append(" select - message not found ")
.append(mboxFile);
getLogger().debug(logBuffer.toString());
}
}
if (ins != null) try { ins.close(); } catch (IOException e) { getLogger().error("Unable to close file (General I/O problem) " + mboxFile, e); }
}
return foundMessage;
|
public void | service(org.apache.avalon.framework.service.ServiceManager componentManager)
|
public void | store(org.apache.mailet.Mail mc)Store the given email in the current mbox file
if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
StringBuffer logBuffer =
new StringBuffer(128)
.append(this.getClass().getName())
.append(" Will store message to file ")
.append(mboxFile);
getLogger().debug(logBuffer.toString());
}
this.mList = null;
// Now make up the from header
String fromHeader = null;
String message = null;
try {
message = getRawMessage(mc.getMessage());
// check for nullsender
if (mc.getMessage().getFrom() == null) {
fromHeader = "From " + dy.format(Calendar.getInstance().getTime());
} else {
fromHeader = "From " + mc.getMessage().getFrom()[0] + " " + dy.format(Calendar.getInstance().getTime());
}
} catch (IOException e) {
getLogger().error("Unable to parse mime message for " + mboxFile, e);
} catch (MessagingException e) {
getLogger().error("Unable to parse mime message for " + mboxFile, e);
}
// And save only the new stuff to disk
RandomAccessFile saveFile = null;
try {
saveFile = new RandomAccessFile(mboxFile, "rw");
saveFile.seek(saveFile.length()); // Move to the end
saveFile.writeBytes((fromHeader + "\n"));
saveFile.writeBytes((message + "\n"));
saveFile.close();
} catch (FileNotFoundException e) {
getLogger().error("Unable to save(open) file (File not found) " + mboxFile, e);
} catch (IOException e) {
getLogger().error("Unable to write file (General I/O problem) " + mboxFile, e);
}
|
public boolean | unlock(java.lang.String key)Not implemented
return false;
|
private void | unlockMBox()Unlock a previously locked mbox file
// Just delete the MBOX file
String lockFileName = mboxFile + LOCKEXT;
File mBoxLock = new File(lockFileName);
if (!mBoxLock.delete()) {
StringBuffer logBuffer =
new StringBuffer(128)
.append(this.getClass().getName())
.append(" Failed to delete lock file ")
.append(lockFileName);
getLogger().error(logBuffer.toString());
}
|