/** * Copyright (C) 2011 Brian Ferris (bdferris@google.com) * * Licensed 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.onebusaway.quickstart.bootstrap; import java.io.IOException; import java.net.URL; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.GnuParser; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.Parser; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.bio.SocketConnector; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.ContextHandler.Context; import org.eclipse.jetty.server.handler.HandlerList; import org.eclipse.jetty.webapp.WebAppContext; import org.onebusaway.quickstart.BootstrapCommon; import org.onebusaway.quickstart.WebappCommon; /** * Boostrap a Jetty webapp container for running an instance of OneBusAway. * * @author bdferris * */ public class WebappBootstrapMain { private static final String ARG_PORT = "port"; public static void run(URL warUrl, boolean consoleMode, String[] args) throws Exception { if (args.length == 0 || isHelp(args)) { BootstrapCommon.printUsage(WebappBootstrapMain.class, "usage-webapp.txt"); System.exit(-1); } Options options = createOptions(); Parser parser = new GnuParser(); CommandLine cli = parser.parse(options, args); args = cli.getArgs(); if (args.length != 1) { BootstrapCommon.printUsage(WebappBootstrapMain.class, "usage-webapp.txt"); System.exit(-1); } String bundlePath = args[0]; System.setProperty("bundlePath", bundlePath); int port = 8080; if (cli.hasOption(ARG_PORT)) port = Integer.parseInt(cli.getOptionValue(ARG_PORT)); Server server = new Server(); SocketConnector connector = new SocketConnector(); // Set some timeout options to make debugging easier. connector.setMaxIdleTime(1000 * 60 * 60); connector.setSoLingerTime(-1); connector.setPort(port); server.setConnectors(new Connector[] {connector}); WebAppContext context = new WebAppContext(); context.setContextPath("/"); // context.setWelcomeFiles(new String[] {"index.action"}); context.setWar(warUrl.toExternalForm()); // We store the command line object as a webapp context attribute so it can // be used by the context loader to inject additional beans as needed context.setAttribute(WebappCommon.COMMAND_LINE_CONTEXT_ATTRIBUTE, cli); HandlerList handlers = new HandlerList(); handlers.setHandlers(new Handler[] {new WelcomeFileHandler(context), context}); server.setHandler(handlers); /** * We specify a Jetty override descriptor to inject additional definitions * into our web.xml configuration. Specifically, we specify a * <context-param> to specify the "contextClass" that will be used to create * our Spring ApplicationContext. We create a custom version that will * inject additional beans based on command-line arguments. */ context.addOverrideDescriptor("/WEB-INF/override-web.xml"); if (cli.hasOption(WebappCommon.ARG_BUILD)) { System.setProperty("hibernate.hbm2ddl.auto", "update"); System.setProperty("bundleCacheDir", bundlePath + "/cache"); System.setProperty("gtfsPath", cli.getOptionValue(WebappCommon.ARG_GTFS_PATH)); context.addOverrideDescriptor("/WEB-INF/builder-override-web.xml"); } try { server.start(); System.err.println("============================================================="); System.err.println("="); System.err.println("= Your OneBusAway instance has started. Browse to:"); System.err.println("="); System.err.println("= http://localhost:" + port + "/"); System.err.println("="); System.err.println("= to see your instance in action."); if (consoleMode) { System.err.println("="); System.err.println("= When you are finished, press return to exit gracefully..."); } System.err.println("============================================================="); if (consoleMode) { System.in.read(); server.stop(); server.join(); } } catch (Exception e) { e.printStackTrace(); System.exit(100); } } private static boolean isHelp(String[] options) { for (String option : options) { option = option.replaceAll("-", ""); option = option.toLowerCase(); if (option.equals("help") || option.equals("h") || option.equals("?")) return true; } return false; } private static Options createOptions() { Options options = new Options(); options.addOption(ARG_PORT, true, "port (default=8080)"); options.addOption(WebappCommon.ARG_BUILD, false, ""); options.addOption(WebappCommon.ARG_GTFS_PATH, true, ""); options.addOption(WebappCommon.ARG_GTFS_REALTIME_TRIP_UPDATES_URL, true, ""); options.addOption(WebappCommon.ARG_GTFS_REALTIME_VEHICLE_POSITIONS_URL, true, ""); options.addOption(WebappCommon.ARG_GTFS_REALTIME_ALERTS_URL, true, ""); options.addOption(WebappCommon.ARG_GTFS_REALTIME_REFRESH_INTERVAL, true, ""); Option pOption = new Option("P", "use value for given property"); pOption.setArgName("beanName.beanProperty=value"); pOption.setArgs(2); pOption.setValueSeparator('='); options.addOption(pOption); return options; } private static class WelcomeFileHandler extends AbstractHandler { private final WebAppContext _context; public WelcomeFileHandler(WebAppContext context) { _context = context; } @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { String[] welcomeFiles = _context.getWelcomeFiles(); if (welcomeFiles != null && target.endsWith("/")) { for (String welcomeFile : welcomeFiles) { String path = target; path += welcomeFile; Context context = _context.getServletContext(); URL resource = context.getResource(path); if (resource != null) { target = path; baseRequest.setPathInfo(target); _context.handle(target, baseRequest, request, response); return; } } } } } }