/** * 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>This implementation shuts down the LinearProcessors managed by this JamesSpoolManager * * @throws Exception if an error is encountered during shutdown */ public void dispose() { getLogger().info("JamesSpoolManager dispose..."); active = false; // shutdown the threads for (Iterator it = spoolThreads.iterator(); it.hasNext(); ) { ((Thread) it.next()).interrupt(); // interrupt any waiting accept() calls. } long stop = System.currentTimeMillis() + 60000; // give the spooler threads one minute to terminate gracefully while (numActive != 0 && stop > System.currentTimeMillis()) { try { Thread.sleep(1000); } catch (Exception ignored) { } } getLogger().info("JamesSpoolManager thread shutdown completed."); Iterator it = processors.keySet().iterator(); while (it.hasNext()) { String processorName = (String) it.next(); if (getLogger().isDebugEnabled()) { getLogger().debug("Processor " + processorName); } LinearProcessor processor = (LinearProcessor) processors.get(processorName); processor.dispose(); processors.remove(processor); } }
/** @see org.apache.avalon.framework.activity.Initializable#initialize() */ public void initialize() throws Exception { getLogger().info("JamesSpoolManager init..."); spool = (SpoolRepository) compMgr.lookup(SpoolRepository.ROLE); MailetLoader mailetLoader = (MailetLoader) compMgr.lookup(MailetLoader.ROLE); MatcherLoader matchLoader = (MatcherLoader) compMgr.lookup(MatcherLoader.ROLE); // A processor is a Collection of processors = new HashMap(); final Configuration[] processorConfs = conf.getChildren("processor"); for (int i = 0; i < processorConfs.length; i++) { Configuration processorConf = processorConfs[i]; String processorName = processorConf.getAttribute("name"); try { LinearProcessor processor = new LinearProcessor(); setupLogger(processor, processorName); processor.setSpool(spool); processor.initialize(); processors.put(processorName, processor); final Configuration[] mailetConfs = processorConf.getChildren("mailet"); // Loop through the mailet configuration, load // all of the matcher and mailets, and add // them to the processor. for (int j = 0; j < mailetConfs.length; j++) { Configuration c = mailetConfs[j]; String mailetClassName = c.getAttribute("class"); String matcherName = c.getAttribute("match"); Mailet mailet = null; Matcher matcher = null; try { matcher = matchLoader.getMatcher(matcherName); // The matcher itself should log that it's been inited. if (getLogger().isInfoEnabled()) { StringBuffer infoBuffer = new StringBuffer(64) .append("Matcher ") .append(matcherName) .append(" instantiated."); getLogger().info(infoBuffer.toString()); } } catch (MessagingException ex) { // **** Do better job printing out exception if (getLogger().isErrorEnabled()) { StringBuffer errorBuffer = new StringBuffer(256) .append("Unable to init matcher ") .append(matcherName) .append(": ") .append(ex.toString()); getLogger().error(errorBuffer.toString(), ex); if (ex.getNextException() != null) { getLogger().error("Caused by nested exception: ", ex.getNextException()); } } System.err.println("Unable to init matcher " + matcherName); System.err.println("Check spool manager logs for more details."); // System.exit(1); throw ex; } try { mailet = mailetLoader.getMailet(mailetClassName, c); if (getLogger().isInfoEnabled()) { StringBuffer infoBuffer = new StringBuffer(64) .append("Mailet ") .append(mailetClassName) .append(" instantiated."); getLogger().info(infoBuffer.toString()); } } catch (MessagingException ex) { // **** Do better job printing out exception if (getLogger().isErrorEnabled()) { StringBuffer errorBuffer = new StringBuffer(256) .append("Unable to init mailet ") .append(mailetClassName) .append(": ") .append(ex.toString()); getLogger().error(errorBuffer.toString(), ex); if (ex.getNextException() != null) { getLogger().error("Caused by nested exception: ", ex.getNextException()); } } System.err.println("Unable to init mailet " + mailetClassName); System.err.println("Check spool manager logs for more details."); // System.exit(1); throw ex; } // Add this pair to the processor processor.add(matcher, mailet); } // Close the processor matcher/mailet lists. // // Please note that this is critical to the proper operation // of the LinearProcessor code. The processor will not be // able to service mails until this call is made. processor.closeProcessorLists(); if (getLogger().isInfoEnabled()) { StringBuffer infoBuffer = new StringBuffer(64) .append("Processor ") .append(processorName) .append(" instantiated."); getLogger().info(infoBuffer.toString()); } } catch (Exception ex) { if (getLogger().isErrorEnabled()) { StringBuffer errorBuffer = new StringBuffer(256) .append("Unable to init processor ") .append(processorName) .append(": ") .append(ex.toString()); getLogger().error(errorBuffer.toString(), ex); } throw ex; } } if (getLogger().isInfoEnabled()) { StringBuffer infoBuffer = new StringBuffer(64) .append("Spooler Manager uses ") .append(numThreads) .append(" Thread(s)"); getLogger().info(infoBuffer.toString()); } active = true; numActive = 0; spoolThreads = new java.util.ArrayList(numThreads); for (int i = 0; i < numThreads; i++) { Thread reader = new Thread(this, "Spool Thread #" + i); spoolThreads.add(reader); reader.start(); } }
/** * Process this mail message by the appropriate processor as designated in the state of the Mail * object. * * @param mail the mail message to be processed */ protected void process(Mail mail) { while (true) { String processorName = mail.getState(); if (processorName.equals(Mail.GHOST)) { // This message should disappear return; } try { LinearProcessor processor = (LinearProcessor) processors.get(processorName); if (processor == null) { StringBuffer exceptionMessageBuffer = new StringBuffer(128) .append("Unable to find processor ") .append(processorName) .append(" requested for processing of ") .append(mail.getName()); String exceptionMessage = exceptionMessageBuffer.toString(); getLogger().debug(exceptionMessage); mail.setState(Mail.ERROR); throw new MailetException(exceptionMessage); } StringBuffer logMessageBuffer = null; if (getLogger().isDebugEnabled()) { logMessageBuffer = new StringBuffer(64) .append("Processing ") .append(mail.getName()) .append(" through ") .append(processorName); getLogger().debug(logMessageBuffer.toString()); } processor.service(mail); if (getLogger().isDebugEnabled()) { logMessageBuffer = new StringBuffer(128) .append("Processed ") .append(mail.getName()) .append(" through ") .append(processorName); getLogger().debug(logMessageBuffer.toString()); getLogger().debug("Result was " + mail.getState()); } return; } catch (Throwable e) { // This is a strange error situation that shouldn't ordinarily // happen StringBuffer exceptionBuffer = new StringBuffer(64) .append("Exception in processor <") .append(processorName) .append(">"); getLogger().error(exceptionBuffer.toString(), e); if (processorName.equals(Mail.ERROR)) { // We got an error on the error processor... // kill the message mail.setState(Mail.GHOST); mail.setErrorMessage(e.getMessage()); } else { // We got an error... send it to the requested processor if (!(e instanceof MessagingException)) { // We got an error... send it to the error processor mail.setState(Mail.ERROR); } mail.setErrorMessage(e.getMessage()); } } if (getLogger().isErrorEnabled()) { StringBuffer logMessageBuffer = new StringBuffer(128) .append("An error occurred processing ") .append(mail.getName()) .append(" through ") .append(processorName); getLogger().error(logMessageBuffer.toString()); getLogger().error("Result was " + mail.getState()); } } }