package org.gjt.bugrat.servlet;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;
import javax.mail.*;
import javax.mail.internet.*;
import org.gjt.mail.EnhancedMimeMsg;
import org.gjt.bugrat.util.BugRatLogger;
public
class MailQueueThread
extends Thread
{
private static MailQueueThread instance = null;
private boolean done = false;
private boolean debug = false;
private Date startTime = null;
private Date lastMsgMailed = null;
private Session mailSession = null;
private String transport = null;
private String mailHostName = null;
private String adminAddress = null;
private Vector mailQueue = null;
private Vector exceptions = null;
private int numMsgsFailed = 0;
private int numMsgsMailed = 0;
private String lineTerm = "\n";
private SimpleDateFormat dateFmt = null;
private BugRatLogger logger = null;
private
MailQueueThread(
String transport,
String mailHostName,
String adminAddr,
BugRatLogger logger )
{
super();
Properties mailProps = new Properties();
mailProps.put( "mail.host", mailHostName );
mailProps.put( "mail.transport.protocol", transport );
javax.mail.Authenticator mailAuth = this.new MQAuth();
this.mailSession = Session.getInstance( mailProps, mailAuth );
this.logger = logger;
this.transport = transport;
this.mailHostName = mailHostName;
this.adminAddress = adminAddr;
this.numMsgsFailed = 0;
this.numMsgsMailed = 0;
this.mailQueue = new Vector();
this.exceptions = new Vector();
this.lineTerm =
System.getProperty( "line.separator", "\n" );
this.dateFmt =
new SimpleDateFormat
( "EEEE, hh:mm:ss a zzz, MM.dd.yyyy" );
}
public static MailQueueThread
establishMailQueue(
String transport,
String mailHostName,
String adminAddr,
BugRatLogger logger )
{
if ( MailQueueThread.instance == null )
{
MailQueueThread.instance =
new MailQueueThread
( transport, mailHostName, adminAddr, logger );
MailQueueThread.instance.startTime = new Date();
MailQueueThread.instance.start();
}
return MailQueueThread.instance;
}
public synchronized void
shutdown()
{
this.done = true;
// UNDONE - We need to store and retrieve unmailed jobs!
this.notify();
}
public String
getTransportName()
{
return this.transport;
}
public String
getMailHostname()
{
return this.mailHostName;
}
public String
getAdminAddress()
{
return this.adminAddress;
}
public synchronized Date
getStartTime()
{
return this.startTime;
}
public synchronized int
getNumMessagesFailed()
{
return this.numMsgsFailed;
}
public synchronized int
getNumMessagesMailed()
{
return this.numMsgsMailed;
}
public synchronized Enumeration
getMessageExceptions()
{
return this.exceptions.elements();
}
public synchronized Date
getLastMailTime()
{
return this.lastMsgMailed;
}
public int
getQueueSize()
{
int result = 0;
synchronized ( this.mailQueue )
{
result = this.mailQueue.size();
}
return result;
}
public void
run()
{
if ( this.logger != null )
this.logger.log( "MailQueue thread started." );
for ( ; ; )
{
synchronized ( this )
{
if ( this.done )
break;
}
MailJob nextJob = null;
synchronized ( this.mailQueue )
{
if ( this.mailQueue.size() > 0 )
{
nextJob = (MailJob) this.mailQueue.elementAt(0);
this.mailQueue.removeElementAt(0);
}
}
if ( nextJob != null )
{
try {
nextJob.sendMessage( this.mailSession );
synchronized ( this )
{
this.lastMsgMailed = new Date();
this.numMsgsMailed++;
}
}
catch ( MessagingException ex )
{
this.numMsgsFailed++;
if ( this.exceptions.size() > 10 )
{
this.exceptions.removeElementAt
( this.exceptions.size() - 1 );
}
StringWriter sW = new StringWriter();
PrintWriter pW = new PrintWriter( sW );
ex.printStackTrace( pW );
pW.close();
String tstamp =
this.dateFmt.format( new Date() );
String exStr =
"<B>" + ex.getMessage() + "</B><br>"
+ this.lineTerm
+ tstamp + "<br>"
+ this.lineTerm
+ "<pre>" + sW.toString() + "</pre>";
this.exceptions.insertElementAt( exStr, 0 );
if ( this.logger != null )
this.logger.log( "sending message", ex );
}
}
synchronized ( this )
{
if ( this.done )
break;
try { this.wait( 60 * 1000 ); }
catch ( InterruptedException ex )
{
this.logger.log( "while waiting...", ex );
}
}
}
if ( this.logger != null )
this.logger.log( "MailQueue thread terminated." );
}
public void
addMailJob( String subject, String body, String to, String cc )
throws MessagingException
{
this.addMailJob( subject, body, null, to, cc );
}
public void
addMailJob( String subject, String body, String from, String to, String cc )
throws MessagingException
{
this.addMailJob( subject, body, from, to, cc, null );
}
public void
addMailJob(
String subject, String body, String from,
String to, String cc, Vector attach )
throws MessagingException
{
InternetAddress[] toAddrs =
(to == null)
? null
: InternetAddress.parse( to );
InternetAddress[] ccAddrs =
(cc == null)
? null
: InternetAddress.parse( cc );
InternetAddress fromAddr =
(from == null)
? null
: InternetAddress.parse( from )[0]; // UNDONE I don't like that code.
this.addMailJob( subject, body, fromAddr, toAddrs, ccAddrs, attach );
}
public void
addMailJob( String subject, String body, Address[] to, Address[] cc )
{
this.addMailJob( subject, body, null, to, cc );
}
public void
addMailJob( String subject, String body, Address from, Address[] to, Address[] cc )
{
MailJob job =
this.new MailJob( subject, body, from, to, cc, null );
synchronized ( this.mailQueue )
{
this.mailQueue.addElement( job );
}
synchronized ( this )
{
this.notify();
}
}
public void
addMailJob(
String subject, String body, Address from,
Address[] to, Address[] cc, Vector attach )
{
MailJob job =
this.new MailJob( subject, body, from, to, cc, attach );
synchronized ( this.mailQueue )
{
this.mailQueue.addElement( job );
}
synchronized ( this )
{
this.notify();
}
}
private
class MailJob
{
String subject = null;
String msgBody = null;
Address fromAddr = null;
Address[] toAddr = null;
Address[] ccAddr = null;
Vector attach = null;
public
MailJob(
String subject, String msgBody, Address fromAddr,
Address[] toAddr, Address[] ccAddr, Vector attach )
{
this.subject = subject;
this.msgBody = msgBody;
this.fromAddr = fromAddr;
this.toAddr = toAddr;
this.ccAddr = ccAddr;
this.attach = attach;
}
public void
sendMessage( Session sess )
throws MessagingException
{
if ( this.fromAddr == null )
{
try {
this.fromAddr = new InternetAddress
( adminAddress, "BugRat Mail System" );
}
catch ( UnsupportedEncodingException ex )
{
throw new MessagingException
( "error creating From address, " + ex.getMessage() );
}
}
EnhancedMimeMsg msg = new EnhancedMimeMsg( sess );
msg.buildMimeMessage
( this.fromAddr, this.fromAddr,
this.toAddr, this.ccAddr, null,
this.subject, this.msgBody, attach );
Transport.send( msg );
}
}
private
class MQAuth
extends javax.mail.Authenticator
{
public
MQAuth()
{
}
public PasswordAuthentication
getPasswordAuthentication()
{
return new PasswordAuthentication( "", "" );
}
}
}