View Javadoc

    1   /**
    2    * Copyright (c) 2002-2011 "Neo Technology,"
    3    * Network Engine for Objects in Lund AB [http://neotechnology.com]
    4    *
    5    * This file is part of Neo4j.
    6    *
    7    * Neo4j is free software: you can redistribute it and/or modify
    8    * it under the terms of the GNU General Public License as published by
    9    * the Free Software Foundation, either version 3 of the License, or
    10   * (at your option) any later version.
    11   *
    12   * This program is distributed in the hope that it will be useful,
    13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15   * GNU General Public License for more details.
    16   *
    17   * You should have received a copy of the GNU General Public License
    18   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    19   */
    20  package org.neo4j.server.web;
    21
    22  import com.sun.jersey.api.core.ResourceConfig;
    23  import com.sun.jersey.spi.container.servlet.ServletContainer;
    24  import org.mortbay.jetty.Server;
    25  import org.mortbay.jetty.SessionManager;
    26  import org.mortbay.jetty.handler.MovedContextHandler;
    27  import org.mortbay.jetty.servlet.Context;
    28  import org.mortbay.jetty.servlet.HashSessionManager;
    29  import org.mortbay.jetty.servlet.ServletHolder;
    30  import org.mortbay.jetty.servlet.SessionHandler;
    31  import org.mortbay.jetty.webapp.WebAppContext;
    32  import org.mortbay.resource.Resource;
    33  import org.mortbay.thread.QueuedThreadPool;
    34  import org.neo4j.server.NeoServer;
    35  import org.neo4j.server.logging.Logger;
    36  import org.neo4j.server.rest.web.AllowAjaxFilter;
    37
    38  import java.net.URI;
    39  import java.net.URISyntaxException;
    40  import java.net.URL;
    41  import java.util.HashMap;
    42  import java.util.List;
    43
    44  import javax.servlet.Servlet;
    45
    46  public class Jetty6WebServer implements WebServer
    47  {
    48      public static final Logger log = Logger.getLogger( Jetty6WebServer.class );
    49
    50
    51      private Server jetty;
    52      private int jettyPort = 80;
    53
    54      private final HashMap<String, String> staticContent = new HashMap<String, String>();
    55      private final HashMap<String, ServletHolder> jaxRSPackages = new HashMap<String, ServletHolder>();
    56      private NeoServer server;
    57
    58
    59      @Override
    60      public void setNeoServer( NeoServer server )
    61      {
    62          this.server = server;
    63      }
    64
    65      @Override
    66      public void start() {
    67          jetty = new Server(jettyPort);
    68          jetty.setStopAtShutdown(true);
    69          MovedContextHandler redirector = new MovedContextHandler();
    70
    71          jetty.addHandler( redirector );
    72
    73          loadStaticContent();
    74          loadJAXRSPackages();
    75
    76          try {
    77              jetty.start();
    78          } catch (Exception e) {
    79              throw new RuntimeException(e);
    80          }
    81      }
    82
    83      @Override
    84      public void stop()
    85      {
    86          try
    87          {
    88              jetty.stop();
    89              jetty.join();
    90          }
    91          catch ( Exception e )
    92          {
    93              throw new RuntimeException(e);
    94          }
    95          finally
    96          {
    97              // Jetty doesn't remove its shutdown hook automatically on stop()
    98              jetty.setStopAtShutdown( false );
    99          }
    100     }
    101
    102     @Override
    103     public void setPort(int portNo) {
    104         jettyPort = portNo;
    105     }
    106
    107     @Override
    108     public void setMaxThreads(int maxThreads) {
    109         jetty.setThreadPool(new QueuedThreadPool(maxThreads));
    110     }
    111
    112     @Override
    113     public void addJAXRSPackages(List<String> packageNames, String mountPoint) {
    114         // We don't want absolute URIs at this point
    115         mountPoint = ensureRelativeUri(mountPoint);
    116
    117         // Trim any trailing slash to keep Jetty happy
    118         mountPoint = trimTrailingSlash(mountPoint);
    119
    120         ServletContainer container = new NeoServletContainer(server, server.getInjectables( packageNames ) );
    121         ServletHolder servletHolder = new ServletHolder(container);
    122         servletHolder.setInitParameter("com.sun.jersey.config.property.packages", toCommaSeparatedList(packageNames));
    123         servletHolder.setInitParameter(ResourceConfig.PROPERTY_CONTAINER_RESPONSE_FILTERS, AllowAjaxFilter.class.getName());
    124         log.info("Adding JAXRS package %s at [%s]", packageNames, mountPoint);
    125         jaxRSPackages.put(mountPoint, servletHolder);
    126     }
    127
    128     @Override
    129     public void addServlet( Servlet unmanagedServlet, String mountPoint )
    130     {
    131         log.info("adding Servlet [%s] at [%s]", unmanagedServlet.getClass().getName(), mountPoint);
    132         Context servletContext = new Context(jetty, mountPoint);
    133         SessionManager sm = new HashSessionManager();
    134         SessionHandler sh = new SessionHandler(sm);
    135         ServletHolder servletHolder = new ServletHolder(unmanagedServlet);
    136         servletContext.addServlet(servletHolder, "/*");
    137         servletContext.setSessionHandler(sh);
    138     }
    139
    140     private String trimTrailingSlash(String mountPoint) {
    141         if(mountPoint.equals("/")) {
    142             return mountPoint;
    143         }
    144
    145         if(mountPoint.endsWith("/")) {
    146             mountPoint = mountPoint.substring(0, mountPoint.length() -1);
    147         }
    148         return mountPoint;
    149     }
    150
    151     private String ensureRelativeUri(String mountPoint) {
    152         try {
    153             URI result = new URI(mountPoint);
    154             if(result.isAbsolute()) {
    155                 return result.getPath();
    156             } else {
    157                 return result.toString();
    158             }
    159         } catch (URISyntaxException e) {
    160             log.debug("Unable to translate [%s] to a relative URI in ensureRelativeUri(String mountPoint)", mountPoint);
    161             return mountPoint;
    162         }
    163     }
    164
    165     @Override
    166     public void addStaticContent(String contentLocation, String serverMountPoint) {
    167         staticContent.put(serverMountPoint, contentLocation);
    168     }
    169
    170     private void loadStaticContent() {
    171         for (String mountPoint : staticContent.keySet()) {
    172             String contentLocation = staticContent.get(mountPoint);
    173             log.info("Mounting static content at [%s] from [%s]", mountPoint, contentLocation);
    174             try {
    175                 final WebAppContext staticContext = new WebAppContext();
    176                 staticContext.setServer(jetty);
    177                 staticContext.setContextPath(mountPoint);
    178                 URL resourceLoc = getClass().getClassLoader().getResource(contentLocation);
    179                 if(resourceLoc != null) {
    180                     log.info("Found [%s]", resourceLoc);
    181                     URL url = resourceLoc.toURI().toURL();
    182                     final Resource resource = Resource.newResource(url);
    183                     staticContext.setBaseResource(resource);
    184                     log.info("Mounting static content from [%s] at [%s]", url, mountPoint);
    185                     jetty.addHandler(staticContext);
    186                 } else {
    187                     log.error("No static content available for Neo Server at port [%d], management console may not be available.", jettyPort);
    188                 }
    189             } catch (Exception e) {
    190                 log.error(e);
    191                 e.printStackTrace();
    192                 throw new RuntimeException(e);
    193             }
    194         }
    195     }
    196
    197     private void loadJAXRSPackages() {
    198         for (String mountPoint : jaxRSPackages.keySet()) {
    199
    200             ServletHolder servletHolder = jaxRSPackages.get(mountPoint);
    201             log.info("Mounting servlet at [%s]", mountPoint);
    202             Context jerseyContext = new Context(jetty, mountPoint);
    203             SessionManager sm = new HashSessionManager();
    204             SessionHandler sh = new SessionHandler(sm);
    205             jerseyContext.addServlet(servletHolder, "/*");
    206             jerseyContext.setSessionHandler(sh);
    207         }
    208     }
    209
    210     private String toCommaSeparatedList(List<String> packageNames) {
    211         StringBuilder sb = new StringBuilder();
    212
    213         for (String str : packageNames) {
    214             sb.append(str);
    215             sb.append(", ");
    216         }
    217
    218         String result = sb.toString();
    219         return result.substring(0, result.length() - 2);
    220     }
    221 }