1
2
3
4
5
6
7
8
9
10 package org.mule.transport.ajax;
11
12 import org.mule.api.MuleEvent;
13 import org.mule.api.MuleMessage;
14 import org.mule.api.endpoint.OutboundEndpoint;
15 import org.mule.api.lifecycle.CreateException;
16 import org.mule.api.lifecycle.InitialisationException;
17 import org.mule.transport.AbstractMessageDispatcher;
18 import org.mule.transport.NullPayload;
19 import org.mule.transport.ajax.i18n.AjaxMessages;
20 import org.mule.util.MapUtils;
21 import org.mule.util.StringUtils;
22
23 import org.apache.commons.collections.Buffer;
24 import org.apache.commons.collections.buffer.BoundedFifoBuffer;
25 import org.cometd.Channel;
26 import org.cometd.Client;
27 import org.mortbay.cometd.AbstractBayeux;
28
29
30
31
32 public class AjaxMessageDispatcher extends AbstractMessageDispatcher implements BayeuxAware
33 {
34 protected AbstractBayeux bayeux;
35
36 protected boolean cacheMessages = false;
37
38 protected int messageCacheSize = 500;
39
40 protected Buffer messageCache;
41
42 protected String channel;
43
44 protected Client client;
45
46 public AjaxMessageDispatcher(OutboundEndpoint endpoint) throws CreateException
47 {
48 super(endpoint);
49 cacheMessages = MapUtils.getBoolean(endpoint.getProperties(), "cacheMessages", false);
50 messageCacheSize = MapUtils.getInteger(endpoint.getProperties(), "messageCacheSize", 500);
51 channel = endpoint.getEndpointURI().getPath();
52 if(StringUtils.isEmpty(channel) || channel.equals("/"))
53 {
54
55 throw new CreateException(AjaxMessages.createStaticMessage("The subscription path cannot be empty or equal '/'"), this);
56 }
57 }
58
59 public AbstractBayeux getBayeux()
60 {
61 return bayeux;
62 }
63
64 public void setBayeux(AbstractBayeux bayeux)
65 {
66 this.bayeux = bayeux;
67 }
68
69 @Override
70 protected void doInitialise() throws InitialisationException
71 {
72 if (cacheMessages)
73 {
74 messageCache = new BoundedFifoBuffer(messageCacheSize);
75 }
76 }
77
78 protected Client getClient()
79 {
80 if(client == null)
81 {
82 client = bayeux.newClient(channel);
83 }
84 return client;
85 }
86
87 protected void doDispatch(MuleEvent event) throws Exception
88 {
89
90 if(NullPayload.getInstance().equals(event.getMessage().getPayload()))
91 {
92 return;
93 }
94 if (!connector.isStarted())
95 {
96
97 logger.warn("Servlet container has not yet initialised, ignoring event: " + event.getMessage().getPayload());
98 return;
99 }
100
101 Channel chan = bayeux.getChannel(channel);
102 if(chan!=null)
103 {
104 if (chan.getSubscribers().size() > 0 && cacheMessages && !messageCache.isEmpty())
105 {
106 while (!messageCache.isEmpty())
107 {
108 for (Client client : chan.getSubscribers())
109 {
110 deliver(client, channel, messageCache.remove());
111 }
112
113 }
114 }
115
116 Object data = event.getMessage().getPayload();
117
118 for (Client client : chan.getSubscribers())
119 {
120 deliver(client, channel, data);
121 }
122 }
123 else if (cacheMessages)
124 {
125 Object data = event.getMessage().getPayload();
126 if (logger.isTraceEnabled())
127 {
128 logger.trace("There are no clients waiting, adding message to cache: " + data);
129 }
130 messageCache.add(data);
131 }
132 }
133
134 protected void deliver(Client client, String channel, Object data)
135 {
136 if (logger.isTraceEnabled())
137 {
138 logger.trace("Delivering to client id: " + client.getId() + " channel:" + channel);
139 }
140 client.deliver(client, channel, data, null);
141 }
142
143 protected MuleMessage doSend(MuleEvent event) throws Exception
144 {
145 doDispatch(event);
146 return null;
147 }
148
149 @Override
150 protected void doDispose()
151 {
152 if (messageCache != null)
153 {
154 messageCache.clear();
155 messageCache = null;
156 }
157 }
158 }