All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mule.routing.AbstractSelectiveRouter Maven / Gradle / Ivy

There is a newer version: 3.9.0
Show newest version
/*
 * $Id: AbstractSelectiveRouter.java 23008 2011-09-22 07:58:14Z dirk.olmes $
 * --------------------------------------------------------------------------------------
 * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 *
 * The software in this package is published under the terms of the CPAL v1.0
 * license, a copy of which has been included with this distribution in the
 * LICENSE.txt file.
 */

package org.mule.routing;

import org.mule.api.AnnotatedObject;
import org.mule.api.MuleContext;
import org.mule.api.MuleEvent;
import org.mule.api.MuleException;
import org.mule.api.MuleRuntimeException;
import org.mule.api.construct.FlowConstruct;
import org.mule.api.construct.FlowConstructAware;
import org.mule.api.context.MuleContextAware;
import org.mule.api.lifecycle.Disposable;
import org.mule.api.lifecycle.Initialisable;
import org.mule.api.lifecycle.InitialisationException;
import org.mule.api.lifecycle.Lifecycle;
import org.mule.api.lifecycle.Startable;
import org.mule.api.lifecycle.Stoppable;
import org.mule.api.processor.MessageProcessor;
import org.mule.api.routing.RoutePathNotFoundException;
import org.mule.api.routing.RouterResultsHandler;
import org.mule.api.routing.RouterStatisticsRecorder;
import org.mule.api.routing.SelectiveRouter;
import org.mule.api.routing.filter.Filter;
import org.mule.config.i18n.MessageFactory;
import org.mule.management.stats.RouterStatistics;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.xml.namespace.QName;

import org.apache.commons.collections.ListUtils;

public abstract class AbstractSelectiveRouter
    implements SelectiveRouter, RouterStatisticsRecorder, Lifecycle, FlowConstructAware, MuleContextAware, AnnotatedObject
{
    private final List conditionalMessageProcessors = new ArrayList();
    private MessageProcessor defaultProcessor;
    private final RouterResultsHandler resultsHandler = new DefaultRouterResultsHandler();
    private RouterStatistics routerStatistics;

    final AtomicBoolean initialised = new AtomicBoolean(false);
    final AtomicBoolean starting = new AtomicBoolean(false);
    final AtomicBoolean started = new AtomicBoolean(false);
    private FlowConstruct flowConstruct;
    private MuleContext muleContext;
    private final Map annotations = new ConcurrentHashMap();

    public AbstractSelectiveRouter()
    {
        routerStatistics = new RouterStatistics(RouterStatistics.TYPE_OUTBOUND);
    }

    public void setFlowConstruct(FlowConstruct flowConstruct)
    {
        this.flowConstruct = flowConstruct;
    }

    public void setMuleContext(MuleContext context)
    {
        this.muleContext = context;
    }

    public void initialise() throws InitialisationException
    {
        synchronized (conditionalMessageProcessors)
        {
            for (Object o : getLifecycleManagedObjects())
            {
                if (o instanceof FlowConstructAware)
                {
                    ((FlowConstructAware) o).setFlowConstruct(flowConstruct);
                }
                if (o instanceof MuleContextAware)
                {
                    ((MuleContextAware) o).setMuleContext(muleContext);
                }
                if (o instanceof Initialisable)
                {
                    ((Initialisable) o).initialise();
                }
            }
        }
        initialised.set(true);
    }

    public void start() throws MuleException
    {
        synchronized (conditionalMessageProcessors)
        {
            starting.set(true);
            for (Object o : getLifecycleManagedObjects())
            {
                if (o instanceof Startable)
                {
                    ((Startable) o).start();
                }
            }

            started.set(true);
            starting.set(false);
        }
    }

    public void stop() throws MuleException
    {
        synchronized (conditionalMessageProcessors)
        {
            for (Object o : getLifecycleManagedObjects())
            {
                if (o instanceof Stoppable)
                {
                    ((Stoppable) o).stop();
                }
            }

            started.set(false);
        }
    }

    public void dispose()
    {
        synchronized (conditionalMessageProcessors)
        {
            for (Object o : getLifecycleManagedObjects())
            {
                if (o instanceof Disposable)
                {
                    ((Disposable) o).dispose();
                }
            }
        }
    }

    public void addRoute(MessageProcessor processor, Filter filter)
    {
        synchronized (conditionalMessageProcessors)
        {
            MessageProcessorFilterPair addedPair = new MessageProcessorFilterPair(processor, filter);
            conditionalMessageProcessors.add(transitionLifecycleManagedObjectForAddition(addedPair));
        }
    }

    public void removeRoute(MessageProcessor processor)
    {
        updateRoute(processor, new RoutesUpdater()
        {
            public void updateAt(int index)
            {
                MessageProcessorFilterPair removedPair = conditionalMessageProcessors.remove(index);

                transitionLifecycleManagedObjectForRemoval(removedPair);
            }
        });
    }

    public void updateRoute(final MessageProcessor processor, final Filter filter)
    {
        updateRoute(processor, new RoutesUpdater()
        {
            public void updateAt(int index)
            {
                MessageProcessorFilterPair addedPair = new MessageProcessorFilterPair(processor, filter);

                MessageProcessorFilterPair removedPair = conditionalMessageProcessors.set(index,
                    transitionLifecycleManagedObjectForAddition(addedPair));

                transitionLifecycleManagedObjectForRemoval(removedPair);
            }
        });
    }

    public void setDefaultRoute(MessageProcessor processor)
    {
        defaultProcessor = processor;
    }

    public MuleEvent process(MuleEvent event) throws MuleException
    {
        Collection selectedProcessors = selectProcessors(event);

        if (!selectedProcessors.isEmpty())
        {
            return routeWithProcessors(selectedProcessors, event);
        }

        if (defaultProcessor != null)
        {
            return routeWithProcessor(defaultProcessor, event);
        }

        if (getRouterStatistics() != null  && getRouterStatistics().isEnabled())
        {
            getRouterStatistics().incrementNoRoutedMessage();
        }

        throw new RoutePathNotFoundException(
            MessageFactory.createStaticMessage("Can't process message because no route has been found matching any filter and no default route is defined"),
            event, this);
    }

    /**
     * @return the processors selected according to the specific router strategy or
     *         an empty collection (not null).
     */
    protected abstract Collection selectProcessors(MuleEvent event);

    private Collection getLifecycleManagedObjects()
    {
        if (defaultProcessor == null)
        {
            return conditionalMessageProcessors;
        }

        return ListUtils.union(conditionalMessageProcessors, Collections.singletonList(defaultProcessor));
    }

    private  O transitionLifecycleManagedObjectForAddition(O managedObject)
    {
        try
        {
            if ((flowConstruct != null) && (managedObject instanceof FlowConstructAware))
            {
                ((FlowConstructAware) managedObject).setFlowConstruct(flowConstruct);
            }

            if ((muleContext != null) && (managedObject instanceof MuleContextAware))
            {
                ((MuleContextAware) managedObject).setMuleContext(muleContext);
            }

            if ((initialised.get()) && (managedObject instanceof Initialisable))
            {
                ((Initialisable) managedObject).initialise();
            }

            if ((started.get()) && (managedObject instanceof Startable))
            {
                ((Startable) managedObject).start();
            }
        }
        catch (MuleException me)
        {
            throw new MuleRuntimeException(me);
        }

        return managedObject;
    }

    private  O transitionLifecycleManagedObjectForRemoval(O managedObject)
    {
        try
        {
            if (managedObject instanceof Stoppable)
            {
                ((Stoppable) managedObject).stop();
            }

            if (managedObject instanceof Disposable)
            {
                ((Disposable) managedObject).dispose();
            }
        }
        catch (MuleException me)
        {
            throw new MuleRuntimeException(me);
        }

        return managedObject;
    }

    private MuleEvent routeWithProcessor(MessageProcessor processor, MuleEvent event) throws MuleException
    {
        return routeWithProcessors(Collections.singleton(processor), event);
    }

    private MuleEvent routeWithProcessors(Collection processors, MuleEvent event)
        throws MuleException
    {
        List results = new ArrayList();

        for (MessageProcessor processor : processors)
        {
            processEventWithProcessor(event, processor, results);
        }

        return resultsHandler.aggregateResults(results, event, event.getMuleContext());
    }

    private void processEventWithProcessor(MuleEvent event,
                                           MessageProcessor processor,
                                           List results) throws MuleException
    {
        results.add(processor.process(event));

        if (getRouterStatistics() != null && getRouterStatistics().isEnabled())
        {
            getRouterStatistics().incrementRoutedMessage(processor);
        }
    }

    public List getConditionalMessageProcessors()
    {
        return Collections.unmodifiableList(conditionalMessageProcessors);
    }

    private interface RoutesUpdater
    {
        void updateAt(int index);
    }

    private void updateRoute(MessageProcessor processor, RoutesUpdater routesUpdater)
    {
        synchronized (conditionalMessageProcessors)
        {
            for (int i = 0; i < conditionalMessageProcessors.size(); i++)
            {
                if (conditionalMessageProcessors.get(i).getMessageProcessor().equals(processor))
                {
                    routesUpdater.updateAt(i);
                }
            }
        }
    }

    public RouterStatistics getRouterStatistics()
    {
        return routerStatistics;
    }

    public void setRouterStatistics(RouterStatistics routerStatistics)
    {
        this.routerStatistics = routerStatistics;
    }

    public final Object getAnnotation(QName name)
    {
        return annotations.get(name);
    }

    public final Map getAnnotations()
    {
        return Collections.unmodifiableMap(annotations);
    }

    public synchronized final void setAnnotations(Map newAnnotations)
    {
        annotations.clear();
        annotations.putAll(newAnnotations);
    }

    @Override
    public String toString()
    {
        return String.format("%s [flow-construct=%s, started=%s]", getClass().getSimpleName(),
            flowConstruct != null ? flowConstruct.getName() : null, started);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy