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