📄 linearprocessor.java
字号:
/*********************************************************************** * Copyright (c) 2000-2004 The Apache Software Foundation. * * All rights reserved. * * ------------------------------------------------------------------- * * Licensed under the Apache License, Version 2.0 (the "License"); you * * may not use this file except in compliance with the License. You * * may obtain a copy of the License at: * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * * implied. See the License for the specific language governing * * permissions and limitations under the License. * ***********************************************************************/package org.apache.james.transport;import org.apache.avalon.framework.activity.Initializable;import org.apache.avalon.framework.activity.Disposable;import org.apache.avalon.framework.logger.AbstractLogEnabled;import org.apache.avalon.framework.logger.Logger;import org.apache.james.core.MailImpl;import org.apache.james.core.MailetConfigImpl;import org.apache.james.services.SpoolRepository;import org.apache.mailet.*;import javax.mail.MessagingException;import java.io.PrintWriter;import java.io.StringWriter;import java.util.ArrayList;import java.util.Collection;import java.util.List;import java.util.Random;import java.util.Iterator;import java.util.Locale;/** * Implements a processor for mails, directing the mail down * the chain of matchers/mailets. * * SAMPLE CONFIGURATION * <processor name="try" onerror="return,log"> * <mailet match="RecipientIsLocal" class="LocalDelivery"> * </mailet> * <mailet match="All" class="RemoteDelivery"> * <delayTime>21600000</delayTime> * <maxRetries>5</maxRetries> * </mailet> * </processor> * * Note that the 'onerror' attribute is not yet supported. * * As of James v2.2.0a5, 'onerror' functionality is implemented, but * it is implemented on the <mailet> tag. The specification is: * * <mailet match="..." class="..." * [onMatchException="{noMatch|matchAll|error|<aProcessorName>}"] * [onMailetException="{ignore|error|<aProcessorName>}"]> * * noMatch: no addresses are considered to match * matchAll: all addresses are considered to match * error: as before, send the message to the ERROR processor * * Otherwise, a processor name can be specified, and the message will * be sent there. * * <P>CVS $Id: LinearProcessor.java,v 1.10.4.7 2004/04/14 06:41:56 noel Exp $</P> * @version 2.2.0 */public class LinearProcessor extends AbstractLogEnabled implements Initializable, Disposable { private static final Random random = new Random(); // Used to generate new mail names /** * The name of the matcher used to terminate the matcher chain. The * end of the matcher/mailet chain must be a matcher that matches * all mails and a mailet that sets every mail to GHOST status. * This is necessary to ensure that mails are removed from the spool * in an orderly fashion. */ private static final String TERMINATING_MATCHER_NAME = "Terminating%Matcher%Name"; /** * The name of the mailet used to terminate the mailet chain. The * end of the matcher/mailet chain must be a matcher that matches * all mails and a mailet that sets every mail to GHOST status. * This is necessary to ensure that mails are removed from the spool * in an orderly fashion. */ private static final String TERMINATING_MAILET_NAME = "Terminating%Mailet%Name"; private List mailets; // The list of mailets for this processor private List matchers; // The list of matchers for this processor private volatile boolean listsClosed; // Whether the matcher/mailet lists have been closed. private SpoolRepository spool; // The spool on which this processor is acting /** * Set the spool to be used by this LinearProcessor. * * @param spool the spool to be used by this processor * * @throws IllegalArgumentException when the spool passed in is null */ public void setSpool(SpoolRepository spool) { if (spool == null) { throw new IllegalArgumentException("The spool cannot be null"); } this.spool = spool; } /** * @see org.apache.avalon.framework.activity.Initializable#initialize() */ public void initialize() { matchers = new ArrayList(); mailets = new ArrayList(); } /** * <p>The dispose operation is called at the end of a components lifecycle. * Instances of this class use this method to release and destroy any * resources that they own.</p> * * <p>This implementation disposes of all the mailet instances added to the * processor</p> * * @throws Exception if an error is encountered during shutdown */ public void dispose() { Iterator it = mailets.iterator(); boolean debugEnabled = getLogger().isDebugEnabled(); while (it.hasNext()) { Mailet mailet = (Mailet)it.next(); if (debugEnabled) { getLogger().debug("Shutdown mailet " + mailet.getMailetInfo()); } mailet.destroy(); } } /** * <p>Adds a new <code>Matcher</code> / <code>Mailet</code> pair * to the processor. Checks to ensure that the matcher and * mailet passed in are not null. Synchronized to ensure that * the matchers and mailets are kept in sync.</p> * * <p>It is an essential part of the contract of the LinearProcessor * that a particular matcher/mailet combination be used to * terminate the processor chain. This is done by calling the * closeProcessorList method.</p> * * <p>Once the closeProcessorList has been called any subsequent * call to the add method will result in an IllegalStateException.</p> * * <p>This method is synchronized to protect against corruption of * matcher/mailets lists</p> * * @param matcher the new matcher being added * @param mailet the new mailet being added * * @throws IllegalArgumentException when the matcher or mailet passed in is null * @throws IllegalStateException when this method is called after the processor lists have been closed */ public synchronized void add(Matcher matcher, Mailet mailet) { if (matcher == null) { throw new IllegalArgumentException("Null valued matcher passed to LinearProcessor."); } if (mailet == null) { throw new IllegalArgumentException("Null valued mailet passed to LinearProcessor."); } if (listsClosed) { throw new IllegalStateException("Attempt to add matcher/mailet after lists have been closed"); } matchers.add(matcher); mailets.add(mailet); } /** * <p>Closes the processor matcher/mailet list.</p> * * <p>This method is synchronized to protect against corruption of * matcher/mailets lists</p> * * @throws IllegalStateException when this method is called after the processor lists have been closed */ public synchronized void closeProcessorLists() { if (listsClosed) { throw new IllegalStateException("Processor's matcher/mailet lists have already been closed."); } Matcher terminatingMatcher = new GenericMatcher() { public Collection match(Mail mail) { return mail.getRecipients(); } public String getMatcherInfo() { return TERMINATING_MATCHER_NAME; } }; Mailet terminatingMailet = new GenericMailet() { public void service(Mail mail) { if (!(Mail.ERROR.equals(mail.getState()))) { // Don't complain if we fall off the end of the // error processor. That is currently the // normal situation for James, and the message // will show up in the error store. StringBuffer warnBuffer = new StringBuffer(256) .append("Message ") .append(((MailImpl)mail).getName()) .append(" reached the end of this processor, and is automatically deleted. This may indicate a configuration error."); LinearProcessor.this.getLogger().warn(warnBuffer.toString()); } mail.setState(Mail.GHOST); } public String getMailetInfo() { return getMailetName(); } public String getMailetName() { return TERMINATING_MAILET_NAME; } }; add(terminatingMatcher, terminatingMailet); listsClosed = true; } /** * <p>Processes a single mail message through the chain of matchers and mailets.</p> * * <p>Calls to this method before setSpool has been called with a non-null argument * will result in an <code>IllegalStateException</code>.</p> * * <p>If the matcher/mailet lists have not been closed by a call to the closeProcessorLists * method then a call to this method will result in an <code>IllegalStateException</code>. * The end of the matcher/mailet chain must be a matcher that matches all mails and * a mailet that sets every mail to GHOST status. This is necessary to ensure that * mails are removed from the spool in an orderly fashion. The closeProcessorLists method * ensures this.</p> * * @param mail the new mail to be processed * * @throws IllegalStateException when this method is called before the processor lists have been closed * or the spool has been initialized */ public void service(MailImpl mail) throws MessagingException { if (spool == null) { throw new IllegalStateException("Attempt to service mail before the spool has been set to a non-null value"); } if (!listsClosed) { throw new IllegalStateException("Attempt to service mail before matcher/mailet lists have been closed"); } if (getLogger().isDebugEnabled()) { getLogger().debug("Servicing mail: " + mail.getName()); } // unprocessed is an array of Lists of Mail objects
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -