This project has retired. For details please refer to its Attic page.
Source code
001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.reef.webserver;
020
021import org.apache.reef.tang.annotations.Parameter;
022import org.apache.reef.util.logging.LoggingScope;
023import org.apache.reef.util.logging.LoggingScopeFactory;
024import org.apache.reef.wake.remote.ports.TcpPortProvider;
025import org.apache.reef.wake.remote.ports.parameters.TcpPortRangeBegin;
026import org.mortbay.jetty.Server;
027
028import javax.inject.Inject;
029import java.net.BindException;
030import java.util.Iterator;
031import java.util.logging.Level;
032import java.util.logging.Logger;
033
034/**
035 * HttpServer. It manages Jetty Server and Event Handlers
036 */
037public final class HttpServerImpl implements HttpServer {
038  /**
039   * Standard Java logger.
040   */
041  private static final Logger LOG = Logger.getLogger(HttpServerImpl.class.getName());
042
043  /**
044   *  JettyHandler injected in the constructor.
045   */
046  private JettyHandler jettyHandler;
047
048  /**
049   * Jetty server.
050   */
051  private final Server server;
052
053  /**
054   * port number used in Jetty Server.
055   */
056  private final int port;
057
058  /**
059   * Logging scope factory.
060   */
061  private final LoggingScopeFactory loggingScopeFactory;
062
063  /**
064   * Constructor of HttpServer that wraps Jetty Server.
065   *
066   * @param jettyHandler
067   * @param portNumber
068   * @throws Exception
069   */
070  @Inject
071  HttpServerImpl(final JettyHandler jettyHandler,
072                 @Parameter(TcpPortRangeBegin.class) final int portNumber,
073                 final TcpPortProvider tcpPortProvider,
074                 final LoggingScopeFactory loggingScopeFactory) throws Exception {
075
076    this.loggingScopeFactory = loggingScopeFactory;
077    this.jettyHandler = jettyHandler;
078    int availablePort = portNumber;
079    Server srv = null;
080
081    try (final LoggingScope ls = this.loggingScopeFactory.httpServer()) {
082
083      final Iterator<Integer> ports = tcpPortProvider.iterator();
084      while (ports.hasNext() && srv  == null) {
085        availablePort = ports.next();
086        srv = tryPort(availablePort);
087      }
088
089      if (srv  != null) {
090        this.server = srv;
091        this.port = availablePort;
092        this.server.setHandler(jettyHandler);
093        LOG.log(Level.INFO, "Jetty Server started with port: {0}", availablePort);
094      } else {
095        throw new RuntimeException("Could not find available port for http");
096      }
097    }
098  }
099
100  private Server tryPort(final int portNumber) throws Exception {
101    Server srv = new Server(portNumber);
102    try {
103      srv.start();
104      LOG.log(Level.INFO, "Jetty Server started with port: {0}", portNumber);
105    } catch (final BindException ex) {
106      srv = null;
107      LOG.log(Level.FINEST, "Cannot use port: {0}. Will try another", portNumber);
108    }
109    return srv;
110  }
111
112  /**
113   * get a random port number in min and max range.
114   *
115   * @return
116   */
117  private int getNextPort(final int maxPort, final int minPort) {
118    return minPort + (int) (Math.random() * ((maxPort - minPort) + 1));
119  }
120
121  /**
122   * It will be called from RuntimeStartHandler.
123   * As the Jetty server has been started at initialization phase, no need to start here.
124   *
125   * @throws Exception
126   */
127  @Override
128  public void start() throws Exception {
129  }
130
131  /**
132   * stop Jetty Server. It will be called from RuntimeStopHandler
133   *
134   * @throws Exception
135   */
136  @Override
137  public void stop() throws Exception {
138    server.stop();
139  }
140
141  @Override
142  public int getPort() {
143    return port;
144  }
145
146  /**
147   * Add a HttpHandler to Jetty Handler.
148   *
149   * @param httpHandler
150   */
151  @Override
152  public void addHttpHandler(final HttpHandler httpHandler) {
153    LOG.log(Level.INFO, "addHttpHandler: {0}", httpHandler.getUriSpecification());
154    jettyHandler.addHandler(httpHandler);
155  }
156}