Hi Philip, i opened a bug report:
http://issues.apache.org/jira/browse/JAMES-744 Thx for reporting. bye Norman Philip Tomlinson schrieb: > Hi, > > I think I've answered my own question and discovered a bug with > MBoxMailRepository and a fix is below. > > Line 283 > was: > prevMessageStart = ins.getFilePointer() - line.length() ; > should be: > prevMessageStart = ins.getFilePointer() - line.length() - 2; > This is the case because we need to subtract -1 to back up in front of > the character we are looking for and -1 because the readLine doesnt > return the carriage return > Now the preMessageStart points to the F character in the pattern From > ....... > > and line 413 > was: > ins.seek(messageStart -1); > should be: > ins.seek(messageStart ); > Given that the messageStart now points at the F character there is no > longer a need to back up one character. > > The full file is attached. > > Now I can parse Thunderbird mail files without a problem > > Rgds, > Phil > >> I've been trying to use the MBoxMailRepository to parse a Thunderbird >> mail file. >> It doesnt seem to work propely. (After loading the messages, the >> retrieve operation quite often doesnt return a message for a key). >> >> Is this because the MBoxMailRepository class doesnt support mboxrd? >> > ------------------------- > Email: [EMAIL PROTECTED] > > > ------------------------------------------------------------------------ > > /**************************************************************** > * 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. * > ****************************************************************/ > > > > /* TODO: > * > * 1. Currently, iterating through the message collection does not > * preserve the order in the file. Change this with some form of > * OrderedMap. There is a suitable class in Jakarta Commons > * Collections. > * > * 2. Optimize the remove operation. > * > * 3. Don't load entire message into memory. This would mean computing > * the hash during I/O streaming, rather than loading entire message > * into memory, and using a MimeMessageWrapper with a suitable data > * source. As a strawman, the interface to MessageAction would > * carry the hash, along with a size-limited stream providing the > * message body. > * > * 4. Decide what to do when there are IDENTICAL messages in the file. > * Right now only the last one will ever be processed, due to key > * collissions. > * > * 5. isComplete() - DONE. > * > * 6. Buffered I/O. - Partially done, and optional. > * > */ > > package org.apache.james.mailrepository; > > import org.apache.avalon.framework.configuration.Configurable; > import org.apache.avalon.framework.configuration.Configuration; > import org.apache.avalon.framework.configuration.ConfigurationException; > import org.apache.avalon.framework.logger.AbstractLogEnabled; > import org.apache.james.core.MailImpl; > import org.apache.james.services.MailRepository; > import org.apache.mailet.Mail; > import org.apache.oro.text.regex.MalformedPatternException; > import org.apache.oro.text.regex.Perl5Compiler; > import org.apache.oro.text.regex.Pattern; > import org.apache.oro.text.regex.Perl5Matcher; > > import javax.mail.MessagingException; > import javax.mail.Session; > import javax.mail.internet.MimeMessage; > > import java.io.ByteArrayInputStream; > import java.io.ByteArrayOutputStream; > import java.io.File; > import java.io.FileNotFoundException; > import java.io.IOException; > import java.io.RandomAccessFile; > import java.security.NoSuchAlgorithmException; > import java.security.MessageDigest; > import java.text.SimpleDateFormat; > import java.util.ArrayList; > import java.util.Calendar; > import java.util.Collection; > import java.util.Collections; > import java.util.Hashtable; > import java.util.Iterator; > import java.util.Locale; > import java.util.Properties; > import java.util.Vector; > > /** > * Implementation of a MailRepository using UNIX mbox files. > * > * <p>Requires a configuration element in the .conf.xml file of the form: > * <br><repository destinationURL="mbox://<directory>" > * <br> type="MAIL" > * <br></directory> is where the individual mbox files are read > from/written to > * <br>Type can ONLY be MAIL (SPOOL is NOT supported) > * > * <p>Requires a logger called MailRepository. > * > * <p> Implementation notes: > * <p> > * This class keeps an internal store of the mbox file > * When the internal mbox file is updated (added/deleted) > * then the file will be re-read from disk and then written back. > * This is a bit inefficent but means that the file on disk > * should be correct. > * <p> > * The mbox store is mainly meant to be used as a one-way street. > * Storing new emails is very fast (append to file) whereas reading them (via > POP3) is > * slower (read from disk and parse). > * Therefore this implementation is best suited to people who wish to use the > mbox format > * for taking data out of James and into something else (IMAP server or mail > list displayer) > * > * @version CVS $Revision: 453945 $ > */ > > > public class MBoxMailRepository > extends AbstractLogEnabled > implements MailRepository, Configurable { > > > static final SimpleDateFormat dy = new SimpleDateFormat("EE MMM dd > HH:mm:ss yyyy", Locale.US); > static final String LOCKEXT = ".lock"; > static final String WORKEXT = ".work"; > static final int LOCKSLEEPDELAY = 2000; // 2 second back off in the event > of a problem with the lock file > static final int MAXSLEEPTIMES = 100; // > static final long MLISTPRESIZEFACTOR = 10 * 1024; // The hash table will > be loaded with a initial capacity of filelength/MLISTPRESIZEFACTOR > static final long DEFAULTMLISTCAPACITY = 20; // Set up a hashtable to > have a meaningful default > > /** > * Whether line buffering is turned used. > */ > private static boolean BUFFERING = true; > > /** > * Whether 'deep debugging' is turned on. > */ > private static final boolean DEEP_DEBUG = true; > > /** > * The internal list of the emails > * The key is an adapted MD5 checksum of the mail > */ > private Hashtable mList = null; > /** > * The filename to read & write the mbox from/to > */ > private String mboxFile; > > private boolean fifo; > > /** > * A callback used when a message is read from the mbox file > */ > public interface MessageAction { > public boolean isComplete(); // *** Not valid until AFTER each call > to messageAction(...)! > public MimeMessage messageAction(String messageSeparator, String > bodyText, long messageStart); > } > > > /** > * Convert a MimeMessage into raw text > * @param mc The mime message to convert > * @return A string representation of the mime message > * @throws IOException > * @throws MessagingException > */ > private String getRawMessage(MimeMessage mc) throws IOException, > MessagingException { > > ByteArrayOutputStream rawMessage = new ByteArrayOutputStream(); > mc.writeTo(rawMessage); > return rawMessage.toString(); > } > > /** > * Parse a text block as an email and convert it into a mime message > * @param emailBody The headers and body of an email. This will be parsed > into a mime message and stored > */ > private MimeMessage convertTextToMimeMessage(String emailBody) { > //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; > } > > /** > * Generate a hex representation of an MD5 checksum on the emailbody > * @param emailBody > * @return A hex representation of the text > * @throws NoSuchAlgorithmException > */ > private String generateKeyValue(String emailBody) throws > NoSuchAlgorithmException { > // 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(); > } > > /** > * Parse the mbox file. > * @param ins The random access file to load. Note that the file may or > may not start at offset 0 in the file > * @param messAct The action to take when a message is found > */ > private MimeMessage parseMboxFile(RandomAccessFile ins, MessageAction > messAct) { > 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() - > 2; > 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; > } > > /** > * 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 > * > * @param key The key of the message to find > */ > private MimeMessage findMessage(String key) { > 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; > } > > /** > * Quickly find a message by using the stored message offsets > * @param key The key of the message to find > */ > private MimeMessage selectMessage(final String key) { > 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 ); > } > 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; > } > > /** > * Load the message keys and file pointer offsets from disk > */ > private synchronized void loadKeys() { > 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); } > } > } > > > /** > * @see org.apache.james.services.MailRepository#store(Mail) > */ > public void store(Mail mc) { > > 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); > } > } > > > /** > * @see org.apache.james.services.MailRepository#list() > */ > public Iterator list() { > loadKeys(); > ArrayList keys = new ArrayList(mList.keySet()); > > if (keys.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) keys.iterator().next()); > } > if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) { > StringBuffer logBuffer = > new StringBuffer(128) > .append(this.getClass().getName()) > .append(" ") > .append(keys.size()) > .append(" keys to be iterated over."); > > getLogger().debug(logBuffer.toString()); > } > if (fifo) Collections.sort(keys); // Keys is a HashSet; impose FIFO > for apps that need it > return keys.iterator(); > } > > /** > * @see org.apache.james.services.MailRepository#retrieve(String) > */ > public Mail retrieve(String key) { > > 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; > } > > /** > * @see org.apache.james.services.MailRepository#remove(Mail) > */ > public void remove(Mail mail) { > // Convert the message into a key > Vector delVec = new Vector(); > delVec.addElement(mail); > remove(delVec); > } > > /** > * Attempt to get a lock on the mbox by creating > * the file mboxname.lock > * @throws Exception > */ > private void lockMBox() throws Exception { > // 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); > } > } > } > > /** > * Unlock a previously locked mbox file > */ > private void unlockMBox() { > // 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()); > } > } > > > > /** > * @see org.apache.james.services.MailRepository#remove(Collection) > */ > public void remove(final Collection mails) > { > 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); > } > } > > /** > * @see org.apache.james.services.MailRepository#remove(String) > */ > public void remove(String key) { > loadKeys(); > try { > lockMBox(); > } catch (Exception e) { > getLogger().error("Lock failed!",e); > return; // No lock, so exit > } > ArrayList keys = new ArrayList(); > keys.add(key); > > this.remove(keys); > unlockMBox(); > } > > /** > * @see org.apache.james.services.MailRepository#lock(String) > */ > public boolean lock(String key) { > return false; > } > > /** > * @see org.apache.james.services.MailRepository#unlock(String) > */ > public boolean unlock(String key) { > return false; > } > > /** > * @see > org.apache.avalon.framework.configuration.Configurable#configure(Configuration) > */ > public void configure(Configuration conf) throws ConfigurationException { > String destination; > this.mList = null; > BUFFERING = conf.getAttributeAsBoolean("BUFFERING", true); > fifo = conf.getAttributeAsBoolean("FIFO", false); > 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); > } > } > > } > > > ------------------------------------------------------------------------ > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]