You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by Oki DZ <ok...@pindad.com> on 2001/09/27 05:31:39 UTC

Turning mailets into Avalon components

Hi,

I think it would be nice if James mailets can be changed into Avalon
components. By doing so, you could get access to the might be useful
components from Excalibur or Cornerstone from your mailets. I don't think
there would be many changes in James, all you need is to have
GenericMailet to extend AbstractLoggable and implement Component, and also
some lines in the JamesSpoolManager like in the following:  (the "if
(mailet instanceof Component)" might not be needed). 

try {
   mailet = mailetLoader.getMailet(mailetClassName, mailetcontext,c);
   if (mailet instanceof Component) {
      if (mailet instanceof AbstractLoggable) {
         ((GenericMailet) mailet).setLogger(getLogger());
      } 
      if (mailet instanceof Composable) {
         ((Composable) mailet).compose(compMgr);
      } 
      if (mailet instanceof Initializable) {
         ((Initializable) mailet).initialize();
      }
   } 
   getLogger().info("Mailet " + mailetClassName + " instantiated");
} catch (MessagingException ex) {
   // ...
}

The init() method in the mailets can be replaced by initialize(), but the
init() signature should be left there (it is invoked by
mailetLoader.getMailet()). But since the code changes in
JamesSpoolRepository tests whether the mailet is a Component or not, the
current mailets (which are not Component) would work as they should be.

The following is a mailet which stores some information of a message into
a database table; could be useful if you want to have some statistics of
your email users.

As I understand it, the latest James already uses JdbcDataSource, so the
componentManager.lookup() below can be changed to use the interface (role)
of the block where the latest James gets the JdbcDataSource from. And
also, it would be nicer if the SQL statement used is retrieved from the
SQL repository. 

public class StoreSenderAndRecipients extends GenericMailet 
implements Composable, Initializable { 

    private String sender;
    private String recipients;
    private String remoteAddr;
    private int size;

    private JdbcDataSource dataSource;
    private DataSourceSelector dataSourceSelector;
    private String storeSQL;
    private JdbcConnection conn;
    private PreparedStatement ps;

    public StoreSenderAndRecipients() {}

    public void compose(ComponentManager componentManager)
	throws ComponentException {

	dataSourceSelector = (DataSourceSelector)

componentManager.lookup("com.pindad.james.services.DataSourceSelector");
  	getLogger().debug(getClass().getName() +
".compose(ComponentManager): " +
  			  "Composed");
    }

    public void initialize() throws Exception {
	    dataSource = (JdbcDataSource)
dataSourceSelector.select("mailetsource");
	    storeSQL = 
		"insert into SenderRecipients (sender, recipients,
remote_addr, size) " +
		"values (?, ?, ?, ?)";
	    conn = (JdbcConnection) dataSource.getConnection();
	    ps = conn.prepareStatement(storeSQL);
	    getLogger().debug(getClass().getName() + ".initialize():
Initialized");
    }

    public void init() {
    }

    public void service(Mail mail) throws MessagingException {
	MimeMessage message = mail.getMessage();
	size = message.getSize();
	MailImpl mc = (MailImpl) mail;
	sender = mc.getSender().toString();
	remoteAddr = mc.getRemoteAddr();
	StringBuffer buff = new StringBuffer();
	Collection rcpts = mc.getRecipients();
	for (Iterator i = rcpts.iterator(); i.hasNext();) {
	    String address = ((MailAddress) i.next()).toString();
	    buff.append(address + " ");
	}
	recipients = buff.toString();
//	System.out.println("Sender: " + sender);
//	System.out.println("Recipients: " + recipients);
//	System.out.println("Size: " + size);

	try {
	    ps.setString(1, sender);
	    ps.setString(2, recipients);
	    ps.setString(3, remoteAddr);
	    ps.setInt(4, size);
	    ps.execute();
	} catch(SQLException sqe) {
	    getLogger().error(getClass().getName() + ".service(Mail): " + 
			      sqe.getMessage());
	}
    }

    public void finalize() {
	try {
	    conn.close();
	} catch(Exception e) {
	    getLogger().error(getClass().getName() + ".finalize(): " +
e.getMessage());
	}
    }

    public String getMailetInfo() {
	return getClass().getName();
    }
}  

Just some ideas of improvement (I think),
Oki
ps: Could be nicer if matchers are Components too; say, you'd like to have
your own spam blackhole matcher based on a database table; which could be
neat, because you don't have to restart James to have it in effect.


---------------------------------------------------------------------
To unsubscribe, e-mail: james-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: james-dev-help@jakarta.apache.org


Re: Turning mailets into Avalon components

Posted by Serge Knystautas <se...@lokitech.com>.
----- Original Message -----
From: "Oki DZ" <ok...@pindad.com>


> > The RemoteDelivery mailet already grabs Avalon resources, which it does
> > by grabbing a ComponentManager from a MailetContext attribute.  Seems
> > like this approach could give you similar access to Jdbc sources or
> > whatever.  I plan to rewrite the Town alias and Town listserv without
> > Town (using the internal jdbc datasource), and I'll see if I can figure
> > a nice way to get these to work.
>
> Yes please; basically, all I need is to have an easy way to get a
> reference to Avalon's ComponentManager from my matchers/mailets. Well, I
> want to make sure that the compose() or initialize() methods in the
> mailets would get invoked too...

Again, check the RemoteDelivery mailet.  In one line it gets an instance of
Avalon's ComponentManager... it's very easy.  The JDBCAlias mailet also
grabs a DB connection, but I haven't resolved how to get the base directory
just yet.  I started moving towards your first idea of optionally making
mailets contextualizable/etc., but I'm still trying to figure a way to avoid
that.

Serge Knystautas
Loki Technologies
http://www.lokitech.com/


---------------------------------------------------------------------
To unsubscribe, e-mail: james-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: james-dev-help@jakarta.apache.org


Re: Turning mailets into Avalon components

Posted by Oki DZ <ok...@pindad.com>.
On Thu, 27 Sep 2001, Serge Knystautas wrote:
> I don't like making the mailet API tied to the Avalon structure.  I'm
> hoping mailets and matchers can eventually become used enough that other
> mail server engines start supporting them. 

Think about James mailets which would have reached the critical-mass
sometime in the future... in effect, developers would write mail-servers
based on Avalon. You'd get credits from the Avalon team.

> Another idea would to leave the GenericMailet as is, but then also offer
> a GenericAvalonMailet that would have easier access to Avalon
> information.  I'd probably be +0 on this since it does in effect
> encourage people to write non-generic mailets.  I may just be
> unrealistic in this hope though. 

I believe that would be too much; besides, it would complicate the
documentation.
 
> The RemoteDelivery mailet already grabs Avalon resources, which it does
> by grabbing a ComponentManager from a MailetContext attribute.  Seems
> like this approach could give you similar access to Jdbc sources or
> whatever.  I plan to rewrite the Town alias and Town listserv without
> Town (using the internal jdbc datasource), and I'll see if I can figure
> a nice way to get these to work. 

Yes please; basically, all I need is to have an easy way to get a
reference to Avalon's ComponentManager from my matchers/mailets. Well, I
want to make sure that the compose() or initialize() methods in the
mailets would get invoked too...

Oki




---------------------------------------------------------------------
To unsubscribe, e-mail: james-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: james-dev-help@jakarta.apache.org


Re: Turning mailets into Avalon components

Posted by Serge Knystautas <se...@lokitech.com>.
I don't like making the mailet API tied to the Avalon structure.  I'm hoping
mailets and matchers can eventually become used enough that other mail
server engines start supporting them.

Another idea would to leave the GenericMailet as is, but then also offer a
GenericAvalonMailet that would have easier access to Avalon information.
I'd probably be +0 on this since it does in effect encourage people to write
non-generic mailets.  I may just be unrealistic in this hope though.

The RemoteDelivery mailet already grabs Avalon resources, which it does by
grabbing a ComponentManager from a MailetContext attribute.  Seems like this
approach could give you similar access to Jdbc sources or whatever.  I plan
to rewrite the Town alias and Town listserv without Town (using the internal
jdbc datasource), and I'll see if I can figure a nice way to get these to
work.

Serge Knystautas
Loki Technologies
http://www.lokitech.com/
----- Original Message -----
From: "Oki DZ" <ok...@pindad.com>
To: <ja...@jakarta.apache.org>
Sent: Wednesday, September 26, 2001 11:31 PM
Subject: Turning mailets into Avalon components


> Hi,
>
> I think it would be nice if James mailets can be changed into Avalon
> components. By doing so, you could get access to the might be useful
> components from Excalibur or Cornerstone from your mailets. I don't think
> there would be many changes in James, all you need is to have
> GenericMailet to extend AbstractLoggable and implement Component, and also
> some lines in the JamesSpoolManager like in the following:  (the "if
> (mailet instanceof Component)" might not be needed).
>
> try {
>    mailet = mailetLoader.getMailet(mailetClassName, mailetcontext,c);
>    if (mailet instanceof Component) {
>       if (mailet instanceof AbstractLoggable) {
>          ((GenericMailet) mailet).setLogger(getLogger());
>       }
>       if (mailet instanceof Composable) {
>          ((Composable) mailet).compose(compMgr);
>       }
>       if (mailet instanceof Initializable) {
>          ((Initializable) mailet).initialize();
>       }
>    }
>    getLogger().info("Mailet " + mailetClassName + " instantiated");
> } catch (MessagingException ex) {
>    // ...
> }
>
> The init() method in the mailets can be replaced by initialize(), but the
> init() signature should be left there (it is invoked by
> mailetLoader.getMailet()). But since the code changes in
> JamesSpoolRepository tests whether the mailet is a Component or not, the
> current mailets (which are not Component) would work as they should be.
>
> The following is a mailet which stores some information of a message into
> a database table; could be useful if you want to have some statistics of
> your email users.
>
> As I understand it, the latest James already uses JdbcDataSource, so the
> componentManager.lookup() below can be changed to use the interface (role)
> of the block where the latest James gets the JdbcDataSource from. And
> also, it would be nicer if the SQL statement used is retrieved from the
> SQL repository.
>
> public class StoreSenderAndRecipients extends GenericMailet
> implements Composable, Initializable {
>
>     private String sender;
>     private String recipients;
>     private String remoteAddr;
>     private int size;
>
>     private JdbcDataSource dataSource;
>     private DataSourceSelector dataSourceSelector;
>     private String storeSQL;
>     private JdbcConnection conn;
>     private PreparedStatement ps;
>
>     public StoreSenderAndRecipients() {}
>
>     public void compose(ComponentManager componentManager)
> throws ComponentException {
>
> dataSourceSelector = (DataSourceSelector)
>
> componentManager.lookup("com.pindad.james.services.DataSourceSelector");
>   getLogger().debug(getClass().getName() +
> ".compose(ComponentManager): " +
>     "Composed");
>     }
>
>     public void initialize() throws Exception {
>     dataSource = (JdbcDataSource)
> dataSourceSelector.select("mailetsource");
>     storeSQL =
> "insert into SenderRecipients (sender, recipients,
> remote_addr, size) " +
> "values (?, ?, ?, ?)";
>     conn = (JdbcConnection) dataSource.getConnection();
>     ps = conn.prepareStatement(storeSQL);
>     getLogger().debug(getClass().getName() + ".initialize():
> Initialized");
>     }
>
>     public void init() {
>     }
>
>     public void service(Mail mail) throws MessagingException {
> MimeMessage message = mail.getMessage();
> size = message.getSize();
> MailImpl mc = (MailImpl) mail;
> sender = mc.getSender().toString();
> remoteAddr = mc.getRemoteAddr();
> StringBuffer buff = new StringBuffer();
> Collection rcpts = mc.getRecipients();
> for (Iterator i = rcpts.iterator(); i.hasNext();) {
>     String address = ((MailAddress) i.next()).toString();
>     buff.append(address + " ");
> }
> recipients = buff.toString();
> // System.out.println("Sender: " + sender);
> // System.out.println("Recipients: " + recipients);
> // System.out.println("Size: " + size);
>
> try {
>     ps.setString(1, sender);
>     ps.setString(2, recipients);
>     ps.setString(3, remoteAddr);
>     ps.setInt(4, size);
>     ps.execute();
> } catch(SQLException sqe) {
>     getLogger().error(getClass().getName() + ".service(Mail): " +
>       sqe.getMessage());
> }
>     }
>
>     public void finalize() {
> try {
>     conn.close();
> } catch(Exception e) {
>     getLogger().error(getClass().getName() + ".finalize(): " +
> e.getMessage());
> }
>     }
>
>     public String getMailetInfo() {
> return getClass().getName();
>     }
> }
>
> Just some ideas of improvement (I think),
> Oki
> ps: Could be nicer if matchers are Components too; say, you'd like to have
> your own spam blackhole matcher based on a database table; which could be
> neat, because you don't have to restart James to have it in effect.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: james-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: james-dev-help@jakarta.apache.org
>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: james-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: james-dev-help@jakarta.apache.org