org.mule.component.AbstractComponent.java Source code

Java tutorial

Introduction

Here is the source code for org.mule.component.AbstractComponent.java

Source

/*
 * $Id$
 * --------------------------------------------------------------------------------------
 * 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.component;

import org.mule.DefaultMuleEvent;
import org.mule.DefaultMuleMessage;
import org.mule.OptimizedRequestContext;
import org.mule.VoidResult;
import org.mule.api.AnnotatedObject;
import org.mule.api.MuleContext;
import org.mule.api.MuleEvent;
import org.mule.api.MuleException;
import org.mule.api.MuleMessage;
import org.mule.api.component.Component;
import org.mule.api.construct.FlowConstruct;
import org.mule.api.context.MuleContextAware;
import org.mule.api.context.notification.ServerNotificationHandler;
import org.mule.api.interceptor.Interceptor;
import org.mule.api.lifecycle.Initialisable;
import org.mule.api.lifecycle.InitialisationException;
import org.mule.api.lifecycle.Lifecycle;
import org.mule.api.lifecycle.LifecycleCallback;
import org.mule.api.lifecycle.LifecycleException;
import org.mule.api.processor.MessageProcessor;
import org.mule.api.processor.MessageProcessorChain;
import org.mule.api.service.Service;
import org.mule.api.transformer.Transformer;
import org.mule.config.i18n.CoreMessages;
import org.mule.config.i18n.MessageFactory;
import org.mule.construct.SimpleService;
import org.mule.context.notification.ComponentMessageNotification;
import org.mule.context.notification.OptimisedNotificationHandler;
import org.mule.management.stats.ComponentStatistics;
import org.mule.processor.chain.DefaultMessageProcessorChainBuilder;
import org.mule.transformer.TransformerTemplate;
import org.mule.transport.NullPayload;
import org.mule.util.ClassUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.xml.namespace.QName;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Abstract {@link Component} to be used by all {@link Component} implementations.
 */
public abstract class AbstractComponent implements Component, MuleContextAware, Lifecycle, AnnotatedObject {

    /**
     * logger used by this class
     */
    protected final Log logger = LogFactory.getLog(this.getClass());

    protected FlowConstruct flowConstruct;
    protected ComponentStatistics statistics = null;
    protected ServerNotificationHandler notificationHandler;
    protected List<Interceptor> interceptors = new ArrayList<Interceptor>();
    protected MessageProcessorChain interceptorChain;
    protected MuleContext muleContext;
    protected ComponentLifecycleManager lifecycleManager;
    private final Map<QName, Object> annotations = new ConcurrentHashMap<QName, Object>();

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

    public List<Interceptor> getInterceptors() {
        return interceptors;
    }

    public void setInterceptors(List<Interceptor> interceptors) {
        this.interceptors = interceptors;
    }

    public AbstractComponent() {
        statistics = new ComponentStatistics();
        lifecycleManager = new ComponentLifecycleManager(getName(), this);
    }

    private MuleEvent invokeInternal(MuleEvent event) throws MuleException {
        // Ensure we have event in ThreadLocal
        OptimizedRequestContext.unsafeSetEvent(event);

        if (logger.isTraceEnabled()) {
            logger.trace(String.format("Invoking %s component for service %s", this.getClass().getName(),
                    flowConstruct.getName()));
        }

        if (!lifecycleManager.getState().isStarted() || lifecycleManager.getState().isStopping()) {
            throw new LifecycleException(CoreMessages.isStopped(flowConstruct.getName()), this);
        }

        // Invoke component implementation and gather statistics
        try {
            fireComponentNotification(event.getMessage(), ComponentMessageNotification.COMPONENT_PRE_INVOKE);

            long startTime = 0;
            if (statistics.isEnabled()) {
                startTime = System.currentTimeMillis();
            }

            Object result = doInvoke(event);

            if (statistics.isEnabled()) {
                statistics.addExecutionTime(System.currentTimeMillis() - startTime);
            }

            MuleEvent resultEvent = createResultEvent(event, result);
            // Components only have access to the original event, so propogate the
            // stop further processing
            resultEvent.setStopFurtherProcessing(event.isStopFurtherProcessing());
            fireComponentNotification(resultEvent.getMessage(), ComponentMessageNotification.COMPONENT_POST_INVOKE);

            return resultEvent;
        } catch (MuleException me) {
            throw me;
        } catch (Exception e) {
            throw new ComponentException(CoreMessages.failedToInvoke(this.toString()), event, this, e);
        }
    }

    public MuleEvent process(MuleEvent event) throws MuleException {
        if (interceptorChain == null) {
            return invokeInternal(event);
        } else {
            return interceptorChain.process(event);
        }
    }

    protected MuleEvent createResultEvent(MuleEvent event, Object result) throws MuleException {
        if (result instanceof MuleMessage) {
            return new DefaultMuleEvent((MuleMessage) result, event);
        } else if (result instanceof VoidResult) {
            return event;
        } else if (result != null) {
            event.getMessage().applyTransformers(event, Collections.<Transformer>singletonList(
                    new TransformerTemplate(new TransformerTemplate.OverwitePayloadCallback(result))));
            return event;
        } else {
            DefaultMuleMessage emptyMessage = new DefaultMuleMessage(NullPayload.getInstance(), muleContext);
            emptyMessage.propagateRootId(event.getMessage());
            return new DefaultMuleEvent(emptyMessage, event);
        }
    }

    protected abstract Object doInvoke(MuleEvent event) throws Exception;

    @Override
    public String toString() {
        return String.format("%s{%s}", ClassUtils.getSimpleName(this.getClass()), getName());
    }

    public void release() {
        // nothing to do
    }

    public ComponentStatistics getStatistics() {
        return statistics;
    }

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

    public FlowConstruct getFlowConstruct() {
        return flowConstruct;
    }

    public final void initialise() throws InitialisationException {
        if (flowConstruct == null) {
            throw new InitialisationException(MessageFactory
                    .createStaticMessage("Component has not been initialized properly, no flow constuct."), this);
        }

        lifecycleManager.fireInitialisePhase(new LifecycleCallback<Component>() {
            public void onTransition(String phaseName, Component object) throws MuleException {
                DefaultMessageProcessorChainBuilder chainBuilder = new DefaultMessageProcessorChainBuilder(
                        flowConstruct);
                chainBuilder.setName("Component interceptor processor chain for :" + getName());
                for (Interceptor interceptor : interceptors) {
                    chainBuilder.chain(interceptor);
                }
                chainBuilder.chain(new MessageProcessor() {
                    public MuleEvent process(MuleEvent event) throws MuleException {
                        return invokeInternal(event);
                    }
                });

                interceptorChain = chainBuilder.build();
                if (interceptorChain instanceof MuleContextAware) {
                    ((MuleContextAware) interceptorChain).setMuleContext(muleContext);
                }
                if (interceptorChain instanceof Initialisable) {
                    ((Initialisable) interceptorChain).initialise();
                }
                doInitialise();
            }
        });
    }

    protected void doInitialise() throws InitialisationException {
        // Default implementation is no-op
    }

    public void dispose() {
        lifecycleManager.fireDisposePhase(new LifecycleCallback<Component>() {
            public void onTransition(String phaseName, Component object) throws MuleException {
                doDispose();
            }
        });
    }

    protected void doDispose() {
        // Default implementation is no-op
    }

    public void stop() throws MuleException {
        try {
            lifecycleManager.fireStopPhase(new LifecycleCallback<Component>() {
                public void onTransition(String phaseName, Component object) throws MuleException {
                    doStop();
                }
            });
        } catch (MuleException e) {
            e.printStackTrace();
            throw e;
        }
    }

    protected void doStart() throws MuleException {
        // Default implementation is no-op
    }

    public void start() throws MuleException {
        lifecycleManager.fireStartPhase(new LifecycleCallback<Component>() {
            public void onTransition(String phaseName, Component object) throws MuleException {
                notificationHandler = new OptimisedNotificationHandler(muleContext.getNotificationManager(),
                        ComponentMessageNotification.class);
                doStart();
            }
        });

    }

    protected void doStop() throws MuleException {
        // Default implementation is no-op
    }

    protected void fireComponentNotification(MuleMessage message, int action) {
        if (notificationHandler != null
                && notificationHandler.isNotificationEnabled(ComponentMessageNotification.class)) {
            notificationHandler
                    .fireNotification(new ComponentMessageNotification(message, this, flowConstruct, action));
        }
    }

    protected String getName() {
        StringBuffer sb = new StringBuffer();
        if (flowConstruct != null) {
            sb.append(flowConstruct.getName());
            sb.append(".");
        }
        sb.append("component");
        if (!(flowConstruct instanceof Service || flowConstruct instanceof SimpleService)) {
            sb.append(".");
            sb.append(System.identityHashCode(this));
        }
        return sb.toString();
    }

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

    public final Map<QName, Object> getAnnotations() {
        return Collections.unmodifiableMap(annotations);
    }

    public synchronized final void setAnnotations(Map<QName, Object> newAnnotations) {
        annotations.clear();
        annotations.putAll(newAnnotations);
    }
}