/*
* $Id: SimpleMessageListenerAdapter.java 337 2009-06-29 19:20:58Z latchkey $
* $URL: http://subethasmtp.googlecode.com/svn/trunk/src/main/java/org/subethamail/smtp/helper/SimpleMessageListenerAdapter.java $
*/
package org.subethamail.smtp.helper;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.subethamail.smtp.MessageContext;
import org.subethamail.smtp.MessageHandler;
import org.subethamail.smtp.MessageHandlerFactory;
import org.subethamail.smtp.RejectException;
import org.subethamail.smtp.TooMuchDataException;
import org.subethamail.smtp.io.DeferredFileOutputStream;
/**
* MessageHandlerFactory implementation which adapts to a collection of
* MessageListeners. This allows us to preserve the old, convenient
* interface.
*
* @author Jeff Schnitzer
*/
public class SimpleMessageListenerAdapter implements MessageHandlerFactory
{
/**
* 5 megs by default. The server will buffer incoming messages to disk
* when they hit this limit in the DATA received.
*/
private static int DEFAULT_DATA_DEFERRED_SIZE = 1024*1024*5;
private Collection<SimpleMessageListener> listeners;
private int dataDeferredSize;
/**
* Initializes this factory with a single listener.
*
* Default data deferred size is 5 megs.
*/
public SimpleMessageListenerAdapter(SimpleMessageListener listener)
{
this(Collections.singleton(listener), DEFAULT_DATA_DEFERRED_SIZE);
}
/**
* Initializes this factory with the listeners.
*
* Default data deferred size is 5 megs.
*/
public SimpleMessageListenerAdapter(Collection<SimpleMessageListener> listeners)
{
this(listeners, DEFAULT_DATA_DEFERRED_SIZE);
}
/**
* Initializes this factory with the listeners.
* @param dataDeferredSize The server will buffer
* incoming messages to disk when they hit this limit in the
* DATA received.
*/
public SimpleMessageListenerAdapter(Collection<SimpleMessageListener> listeners, int dataDeferredSize)
{
this.listeners = listeners;
this.dataDeferredSize = dataDeferredSize;
}
/* (non-Javadoc)
* @see org.subethamail.smtp.MessageHandlerFactory#create(org.subethamail.smtp.MessageContext)
*/
public MessageHandler create(MessageContext ctx)
{
return new Handler(ctx);
}
/**
* Needed by this class to track which listeners need delivery.
*/
static class Delivery
{
SimpleMessageListener listener;
public SimpleMessageListener getListener() { return this.listener; }
String recipient;
public String getRecipient() { return this.recipient; }
public Delivery(SimpleMessageListener listener, String recipient)
{
this.listener = listener;
this.recipient = recipient;
}
}
/**
* Class which implements the actual handler interface.
*/
class Handler implements MessageHandler
{
MessageContext ctx;
String from;
List<Delivery> deliveries = new ArrayList<Delivery>();
/** */
public Handler(MessageContext ctx)
{
this.ctx = ctx;
}
/** */
public void from(String from) throws RejectException
{
this.from = from;
}
/** */
public void recipient(String recipient) throws RejectException
{
boolean addedListener = false;
for (SimpleMessageListener listener: SimpleMessageListenerAdapter.this.listeners)
{
if (listener.accept(this.from, recipient))
{
this.deliveries.add(new Delivery(listener, recipient));
addedListener = true;
}
}
if (!addedListener)
throw new RejectException(553, "<" + recipient + "> address unknown.");
}
/** */
public void data(InputStream data) throws TooMuchDataException, IOException
{
if (this.deliveries.size() == 1)
{
Delivery delivery = this.deliveries.get(0);
delivery.getListener().deliver(this.from, delivery.getRecipient(), data);
}
else
{
DeferredFileOutputStream dfos = new DeferredFileOutputStream(SimpleMessageListenerAdapter.this.dataDeferredSize);
try
{
int value;
while ((value = data.read()) >= 0)
{
dfos.write(value);
}
for (Delivery delivery: this.deliveries)
{
delivery.getListener().deliver(this.from, delivery.getRecipient(), dfos.getInputStream());
}
}
finally
{
dfos.close();
}
}
}
/** */
public void done()
{
}
}
}