001    /**
002     * Copyright (c) 2010 Yahoo! Inc. All rights reserved.
003     * Licensed under the Apache License, Version 2.0 (the "License");
004     * you may not use this file except in compliance with the License.
005     * You may obtain a copy of the License at
006     *
007     *   http://www.apache.org/licenses/LICENSE-2.0
008     *
009     *  Unless required by applicable law or agreed to in writing, software
010     *  distributed under the License is distributed on an "AS IS" BASIS,
011     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012     *  See the License for the specific language governing permissions and
013     *  limitations under the License. See accompanying LICENSE file.
014     */
015    package org.apache.oozie.test;
016    
017    import org.mortbay.jetty.Server;
018    import org.mortbay.jetty.servlet.ServletHolder;
019    import org.mortbay.jetty.servlet.Context;
020    
021    import java.net.InetAddress;
022    import java.net.ServerSocket;
023    
024    /**
025     * An embedded servlet container for testing purposes. <p/> It provides reduced functionality, it supports only
026     * Servlets. <p/> The servlet container is started in a free port.
027     */
028    public class EmbeddedServletContainer {
029        private Server server;
030        private String host = null;
031        private int port = -1;
032        private String contextPath;
033        Context context;
034    
035        /**
036         * Create a servlet container.
037         *
038         * @param contextPath context path for the servlet, it must not be prefixed or append with "/", for the default
039         * context use ""
040         */
041        public EmbeddedServletContainer(String contextPath) {
042            this.contextPath = contextPath;
043            server = new Server(0);
044            context = new Context();
045            context.setContextPath("/" + contextPath);
046            server.setHandler(context);
047        }
048    
049        /**
050         * Add a servlet to the container.
051         *
052         * @param servletPath servlet path for the servlet, it should be prefixed with '/", it may contain a wild card at
053         * the end.
054         * @param servletClass servlet class
055         */
056        public void addServletEndpoint(String servletPath, Class servletClass) {
057            context.addServlet(new ServletHolder(servletClass), servletPath);
058        }
059    
060        /**
061         * Start the servlet container. <p/> The container starts on a free port.
062         *
063         * @throws Exception thrown if the container could not start.
064         */
065        public void start() throws Exception {
066            host = InetAddress.getLocalHost().getHostName();
067            ServerSocket ss = new ServerSocket(0);
068            port = ss.getLocalPort();
069            ss.close();
070            server.getConnectors()[0].setHost(host);
071            server.getConnectors()[0].setPort(port);
072            server.start();
073            System.out.println("Running embedded servlet container at: http://" + host + ":" + port);
074        }
075    
076        /**
077         * Return the hostname the servlet container is bound to.
078         *
079         * @return the hostname.
080         */
081        public String getHost() {
082            return host;
083        }
084    
085        /**
086         * Return the port number the servlet container is bound to.
087         *
088         * @return the port number.
089         */
090        public int getPort() {
091            return port;
092        }
093    
094        /**
095         * Return the full URL (including protocol, host, port, context path, servlet path) for the context path.
096         *
097         * @return URL to the context path.
098         */
099        public String getContextURL() {
100            return "http://" + host + ":" + port + "/" + contextPath;
101        }
102    
103        /**
104         * Return the full URL (including protocol, host, port, context path, servlet path) for a servlet path.
105         *
106         * @param servletPath the path which will be expanded to a full URL.
107         * @return URL to the servlet.
108         */
109        public String getServletURL(String servletPath) {
110            String path = servletPath;
111            if (path.endsWith("*")) {
112                path = path.substring(0, path.length() - 1);
113            }
114            return getContextURL() + path;
115        }
116    
117        /**
118         * Stop the servlet container.
119         */
120        public void stop() {
121            try {
122                server.stop();
123            }
124            catch (Exception e) {
125                // ignore exception
126            }
127    
128            try {
129                server.destroy();
130            }
131            catch (Exception e) {
132                // ignore exception
133            }
134    
135            host = null;
136            port = -1;
137        }
138    
139    }