Coverage Report - org.mule.construct.AbstractFlowConstruct
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractFlowConstruct
0%
0/74
0%
0/14
0
AbstractFlowConstruct$1
0%
0/11
0%
0/2
0
AbstractFlowConstruct$1$1
0%
0/2
N/A
0
AbstractFlowConstruct$2
0%
0/5
N/A
0
AbstractFlowConstruct$3
0%
0/5
N/A
0
AbstractFlowConstruct$4
0%
0/5
N/A
0
 
 1  
 /*
 2  
  * $Id$
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 5  
  *
 6  
  * The software in this package is published under the terms of the CPAL v1.0
 7  
  * license, a copy of which has been included with this distribution in the
 8  
  * LICENSE.txt file.
 9  
  */
 10  
 
 11  
 package org.mule.construct;
 12  
 
 13  
 import org.mule.DefaultMuleEvent;
 14  
 import org.mule.RequestContext;
 15  
 import org.mule.api.MuleContext;
 16  
 import org.mule.api.MuleEvent;
 17  
 import org.mule.api.MuleException;
 18  
 import org.mule.api.construct.FlowConstruct;
 19  
 import org.mule.api.construct.FlowConstructAware;
 20  
 import org.mule.api.construct.FlowConstructInvalidException;
 21  
 import org.mule.api.context.MuleContextAware;
 22  
 import org.mule.api.exception.MessagingExceptionHandler;
 23  
 import org.mule.api.lifecycle.Disposable;
 24  
 import org.mule.api.lifecycle.Initialisable;
 25  
 import org.mule.api.lifecycle.InitialisationException;
 26  
 import org.mule.api.lifecycle.Lifecycle;
 27  
 import org.mule.api.lifecycle.LifecycleCallback;
 28  
 import org.mule.api.lifecycle.LifecycleState;
 29  
 import org.mule.api.lifecycle.Startable;
 30  
 import org.mule.api.lifecycle.Stoppable;
 31  
 import org.mule.api.processor.MessageProcessor;
 32  
 import org.mule.api.processor.MessageProcessorBuilder;
 33  
 import org.mule.api.routing.MessageInfoMapping;
 34  
 import org.mule.api.source.MessageSource;
 35  
 import org.mule.exception.DefaultServiceExceptionStrategy;
 36  
 import org.mule.management.stats.FlowConstructStatistics;
 37  
 import org.mule.processor.AbstractInterceptingMessageProcessor;
 38  
 import org.mule.processor.builder.InterceptingChainMessageProcessorBuilder;
 39  
 import org.mule.routing.MuleMessageInfoMapping;
 40  
 import org.mule.util.ClassUtils;
 41  
 
 42  
 import java.beans.ExceptionListener;
 43  
 
 44  
 import org.apache.commons.logging.Log;
 45  
 import org.apache.commons.logging.LogFactory;
 46  
 
 47  
 /**
 48  
  * Abstract implementation of {@link FlowConstruct} that: <li>Is constructed with
 49  
  * unique name and {@link MuleContext}. <li>Uses a {@link MessageSource} as the
 50  
  * source of messages. <li>Uses a chain of {@link MessageProcessor}s to process
 51  
  * messages. <li>Has lifecycle and propagates this lifecycle to both
 52  
  * {@link MessageSource} and {@link MessageProcessor}s in the correct order depending
 53  
  * on the lifecycle phase. <li>Allows an {@link ExceptionListener} to be set. <br/>
 54  
  * Implementations of <code>AbstractFlowConstuct</code> should implement
 55  
  * {@link#configureMessageProcessors(ChainMessageProcessorBuilder)} and
 56  
  * {@link #validateConstruct()} to construct the processing chain required and
 57  
  * validate the resulting construct. Validation may include validation of the type of
 58  
  * attributes of the {@link MessageSource}.
 59  
  * <p/>
 60  
  * Implementations may also implement {@link #doInitialise()}, {@link #doStart()},
 61  
  * {@link #doStop()} and {@link #doDispose()} if they need to perform any action on
 62  
  * lifecycle transitions.
 63  
  */
 64  0
 public abstract class AbstractFlowConstruct implements FlowConstruct, Lifecycle, MessageProcessor
 65  
 {
 66  0
     protected transient Log logger = LogFactory.getLog(getClass());
 67  
 
 68  
     protected String name;
 69  
     protected MessageSource messageSource;
 70  
     protected MessageProcessor messageProcessorChain;
 71  
     protected MessagingExceptionHandler exceptionListener;
 72  
     protected final FlowConstructLifecycleManager lifecycleManager;
 73  
     protected final MuleContext muleContext;
 74  
     protected final FlowConstructStatistics statistics;
 75  0
     protected MessageInfoMapping messageInfoMapping = new MuleMessageInfoMapping();
 76  
 
 77  
     public AbstractFlowConstruct(String name, MuleContext muleContext)
 78  0
     {
 79  0
         this.muleContext = muleContext;
 80  0
         this.name = name;
 81  0
         this.lifecycleManager = new FlowConstructLifecycleManager(this);
 82  0
         this.statistics = new FlowConstructStatistics(name);
 83  0
         this.exceptionListener = new DefaultServiceExceptionStrategy(muleContext);
 84  0
     }
 85  
 
 86  
     public final void initialise() throws InitialisationException
 87  
     {
 88  
         try
 89  
         {
 90  0
             lifecycleManager.fireInitialisePhase(new LifecycleCallback<FlowConstruct>()
 91  0
             {
 92  
                 public void onTransition(String phaseName, FlowConstruct object) throws MuleException
 93  
                 {
 94  0
                     createMessageProcessor();
 95  
 
 96  0
                     if (messageSource != null)
 97  
                     {
 98  
                         // Wrap chain to decouple lifecycle
 99  0
                         messageSource.setListener(new AbstractInterceptingMessageProcessor()
 100  0
                         {
 101  
                             public MuleEvent process(MuleEvent event) throws MuleException
 102  
                             {
 103  0
                                 return messageProcessorChain.process(event);
 104  
                             }
 105  
                         });
 106  
                     }
 107  
 
 108  0
                     injectFlowConstructMuleContext(messageSource);
 109  0
                     injectFlowConstructMuleContext(messageProcessorChain);
 110  0
                     initialiseIfInitialisable(messageSource);
 111  0
                     initialiseIfInitialisable(messageProcessorChain);
 112  
 
 113  0
                     doInitialise();
 114  
 
 115  0
                     validateConstruct();
 116  0
                 }
 117  
             });
 118  
 
 119  
         }
 120  0
         catch (InitialisationException e)
 121  
         {
 122  0
             throw e;
 123  
         }
 124  0
         catch (MuleException e)
 125  
         {
 126  0
             throw new InitialisationException(e, this);
 127  0
         }
 128  0
     }
 129  
 
 130  
     public final void start() throws MuleException
 131  
     {
 132  0
         lifecycleManager.fireStartPhase(new LifecycleCallback<FlowConstruct>()
 133  0
         {
 134  
             public void onTransition(String phaseName, FlowConstruct object) throws MuleException
 135  
             {
 136  0
                 startIfStartable(messageProcessorChain);
 137  0
                 startIfStartable(messageSource);
 138  0
                 doStart();
 139  0
             }
 140  
         });
 141  0
     }
 142  
 
 143  
     public final void stop() throws MuleException
 144  
     {
 145  0
         lifecycleManager.fireStopPhase(new LifecycleCallback<FlowConstruct>()
 146  0
         {
 147  
             public void onTransition(String phaseName, FlowConstruct object) throws MuleException
 148  
             {
 149  0
                 stopIfStoppable(messageSource);
 150  0
                 stopIfStoppable(messageProcessorChain);
 151  0
                 doStop();
 152  0
             }
 153  
         });
 154  0
     }
 155  
 
 156  
     public final void dispose()
 157  
     {
 158  
         try
 159  
         {
 160  0
             if (isStarted())
 161  
             {
 162  0
                 stop();
 163  
             }
 164  
 
 165  0
             lifecycleManager.fireDisposePhase(new LifecycleCallback<FlowConstruct>()
 166  0
             {
 167  
                 public void onTransition(String phaseName, FlowConstruct object) throws MuleException
 168  
                 {
 169  0
                     disposeIfDisposable(messageProcessorChain);
 170  0
                     disposeIfDisposable(messageSource);
 171  0
                     doDispose();
 172  0
                 }
 173  
             });
 174  
         }
 175  0
         catch (MuleException e)
 176  
         {
 177  0
             logger.error("Failed to stop service: " + name, e);
 178  0
         }
 179  0
     }
 180  
 
 181  
     public boolean isStarted()
 182  
     {
 183  0
         return lifecycleManager.getState().isStarted();
 184  
     }
 185  
 
 186  
     public boolean isStopped()
 187  
     {
 188  0
         return lifecycleManager.getState().isStopped();
 189  
     }
 190  
 
 191  
     public boolean isStopping()
 192  
     {
 193  0
         return lifecycleManager.getState().isStopping();
 194  
     }
 195  
 
 196  
     /**
 197  
      * Creates a {@link MessageProcessor} that will process messages from the
 198  
      * configured {@link MessageSource}.
 199  
      * <p>
 200  
      * The default implementation of this methods uses a
 201  
      * {@link InterceptingChainMessageProcessorBuilder} and allows a chain of
 202  
      * {@link MessageProcessor}s to be configured using the
 203  
      * {@link #configureMessageProcessors(InterceptingChainMessageProcessorBuilder)}
 204  
      * method but if you wish to use another {@link MessageProcessorBuilder} or just
 205  
      * a single {@link MessageProcessor} then this method can be overridden and
 206  
      * return a single {@link MessageProcessor} instead.
 207  
      * 
 208  
      * @throws MuleException
 209  
      */
 210  
     protected void createMessageProcessor() throws MuleException
 211  
     {
 212  0
         InterceptingChainMessageProcessorBuilder builder = new InterceptingChainMessageProcessorBuilder(this);
 213  0
         configureMessageProcessors(builder);
 214  0
         messageProcessorChain = builder.build();
 215  0
     }
 216  
 
 217  
     /**
 218  
      * Used to configure the processing chain for this <code>FlowConstuct</code by
 219  
      * adding {@link MessageProcessor}s to the chain using the builder provided.
 220  
      * <p>
 221  
      * To use a different builder of to construct a composite
 222  
      * {@link MessageProcessor} manually override {@link #createMessageProcessor()}
 223  
      * instead.
 224  
      * 
 225  
      * @param builder instance of {@link InterceptingChainMessageProcessorBuilder}
 226  
      * @throws MuleException 
 227  
      */
 228  
     protected abstract void configureMessageProcessors(InterceptingChainMessageProcessorBuilder builder) throws MuleException;
 229  
 
 230  
     public String getName()
 231  
     {
 232  0
         return name;
 233  
     }
 234  
 
 235  
     public MessagingExceptionHandler getExceptionListener()
 236  
     {
 237  0
         return exceptionListener;
 238  
     }
 239  
 
 240  
     public void setExceptionListener(MessagingExceptionHandler exceptionListener)
 241  
     {
 242  0
         this.exceptionListener = exceptionListener;
 243  0
     }
 244  
 
 245  
     public LifecycleState getLifecycleState()
 246  
     {
 247  0
         return lifecycleManager.getState();
 248  
     }
 249  
 
 250  
     public MuleContext getMuleContext()
 251  
     {
 252  0
         return muleContext;
 253  
     }
 254  
 
 255  
     public MessageSource getMessageSource()
 256  
     {
 257  0
         return messageSource;
 258  
     }
 259  
 
 260  
     public void setMessageSource(MessageSource messageSource)
 261  
     {
 262  0
         this.messageSource = messageSource;
 263  0
     }
 264  
 
 265  
     public FlowConstructStatistics getStatistics()
 266  
     {
 267  0
         return statistics;
 268  
     }
 269  
 
 270  
     public MessageInfoMapping getMessageInfoMapping()
 271  
     {
 272  0
         return messageInfoMapping;
 273  
     }
 274  
 
 275  
     public void setMessageInfoMapping(MessageInfoMapping messageInfoMapping)
 276  
     {
 277  0
         this.messageInfoMapping = messageInfoMapping;
 278  0
     }
 279  
 
 280  
     protected void doInitialise() throws InitialisationException
 281  
     {
 282  
         // Empty template method
 283  0
     }
 284  
 
 285  
     protected void doStart() throws MuleException
 286  
     {
 287  
         // Empty template method
 288  0
     }
 289  
 
 290  
     protected void doStop() throws MuleException
 291  
     {
 292  
         // Empty template method
 293  0
     }
 294  
 
 295  
     protected void doDispose()
 296  
     {
 297  
         // Empty template method
 298  0
     }
 299  
 
 300  
     /**
 301  
      * Validates configured flow construct
 302  
      * 
 303  
      * @throws FlowConstructInvalidException if the flow construct does not pass
 304  
      *             validation
 305  
      */
 306  
     protected void validateConstruct() throws FlowConstructInvalidException
 307  
     {
 308  
         // Empty template method
 309  0
     }
 310  
 
 311  
     private void injectFlowConstructMuleContext(Object candidate)
 312  
     {
 313  0
         if (candidate instanceof FlowConstructAware)
 314  
         {
 315  0
             ((FlowConstructAware) candidate).setFlowConstruct(this);
 316  
         }
 317  0
         if (candidate instanceof MuleContextAware)
 318  
         {
 319  0
             ((MuleContextAware) candidate).setMuleContext(muleContext);
 320  
         }
 321  0
     }
 322  
 
 323  
     @Override
 324  
     public String toString()
 325  
     {
 326  0
         return String.format("%s{%s}", ClassUtils.getSimpleName(this.getClass()), getName());
 327  
     }
 328  
 
 329  
     private void initialiseIfInitialisable(Object candidate) throws InitialisationException
 330  
     {
 331  0
         if (candidate instanceof Initialisable)
 332  
         {
 333  0
             ((Initialisable) candidate).initialise();
 334  
         }
 335  0
     }
 336  
 
 337  
     private void startIfStartable(Object candidate) throws MuleException
 338  
     {
 339  0
         if (candidate instanceof Startable)
 340  
         {
 341  0
             ((Startable) candidate).start();
 342  
         }
 343  0
     }
 344  
 
 345  
     private void stopIfStoppable(Object candidate) throws MuleException
 346  
     {
 347  0
         if (candidate instanceof Stoppable)
 348  
         {
 349  0
             ((Stoppable) candidate).stop();
 350  
         }
 351  0
     }
 352  
 
 353  
     private void disposeIfDisposable(Object candidate)
 354  
     {
 355  0
         if (candidate instanceof Disposable)
 356  
         {
 357  0
             ((Disposable) candidate).dispose();
 358  
         }
 359  0
     }
 360  
     
 361  
     public MuleEvent process(MuleEvent event) throws MuleException
 362  
     {
 363  0
         MuleEvent newEvent = new DefaultMuleEvent(event.getMessage(), event.getEndpoint(), this, event);
 364  0
         RequestContext.setEvent(newEvent);
 365  0
         return messageProcessorChain.process(newEvent);
 366  
     }
 367  
 
 368  
 }