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, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    package org.apache.oozie.test;
019    
020    import org.mortbay.jetty.Server;
021    import org.mortbay.jetty.servlet.FilterHolder;
022    import org.mortbay.jetty.servlet.ServletHolder;
023    import org.mortbay.jetty.servlet.Context;
024    
025    import java.net.InetAddress;
026    import java.net.ServerSocket;
027    import java.util.Map;
028    
029    /**
030     * An embedded servlet container for testing purposes. <p/> It provides reduced functionality, it supports only
031     * Servlets. <p/> The servlet container is started in a free port.
032     */
033    public class EmbeddedServletContainer {
034        private Server server;
035        private String host = null;
036        private int port = -1;
037        private String contextPath;
038        Context context;
039    
040        /**
041         * Create a servlet container.
042         *
043         * @param contextPath context path for the servlet, it must not be prefixed or append with "/", for the default
044         * context use ""
045         */
046        public EmbeddedServletContainer(String contextPath) {
047            this.contextPath = contextPath;
048            server = new Server(0);
049            context = new Context();
050            context.setContextPath("/" + contextPath);
051            server.setHandler(context);
052        }
053    
054        /**
055         * Add a servlet to the container.
056         *
057         * @param servletPath servlet path for the servlet, it should be prefixed with '/", it may contain a wild card at
058         * the end.
059         * @param servletClass servlet class
060         * @param initParams a mapping of init parameters for the servlet, or null
061         */
062        public void addServletEndpoint(String servletPath, Class servletClass, Map<String, String> initParams) {
063            ServletHolder s = new ServletHolder(servletClass);
064            context.addServlet(s, servletPath);
065            if (initParams != null) {
066                s.setInitParameters(initParams);
067            }
068        }
069    
070        /**
071         * Add a servlet to the container.
072         *
073         * @param servletPath servlet path for the servlet, it should be prefixed with '/", it may contain a wild card at
074         * the end.
075         * @param servletClass servlet class
076         */
077        public void addServletEndpoint(String servletPath, Class servletClass) {
078            addServletEndpoint(servletPath, servletClass, null);
079        }
080    
081        /**
082         * Add a filter to the container.
083         *
084         * @param filterPath path for the filter, it should be prefixed with '/", it may contain a wild card at
085         * the end.
086         * @param filterClass servlet class
087         */
088        public void addFilter(String filterPath, Class filterClass) {
089            context.addFilter(new FilterHolder(filterClass), filterPath, 0);
090        }
091    
092        /**
093         * Start the servlet container. <p/> The container starts on a free port.
094         *
095         * @throws Exception thrown if the container could not start.
096         */
097        public void start() throws Exception {
098            host = InetAddress.getLocalHost().getHostName();
099            ServerSocket ss = new ServerSocket(0);
100            port = ss.getLocalPort();
101            ss.close();
102            server.getConnectors()[0].setHost(host);
103            server.getConnectors()[0].setPort(port);
104            server.start();
105            System.out.println("Running embedded servlet container at: http://" + host + ":" + port);
106        }
107    
108        /**
109         * Return the hostname the servlet container is bound to.
110         *
111         * @return the hostname.
112         */
113        public String getHost() {
114            return host;
115        }
116    
117        /**
118         * Return the port number the servlet container is bound to.
119         *
120         * @return the port number.
121         */
122        public int getPort() {
123            return port;
124        }
125    
126        /**
127         * Return the full URL (including protocol, host, port, context path, servlet path) for the context path.
128         *
129         * @return URL to the context path.
130         */
131        public String getContextURL() {
132            return "http://" + host + ":" + port + "/" + contextPath;
133        }
134    
135        /**
136         * Return the full URL (including protocol, host, port, context path, servlet path) for a servlet path.
137         *
138         * @param servletPath the path which will be expanded to a full URL.
139         * @return URL to the servlet.
140         */
141        public String getServletURL(String servletPath) {
142            String path = servletPath;
143            if (path.endsWith("*")) {
144                path = path.substring(0, path.length() - 1);
145            }
146            return getContextURL() + path;
147        }
148    
149        /**
150         * Stop the servlet container.
151         */
152        public void stop() {
153            try {
154                server.stop();
155            }
156            catch (Exception e) {
157                // ignore exception
158            }
159    
160            try {
161                server.destroy();
162            }
163            catch (Exception e) {
164                // ignore exception
165            }
166    
167            host = null;
168            port = -1;
169        }
170    
171    }