| // |
| // ======================================================================== |
| // Copyright (c) 1995-2012 Sabre Holdings. |
| // ------------------------------------------------------------------------ |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // and Apache License v2.0 which accompanies this distribution. |
| // |
| // The Eclipse Public License is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // |
| // The Apache License v2.0 is available at |
| // http://www.opensource.org/licenses/apache2.0.php |
| // |
| // You may elect to redistribute this code under either of these licenses. |
| // ======================================================================== |
| // |
| |
| |
| package org.eclipse.jetty.ant; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.net.MalformedURLException; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.jetty.ant.types.Connector; |
| import org.eclipse.jetty.ant.types.ContextHandlers; |
| import org.eclipse.jetty.ant.utils.ServerProxy; |
| import org.eclipse.jetty.ant.utils.TaskLog; |
| import org.eclipse.jetty.security.LoginService; |
| import org.eclipse.jetty.server.Handler; |
| import org.eclipse.jetty.server.RequestLog; |
| import org.eclipse.jetty.server.Server; |
| import org.eclipse.jetty.server.ServerConnector; |
| import org.eclipse.jetty.server.ShutdownMonitor; |
| import org.eclipse.jetty.server.handler.ContextHandler; |
| import org.eclipse.jetty.server.handler.ContextHandlerCollection; |
| import org.eclipse.jetty.server.handler.DefaultHandler; |
| import org.eclipse.jetty.server.handler.HandlerCollection; |
| import org.eclipse.jetty.server.handler.RequestLogHandler; |
| import org.eclipse.jetty.util.Scanner; |
| import org.eclipse.jetty.util.resource.Resource; |
| import org.eclipse.jetty.xml.XmlConfiguration; |
| import org.xml.sax.SAXException; |
| |
| |
| |
| /** |
| * A proxy class for interaction with Jetty server object. Used to have some |
| * level of abstraction over standard Jetty classes. |
| */ |
| public class ServerProxyImpl implements ServerProxy |
| { |
| |
| /** Proxied Jetty server object. */ |
| private Server server; |
| |
| /** Temporary files directory. */ |
| private File tempDirectory; |
| |
| /** Collection of context handlers (web application contexts). */ |
| private ContextHandlerCollection contexts; |
| |
| /** Location of jetty.xml file. */ |
| private File jettyXml; |
| |
| /** List of connectors. */ |
| private List<Connector> connectors; |
| |
| /** Request logger. */ |
| private RequestLog requestLog; |
| |
| /** User realms. */ |
| private List<LoginService> loginServices; |
| |
| /** List of added web applications. */ |
| private List<AntWebAppContext> webApplications = new ArrayList<AntWebAppContext>(); |
| |
| /** other contexts to deploy */ |
| private ContextHandlers contextHandlers; |
| |
| /** scan interval for changed files */ |
| private int scanIntervalSecs; |
| |
| /** port to listen for stop command */ |
| private int stopPort; |
| |
| /** security key for stop command */ |
| private String stopKey; |
| |
| /** wait for all jetty threads to exit or continue */ |
| private boolean daemon; |
| |
| |
| private boolean configured = false; |
| |
| |
| |
| /** |
| * WebAppScannerListener |
| * |
| * Handle notifications that files we are interested in have changed |
| * during execution. |
| * |
| */ |
| public static class WebAppScannerListener implements Scanner.BulkListener |
| { |
| AntWebAppContext awc; |
| |
| public WebAppScannerListener (AntWebAppContext awc) |
| { |
| this.awc = awc; |
| } |
| |
| public void filesChanged(List<String> changedFileNames) |
| { |
| boolean isScanned = false; |
| try |
| { |
| Iterator<String> itor = changedFileNames.iterator(); |
| while (!isScanned && itor.hasNext()) |
| { |
| isScanned = awc.isScanned(Resource.newResource(itor.next()).getFile()); |
| } |
| if (isScanned) |
| { |
| awc.stop(); |
| awc.start(); |
| } |
| } |
| catch (Exception e) |
| { |
| TaskLog.log(e.getMessage()); |
| } |
| } |
| |
| } |
| |
| |
| /** |
| * Default constructor. Creates a new Jetty server with a standard connector |
| * listening on a given port. |
| */ |
| public ServerProxyImpl () |
| { |
| server = new Server(); |
| server.setStopAtShutdown(true); |
| } |
| |
| |
| public void addWebApplication(AntWebAppContext webApp) |
| { |
| webApplications.add(webApp); |
| } |
| |
| public int getStopPort() |
| { |
| return stopPort; |
| } |
| |
| public void setStopPort(int stopPort) |
| { |
| this.stopPort = stopPort; |
| } |
| |
| public String getStopKey() |
| { |
| return stopKey; |
| } |
| |
| public void setStopKey(String stopKey) |
| { |
| this.stopKey = stopKey; |
| } |
| |
| public File getJettyXml() |
| { |
| return jettyXml; |
| } |
| |
| public void setJettyXml(File jettyXml) |
| { |
| this.jettyXml = jettyXml; |
| } |
| |
| public List<Connector> getConnectors() |
| { |
| return connectors; |
| } |
| |
| public void setConnectors(List<Connector> connectors) |
| { |
| this.connectors = connectors; |
| } |
| |
| public RequestLog getRequestLog() |
| { |
| return requestLog; |
| } |
| |
| public void setRequestLog(RequestLog requestLog) |
| { |
| this.requestLog = requestLog; |
| } |
| |
| public List<LoginService> getLoginServices() |
| { |
| return loginServices; |
| } |
| |
| public void setLoginServices(List<LoginService> loginServices) |
| { |
| this.loginServices = loginServices; |
| } |
| |
| public List<AntWebAppContext> getWebApplications() |
| { |
| return webApplications; |
| } |
| |
| public void setWebApplications(List<AntWebAppContext> webApplications) |
| { |
| this.webApplications = webApplications; |
| } |
| |
| |
| public File getTempDirectory() |
| { |
| return tempDirectory; |
| } |
| |
| |
| public void setTempDirectory(File tempDirectory) |
| { |
| this.tempDirectory = tempDirectory; |
| } |
| |
| |
| /** |
| * @see org.eclipse.jetty.ant.utils.ServerProxy#start() |
| */ |
| public void start() |
| { |
| try |
| { |
| configure(); |
| |
| configureWebApps(); |
| |
| server.start(); |
| |
| System.setProperty("jetty.ant.server.port","" + ((ServerConnector)server.getConnectors()[0]).getLocalPort()); |
| |
| String host = ((ServerConnector)server.getConnectors()[0]).getHost(); |
| |
| if (host == null) |
| { |
| System.setProperty("jetty.ant.server.host", "localhost"); |
| } |
| else |
| { |
| System.setProperty("jetty.ant.server.host", host); |
| } |
| |
| startScanners(); |
| |
| TaskLog.log("Jetty AntTask Started"); |
| |
| if (!daemon) |
| server.join(); |
| } |
| catch (InterruptedException e) |
| { |
| new RuntimeException(e); |
| } |
| catch (Exception e) |
| { |
| e.printStackTrace(); |
| new RuntimeException(e); |
| } |
| } |
| |
| |
| |
| |
| /** |
| * @see org.eclipse.jetty.ant.utils.ServerProxy#getProxiedObject() |
| */ |
| public Object getProxiedObject() |
| { |
| return server; |
| } |
| |
| |
| /** |
| * @return the daemon |
| */ |
| public boolean isDaemon() |
| { |
| return daemon; |
| } |
| |
| |
| /** |
| * @param daemon the daemon to set |
| */ |
| public void setDaemon(boolean daemon) |
| { |
| this.daemon = daemon; |
| } |
| |
| |
| /** |
| * @return the contextHandlers |
| */ |
| public ContextHandlers getContextHandlers() |
| { |
| return contextHandlers; |
| } |
| |
| |
| /** |
| * @param contextHandlers the contextHandlers to set |
| */ |
| public void setContextHandlers (ContextHandlers contextHandlers) |
| { |
| this.contextHandlers = contextHandlers; |
| } |
| |
| |
| public int getScanIntervalSecs() |
| { |
| return scanIntervalSecs; |
| } |
| |
| |
| public void setScanIntervalSecs(int scanIntervalSecs) |
| { |
| this.scanIntervalSecs = scanIntervalSecs; |
| } |
| |
| |
| /** |
| * Configures Jetty server before adding any web applications to it. |
| */ |
| private void configure() |
| { |
| if (configured) |
| return; |
| |
| configured = true; |
| |
| if(stopPort>0 && stopKey!=null) |
| { |
| ShutdownMonitor monitor = ShutdownMonitor.getInstance(); |
| monitor.setPort(stopPort); |
| monitor.setKey(stopKey); |
| monitor.setExitVm(false); |
| } |
| |
| if (tempDirectory != null && !tempDirectory.exists()) |
| tempDirectory.mkdirs(); |
| |
| // Applies external configuration via jetty.xml |
| applyJettyXml(); |
| |
| // Configures connectors for this server instance. |
| if (connectors != null) |
| { |
| for (Connector c:connectors) |
| { |
| ServerConnector jc = new ServerConnector(server); |
| |
| jc.setPort(c.getPort()); |
| jc.setIdleTimeout(c.getMaxIdleTime()); |
| |
| server.addConnector(jc); |
| } |
| } |
| |
| // Configures login services |
| if (loginServices != null) |
| { |
| for (LoginService ls:loginServices) |
| { |
| server.addBean(ls); |
| } |
| } |
| |
| // Does not cache resources, to prevent Windows from locking files |
| Resource.setDefaultUseCaches(false); |
| |
| // Set default server handlers |
| configureHandlers(); |
| } |
| |
| |
| /** |
| * |
| */ |
| private void configureHandlers() |
| { |
| RequestLogHandler requestLogHandler = new RequestLogHandler(); |
| if (requestLog != null) |
| requestLogHandler.setRequestLog(requestLog); |
| |
| contexts = (ContextHandlerCollection) server |
| .getChildHandlerByClass(ContextHandlerCollection.class); |
| if (contexts == null) |
| { |
| contexts = new ContextHandlerCollection(); |
| HandlerCollection handlers = (HandlerCollection) server |
| .getChildHandlerByClass(HandlerCollection.class); |
| if (handlers == null) |
| { |
| handlers = new HandlerCollection(); |
| server.setHandler(handlers); |
| handlers.setHandlers(new Handler[] { contexts, new DefaultHandler(), |
| requestLogHandler }); |
| } |
| else |
| { |
| handlers.addHandler(contexts); |
| } |
| } |
| |
| //if there are any extra contexts to deploy |
| if (contextHandlers != null && contextHandlers.getContextHandlers() != null) |
| { |
| for (ContextHandler c:contextHandlers.getContextHandlers()) |
| contexts.addHandler(c); |
| } |
| } |
| |
| |
| |
| |
| /** |
| * Applies jetty.xml configuration to the Jetty server instance. |
| */ |
| private void applyJettyXml() |
| { |
| if (jettyXml != null && jettyXml.exists()) |
| { |
| TaskLog.log("Configuring jetty from xml configuration file = " |
| + jettyXml.getAbsolutePath()); |
| XmlConfiguration configuration; |
| try |
| { |
| configuration = new XmlConfiguration(Resource.toURL(jettyXml)); |
| configuration.configure(server); |
| } |
| catch (MalformedURLException e) |
| { |
| throw new RuntimeException(e); |
| } |
| catch (SAXException e) |
| { |
| throw new RuntimeException(e); |
| } |
| catch (IOException e) |
| { |
| throw new RuntimeException(e); |
| } |
| catch (Exception e) |
| { |
| throw new RuntimeException(e); |
| } |
| } |
| } |
| |
| |
| /** |
| * Starts web applications' scanners. |
| */ |
| private void startScanners() throws Exception |
| { |
| for (AntWebAppContext awc:webApplications) |
| { |
| if (scanIntervalSecs <= 0) |
| return; |
| |
| List<File> scanList = awc.getScanFiles(); |
| |
| TaskLog.log("Web application '" + awc + "': starting scanner at interval of " |
| + scanIntervalSecs + " seconds."); |
| Scanner.Listener changeListener = new WebAppScannerListener(awc); |
| Scanner scanner = new Scanner(); |
| scanner.setScanInterval(scanIntervalSecs); |
| scanner.addListener(changeListener); |
| scanner.setScanDirs(scanList); |
| scanner.setReportExistingFilesOnStartup(false); |
| scanner.start(); |
| } |
| } |
| |
| |
| /** |
| * |
| */ |
| private void configureWebApps() |
| { |
| for (AntWebAppContext awc:webApplications) |
| { |
| awc.setAttribute(AntWebAppContext.BASETEMPDIR, tempDirectory); |
| if (contexts != null) |
| contexts.addHandler(awc); |
| } |
| } |
| |
| } |