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.mortbay.jetty.Server;
025
026import javax.inject.Inject;
027import java.net.BindException;
028import java.util.logging.Level;
029import java.util.logging.Logger;
030
031/**
032 * HttpServer. It manages Jetty Server and Event Handlers
033 */
034public final class HttpServerImpl implements HttpServer {
035  /**
036   * Standard Java logger.
037   */
038  private static final Logger LOG = Logger.getLogger(HttpServerImpl.class.getName());
039
040  /**
041   *  JettyHandler injected in the constructor
042   */
043  private JettyHandler jettyHandler;
044
045  /**
046   * Jetty server.
047   */
048  private final Server server;
049
050  /**
051   * port number used in Jetty Server
052   */
053  private final int port;
054
055  /**
056   * Logging scope factory
057   */
058  private final LoggingScopeFactory loggingScopeFactory;
059
060  /**
061   * Constructor of HttpServer that wraps Jetty Server
062   *
063   * @param jettyHandler
064   * @param portNumber
065   * @throws Exception
066   */
067  @Inject
068  HttpServerImpl(final JettyHandler jettyHandler,
069                 final @Parameter(PortNumber.class) int portNumber,
070                 final @Parameter(MaxPortNumber.class) int maxPortNumber,
071                 final @Parameter(MinPortNumber.class) int minPortNumber,
072                 final @Parameter(MaxRetryAttempts.class) int maxRetryAttempts,
073                 final LoggingScopeFactory loggingScopeFactory) throws Exception {
074
075    this.loggingScopeFactory = loggingScopeFactory;
076    try (final LoggingScope ls = this.loggingScopeFactory.httpServer()) {
077      this.jettyHandler = jettyHandler;
078      int port = portNumber;
079      Server srv = null;
080      boolean found = false;
081      for (int attempt = 0; attempt < maxRetryAttempts; ++attempt) {
082        if (attempt > 0) {
083          port = getNextPort(maxPortNumber, minPortNumber);
084        }
085        srv = new Server(port);
086        try {
087          srv.start();
088          found = true;
089          break;
090        } catch (final BindException ex) {
091          LOG.log(Level.FINEST, "Cannot use port: {0}. Will try another", port);
092        }
093      }
094
095      if (found) {
096        this.server = srv;
097        this.port = port;
098        this.server.setHandler(jettyHandler);
099        LOG.log(Level.INFO, "Jetty Server started with port: {0}", port);
100      } else {
101        throw new RuntimeException("Could not find available port in " + maxRetryAttempts + " attempts");
102      }
103    }
104  }
105
106  /**
107   * get a random port number in min and max range
108   *
109   * @return
110   */
111  private int getNextPort(final int maxPort, final int minPort) {
112    return minPort + (int) (Math.random() * ((maxPort - minPort) + 1));
113  }
114
115  /**
116   * It will be called from RuntimeStartHandler. As the Jetty server has been started at initialization phase, no need to start here.
117   *
118   * @throws Exception
119   */
120  @Override
121  public void start() throws Exception {
122  }
123
124  /**
125   * stop Jetty Server. It will be called from RuntimeStopHandler
126   *
127   * @throws Exception
128   */
129  @Override
130  public void stop() throws Exception {
131    server.stop();
132  }
133
134  @Override
135  public int getPort() {
136    return port;
137  }
138
139  /**
140   * Add a HttpHandler to Jetty Handler
141   *
142   * @param httpHandler
143   */
144  @Override
145  public void addHttpHandler(final HttpHandler httpHandler) {
146    LOG.log(Level.INFO, "addHttpHandler: {0}", httpHandler.getUriSpecification());
147    jettyHandler.addHandler(httpHandler);
148  }
149}