1
2
3
4
5
6
7
8
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
43
44
45
46
47
48
49
50
51 public class StartableCompositeMessageSource
52 implements CompositeMessageSource, Lifecycle, FlowConstructAware
53 {
54 protected static final Log log = LogFactory.getLog(StartableCompositeMessageSource.class);
55
56 protected MessageProcessor listener;
57 protected AtomicBoolean initialised = new AtomicBoolean(false);
58 protected AtomicBoolean started = new AtomicBoolean(false);
59 protected final List<MessageSource> sources = Collections.synchronizedList(new ArrayList<MessageSource>());
60 protected AtomicBoolean starting = new AtomicBoolean(false);
61 protected FlowConstruct flowConstruct;
62 private final MessageProcessor internalListener = new InternalMessageProcessor();
63
64 public void addSource(MessageSource source) throws MuleException
65 {
66 synchronized (sources)
67 {
68 sources.add(source);
69 }
70 source.setListener(internalListener);
71 if (initialised.get())
72 {
73 if (source instanceof FlowConstructAware)
74 {
75 ((FlowConstructAware) source).setFlowConstruct(flowConstruct);
76 }
77 if (source instanceof Initialisable)
78 {
79 ((Initialisable) source).initialise();
80 }
81 }
82 if (started.get() && source instanceof Startable)
83 {
84 ((Startable) source).start();
85 }
86 }
87
88 public void removeSource(MessageSource source) throws MuleException
89 {
90 if (started.get())
91 {
92 if (source instanceof Stoppable)
93 {
94 ((Stoppable) source).stop();
95 }
96 if (source instanceof Disposable)
97 {
98 ((Disposable) source).dispose();
99 }
100 }
101 synchronized (sources)
102 {
103 sources.remove(source);
104 }
105 }
106
107 public void setMessageSources(List<MessageSource> sources) throws MuleException
108 {
109 this.sources.clear();
110 for (MessageSource messageSource : sources)
111 {
112 addSource(messageSource);
113 }
114 }
115
116 public void initialise() throws InitialisationException
117 {
118 if (listener == null)
119 {
120 throw new InitialisationException(CoreMessages.objectIsNull("listener"), this);
121 }
122 synchronized (sources)
123 {
124 for (MessageSource source : sources)
125 {
126 if (source instanceof FlowConstructAware)
127 {
128 ((FlowConstructAware) source).setFlowConstruct(flowConstruct);
129 }
130 if (source instanceof Initialisable)
131 {
132 ((Initialisable) source).initialise();
133 }
134 }
135 }
136 initialised.set(true);
137 }
138
139 public void start() throws MuleException
140 {
141 if (listener == null)
142 {
143 throw new LifecycleException(CoreMessages.objectIsNull("listener"), this);
144 }
145
146 synchronized (sources)
147 {
148 starting.set(true);
149 for (MessageSource source : sources)
150 {
151 if (source instanceof Startable)
152 {
153 ((Startable) source).start();
154 }
155 }
156
157 started.set(true);
158 starting.set(false);
159 }
160 }
161
162 public void stop() throws MuleException
163 {
164 synchronized (sources)
165 {
166 for (MessageSource source : sources)
167 {
168 if (source instanceof Stoppable)
169 {
170 ((Stoppable) source).stop();
171 }
172 }
173
174 started.set(false);
175 }
176 }
177
178 public void dispose()
179 {
180 synchronized (sources)
181 {
182 for (MessageSource source : sources)
183 {
184 if (source instanceof Disposable)
185 {
186 ((Disposable) source).dispose();
187 }
188 }
189 }
190 }
191
192 public void setListener(MessageProcessor listener)
193 {
194 this.listener = listener;
195 }
196
197 public void setFlowConstruct(FlowConstruct pattern)
198 {
199 this.flowConstruct = pattern;
200
201 }
202
203 @Override
204 public String toString()
205 {
206 return String.format("%s [listener=%s, sources=%s, started=%s]", getClass().getSimpleName(),
207 listener, sources, started);
208 }
209
210 private class InternalMessageProcessor implements MessageProcessor
211 {
212 public InternalMessageProcessor()
213 {
214 super();
215 }
216
217 public MuleEvent process(MuleEvent event) throws MuleException
218 {
219 if (started.get() || starting.get())
220 {
221
222 if (listener instanceof OutboundEndpoint)
223 {
224 event = new DefaultMuleEvent(event.getMessage(), (OutboundEndpoint) listener, event.getSession());
225 }
226 return listener.process(event);
227 }
228 else
229 {
230 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 return null;
234 }
235
236 }
237
238 @Override
239 public String toString()
240 {
241 return ObjectUtils.toString(this);
242 }
243 }
244 }