📄 linearprocessor.java
字号:
// the array indicates which matcher/mailet (stage in the linear // processor) that this Mail needs to be processed. // e.g., a Mail in unprocessed[0] needs to be // processed by the first matcher/mailet. // // It is a List of Mail objects at each array spot as multiple Mail // objects could be at the same stage. // // Note that every Mail object in this array will either be the // original Mail object passed in, or a result of this method's // (and hence this thread's) processing. List[] unprocessed = new List[matchers.size() + 1]; for (int i = 0; i < unprocessed.length; i++) { // No need to use synchronization, as this is totally // local to the method unprocessed[i] = new ArrayList(); } //Add the object to the bottom of the list unprocessed[0].add(mail); //This is the original state of the message String originalState = mail.getState(); //We'll use these as temporary variables in the loop mail = null; // the message we're currently processing int i = 0; // where in the stage we're looking while (true) { // The last element in the unprocessed array has mail messages // that have completed all stages. We want them to just die, // so we clear that spot to allow garbage collection of the // objects. // // Please note that the presence of the terminating mailet at the end // of the chain is critical to the proper operation // of the LinearProcessor code. If this mailet is not placed // at the end of the chain with a terminating matcher, there is a // potential for configuration or implementation errors to // lead to mails trapped in the spool. This matcher/mailet // combination is added when the closeProcessorList method // is called. unprocessed[unprocessed.length - 1].clear(); //initialize the mail reference we will be searching on mail = null; //Scan through all stages, trying to find a message to process for (i = 0; i < unprocessed.length; i++) { if (unprocessed[i].size() > 0) { //Get the first element from the queue, and remove it from there mail = (MailImpl)unprocessed[i].remove(0); break; } } //Check it we found anything if (mail == null) { //We found no messages to process... we're done servicing the mail object return; } //Call the matcher and find what recipients match Collection recipients = null; Matcher matcher = (Matcher) matchers.get(i); StringBuffer logMessageBuffer = null; if (getLogger().isDebugEnabled()) { logMessageBuffer = new StringBuffer(128) .append("Checking ") .append(mail.getName()) .append(" with ") .append(matcher); getLogger().debug(logMessageBuffer.toString()); } try { recipients = matcher.match(mail); if (recipients == null) { //In case the matcher returned null, create an empty Collection recipients = new ArrayList(0); } else if (recipients != mail.getRecipients()) { //Make sure all the objects are MailAddress objects verifyMailAddresses(recipients); } } catch (MessagingException me) { // look in the matcher's mailet's init attributes MailetConfig mailetConfig = ((Mailet) mailets.get(i)).getMailetConfig(); String onMatchException = ((MailetConfigImpl) mailetConfig).getInitAttribute("onMatchException"); if (onMatchException == null) { onMatchException = Mail.ERROR; } else { onMatchException = onMatchException.trim().toLowerCase(Locale.US); } if (onMatchException.compareTo("nomatch") == 0) { //In case the matcher returned null, create an empty Collection recipients = new ArrayList(0); } else if (onMatchException.compareTo("matchall") == 0) { recipients = mail.getRecipients(); // no need to verify addresses } else { handleException(me, mail, matcher.getMatcherConfig().getMatcherName(), onMatchException); } } // Split the recipients into two pools. notRecipients will contain the // recipients on the message that the matcher did not return. Collection notRecipients; if (recipients == mail.getRecipients() || recipients.size() == 0) { notRecipients = new ArrayList(0); } else { notRecipients = new ArrayList(mail.getRecipients()); notRecipients.removeAll(recipients); } if (recipients.size() == 0) { //Everything was not a match... store it in the next spot in the array unprocessed[i + 1].add(mail); continue; } if (notRecipients.size() != 0) { // There are a mix of recipients and not recipients. // We need to clone this message, put the notRecipients on the clone // and store it in the next spot MailImpl notMail = (MailImpl)mail.duplicate(newName(mail)); notMail.setRecipients(notRecipients); unprocessed[i + 1].add(notMail); //We have to set the reduce possible recipients on the old message mail.setRecipients(recipients); } // We have messages that need to process... time to run the mailet. Mailet mailet = (Mailet) mailets.get(i); if (getLogger().isDebugEnabled()) { logMessageBuffer = new StringBuffer(128) .append("Servicing ") .append(mail.getName()) .append(" by ") .append(mailet.getMailetInfo()); getLogger().debug(logMessageBuffer.toString()); } try { mailet.service(mail); // Make sure all the recipients are still MailAddress objects verifyMailAddresses(mail.getRecipients()); } catch (MessagingException me) { MailetConfig mailetConfig = mailet.getMailetConfig(); String onMailetException = ((MailetConfigImpl) mailetConfig).getInitAttribute("onMailetException"); if (onMailetException == null) { onMailetException = Mail.ERROR; } else { onMailetException = onMailetException.trim().toLowerCase(Locale.US); } if (onMailetException.compareTo("ignore") == 0) { // ignore the exception and continue // this option should not be used if the mail object can be changed by the mailet verifyMailAddresses(mail.getRecipients()); } else { handleException(me, mail, mailet.getMailetConfig().getMailetName(), onMailetException); } } // See if the state was changed by the mailet if (!mail.getState().equals(originalState)) { //If this message was ghosted, we just want to let it die if (mail.getState().equals(Mail.GHOST)) { // let this instance die... mail = null; continue; } // This was just set to another state requiring further processing... // Store this back in the spool and it will get picked up and // run in that processor spool.store(mail); mail = null; continue; } else { // Ok, we made it through with the same state... move it to the next // spot in the array unprocessed[i + 1].add(mail); } } } /** * Create a unique new primary key name. * * @param mail the mail to use as the basis for the new mail name * * @return a new name */ private String newName(MailImpl mail) { StringBuffer nameBuffer = new StringBuffer(64) .append(mail.getName()) .append("-!") .append(random.nextInt(1048576)); return nameBuffer.toString(); } /** * Checks that all objects in this class are of the form MailAddress. * * @throws MessagingException when the <code>Collection</code> contains objects that are not <code>MailAddress</code> objects */ private void verifyMailAddresses(Collection col) throws MessagingException { try { MailAddress addresses[] = (MailAddress[])col.toArray(new MailAddress[0]); // Why is this here? According to the javadoc for // java.util.Collection.toArray(Object[]), this should // never happen. The exception will be thrown. if (addresses.length != col.size()) { throw new MailetException("The recipient list contains objects other than MailAddress objects"); } } catch (ArrayStoreException ase) { throw new MailetException("The recipient list contains objects other than MailAddress objects"); } } /** * This is a helper method that updates the state of the mail object to * Mail.ERROR as well as recording the exception to the log * * @param me the exception to be handled * @param mail the mail being processed when the exception was generated * @param offendersName the matcher or mailet than generated the exception * @param nextState the next state to set * * @throws MessagingException thrown always, rethrowing the passed in exception */ private void handleException(MessagingException me, Mail mail, String offendersName, String nextState) throws MessagingException { System.err.println("exception! " + me); mail.setState(nextState); StringWriter sout = new StringWriter(); PrintWriter out = new PrintWriter(sout, true); StringBuffer exceptionBuffer = new StringBuffer(128) .append("Exception calling ") .append(offendersName) .append(": ") .append(me.getMessage()); out.println(exceptionBuffer.toString()); Exception e = me; while (e != null) { e.printStackTrace(out); if (e instanceof MessagingException) { e = ((MessagingException)e).getNextException(); } else { e = null; } } String errorString = sout.toString(); mail.setErrorMessage(errorString); getLogger().error(errorString); throw me; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -