1
2
3
4
5
6
7
8
9
10 package org.mule.transport.ajax.embedded;
11
12 import org.mule.api.MuleContext;
13 import org.mule.api.MuleException;
14 import org.mule.api.construct.FlowConstruct;
15 import org.mule.api.endpoint.EndpointBuilder;
16 import org.mule.api.endpoint.ImmutableEndpoint;
17 import org.mule.api.endpoint.InboundEndpoint;
18 import org.mule.api.lifecycle.InitialisationException;
19 import org.mule.api.transport.MessageReceiver;
20 import org.mule.api.transport.ReplyToHandler;
21 import org.mule.transport.ajax.AjaxMessageReceiver;
22 import org.mule.transport.ajax.AjaxMuleMessageFactory;
23 import org.mule.transport.ajax.AjaxReplyToHandler;
24 import org.mule.transport.ajax.BayeuxAware;
25 import org.mule.transport.ajax.container.MuleAjaxServlet;
26 import org.mule.transport.ajax.i18n.AjaxMessages;
27 import org.mule.transport.servlet.JarResourceServlet;
28 import org.mule.transport.servlet.MuleServletContextListener;
29 import org.mule.transport.servlet.jetty.JettyHttpsConnector;
30 import org.mule.util.StringUtils;
31
32 import java.net.URL;
33 import java.util.Map;
34
35 import javax.servlet.Servlet;
36
37 import org.mortbay.cometd.AbstractBayeux;
38 import org.mortbay.cometd.continuation.ContinuationCometdServlet;
39 import org.mortbay.jetty.AbstractConnector;
40 import org.mortbay.jetty.Connector;
41 import org.mortbay.jetty.handler.ContextHandlerCollection;
42 import org.mortbay.jetty.nio.SelectChannelConnector;
43 import org.mortbay.jetty.servlet.Context;
44 import org.mortbay.jetty.servlet.DefaultServlet;
45 import org.mortbay.jetty.servlet.ServletHolder;
46
47
48
49
50
51
52
53
54
55 public class AjaxConnector extends JettyHttpsConnector implements BayeuxAware
56 {
57 public static final String PROTOCOL = "ajax";
58
59 public static final String CHANNEL_PROPERTY = "channel";
60
61 public static final String AJAX_PATH_SPEC = "/ajax/*";
62
63 public static final String COMETD_CLIENT = "cometd.client";
64
65
66
67
68
69 public static final String REPLYTO_PARAM = "replyTo";
70
71 private URL serverUrl;
72
73
74
75
76
77 private int interval = INT_VALUE_NOT_SET;
78
79
80
81
82
83 private int maxInterval = INT_VALUE_NOT_SET;
84
85
86
87
88
89 private int multiFrameInterval = INT_VALUE_NOT_SET;
90
91
92
93
94 private int logLevel = INT_VALUE_NOT_SET;
95
96
97
98
99
100 private int timeout = INT_VALUE_NOT_SET;
101
102
103
104
105
106 private boolean jsonCommented = true;
107
108
109
110
111
112 private String filters;
113
114
115
116
117
118 private boolean requestAvailable = true;
119
120
121
122
123
124 private boolean directDeliver = true;
125
126
127
128
129
130
131 private int refsThreshold = INT_VALUE_NOT_SET;
132
133 private ContinuationCometdServlet servlet;
134
135 public AjaxConnector(MuleContext context)
136 {
137 super(context);
138 unregisterSupportedProtocol("http");
139 unregisterSupportedProtocol("https");
140 unregisterSupportedProtocol("jetty-ssl");
141 unregisterSupportedProtocol("jetty");
142 setInitialStateStopped(true);
143 }
144
145 @Override
146 public String getProtocol()
147 {
148 return PROTOCOL;
149 }
150
151 public URL getServerUrl()
152 {
153 return serverUrl;
154 }
155
156 public void setServerUrl(URL serverUrl)
157 {
158 this.serverUrl = serverUrl;
159 }
160
161 @Override
162 protected void doInitialise() throws InitialisationException
163 {
164 if (serverUrl==null)
165 {
166 throw new InitialisationException(AjaxMessages.serverUrlNotDefined(), this);
167 }
168 super.doInitialise();
169 try
170 {
171 createEmbeddedServer();
172 }
173 catch (Exception e)
174 {
175 throw new InitialisationException(e, this);
176 }
177 }
178
179 @Override
180 protected void doStart() throws MuleException
181 {
182 super.doStart();
183 for (MessageReceiver receiver : receivers.values())
184 {
185 ((AjaxMessageReceiver)receiver).setBayeux(getBayeux());
186 }
187 }
188
189 @Override
190 protected void validateSslConfig() throws InitialisationException
191 {
192 if (serverUrl.getProtocol().equals("https"))
193 {
194 super.validateSslConfig();
195 }
196 }
197
198 @Override
199 public ReplyToHandler getReplyToHandler(ImmutableEndpoint endpoint)
200 {
201 return new AjaxReplyToHandler(getDefaultResponseTransformers(endpoint), this);
202 }
203
204 void createEmbeddedServer() throws MuleException
205 {
206 Connector connector = createJettyConnector();
207
208 connector.setPort(serverUrl.getPort());
209 connector.setHost(serverUrl.getHost());
210
211 getHttpServer().addConnector(connector);
212 EndpointBuilder builder = muleContext.getEndpointFactory().getEndpointBuilder(serverUrl.toString());
213
214 servlet = (ContinuationCometdServlet)createServlet(connector, builder.buildInboundEndpoint());
215 }
216
217 @Override
218 public Servlet createServlet(Connector connector, ImmutableEndpoint endpoint)
219 {
220 ContinuationCometdServlet ajaxServlet = new MuleAjaxServlet();
221
222 String path = endpoint.getEndpointURI().getPath();
223 if (StringUtils.isBlank(path))
224 {
225 path = ROOT;
226 }
227
228 ContextHandlerCollection handlerCollection = new ContextHandlerCollection();
229 Context root = new Context(handlerCollection, ROOT, Context.NO_SECURITY);
230 root.setConnectorNames(new String[]{connector.getName()});
231 root.addEventListener(new MuleServletContextListener(muleContext, getName()));
232
233 if (!ROOT.equals(path))
234 {
235 Context resourceContext = new Context(handlerCollection, path, Context.NO_SECURITY);
236 populateContext(resourceContext);
237
238 }
239 else
240 {
241 populateContext(root);
242 }
243
244
245 ServletHolder holder = new ServletHolder();
246 holder.setServlet(ajaxServlet);
247 root.addServlet(holder, AJAX_PATH_SPEC);
248
249 if (getInterval() != INT_VALUE_NOT_SET) holder.setInitParameter("interval", Integer.toString(getInterval()));
250 holder.setInitParameter("JSONCommented", Boolean.toString(isJsonCommented()));
251 if (getLogLevel() != INT_VALUE_NOT_SET) holder.setInitParameter("logLevel", Integer.toString(getLogLevel()));
252 if (getMaxInterval() != INT_VALUE_NOT_SET) holder.setInitParameter("maxInterval", Integer.toString(getMaxInterval()));
253 if (getMultiFrameInterval() != INT_VALUE_NOT_SET) holder.setInitParameter("multiFrameInterval", (Integer.toString(getMultiFrameInterval())));
254 if (getTimeout() != INT_VALUE_NOT_SET) holder.setInitParameter("timeout", Integer.toString(getTimeout()));
255 if (getRefsThreshold() != INT_VALUE_NOT_SET) holder.setInitParameter("refsThreshold", Integer.toString(getRefsThreshold()));
256 holder.setInitParameter("requestAvailable", Boolean.toString(isRequestAvailable()));
257
258
259 this.getHttpServer().addHandler(handlerCollection);
260 return ajaxServlet;
261 }
262
263 protected void populateContext(Context context)
264 {
265 context.addServlet(DefaultServlet.class, ROOT);
266 context.addServlet(JarResourceServlet.class, JarResourceServlet.DEFAULT_PATH_SPEC);
267
268 String base = getResourceBase();
269 if (base != null)
270 {
271 context.setResourceBase(base);
272 }
273 }
274
275 @Override
276 protected AbstractConnector createJettyConnector()
277 {
278 if (serverUrl.getProtocol().equals("https"))
279 {
280 return super.createJettyConnector();
281 }
282 else
283 {
284 return new SelectChannelConnector();
285 }
286 }
287
288 public AbstractBayeux getBayeux( )
289 {
290 return servlet.getBayeux();
291 }
292
293 public void setBayeux(AbstractBayeux bayeux)
294 {
295
296 }
297
298 @Override
299 protected MessageReceiver createReceiver(FlowConstruct flowConstruct, InboundEndpoint endpoint) throws Exception
300 {
301 MessageReceiver receiver = getServiceDescriptor().createMessageReceiver(this, flowConstruct, endpoint);
302
303 ((AjaxMessageReceiver) receiver).setBayeux(getBayeux());
304 return receiver;
305 }
306
307
308 public int getInterval()
309 {
310 return interval;
311 }
312
313 public void setInterval(int interval)
314 {
315 this.interval = interval;
316 }
317
318 public int getMaxInterval()
319 {
320 return maxInterval;
321 }
322
323 public void setMaxInterval(int maxInterval)
324 {
325 this.maxInterval = maxInterval;
326 }
327
328 public int getMultiFrameInterval()
329 {
330 return multiFrameInterval;
331 }
332
333 public void setMultiFrameInterval(int multiFrameInterval)
334 {
335 this.multiFrameInterval = multiFrameInterval;
336 }
337
338 public int getLogLevel()
339 {
340 return logLevel;
341 }
342
343 public void setLogLevel(int logLevel)
344 {
345 this.logLevel = logLevel;
346 }
347
348 public int getTimeout()
349 {
350 return timeout;
351 }
352
353 public void setTimeout(int timeout)
354 {
355 this.timeout = timeout;
356 }
357
358 public boolean isJsonCommented()
359 {
360 return jsonCommented;
361 }
362
363 public void setJsonCommented(boolean jsonCommented)
364 {
365 this.jsonCommented = jsonCommented;
366 }
367
368 public String getFilters()
369 {
370 return filters;
371 }
372
373 public void setFilters(String filters)
374 {
375 this.filters = filters;
376 }
377
378 public boolean isRequestAvailable()
379 {
380 return requestAvailable;
381 }
382
383 public void setRequestAvailable(boolean requestAvailable)
384 {
385 this.requestAvailable = requestAvailable;
386 }
387
388 public boolean isDirectDeliver()
389 {
390 return directDeliver;
391 }
392
393 public void setDirectDeliver(boolean directDeliver)
394 {
395 this.directDeliver = directDeliver;
396 }
397
398 public int getRefsThreshold()
399 {
400 return refsThreshold;
401 }
402
403 public void setRefsThreshold(int refsThreshold)
404 {
405 this.refsThreshold = refsThreshold;
406 }
407 }