Coverage Report - org.mule.transport.ajax.embedded.AjaxConnector
 
Classes in this File Line Coverage Branch Coverage Complexity
AjaxConnector
0%
0/116
0%
0/26
0
 
 1  
 /*
 2  
  * $Id: AjaxConnector.java 19939 2010-10-15 15:34:05Z dirk.olmes $
 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  
 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  
  * Creates an 'embedded' Ajax server using Jetty and allows Mule to receiver and send events
 49  
  * to browsers. The browser will need to use the <pre>mule.js</pre> class to publish and
 50  
  * subscribe events.
 51  
  *
 52  
  * Note that a {@link @RESOURCE_BASE_PROPERTY} can be set on the ajax endpoint that provides the location of any web application resources such
 53  
  * as html pages
 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  
      * This is the key that's used to retrieve the reply to destination from a {@link Map} that's
 67  
      * passed into {@link AjaxMuleMessageFactory}.
 68  
      */
 69  
     public static final String REPLYTO_PARAM = "replyTo";
 70  
 
 71  
     private URL serverUrl;
 72  
 
 73  
     /**
 74  
      * The client side poll timeout in milliseconds (default 0). How long a client
 75  
      * will wait between reconnects
 76  
      */
 77  0
     private int interval = INT_VALUE_NOT_SET;
 78  
 
 79  
     /**
 80  
      * The max client side poll timeout in milliseconds (default 30000). A client
 81  
      * will be removed if a connection is not received in this time.
 82  
      */
 83  0
     private int maxInterval = INT_VALUE_NOT_SET;
 84  
 
 85  
     /**
 86  
      * The client side poll timeout if multiple connections are detected from the
 87  
      * same browser (default 1500).
 88  
      */
 89  0
     private int multiFrameInterval = INT_VALUE_NOT_SET;
 90  
 
 91  
     /**
 92  
      * 0=none, 1=info, 2=debug
 93  
      */
 94  0
     private int logLevel = INT_VALUE_NOT_SET;
 95  
 
 96  
     /**
 97  
      * The server side poll timeout in milliseconds (default 250000). This is how long
 98  
      * the server will hold a reconnect request before responding.
 99  
      */
 100  0
     private int timeout = INT_VALUE_NOT_SET;
 101  
 
 102  
     /**
 103  
      * If "true" (default) then the server will accept JSON wrapped in a comment and
 104  
      * will generate JSON wrapped in a comment. This is a defence against Ajax Hijacking.
 105  
      */
 106  0
     private boolean jsonCommented = true;
 107  
 
 108  
     /**
 109  
      * TODO SUPPORT FILTERS
 110  
      * the location of a JSON file describing {@link org.cometd.DataFilter} instances to be installed
 111  
      */
 112  
     private String filters;
 113  
 
 114  
     /**
 115  
      * If true, the current request is made available via the
 116  
      * {@link AbstractBayeux#getCurrentRequest()} method
 117  
      */
 118  0
     private boolean requestAvailable = true;
 119  
 
 120  
     /**
 121  
      * true if published messages are delivered directly to subscribers (default).
 122  
      * If false, a message copy is created with only supported fields (default true).
 123  
      */
 124  0
     private boolean directDeliver = true;
 125  
 
 126  
     /**
 127  
      * The number of message refs at which the a single message response will be
 128  
      * cached instead of being generated for every client delivered to. Done to optimize
 129  
      * a single message being sent to multiple clients.
 130  
      */
 131  0
     private int refsThreshold = INT_VALUE_NOT_SET;
 132  
 
 133  
     private ContinuationCometdServlet servlet;
 134  
 
 135  
     private String resourceBase;
 136  
 
 137  
     public AjaxConnector(MuleContext context)
 138  
     {
 139  0
         super(context);
 140  0
         unregisterSupportedProtocol("http");
 141  0
         unregisterSupportedProtocol("https");
 142  0
         unregisterSupportedProtocol("jetty-ssl");
 143  0
         unregisterSupportedProtocol("jetty");
 144  0
         setInitialStateStopped(true);
 145  0
     }
 146  
 
 147  
     @Override
 148  
     public String getProtocol()
 149  
     {
 150  0
         return PROTOCOL;
 151  
     }
 152  
 
 153  
     public URL getServerUrl()
 154  
     {
 155  0
         return serverUrl;
 156  
     }
 157  
 
 158  
     public void setServerUrl(URL serverUrl)
 159  
     {
 160  0
         this.serverUrl = serverUrl;
 161  0
     }
 162  
 
 163  
     @Override
 164  
     protected void doInitialise() throws InitialisationException
 165  
     {
 166  0
         if (serverUrl==null)
 167  
         {
 168  0
             throw new InitialisationException(AjaxMessages.serverUrlNotDefined(), this);
 169  
         }
 170  0
         super.doInitialise();
 171  
         try
 172  
         {
 173  0
             createEmbeddedServer();
 174  
         }
 175  0
         catch (Exception e)
 176  
         {
 177  0
             throw new InitialisationException(e, this);
 178  0
         }
 179  0
     }
 180  
 
 181  
     @Override
 182  
     protected void doStart() throws MuleException
 183  
     {
 184  0
         super.doStart();
 185  0
         for (MessageReceiver receiver : receivers.values())
 186  
         {
 187  0
             ((AjaxMessageReceiver)receiver).setBayeux(getBayeux());
 188  
         }
 189  0
     }
 190  
 
 191  
     @Override
 192  
     protected void validateSslConfig() throws InitialisationException
 193  
     {
 194  0
         if (serverUrl.getProtocol().equals("https"))
 195  
         {
 196  0
             super.validateSslConfig();
 197  
         }
 198  0
     }
 199  
 
 200  
     @Override
 201  
     public ReplyToHandler getReplyToHandler(ImmutableEndpoint endpoint)
 202  
     {
 203  0
         return new AjaxReplyToHandler(getDefaultResponseTransformers(endpoint), this);
 204  
     }
 205  
 
 206  
     void createEmbeddedServer() throws MuleException
 207  
     {
 208  0
         Connector connector = createJettyConnector();
 209  
 
 210  0
         connector.setPort(serverUrl.getPort());
 211  0
         connector.setHost(serverUrl.getHost());
 212  
         
 213  0
         getHttpServer().addConnector(connector);
 214  0
         EndpointBuilder builder = muleContext.getRegistry().lookupEndpointFactory().getEndpointBuilder(serverUrl.toString());
 215  
 
 216  0
         servlet = (ContinuationCometdServlet)createServlet(connector, builder.buildInboundEndpoint());
 217  0
     }
 218  
 
 219  
     @Override
 220  
     public Servlet createServlet(Connector connector, ImmutableEndpoint endpoint)
 221  
     {
 222  0
         ContinuationCometdServlet ajaxServlet = new MuleAjaxServlet();
 223  
 
 224  0
         String path = endpoint.getEndpointURI().getPath();
 225  0
         if (StringUtils.isBlank(path))
 226  
         {
 227  0
             path = ROOT;
 228  
         }
 229  
 
 230  0
         ContextHandlerCollection handlerCollection = new ContextHandlerCollection();
 231  0
         Context root = new Context(handlerCollection, ROOT, Context.NO_SECURITY);
 232  0
         root.setConnectorNames(new String[]{connector.getName()});
 233  0
         root.addEventListener(new MuleServletContextListener(muleContext, getName()));
 234  
 
 235  0
         if (!ROOT.equals(path))
 236  
         {
 237  0
             Context resourceContext = new Context(handlerCollection, path, Context.NO_SECURITY);
 238  0
             populateContext(resourceContext);
 239  
 
 240  0
         }
 241  
         else
 242  
         {
 243  0
             populateContext(root);
 244  
         }
 245  
 
 246  
         //Add ajax to root
 247  0
         ServletHolder holder = new ServletHolder();
 248  0
         holder.setServlet(ajaxServlet);
 249  0
         root.addServlet(holder, AJAX_PATH_SPEC);
 250  
 
 251  0
         if (getInterval() != INT_VALUE_NOT_SET) holder.setInitParameter("interval", Integer.toString(getInterval()));
 252  0
         holder.setInitParameter("JSONCommented", Boolean.toString(isJsonCommented()));
 253  0
         if (getLogLevel() != INT_VALUE_NOT_SET) holder.setInitParameter("logLevel", Integer.toString(getLogLevel()));
 254  0
         if (getMaxInterval() != INT_VALUE_NOT_SET) holder.setInitParameter("maxInterval", Integer.toString(getMaxInterval()));
 255  0
         if (getMultiFrameInterval() != INT_VALUE_NOT_SET) holder.setInitParameter("multiFrameInterval", (Integer.toString(getMultiFrameInterval())));
 256  0
         if (getTimeout() != INT_VALUE_NOT_SET) holder.setInitParameter("timeout", Integer.toString(getTimeout()));
 257  0
         if (getRefsThreshold() != INT_VALUE_NOT_SET) holder.setInitParameter("refsThreshold", Integer.toString(getRefsThreshold()));
 258  0
         holder.setInitParameter("requestAvailable", Boolean.toString(isRequestAvailable()));
 259  
 
 260  
 
 261  0
         this.getHttpServer().addHandler(handlerCollection);
 262  0
         return ajaxServlet;
 263  
     }
 264  
 
 265  
     protected void populateContext(Context context)
 266  
     {
 267  0
         context.addServlet(DefaultServlet.class, ROOT);
 268  0
         context.addServlet(JarResourceServlet.class, JarResourceServlet.DEFAULT_PATH_SPEC);
 269  
 
 270  0
         String base = getResourceBase();
 271  0
         if (base != null)
 272  
         {
 273  0
             context.setResourceBase(base);
 274  
         }
 275  0
     }
 276  
 
 277  
     @Override
 278  
     protected AbstractConnector createJettyConnector()
 279  
     {
 280  0
         if (serverUrl.getProtocol().equals("https"))
 281  
         {
 282  0
             return super.createJettyConnector();
 283  
         }
 284  
         else
 285  
         {
 286  0
             return new SelectChannelConnector();
 287  
         }
 288  
     }
 289  
 
 290  
     public AbstractBayeux getBayeux( )
 291  
     {
 292  0
         return servlet.getBayeux();
 293  
     }
 294  
 
 295  
     public void setBayeux(AbstractBayeux bayeux)
 296  
     {
 297  
         //Ignore
 298  0
     }
 299  
 
 300  
     @Override
 301  
     protected MessageReceiver createReceiver(FlowConstruct flowConstruct, InboundEndpoint endpoint) throws Exception
 302  
     {
 303  0
         MessageReceiver receiver = getServiceDescriptor().createMessageReceiver(this, flowConstruct, endpoint);
 304  
         //If the connector has not started yet, the Bayeux object will still be null
 305  0
         ((AjaxMessageReceiver) receiver).setBayeux(getBayeux());
 306  0
         return receiver;
 307  
     }
 308  
 
 309  
     public String getResourceBase()
 310  
     {
 311  0
         return resourceBase;
 312  
     }
 313  
 
 314  
     public void setResourceBase(String resourceBase)
 315  
     {
 316  0
         this.resourceBase = resourceBase;
 317  0
     }
 318  
 
 319  
     public int getInterval()
 320  
     {
 321  0
         return interval;
 322  
     }
 323  
 
 324  
     public void setInterval(int interval)
 325  
     {
 326  0
         this.interval = interval;
 327  0
     }
 328  
 
 329  
     public int getMaxInterval()
 330  
     {
 331  0
         return maxInterval;
 332  
     }
 333  
 
 334  
     public void setMaxInterval(int maxInterval)
 335  
     {
 336  0
         this.maxInterval = maxInterval;
 337  0
     }
 338  
 
 339  
     public int getMultiFrameInterval()
 340  
     {
 341  0
         return multiFrameInterval;
 342  
     }
 343  
 
 344  
     public void setMultiFrameInterval(int multiFrameInterval)
 345  
     {
 346  0
         this.multiFrameInterval = multiFrameInterval;
 347  0
     }
 348  
 
 349  
     public int getLogLevel()
 350  
     {
 351  0
         return logLevel;
 352  
     }
 353  
 
 354  
     public void setLogLevel(int logLevel)
 355  
     {
 356  0
         this.logLevel = logLevel;
 357  0
     }
 358  
 
 359  
     public int getTimeout()
 360  
     {
 361  0
         return timeout;
 362  
     }
 363  
 
 364  
     public void setTimeout(int timeout)
 365  
     {
 366  0
         this.timeout = timeout;
 367  0
     }
 368  
 
 369  
     public boolean isJsonCommented()
 370  
     {
 371  0
         return jsonCommented;
 372  
     }
 373  
 
 374  
     public void setJsonCommented(boolean jsonCommented)
 375  
     {
 376  0
         this.jsonCommented = jsonCommented;
 377  0
     }
 378  
 
 379  
     public String getFilters()
 380  
     {
 381  0
         return filters;
 382  
     }
 383  
 
 384  
     public void setFilters(String filters)
 385  
     {
 386  0
         this.filters = filters;
 387  0
     }
 388  
 
 389  
     public boolean isRequestAvailable()
 390  
     {
 391  0
         return requestAvailable;
 392  
     }
 393  
 
 394  
     public void setRequestAvailable(boolean requestAvailable)
 395  
     {
 396  0
         this.requestAvailable = requestAvailable;
 397  0
     }
 398  
 
 399  
     public boolean isDirectDeliver()
 400  
     {
 401  0
         return directDeliver;
 402  
     }
 403  
 
 404  
     public void setDirectDeliver(boolean directDeliver)
 405  
     {
 406  0
         this.directDeliver = directDeliver;
 407  0
     }
 408  
 
 409  
     public int getRefsThreshold()
 410  
     {
 411  0
         return refsThreshold;
 412  
     }
 413  
 
 414  
     public void setRefsThreshold(int refsThreshold)
 415  
     {
 416  0
         this.refsThreshold = refsThreshold;
 417  0
     }
 418  
 }