blob: 0e03150c5eff45a497958706352702e84d1bb177 [file] [log] [blame]
//
// ========================================================================
// 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);
}
}
}