| MailTransportService.java |
/*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.net.axis.transport.mailto.server;
import javax.mail.Flags;
import javax.mail.Message;
import javax.mail.MessagingException;
import org.apache.axis.AxisEngine;
import org.apache.axis.AxisFault;
import org.apache.axis.MessageContext;
import org.apache.axis.server.AxisServer;
import org.jboss.net.axis.server.JMXEngineConfigurationFactory;
import org.jboss.net.axis.transport.mailto.server.MailTransportServiceMBean;
import org.jboss.net.axis.transport.mailto.AbstractMailTransportService;
import org.jboss.net.axis.transport.mailto.MailConstants;
/**
* <dl>
* <dt><b>Title: </b><dd>Mail Transport MBean</dd>
* <p>
* <dt><b>Description: </b>
* <dd>
* <p>This MBean is the service that polls the mail box (pop/imap) and processes any soap messages it finds there.
*
* <p> To define a mail transport and the transport level handlers, the jboss-net.sar/server-config.wsdd file must be
* modified to include:
* <pre>
* <transport name="mail">
* <requestFlow>
* <handler type="java:org.jboss.net.axis.transport.mail.server.handler.TargetServiceHandler"/>
* </requestFlow>
* <responseFlow>
* <!-- response flow specific handlers can go here -->
* </responseFlow>
* </transport>
* </pre>
*
* <p>To enable this service edit the jboss-net.sar/META-INF/jboss-service.xml file to include :
* <pre>
* <mbean code="org.jboss.net.axis.transport.mailto.server.MailTransportService"
* name="jboss.net:service=MailTransport">
* <depends>jboss.net:service=Axis</depends>
* <attribute name="SessionName">java:/Mail</attribute>
* <attribute name="FolderName">INBOX</attribute>
* <attribute name="TransportName">mail</attribute>
* <attribute name="EngineName">jboss.net:service=Axis</attribute>
* <attribute name="DeleteMail">true</attribute>
* </mbean>
* </pre>
*
* <p> If you don't want to hammer on the pollMail button from the mbean interface (jmx|web-console) then it would be
* best to set up a schedule to do it for you (again in the jboss-service.xml file:
* <pre>
* <mbean code="org.jboss.varia.scheduler.Scheduler"
* name="jboss.net:service=Scheduler,name=MailTransport">
* <attribute name="StartAtStartup">true</attribute>
* <attribute name="SchedulableMBean">jboss.net:service=MailTransport</attribute>
* <attribute name="SchedulableMBeanMethod">pollMail()</attribute>
* <attribute name="InitialStartDate">NOW</attribute>
* <attribute name="SchedulePeriod">30000</attribute>
* <attribute name="InitialRepetitions">-1</attribute>
* </mbean>
* </pre>
*
* <p> This transport assumes the use of <a href="http://ws.apache.org/ws-fx/addressing/">ws-addressing</a>
* handlers and as such has no provision for sending a response. The addressing handler will create a new call
* with the response if there is a wsa:Reply-To header. Otherwise the response will disappear into the ether
* with nary a log entry.
*
* </dd>
* </dl>
* @author <a href="mailto:jasone@greenrivercomputing.com">Jason Essington</a>
* @version $Revision: 1.2 $
*
* @jboss.service
* servicefile="jboss"
*
* @jmx.mbean
* name="jboss.net:service=MailTransport"
* description="email transport for soap messages"
* extends="org.jboss.net.axis.transport.mailto.AbstractMailTransportServiceMBean"
*
*/
public class MailTransportService extends AbstractMailTransportService implements MailTransportServiceMBean,
MailConstants
{
// members
private AxisServer server = null;
private String transportName = "mailto";
/**
* @return The name this transport has been given.
*
* @jmx.managed-attribute
* description="the name of the transport for email messages"
* value="mailto"
*/
public String getTransportName()
{
return this.transportName;
}
/**
* @param name The name this transport will be known as (smtp for instance).
*
* @jmx.managed-attribute
*/
public void setTransportName(String name)
{
this.transportName = name;
}
/** override AxisServlet.getEngine() in order to redirect to
* the corresponding AxisEngine.
*
* This is taken pretty much verbatem from the AxisServiceServlet
*/
public AxisServer getEngine() throws AxisFault
{
if (server == null)
{
try
{
server = JMXEngineConfigurationFactory.newJMXFactory(getEngineName()).getAxisServer();
}
catch (NullPointerException e)
{
throw new AxisFault("Could not access JMX configuration factory.", e);
}
}
return server;
}
/* (non-Javadoc)
* @see org.jboss.net.axis.transport.mail.AbstractMailTransportService#processMessages(javax.mail.Message[])
*/
protected void processMessages(Message[] msgs)
{
// iterate over all the messages processing them in turn.
for (int i = 0; i < msgs.length; i++)
{
processMessage(msgs[i]);
/*
* we will need to delete the request messages in all cases
* otherwise the inbox will just pile up with the messages that could not
* be processed.
*
* if deleteMail is set to false then the server will respond to any valid messages repeatedly!
* perhaps we should have a persistent way to remember which messages we have processed?
*/
if (getDeleteMail())
{
try
{
msgs[i].setFlag(Flags.Flag.DELETED, true);
}
catch (MessagingException e1)
{
log.warn("Unable to flag the message for deletion.", e1);
}
}
}
}
/**
* Creates a message context that will be used while processing this request.
*
* @param engine Server engine
* @param msg Email message
* @return
* @throws AxisFault
*/
protected MessageContext createMessageContext(AxisEngine engine, Message msg)
throws AxisFault
{
MessageContext msgCtx = new MessageContext(engine);
// set the transport
msgCtx.setTransportName(transportName);
// NOTE the axis servlet adds lot's more stuff than this to the message context, maybe we should too?
return msgCtx;
}
/**
* Serialize the email message body into a SOAPMessage.
* @param mc MessageContext that will be used while processing this message
* @param msg Email Message
* @throws AxisFault if we need to abort this message (drop the context and delete the email message
* with out sending a response message.)
*/
protected void processMessageBody(MessageContext mc, Message msg) throws AxisFault
{
String msgNS = null;
try
{
org.apache.axis.Message soapMsg = new org.apache.axis.Message(msg.getInputStream(), false, msg
.getContentType(), null);
mc.setRequestMessage(soapMsg);
}
catch (Exception e)
{
log.warn("This message doesn't appear to be a SOAP Message,", e);
}
}
/**
* @param ctx MessageContext that is being used for processing this request
* @param msg Email message that is theoretically holding a SOAP request.
* @return The value of the first Message-ID header found.
*/
protected String processHeaders(MessageContext ctx, Message msg) throws AxisFault
{
// over ride this method if you need to do something funky with
// the headers of the email message.
String msgID = null;
try
{
String[] msgIDs = msg.getHeader(HEADER_MESSAGE_ID);
if (msgIDs != null && msgIDs.length > 0)
{
msgID = msgIDs[0];
}
}
catch (MessagingException e)
{
throw new AxisFault("Unable to process mail headers.", e);
}
return msgID;
}
/**
* Does the actual work of making the incoming request suitable to send off to the axis engine.
*
* @param msg incoming email message.
*/
private void processMessage(Message msg)
//private Message processMessage(Message msg)//, Session mail, Folder folder)
{
org.apache.axis.MessageContext sMsgCtx = null;
org.apache.axis.Message sResMsg = null;
try
{
// create a new soap message context
sMsgCtx = createMessageContext(getEngine(), msg);
// wsa can worry about the headers
String msgID = processHeaders(sMsgCtx, msg);
// decide if the body of our email is a soap envelope
processMessageBody(sMsgCtx, msg);
archiveMessage(msgID, sMsgCtx);
// send it all off to the Axis Server
if (log.isDebugEnabled())
log.debug("Invoking Axis Server.");
getEngine().invoke(sMsgCtx);
if (log.isDebugEnabled())
log.debug("Return from Axis Server.");
}
catch (AxisFault e)
{
// There is not much we can do here since we don't have the ability to send email
// any faults that happened after engine.invoke should be handled by the addressingHandler's onFault() method.
// any faults that happend prior to that will just be logged.
log.fatal("The email message number "+msg.getMessageNumber()+" caused an AxisFault:",e);
}
}
/**
* Override this method if you need to store incoming messages.<br>
* Note: If web service security handlers are in the handler chain,
* the message will not have been verified/decrypted yet.
* @param msgID
* @param msgCtx
*/
protected void archiveMessage(String msgID, MessageContext msgCtx)
{
}
}
| MailTransportService.java |