| /* |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| */ |
| package org.apache.qpid.restapi; |
| |
| import java.io.IOException; |
| import java.net.InetSocketAddress; |
| import java.util.concurrent.Executors; |
| import java.util.List; |
| |
| import com.sun.net.httpserver.HttpServer; |
| |
| import org.apache.qpid.qmf2.util.GetOpt; |
| |
| import org.apache.qpid.restapi.httpserver.Authenticator; |
| import org.apache.qpid.restapi.httpserver.Delegator; |
| |
| /** |
| * Note QpidRestAPI makes use of the Java 1.6 "Easter Egg" HttpServer and associated classes to create a simple |
| * HTTP REST interface to Qpid and QMF2 functionality. |
| * <p> |
| * Because HttpServer is in the com.sun.net.httpserver.HttpServer namespace it is technically not part of core Java |
| * and so may not be supported in all JREs, however it seems to be present in the OpenJDK Runtime Environment that is |
| * installed on many Linux variants. It is documented here <a href="http://docs.oracle.com/javase/6/docs/jre/api/net/httpserver/spec/overview-summary.html">com.sun.net.httpserver</a> |
| * <p> |
| * The reason for choosing com.sun.net.httpserver.HttpServer is simply in order to provide a very lightweight and |
| * dependency free approach to creating an HTTP Proxy. Clearly other approaches such as full-blown Servlet containers |
| * and the like might provide a better mechanism for some environments, but HttpServer really is very simple to use. |
| * <p> |
| * If there is a desire to use Servlets rather than HttpServer it should be fairly straightforward as two interfaces |
| * have been provided (Server and HttpTransaction) that abstract the key behaviour, so for example a concrete HttpTransaction |
| * implementation could be created by wrapping a com.sun.net.httpserver.HttpExchange, but equally another implementation |
| * could wrap javax.servlet.http.HttpServletRequest and javax.servlet.http.HttpServletResponse, so for example an |
| * HttpServlet could delegate to a Server instance passing the Conversation it constructed from the HttpServletRequest |
| * and HttpServletResponse in a similar way that our Delegator implementation of HttpHandler delegates to the Servers. |
| * |
| * <pre> |
| * Usage: QpidRestAPI [options] |
| * |
| * Options: |
| * -h, --help |
| * show this help message and exit |
| * -a <address>, --broker-addr=<address> |
| * broker-addr is in the form: [username/password@] |
| * hostname | ip-address [:<port>] ex: localhost, |
| * 10.1.1.7:10000, broker-host:10000, |
| * guest/guest@localhost |
| * Default is the host QpidRestAPI runs on & port 5672. |
| * -i <address>, --addr=<address> |
| * the hostname of the QpidRestAPI default is the wildcard address |
| * (Bind to a specific address on a multihomed host) |
| * -p <port>, --port=<port> |
| * the port the QpidRestAPI is bound to default is 8080 |
| * -b <backlog>, --backlog=<backlog> |
| * the socket backlog default is 10 |
| * -w <directory>, --webroot=<directory> |
| * the directory of the QpidRestAPI Web Site default is qpid-web |
| * </pre> |
| * @author Fraser Adams |
| */ |
| public class QpidRestAPI |
| { |
| private static final String _usage = |
| "Usage: QpidRestAPI [options]\n"; |
| |
| private static final String _description = |
| "Creates an HTTP REST interface to enable us to send messages to Qpid brokers and use QMF2 via HTTP.\n"; |
| |
| private static final String _options = |
| "Options:\n" + |
| " -h, --help show this help message and exit.\n" + |
| " -a <address>, --broker-addr=<address>\n" + |
| " broker-addr is in the form: [username/password@]\n" + |
| " hostname | ip-address [:<port>] e.g.\n" + |
| " localhost, 10.1.1.7:10000, broker-host:10000,\n" + |
| " guest/guest@localhost, guest/guest@broker-host:10000\n" + |
| " default is the host QpidRestAPI runs on & port 5672.\n" + |
| " -i <address>, --addr=<address>\n" + |
| " the hostname of the QpidRestAPI.\n" + |
| " default is the wildcard address.\n" + |
| " (Bind to a specific address on a multihomed host).\n" + |
| " -p <port>, --port=<port>\n" + |
| " the port the QpidRestAPI is bound to.\n" + |
| " default is 8080.\n" + |
| " -b <backlog>, --backlog=<backlog>\n" + |
| " the socket backlog.\n" + |
| " default is 10\n" + |
| " -w <directory>, --webroot=<directory>\n" + |
| " the directory of the QpidRestAPI Web Site.\n" + |
| " default is qpid-web.\n"; |
| |
| |
| /** |
| * Construct and start an instance of QpidRestAPI. This class used a Delegator class to delegate to underlying |
| * Server instances that actually implement the business logic of the REST API. |
| * |
| * @param addr the the address the QpidRestAPI is bound to (null = default). |
| * @param port the port the QpidRestAPI is bound to. |
| * @param broker the address of the Qpid broker to connect to (null = default). |
| * @param backlog the socket backlog. |
| * @param webroot the directory of the QpidRestAPI Web Site. |
| */ |
| public QpidRestAPI(final String addr, final int port, String broker, final int backlog, final String webroot) |
| throws IOException |
| { |
| final InetSocketAddress inetaddr = (addr == null) ? new InetSocketAddress(port) : |
| new InetSocketAddress(addr, port); |
| final HttpServer server = HttpServer.create(inetaddr, backlog); |
| |
| broker = (broker == null) ? inetaddr.getAddress().getHostAddress() + ":5672" : broker; |
| |
| Delegator fileserver = new Delegator(new FileServer(webroot + "/web", true)); |
| Delegator qpidserver = new Delegator(new QpidServer(broker)); |
| |
| Authenticator authenticator = new Authenticator(this.getClass().getCanonicalName(), webroot + "/authentication"); |
| |
| server.setExecutor(Executors.newCachedThreadPool()); |
| server.createContext("/", fileserver); |
| server.createContext("/ui", fileserver).setAuthenticator(authenticator); |
| server.createContext("/qpid/connection", qpidserver).setAuthenticator(authenticator); |
| server.start(); |
| } |
| |
| /** |
| * Runs QpidRestAPI. |
| * @param args the command line arguments. |
| */ |
| public static void main(String[] args) throws IOException |
| { |
| String logLevel = System.getProperty("amqj.logging.level"); |
| logLevel = (logLevel == null) ? "FATAL" : logLevel; // Set default log level to FATAL rather than DEBUG. |
| System.setProperty("amqj.logging.level", logLevel); |
| |
| String[] longOpts = {"help", "host=", "port=", "backlog=", "webroot="}; |
| try |
| { |
| String addr = null; |
| int port = 8080; |
| String broker = null; |
| int backlog = 10; |
| String webroot = "qpid-web"; |
| |
| GetOpt getopt = new GetOpt(args, "ha:i:p:b:w:", longOpts); |
| List<String[]> optList = getopt.getOptList(); |
| String[] cargs = {}; |
| cargs = getopt.getEncArgs().toArray(cargs); |
| |
| for (String[] opt : optList) |
| { |
| if (opt[0].equals("-h") || opt[0].equals("--help")) |
| { |
| System.out.println(_usage); |
| System.out.println(_description); |
| System.out.println(_options); |
| System.exit(1); |
| } |
| else if (opt[0].equals("-a") || opt[0].equals("--broker-addr")) |
| { |
| broker = opt[1]; |
| } |
| else if (opt[0].equals("-i") || opt[0].equals("--addr")) |
| { |
| addr = opt[1]; |
| } |
| else if (opt[0].equals("-p") || opt[0].equals("--port")) |
| { |
| port = Integer.parseInt(opt[1]); |
| } |
| else if (opt[0].equals("-b") || opt[0].equals("--backlog")) |
| { |
| backlog = Integer.parseInt(opt[1]); |
| } |
| else if (opt[0].equals("-w") || opt[0].equals("--webroot")) |
| { |
| webroot = opt[1]; |
| } |
| } |
| |
| QpidRestAPI restAPI = new QpidRestAPI(addr, port, broker, backlog, webroot); |
| } |
| catch (IllegalArgumentException e) |
| { |
| System.out.println(_usage); |
| System.out.println(e.getMessage()); |
| System.exit(1); |
| } |
| } |
| } |
| |