Coverage Report - org.mule.transport.servlet.jetty.JettyHttpConnector
 
Classes in this File Line Coverage Branch Coverage Complexity
JettyHttpConnector
0%
0/137
0%
0/36
0
JettyHttpConnector$1
0%
0/8
0%
0/2
0
JettyHttpConnector$MuleReceiverConnectorHolder
0%
0/22
0%
0/8
0
 
 1  
 /*
 2  
  * $Id: JettyHttpConnector.java 20413 2010-12-01 01:50:19Z dandiep $
 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  
 
 11  
 package org.mule.transport.servlet.jetty;
 12  
 
 13  
 import org.mule.api.MuleContext;
 14  
 import org.mule.api.MuleException;
 15  
 import org.mule.api.MuleRuntimeException;
 16  
 import org.mule.api.config.MuleProperties;
 17  
 import org.mule.api.construct.FlowConstruct;
 18  
 import org.mule.api.context.notification.MuleContextNotificationListener;
 19  
 import org.mule.api.endpoint.ImmutableEndpoint;
 20  
 import org.mule.api.endpoint.InboundEndpoint;
 21  
 import org.mule.api.lifecycle.InitialisationException;
 22  
 import org.mule.api.lifecycle.LifecycleException;
 23  
 import org.mule.api.transport.MessageReceiver;
 24  
 import org.mule.api.transport.ReplyToHandler;
 25  
 import org.mule.config.i18n.CoreMessages;
 26  
 import org.mule.context.notification.MuleContextNotification;
 27  
 import org.mule.context.notification.NotificationException;
 28  
 import org.mule.transport.AbstractConnector;
 29  
 import org.mule.transport.servlet.JarResourceServlet;
 30  
 import org.mule.transport.servlet.MuleReceiverServlet;
 31  
 import org.mule.transport.servlet.MuleServletContextListener;
 32  
 import org.mule.util.IOUtils;
 33  
 import org.mule.util.StringUtils;
 34  
 
 35  
 import java.io.InputStream;
 36  
 import java.util.ArrayList;
 37  
 import java.util.HashMap;
 38  
 import java.util.List;
 39  
 
 40  
 import javax.servlet.Servlet;
 41  
 import javax.servlet.http.HttpServlet;
 42  
 
 43  
 import edu.emory.mathcs.backport.java.util.Arrays;
 44  
 
 45  
 import org.mortbay.jetty.Connector;
 46  
 import org.mortbay.jetty.Server;
 47  
 import org.mortbay.jetty.handler.ContextHandlerCollection;
 48  
 import org.mortbay.jetty.nio.SelectChannelConnector;
 49  
 import org.mortbay.jetty.servlet.Context;
 50  
 import org.mortbay.jetty.servlet.ServletHolder;
 51  
 import org.mortbay.xml.XmlConfiguration;
 52  
 
 53  
 /**
 54  
  * The <code>JettyConnector</code> can be using to embed a Jetty server to receive requests on an
 55  
  * http inound endpoint. One server is created for each connector declared, many Jetty endpoints
 56  
  * can share the same connector.
 57  
  */
 58  
 public class JettyHttpConnector extends AbstractConnector
 59  
 {
 60  
     public static final String ROOT = "/";
 61  
 
 62  
     public static final String JETTY = "jetty";
 63  
 
 64  
     private Server httpServer;
 65  
 
 66  
     private String configFile;
 67  
 
 68  
     private JettyReceiverServlet receiverServlet;
 69  
 
 70  0
     private boolean useContinuations = false;
 71  
 
 72  
     private String resourceBase;
 73  
 
 74  
     private WebappsConfiguration webappsConfiguration;
 75  
 
 76  0
     protected HashMap<String, ConnectorHolder> holders = new HashMap<String, ConnectorHolder>();
 77  
 
 78  
     private WebAppDeployer deployer;
 79  
 
 80  
     public JettyHttpConnector(MuleContext context)
 81  
     {
 82  0
         super(context);
 83  0
         registerSupportedProtocol("http");
 84  0
         registerSupportedProtocol(JETTY);
 85  0
         setInitialStateStopped(true);
 86  0
     }
 87  
 
 88  
     public String getProtocol()
 89  
     {
 90  0
         return JETTY;
 91  
     }
 92  
 
 93  
     @Override
 94  
     protected void doInitialise() throws InitialisationException
 95  
     {
 96  0
         httpServer = new Server();
 97  
         
 98  0
         if (webappsConfiguration != null)
 99  
         {
 100  0
             deployer = new WebAppDeployer();
 101  0
             deployer.setWebAppDir(webappsConfiguration.getDirectory());
 102  0
             deployer.setExtract(true);
 103  0
             deployer.setParentLoaderPriority(false);
 104  0
             deployer.setServerClasses(webappsConfiguration.getServerClasses());
 105  0
             deployer.setSystemClasses(webappsConfiguration.getSystemClasses());
 106  
 
 107  0
             org.mortbay.jetty.AbstractConnector connector = createJettyConnector();
 108  0
             connector.setHost(webappsConfiguration.getHost());
 109  0
             connector.setPort(webappsConfiguration.getPort());
 110  0
             deployer.setContexts(httpServer);
 111  
 
 112  0
             httpServer.addConnector(connector);
 113  0
             httpServer.addLifeCycle(deployer);
 114  
         }
 115  
         
 116  0
         initialiseFromConfigFile();
 117  
 
 118  
         try
 119  
         {
 120  0
             muleContext.registerListener(new MuleContextNotificationListener<MuleContextNotification>(){
 121  
                 public void onNotification(MuleContextNotification notification)
 122  
                 {
 123  0
                     if (notification.getAction() == MuleContextNotification.CONTEXT_STARTED)
 124  
                     {
 125  
                         //We delay starting until the context has been started since we need the MuleAjaxServlet to initialise first
 126  0
                         setInitialStateStopped(false);
 127  
                         try
 128  
                         {
 129  0
                             start();
 130  
                         }
 131  0
                         catch (MuleException e)
 132  
                         {
 133  0
                             throw new MuleRuntimeException(CoreMessages.failedToStart(getName()), e);
 134  0
                         }
 135  
                     }
 136  0
                 }
 137  
             });
 138  
         }
 139  0
         catch (NotificationException e)
 140  
         {
 141  0
             throw new InitialisationException(e, this);
 142  0
         }
 143  0
     }
 144  
 
 145  
     @SuppressWarnings("unchecked")
 146  
     protected void initialiseFromConfigFile() throws InitialisationException
 147  
     {
 148  0
         if (configFile != null)
 149  
         {
 150  
             try
 151  
             {
 152  0
                 InputStream is = IOUtils.getResourceAsStream(configFile, getClass());
 153  0
                 XmlConfiguration config = new XmlConfiguration(is);
 154  
 
 155  0
                 String appHome =
 156  
                     muleContext.getRegistry().lookupObject(MuleProperties.APP_HOME_DIRECTORY_PROPERTY);
 157  0
                 if (appHome == null)
 158  
                 {
 159  
                     // Mule IDE sets app.home as part of the launch config it creates
 160  0
                     appHome = System.getProperty(MuleProperties.APP_HOME_DIRECTORY_PROPERTY);
 161  
                 }
 162  
 
 163  0
                 if (appHome != null)
 164  
                 {
 165  0
                     config.getProperties().put(MuleProperties.APP_HOME_DIRECTORY_PROPERTY, appHome);
 166  
                 }
 167  
                 
 168  0
                 config.configure(httpServer);
 169  
             }
 170  0
             catch (Exception e)
 171  
             {
 172  0
                 throw new InitialisationException(e, this);
 173  0
             }
 174  
         }
 175  0
     }
 176  
 
 177  
     /**
 178  
      * Template method to dispose any resources associated with this receiver. There
 179  
      * is not need to dispose the connector as this is already done by the framework
 180  
      */
 181  
     @Override
 182  
     protected void doDispose()
 183  
     {
 184  0
         holders.clear();
 185  0
     }
 186  
 
 187  
     @Override
 188  
     protected void doStart() throws MuleException
 189  
     {
 190  
         try
 191  
         {
 192  0
             httpServer.start();
 193  
             
 194  0
             if (deployer != null)
 195  
             {
 196  0
                 deployer.start();
 197  
             }
 198  
             
 199  0
             for (ConnectorHolder<?, ?> contextHolder : holders.values())
 200  
             {
 201  0
                 contextHolder.start();
 202  
             }
 203  
         }
 204  0
         catch (Exception e)
 205  
         {
 206  0
             throw new LifecycleException(CoreMessages.failedToStart("Jetty Http Receiver"), e, this);
 207  0
         }
 208  0
     }
 209  
 
 210  
     @Override
 211  
     protected void doStop() throws MuleException
 212  
     {
 213  
         try
 214  
         {
 215  0
             httpServer.stop();
 216  
             
 217  0
             if (deployer != null)
 218  
             {
 219  0
                 deployer.stop();
 220  
             }
 221  
             
 222  0
             for (ConnectorHolder<?, ?> connectorRef : holders.values())
 223  
             {
 224  0
                 connectorRef.stop();
 225  
             }
 226  
         }
 227  0
         catch (Exception e)
 228  
         {
 229  0
             throw new LifecycleException(CoreMessages.failedToStop("Jetty Http Receiver"), e, this);
 230  0
         }
 231  0
     }
 232  
 
 233  
     /**
 234  
      * Template method where any connections should be made for the connector
 235  
      *
 236  
      * @throws Exception
 237  
      */
 238  
     @Override
 239  
     protected void doConnect() throws Exception
 240  
     {
 241  
         //do nothing
 242  0
     }
 243  
 
 244  
     /**
 245  
      * Template method where any connected resources used by the connector should be
 246  
      * disconnected
 247  
      *
 248  
      * @throws Exception
 249  
      */
 250  
     @Override
 251  
     protected void doDisconnect() throws Exception
 252  
     {
 253  
         //do nothing
 254  0
     }
 255  
 
 256  
      @Override
 257  
     protected MessageReceiver createReceiver(FlowConstruct flowConstruct, InboundEndpoint endpoint) throws Exception
 258  
     {
 259  0
         MessageReceiver receiver = super.createReceiver(flowConstruct, endpoint);
 260  0
         registerJettyEndpoint(receiver, endpoint);
 261  0
         return receiver;
 262  
     }
 263  
 
 264  
     protected org.mortbay.jetty.AbstractConnector createJettyConnector()
 265  
     {
 266  0
         return new SelectChannelConnector();
 267  
     }
 268  
 
 269  
     public void unregisterListener(MessageReceiver receiver) throws MuleException
 270  
     {
 271  0
         String connectorKey = getHolderKey(receiver.getEndpoint());
 272  
 
 273  0
         synchronized (this)
 274  
         {
 275  0
             ConnectorHolder connectorRef = holders.get(connectorKey);
 276  0
             if (connectorRef != null)
 277  
             {
 278  0
                 if (!connectorRef.isReferenced())
 279  
                 {
 280  0
                     getHttpServer().removeConnector(connectorRef.getConnector());
 281  0
                     holders.remove(connectorKey);
 282  0
                     connectorRef.stop();
 283  
                 }
 284  
             }
 285  0
         }
 286  0
     }
 287  
 
 288  
     public Server getHttpServer()
 289  
     {
 290  0
         return httpServer;
 291  
     }
 292  
 
 293  
     public String getConfigFile()
 294  
     {
 295  0
         return configFile;
 296  
     }
 297  
 
 298  
     public void setConfigFile(String configFile)
 299  
     {
 300  0
         this.configFile = configFile;
 301  0
     }
 302  
 
 303  
     public JettyReceiverServlet getReceiverServlet()
 304  
     {
 305  0
         return receiverServlet;
 306  
     }
 307  
 
 308  
     public void setReceiverServlet(JettyReceiverServlet receiverServlet)
 309  
     {
 310  0
         this.receiverServlet = receiverServlet;
 311  0
     }
 312  
 
 313  
     @Override
 314  
     public ReplyToHandler getReplyToHandler(ImmutableEndpoint endpoint)
 315  
     {
 316  0
         if (isUseContinuations())
 317  
         {
 318  0
             return new JettyContinuationsReplyToHandler(getDefaultResponseTransformers(endpoint), muleContext);
 319  
         }
 320  0
         return super.getReplyToHandler(endpoint);
 321  
     }
 322  
 
 323  
     public boolean isUseContinuations()
 324  
     {
 325  0
         return useContinuations;
 326  
     }
 327  
 
 328  
     public void setUseContinuations(boolean useContinuations)
 329  
     {
 330  0
         this.useContinuations = useContinuations;
 331  0
     }
 332  
 
 333  
     ConnectorHolder<? extends MuleReceiverServlet, ? extends JettyHttpMessageReceiver> registerJettyEndpoint(MessageReceiver receiver, InboundEndpoint endpoint) throws MuleException
 334  
     {
 335  
         // Make sure that there is a connector for the requested endpoint.
 336  0
         String connectorKey = getHolderKey(endpoint);
 337  
 
 338  
         ConnectorHolder holder;
 339  
 
 340  0
         synchronized (this)
 341  
         {
 342  0
             holder = holders.get(connectorKey);
 343  0
             if (holder == null)
 344  
             {
 345  0
                 Connector connector = createJettyConnector();
 346  
 
 347  0
                 connector.setPort(endpoint.getEndpointURI().getPort());
 348  0
                 connector.setHost(endpoint.getEndpointURI().getHost());
 349  0
                 if ("localhost".equalsIgnoreCase(endpoint.getEndpointURI().getHost()))
 350  
                 {
 351  0
                     logger.warn("You use localhost interface! It means that no external connections will be available."
 352  
                             + " Don't you want to use 0.0.0.0 instead (all network interfaces)?");
 353  
                 }
 354  0
                 getHttpServer().addConnector(connector);
 355  
 
 356  0
                 holder = createContextHolder(connector, receiver.getEndpoint(), receiver);
 357  0
                 holders.put(connectorKey, holder);
 358  0
                 if(isStarted())
 359  
                 {
 360  0
                     holder.start();
 361  
                 }
 362  0
             }
 363  
             else
 364  
             {
 365  0
                 holder.addReceiver(receiver);
 366  
             }
 367  0
         }
 368  0
         return holder;
 369  
     }
 370  
 
 371  
     protected ConnectorHolder createContextHolder(Connector connector, InboundEndpoint endpoint, MessageReceiver receiver)
 372  
     {
 373  0
         return new MuleReceiverConnectorHolder(connector, (JettyReceiverServlet) createServlet(connector, endpoint), (JettyHttpMessageReceiver)receiver);
 374  
     }
 375  
 
 376  
     protected Servlet createServlet(Connector connector, ImmutableEndpoint endpoint)
 377  
     {
 378  
         HttpServlet servlet;
 379  0
         if (getReceiverServlet() == null)
 380  
         {
 381  0
             if(isUseContinuations())
 382  
             {
 383  0
                 servlet = new JettyContinuationsReceiverServlet();
 384  
             }
 385  
             else
 386  
             {
 387  0
                 servlet = new JettyReceiverServlet();
 388  
             }
 389  
         }
 390  
         else
 391  
         {
 392  0
             servlet = getReceiverServlet();
 393  
         }
 394  
 
 395  0
         String path = endpoint.getEndpointURI().getPath();
 396  0
         if(StringUtils.isBlank(path))
 397  
         {
 398  0
             path = ROOT;
 399  
         }
 400  
 
 401  0
         ContextHandlerCollection handlerCollection = new ContextHandlerCollection();
 402  0
         Context context = new Context(handlerCollection, ROOT, Context.NO_SECURITY);
 403  0
         context.setConnectorNames(new String[]{connector.getName()});
 404  0
         context.addEventListener(new MuleServletContextListener(muleContext, getName()));
 405  
 
 406  0
         if (resourceBase != null)
 407  
         {
 408  0
             Context resourceContext = new Context(handlerCollection, path, Context.NO_SECURITY);
 409  0
             resourceContext.setResourceBase(resourceBase);
 410  
         }
 411  
 
 412  0
         context.addServlet(JarResourceServlet.class, JarResourceServlet.DEFAULT_PATH_SPEC);
 413  
 
 414  0
         ServletHolder holder = new ServletHolder();
 415  0
         holder.setServlet(servlet);
 416  0
         context.addServlet(holder, "/*");
 417  0
         getHttpServer().addHandler(handlerCollection);
 418  0
         return servlet;
 419  
     }
 420  
 
 421  
     protected String getHolderKey(ImmutableEndpoint endpoint)
 422  
     {
 423  0
         return endpoint.getProtocol() + ":" + endpoint.getEndpointURI().getHost() + ":" + endpoint.getEndpointURI().getPort();
 424  
     }
 425  
 
 426  0
     public class MuleReceiverConnectorHolder extends AbstractConnectorHolder<JettyReceiverServlet, JettyHttpMessageReceiver>
 427  
     {
 428  0
         List<MessageReceiver> messageReceivers = new ArrayList<MessageReceiver>();
 429  
 
 430  
         public MuleReceiverConnectorHolder(Connector connector, JettyReceiverServlet servlet, JettyHttpMessageReceiver receiver)
 431  0
         {
 432  0
             super(connector, servlet, receiver);
 433  0
             addReceiver(receiver);
 434  0
         }
 435  
 
 436  
         public boolean isReferenced()
 437  
         {
 438  0
             return messageReceivers.size() > 0;
 439  
         }
 440  
 
 441  
         public void addReceiver(JettyHttpMessageReceiver receiver)
 442  
         {
 443  0
             messageReceivers.add(receiver);
 444  0
             if(started)
 445  
             {
 446  0
                 getServlet().addReceiver(receiver);
 447  
             }
 448  0
         }
 449  
 
 450  
         public void removeReceiver(JettyHttpMessageReceiver receiver)
 451  
         {
 452  0
             messageReceivers.remove(receiver);
 453  0
             getServlet().removeReceiver(receiver);
 454  0
         }
 455  
 
 456  
         @Override
 457  
         public void start() throws MuleException
 458  
         {
 459  0
             super.start();
 460  
             
 461  0
             for (MessageReceiver receiver : messageReceivers)
 462  
             {
 463  0
                 servlet.addReceiver(receiver);
 464  
             }
 465  0
         }
 466  
 
 467  
         @Override
 468  
         public void stop() throws MuleException
 469  
         {
 470  0
             super.stop();
 471  
 
 472  0
             for (MessageReceiver receiver : messageReceivers)
 473  
             {
 474  0
                 servlet.removeReceiver(receiver);
 475  
             }
 476  0
         }
 477  
     }
 478  
 
 479  
     public String getResourceBase()
 480  
     {
 481  0
         return resourceBase;
 482  
     }
 483  
 
 484  
     public void setResourceBase(String resourceBase)
 485  
     {
 486  0
         this.resourceBase = resourceBase;
 487  0
     }
 488  
 
 489  
     public WebappsConfiguration getWebappsConfiguration()
 490  
     {
 491  0
         return webappsConfiguration;
 492  
     }
 493  
 
 494  
     public void setWebappsConfiguration(WebappsConfiguration webappsConfiguration)
 495  
     {
 496  0
         this.webappsConfiguration = webappsConfiguration;
 497  0
     }
 498  
 }