org.apache.james.mailetcontainer.lib.AbstractStateCompositeProcessor.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.james.mailetcontainer.lib.AbstractStateCompositeProcessor.java

Source

/****************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one   *
 * or more contributor license agreements.  See the NOTICE file *
 * distributed with this work for additional information        *
 * regarding copyright ownership.  The ASF licenses this file   *
 * to you 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.mailetcontainer.lib;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.mail.MessagingException;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.james.lifecycle.api.Configurable;
import org.apache.james.lifecycle.api.LifecycleUtil;
import org.apache.james.lifecycle.api.LogEnabled;
import org.apache.james.mailetcontainer.api.MailProcessor;
import org.apache.james.mailetcontainer.impl.jmx.JMXStateCompositeProcessorListener;
import org.apache.mailet.Mail;
import org.slf4j.Logger;

/**
 * Abstract base class for {@link org.apache.james.mailetcontainer.impl.camel.CamelCompositeProcessor} which service the
 * {@link Mail} with a {@link org.apache.james.mailetcontainer.impl.camel.CamelProcessor} instances
 */
public abstract class AbstractStateCompositeProcessor implements MailProcessor, Configurable, LogEnabled {

    private final List<CompositeProcessorListener> listeners = Collections
            .synchronizedList(new ArrayList<CompositeProcessorListener>());
    private final Map<String, MailProcessor> processors = new HashMap<String, MailProcessor>();
    protected Logger logger;
    protected HierarchicalConfiguration config;

    private JMXStateCompositeProcessorListener jmxListener;
    private boolean enableJmx = true;

    /**
     * @see org.apache.james.lifecycle.api.LogEnabled#setLog(org.slf4j.Logger)
     */
    public void setLog(Logger log) {
        this.logger = log;

    }

    public void addListener(CompositeProcessorListener listener) {
        listeners.add(listener);
    }

    public List<CompositeProcessorListener> getListeners() {
        return listeners;
    }

    public void removeListener(CompositeProcessorListener listener) {
        listeners.remove(listener);
    }

    /**
     * @see
     * org.apache.james.lifecycle.api.Configurable#configure(org.apache.commons.configuration.HierarchicalConfiguration)
     */
    public void configure(HierarchicalConfiguration config) throws ConfigurationException {
        this.config = config;
        this.enableJmx = config.getBoolean("[@enableJmx]", true);

    }

    /**
     * Service the given {@link Mail} by hand the {@link Mail} over the
     * {@link MailProcessor} which is responsible for the
     * {@link Mail#getState()}
     */
    public void service(Mail mail) throws MessagingException {
        long start = System.currentTimeMillis();
        MessagingException ex = null;
        MailProcessor processor = getProcessor(mail.getState());

        if (processor != null) {
            logger.debug("Call MailProcessor " + mail.getState());
            try {
                processor.service(mail);

                if (Mail.GHOST.equals(mail.getState())) {
                    LifecycleUtil.dispose(mail);
                }
                /*
                 * // check the mail needs further processing if
                 * (Mail.GHOST.equalsIgnoreCase(mail.getState()) == false) {
                 * service(mail); } else { LifecycleUtil.dispose(mail); }
                 */
            } catch (MessagingException e) {
                ex = e;
                throw e;
            } finally {
                long end = System.currentTimeMillis() - start;
                for (CompositeProcessorListener listener : listeners) {
                    listener.afterProcessor(processor, mail.getName(), end, ex);
                }
            }
        } else {
            throw new MessagingException(
                    "No processor found for mail " + mail.getName() + " with state " + mail.getState());
        }
    }

    /**
     * Return a {@link MailProcessor} for a given state
     * 
     * @param state
     * @return processor
     */
    public MailProcessor getProcessor(String state) {
        return processors.get(state);
    }

    public String[] getProcessorStates() {
        return processors.keySet().toArray(new String[processors.size()]);
    }

    /**
     * Check if all needed Processors are configured and if not throw a
     * {@link ConfigurationException}
     * 
     * @throws ConfigurationException
     */
    private void checkProcessors() throws ConfigurationException {
        boolean errorProcessorFound = false;
        boolean rootProcessorFound = false;
        for (String name : processors.keySet()) {
            if (name.equals(Mail.DEFAULT)) {
                rootProcessorFound = true;
            } else if (name.equals(Mail.ERROR)) {
                errorProcessorFound = true;
            }

            if (errorProcessorFound && rootProcessorFound) {
                return;
            }
        }
        if (!errorProcessorFound) {
            throw new ConfigurationException("You need to configure a Processor with name " + Mail.ERROR);
        } else if (!rootProcessorFound) {
            throw new ConfigurationException("You need to configure a Processor with name " + Mail.DEFAULT);
        }
    }

    @PostConstruct
    public void init() throws Exception {
        List<HierarchicalConfiguration> processorConfs = config.configurationsAt("processor");
        for (HierarchicalConfiguration processorConf : processorConfs) {
            String processorName = processorConf.getString("[@state]");

            // if the "child" processor has no jmx config we just use the one of
            // the composite
            if (!processorConf.containsKey("[@enableJmx]")) {
                processorConf.addProperty("[@enableJmx]", enableJmx);
            }
            processors.put(processorName, createMailProcessor(processorName, processorConf));
        }

        if (enableJmx) {
            this.jmxListener = new JMXStateCompositeProcessorListener(this);
            addListener(jmxListener);
        }

        // check if all needed processors are configured
        checkProcessors();
    }

    @PreDestroy
    public void dispose() {
        String names[] = getProcessorStates();
        for (String name : names) {
            MailProcessor processor = getProcessor(name);
            if (processor instanceof AbstractStateMailetProcessor) {
                ((AbstractStateMailetProcessor) processor).destroy();
            }

        }

        if (jmxListener != null) {
            jmxListener.dispose();
        }
    }

    /**
     * Create a new {@link MailProcessor}
     * 
     * @param state
     * @param config
     * @return container
     * @throws Exception
     */
    protected abstract MailProcessor createMailProcessor(String state, HierarchicalConfiguration config)
            throws Exception;

    /**
     * A Listener which will get called after
     * {@link org.apache.james.mailetcontainer.api.MailProcessor#service(Mail)} was called
     */
    public interface CompositeProcessorListener {

        /**
         * Get called after the processing via a {@link MailProcessor} was
         * complete
         * 
         * @param processor
         * @param mailName
         * @param processTime
         *            in ms
         * @param e
         *            or null if no exception was thrown
         */
        void afterProcessor(MailProcessor processor, String mailName, long processTime, MessagingException e);

    }

}