| 
James
 
Translated
 
Downloads
 
Current Documentation
 
Older Documentation
 
Project
 
Jakarta Information (web)
 
Related Projects (web)
 | 
| Writing a Custom Matcher |  
| 
Implementing a custom matcher is generally a simple task, most of whose complexity 
lies in coding the actual work to be done by the matcher.  This is largely due to the 
simplicity of the Matcher interface and the fact that a couple of abstract Matcher template
classes are provided in the Mailet package.  These two classes, GenericMatcher and 
GenericRecipientMatcher, greatly simplfy the task of Matcher authoring. As discussed elsewhere in this manual, the Matcher interface does not simply match 
or not match a particular message.  Rather, it returns some subset of the original message
recipients as a result of the match(Mail) method.  This leads to the two different abstract
Matcher implementations. The first, GenericMatcher, is intended for matchers where recipient evaluation is not 
necessary.  Basically, you should subclass this implementation if your matcher is going to 
return all or none of the recipients. When subclassing this class, there are four methods that potentially need to be 
overridden.  These are getMatcherInfo(), init(), match(Mail), and destroy().  More on these 
anon. The second implementation, GenericRecipientMatcher, is intended for those matchers where 
each recipient is evaluated individually.  It is a subclass of GenericMatcher, and inherits 
most of its behavior from that class.  The only major difference is that subclasses are 
expected to override matchRecipient(MailAddress) rather than match(Mail). 
| Configuration |  
| 
Matchers are passed a single String as part of their configuration.  Interpretation of this 
list is left entirely to the body of the Matcher.  This String value is available in 
the body of the Matcher through use of the getCondition() method of the 
GenericMatcher class.  This method returns the String value passed to the Matcher, and returns 
null if no value is set.  The method getCondition() is available inside the init(), destroy(), match(Mail), 
and matchRecipient(MailAddress) methods. |  
| Logging |  
| 
There is a simple logging mechanism provided by the Mailet API.  It does not support 
logging levels, so any log filtering will have to be implemented in the Matcher code.  
Logging is done by calling one of the two logging methods on GenericMatcher/GenericRecipientMatcher - log(String) 
or log(String,Throwable).  Logging is available inside the init(), destroy(), match(Mail), 
and matchRecipient(MailAddress) methods. The value of getMatcherInfo() for the Matcher is prepended to the log entries for that 
Matcher.  So it may be desirable for you to override this method so you can distinguish Matcher
log entries by Matcher. |  
| Initialization |  
| 
As part of the Matcher lifecycle, a Matcher is guaranteed to be initialized immediately after 
being instantiated.  This happens once and only once for each Matcher instance.  The 
Initialization phase is where configuration parsing and per-Matcher resource creation generally 
take place.  Depending on your Matcher, it may or may not be necessary to do any initialization 
of the Matcher.  Initialization logic is implemented by overriding the init() method of 
GenericMatcher/GenericRecipientMatcher. |  
| Matching |  
| 
It is the matching phase where the Matcher's work is done.  The exact form of this phase largely 
depends on which Matcher superclass is subclassed. If GenericMatcher is being subclassed, it is the match(Mail) that is implemented.  As described 
above, this method returns a Collection of MailAddresses that is a subset of the original 
recipients for the Mail object. If it is a purely recipient-filtering Matcher, then the GenericRecipientMatcher should be
subclassed.  In this case, developers must provide an implementation of the 
matchRecipient(MailAddress) method.  This method returns true if the recipient matches,
and false otherwise. |  
| Destruction |  
| 
As part of the Matcher lifecycle, a Matcher is guaranteed to be destroyed when the container 
cleans up the Matcher.  This happens once and only once for each Matcher instance.  The 
Destruction phase is where per-Matcher resource release generally takes place.  Depending 
on your Matcher, it may or may not be necessary to do any destruction 
of the Matcher.  Destruction logic is implemented by overriding the destroy() method of 
GenericMatcher/GenericRecipientMatcher. |  |  
| Deploying a Custom Matcher |  
| 
Once a Matcher has been successfully implemented there are only a couple of 
additional steps necessary to actually deploy the Matcher. 
| Adding Your Matcher to the Classpath |  
| 
The Matcher must be added to James' classpath so that the Matcher can be loaded by James.  There 
are two ways to add a custom Matcher to the classpath so that James will be able to load the 
Matcher.  These are:
 
1. Download the source distribution, add a jar file containing the custom files to the lib 
directory of the unpacked source distribution, and build a new .sar file by following the 
directions here.  This new .sar file will now 
include your custom classes.
 
or
 
2. Place a jar file containing the custom class files in the lib subdirectory of the James
installation.  It will also be necessary to unpack the JavaMail and James jar files from 
the provided .sar file and add them to this directory.
 |  
| James Configuration |  
| 
Configuration of the processor chain is discussed 
elsewhere in this documentation.  The 
details of configuring matcher deployment is discussed at length.  Here we will only comment 
that it is important to add the appropriate matcher package for your custom matcher to the 
<matcherpackages> list and that the name of your matcher should not conflict with any of 
the matchers described here.
 |  |  |