blob: 988ea44c4cc5bbf0cb3db65d91a13531f09642be [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>James Server -
James 2.3 - Writing a Custom Matcher</title>
<style type="text/css" media="all">
@import url("./css/maven-base.css");
@import url("./css/maven-theme.css");
@import url("./css/site.css");
</style>
<link rel="stylesheet" href="./css/print.css" type="text/css" media="print" />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
</head>
<body class="composite">
<div id="banner">
<a href="http://james.apache.org/index.html" id="bannerLeft">
<img src="images/james-server-logo.gif" alt="" />
</a>
<a href="http://www.apache.org/index.html" id="bannerRight">
<img src="images/asf-logo-reduced.gif" alt="" />
</a>
<div class="clear">
<hr/>
</div>
</div>
<div id="breadcrumbs">
<div class="xleft">
Last Published: 09/02/2009
</div>
<div class="xright"> <a href="../../index.html">JAMES Project</a>
|
<a href="../../server/index.html">Server</a>
|
<a href="../../mailet/index.html">Mailets</a>
|
<a href="../../jspf/index.html">jSPF</a>
|
<a href="../../mime4j/index.html">Mime4J</a>
|
<a href="../../jsieve/index.html">JSieve</a>
|
<a href="../../postage/index.html">Postage</a>
</div>
<div class="clear">
<hr/>
</div>
</div>
<div id="leftColumn">
<div id="navcolumn">
<h5>James Server</h5>
<ul>
<li class="none">
<a href="../index.html">Overview</a>
</li>
<li class="none">
<a href="../design_objectives.html">Objectives</a>
</li>
<li class="expanded">
<a href="../FAQ.html">James FAQ</a>
<ul>
<li class="none">
<a href="../james_and_sendmail.html">James and Sendmail</a>
</li>
</ul>
</li>
<li class="none">
<a href="http://wiki.apache.org/james">Wiki</a>
</li>
<li class="none">
<a href="../rfclist.html">Useful RFCs</a>
</li>
</ul>
<h5>Overview</h5>
<ul>
<li class="none">
<a href="index.html">Introduction</a>
</li>
<li class="none">
<a href="release-notes.html">Release Notes</a>
</li>
</ul>
<h5>Concepts</h5>
<ul>
<li class="none">
<a href="summary.html">Summary</a>
</li>
<li class="none">
<a href="spoolmanager.html">SpoolManager</a>
</li>
<li class="none">
<a href="repositories.html">Repositories</a>
</li>
<li class="none">
<a href="mailet_api.html">The Mailet API</a>
</li>
</ul>
<h5>How to...</h5>
<ul>
<li class="none">
<a href="build_instructions.html">Build James</a>
</li>
<li class="none">
<a href="installation_instructions.html">Install James</a>
</li>
</ul>
<h5>Configuration</h5>
<ul>
<li class="none">
<a href="dns_configuration.html">DNS Server</a>
</li>
<li class="none">
<a href="pop3_configuration.html">POP3 Server</a>
</li>
<li class="none">
<a href="smtp_configuration.html">SMTP Server</a>
</li>
<li class="none">
<a href="nntp_configuration.html">NNTP Server</a>
</li>
<li class="none">
<a href="fetchmail_configuration.html">FetchMail</a>
</li>
<li class="none">
<a href="remotemanager_configuration.html">RemoteManager</a>
</li>
<li class="none">
<a href="spoolmanager_configuration.html">SpoolManager</a>
</li>
<li class="none">
<a href="serverwide_configuration.html">Server-wide</a>
</li>
<li class="none">
<a href="adding_users.html">Adding Users</a>
</li>
<li class="none">
<a href="provided_matchers.html">Provided Matchers</a>
</li>
<li class="none">
<a href="provided_mailets.html">Provided Mailets</a>
</li>
</ul>
<h5>Common Configurations</h5>
<ul>
<li class="none">
<a href="smtp_auth.html">Using SMTP AUTH</a>
</li>
<li class="none">
<a href="using_database.html">Using a Database with James</a>
</li>
<li class="none">
<a href="usingTLS.html">Using TLS/SSL</a>
</li>
<li class="none">
<a href="mailing_lists.html">Creating Mailing Lists</a>
</li>
</ul>
<h5>Customization</h5>
<ul>
<li class="none">
<strong>How to write a custom Matcher</strong>
</li>
<li class="none">
<a href="custom_mailet.html">How to write a custom Mailet</a>
</li>
</ul>
<h5>Project</h5>
<ul>
<li class="none">
<a href="changelog.html">Changelog</a>
</li>
</ul>
<h5>Project Documentation</h5>
<ul>
<li class="collapsed">
<a href="project-info.html">Project Information</a>
</li>
<li class="collapsed">
<a href="project-reports.html">Project Reports</a>
</li>
</ul>
<h5>Project</h5>
<ul>
<li class="none">
<a href="http://issues.apache.org/jira/browse/JAMES">Bug Database</a>
</li>
<li class="none">
<a href="http://svn.apache.org/viewvc/james/server/">Source Code</a>
</li>
<li class="none">
<a href="../todo.html">TODO</a>
</li>
</ul>
<h5>Downloads</h5>
<ul>
<li class="none">
<a href="../../download.cgi">Stable releases</a>
</li>
<li class="none">
<a href="../../downloadunstable.cgi">Unstable releases</a>
</li>
<li class="none">
<a href="http://people.apache.org/builds/james/nightly/">Nightly builds</a>
</li>
</ul>
<a href="http://maven.apache.org/" title="Built by Maven" id="poweredBy">
<img alt="Built by Maven" src="./images/logos/maven-feather.png"></img>
</a>
</div>
</div>
<div id="bodyColumn">
<div id="contentBox">
<a name="Writing a Custom Matcher"></a><div class="section"><h2>Writing a Custom Matcher</h2>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>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).</p>
<a name="Configuration"></a><div class="section"><h3>Configuration</h3>
<p>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.</p>
</div>
<a name="Logging"></a><div class="section"><h3>Logging</h3>
<p>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.</p>
<p>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.</p>
</div>
<a name="Initialization"></a><div class="section"><h3>Initialization</h3>
<p>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.</p>
</div>
<a name="Matching"></a><div class="section"><h3>Matching</h3>
<p>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.</p>
<p>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.</p>
<p>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.</p>
</div>
<a name="Destruction"></a><div class="section"><h3>Destruction</h3>
<p>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.</p>
</div>
</div>
<a name="Deploying a Custom Matcher"></a><div class="section"><h2>Deploying a Custom Matcher</h2>
<p>Once a Matcher has been successfully implemented there are only a couple of
additional steps necessary to actually deploy the Matcher.</p>
<a name="Adding Your Matcher to the Classpath"></a><div class="section"><h3>Adding Your Matcher to the Classpath</h3>
<p>
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:
</p>
<p>
1a. 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 <a href="build_instructions.html">here</a>. This new .sar file will now
include your custom classes.
</p>
<p>
or
</p>
<p>
1b. 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.
</p>
<p>
or
</p>
<p>
1c. Place a jar file containing the custom class files in the path/to/james/apps/james/SAR-INF/lib subdirectory.
Please note that you must start james once to get the apps/james/SAR-INF directory created. After that is done create
the lib directory and copy the jar to the directory.
</p>
<p>
2. After this is done get sure you add the matcher package to the config.xml. For example:
<p>
<div class="source"><pre>
&lt;!-- Set the Java packages from which to load mailets and matchers --&gt;
&lt;matcherpackages&gt;
&lt;matcherpackage&gt;org.apache.james.transport.matchers&lt;/matcherpackage&gt;
&lt;matcherpackage&gt;org.apache.james.transport.matchers.smime&lt;/matcherpackage&gt;
&lt;matcherpackage&gt;your.costum.package.transport-matchers&lt;/matcherpackage&gt;
&lt;/matcherpackages&gt;
</pre></div>
</p>
After that restart james.
</p>
</div>
<a name="James Configuration"></a><div class="section"><h3>James Configuration</h3>
<p>Configuration of the processor chain is discussed
<a href="spoolmanager_configuration.html">elsewhere</a> 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
&lt;matcherpackages&gt; list and that the name of your matcher should not conflict with any of
the matchers described <a href="provided_matchers.html">here</a>.
</p>
</div>
</div>
</div>
</div>
<div class="clear">
<hr/>
</div>
<div id="footer">
<div class="xright">&#169;
2002-2009
The Apache Software Foundation
</div>
<div class="clear">
<hr/>
</div>
</div>
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-1384591-1";
urchinTracker();
</script>
</body>
</html>