Coverage Report - org.mule.source.StartableCompositeMessageSource
 
Classes in this File Line Coverage Branch Coverage Complexity
StartableCompositeMessageSource
0%
0/73
0%
0/40
0
StartableCompositeMessageSource$InternalMessageProcessor
0%
0/10
0%
0/6
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.source;
 12  
 
 13  
 import org.mule.DefaultMuleEvent;
 14  
 import org.mule.api.MuleEvent;
 15  
 import org.mule.api.MuleException;
 16  
 import org.mule.api.construct.FlowConstruct;
 17  
 import org.mule.api.construct.FlowConstructAware;
 18  
 import org.mule.api.endpoint.OutboundEndpoint;
 19  
 import org.mule.api.lifecycle.Disposable;
 20  
 import org.mule.api.lifecycle.Initialisable;
 21  
 import org.mule.api.lifecycle.InitialisationException;
 22  
 import org.mule.api.lifecycle.Lifecycle;
 23  
 import org.mule.api.lifecycle.LifecycleException;
 24  
 import org.mule.api.lifecycle.Startable;
 25  
 import org.mule.api.lifecycle.Stoppable;
 26  
 import org.mule.api.processor.MessageProcessor;
 27  
 import org.mule.api.source.CompositeMessageSource;
 28  
 import org.mule.api.source.MessageSource;
 29  
 import org.mule.config.i18n.CoreMessages;
 30  
 import org.mule.util.ObjectUtils;
 31  
 
 32  
 import java.util.ArrayList;
 33  
 import java.util.Collections;
 34  
 import java.util.List;
 35  
 
 36  
 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
 37  
 
 38  
 import org.apache.commons.logging.Log;
 39  
 import org.apache.commons.logging.LogFactory;
 40  
 
 41  
 /**
 42  
  * Implementation of {@link CompositeMessageSource} that propagates both injection of {@link FlowConstruct}
 43  
  * and lifecycle to nested {@link MessageSource}s.
 44  
  * <p>
 45  
  * <li>This message source cannot be started without a listener set.
 46  
  * <li>If sources are added when this composie is started they will be started as well.
 47  
  * <li>If a {@link MessageSource} is started in isolation when composite is stopped then messages will be
 48  
  * lost.
 49  
  * <li>Message will only be received from endpoints if the connector is also started.
 50  
  */
 51  0
 public class StartableCompositeMessageSource
 52  
     implements CompositeMessageSource, Lifecycle, FlowConstructAware
 53  
 {
 54  0
     protected static final Log log = LogFactory.getLog(StartableCompositeMessageSource.class);
 55  
 
 56  
     protected MessageProcessor listener;
 57  0
     protected AtomicBoolean initialised = new AtomicBoolean(false);
 58  0
     protected AtomicBoolean started = new AtomicBoolean(false);
 59  0
     protected final List<MessageSource> sources = Collections.synchronizedList(new ArrayList<MessageSource>());
 60  0
     protected AtomicBoolean starting = new AtomicBoolean(false);
 61  
     protected FlowConstruct flowConstruct;
 62  0
     private final MessageProcessor internalListener = new InternalMessageProcessor();
 63  
 
 64  
     public void addSource(MessageSource source) throws MuleException
 65  
     {
 66  0
         synchronized (sources)
 67  
         {
 68  0
             sources.add(source);
 69  0
         }
 70  0
         source.setListener(internalListener);
 71  0
         if (initialised.get())
 72  
         {
 73  0
             if (source instanceof FlowConstructAware)
 74  
             {
 75  0
                 ((FlowConstructAware) source).setFlowConstruct(flowConstruct);
 76  
             }
 77  0
             if (source instanceof Initialisable)
 78  
             {
 79  0
                 ((Initialisable) source).initialise();
 80  
             }
 81  
         }
 82  0
         if (started.get() && source instanceof Startable)
 83  
         {
 84  0
             ((Startable) source).start();
 85  
         }
 86  0
     }
 87  
 
 88  
     public void removeSource(MessageSource source) throws MuleException
 89  
     {
 90  0
         if (started.get())
 91  
         {
 92  0
             if (source instanceof Stoppable)
 93  
             {
 94  0
                 ((Stoppable) source).stop();
 95  
             }
 96  0
             if (source instanceof Disposable)
 97  
             {
 98  0
                 ((Disposable) source).dispose();
 99  
             }
 100  
         }
 101  0
         synchronized (sources)
 102  
         {
 103  0
             sources.remove(source);
 104  0
         }
 105  0
     }
 106  
     
 107  
     public void setMessageSources(List<MessageSource> sources) throws MuleException
 108  
     {
 109  0
         this.sources.clear();
 110  0
         for (MessageSource messageSource : sources)
 111  
         {
 112  0
             addSource(messageSource);
 113  
         }
 114  0
     }
 115  
     
 116  
     public void initialise() throws InitialisationException
 117  
     {
 118  0
         if (listener == null)
 119  
         {
 120  0
             throw new InitialisationException(CoreMessages.objectIsNull("listener"), this);
 121  
         }
 122  0
         synchronized (sources)
 123  
         {
 124  0
             for (MessageSource source : sources)
 125  
             {
 126  0
                 if (source instanceof FlowConstructAware)
 127  
                 {
 128  0
                     ((FlowConstructAware) source).setFlowConstruct(flowConstruct);
 129  
                 }
 130  0
                 if (source instanceof Initialisable)
 131  
                 {
 132  0
                     ((Initialisable) source).initialise();
 133  
                 }
 134  
             }
 135  0
         }
 136  0
         initialised.set(true);
 137  0
     }
 138  
 
 139  
     public void start() throws MuleException
 140  
     {
 141  0
         if (listener == null)
 142  
         {
 143  0
             throw new LifecycleException(CoreMessages.objectIsNull("listener"), this);
 144  
         }
 145  
 
 146  0
         synchronized (sources)
 147  
         {
 148  0
             starting.set(true);
 149  0
             for (MessageSource source : sources)
 150  
             {
 151  0
                 if (source instanceof Startable)
 152  
                 {
 153  0
                     ((Startable) source).start();
 154  
                 }
 155  
             }
 156  
 
 157  0
             started.set(true);
 158  0
             starting.set(false);
 159  0
         }
 160  0
     }
 161  
 
 162  
     public void stop() throws MuleException
 163  
     {
 164  0
         synchronized (sources)
 165  
         {
 166  0
             for (MessageSource source : sources)
 167  
             {
 168  0
                 if (source instanceof Stoppable)
 169  
                 {
 170  0
                     ((Stoppable) source).stop();
 171  
                 }
 172  
             }
 173  
 
 174  0
             started.set(false);
 175  0
         }
 176  0
     }
 177  
     
 178  
     public void dispose()
 179  
     {
 180  0
         synchronized (sources)
 181  
         {
 182  0
             for (MessageSource source : sources)
 183  
             {
 184  0
                 if (source instanceof Disposable)
 185  
                 {
 186  0
                     ((Disposable) source).dispose();
 187  
                 }
 188  
             }
 189  0
         }
 190  0
     }
 191  
 
 192  
     public void setListener(MessageProcessor listener)
 193  
     {
 194  0
         this.listener = listener;
 195  0
     }
 196  
 
 197  
     public void setFlowConstruct(FlowConstruct pattern)
 198  
     {
 199  0
         this.flowConstruct = pattern;
 200  
 
 201  0
     }
 202  
 
 203  
     @Override
 204  
     public String toString()
 205  
     {
 206  0
         return String.format("%s [listener=%s, sources=%s, started=%s]", getClass().getSimpleName(),
 207  
             listener, sources, started);
 208  
     }
 209  
 
 210  0
     private class InternalMessageProcessor implements MessageProcessor
 211  
     {
 212  
         public InternalMessageProcessor()
 213  0
         {
 214  0
             super();
 215  0
         }
 216  
 
 217  
         public MuleEvent process(MuleEvent event) throws MuleException
 218  
         {
 219  0
             if (started.get() || starting.get())
 220  
             {
 221  
                 // If the next message processor is an outbound router then create outbound event
 222  0
                 if (listener instanceof OutboundEndpoint)
 223  
                 {
 224  0
                     event = new DefaultMuleEvent(event.getMessage(), (OutboundEndpoint) listener, event.getSession());
 225  
                 }
 226  0
                 return listener.process(event);
 227  
             }
 228  
             else
 229  
             {
 230  0
                 log.warn(String.format(
 231  
                     "A message was receieved from MessageSource, but message source is stopped. Message will be discarded.%n"
 232  
                                     + "  Message: %s%n" + "  MessageSource:%s", event, this));
 233  0
                 return null;
 234  
             }
 235  
 
 236  
         }
 237  
 
 238  
         @Override
 239  
         public String toString()
 240  
         {
 241  0
             return ObjectUtils.toString(this);
 242  
         }
 243  
     }
 244  
 }