blob: 14a2338286d4998ff477353cb9c572b28b743dc2 [file] [log] [blame]
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.deploy.test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.http.HttpSchemes;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration;
import org.junit.Assert;
/**
* Allows for setting up a Jetty server for testing based on XML configuration files.
*/
public class XmlConfiguredJetty
{
private List<URL> xmlConfigurations;
private Properties properties = new Properties();
private Server server;
private int serverPort;
private String scheme = HttpSchemes.HTTP;
private File jettyHome;
public XmlConfiguredJetty() throws IOException
{
String testname = new Throwable().getStackTrace()[1].getClassName();
xmlConfigurations = new ArrayList<URL>();
properties = new Properties();
jettyHome = MavenTestingUtils.getTargetTestingDir(testname);
deleteContents(jettyHome); // Ensure that we are working with a pristene directory
// Prepare Jetty.Home (Test) dir
jettyHome.mkdirs();
File logsDir = new File(jettyHome,"logs");
logsDir.mkdirs();
File etcDir = new File(jettyHome,"etc");
etcDir.mkdirs();
IO.copyFile(MavenTestingUtils.getTestResourceFile("etc/realm.properties"),new File(etcDir,"realm.properties"));
IO.copyFile(MavenTestingUtils.getTestResourceFile("etc/webdefault.xml"),new File(etcDir,"webdefault.xml"));
File contextsDir = new File(jettyHome,"contexts");
if (contextsDir.exists())
{
deleteContents(contextsDir);
}
contextsDir.mkdirs();
File webappsDir = new File(jettyHome,"webapps");
if (webappsDir.exists())
{
deleteContents(webappsDir);
}
webappsDir.mkdirs();
File tmpDir = new File(jettyHome,"tmp");
tmpDir.mkdirs();
// Setup properties
System.setProperty("java.io.tmpdir",tmpDir.getAbsolutePath());
properties.setProperty("jetty.home",jettyHome.getAbsolutePath());
System.setProperty("jetty.home",jettyHome.getAbsolutePath());
properties.setProperty("test.basedir",MavenTestingUtils.getBasedir().getAbsolutePath());
properties.setProperty("test.resourcesdir",MavenTestingUtils.getTestResourcesDir().getAbsolutePath());
properties.setProperty("test.webapps",webappsDir.getAbsolutePath());
properties.setProperty("test.targetdir",MavenTestingUtils.getTargetDir().getAbsolutePath());
// Write out configuration for use by ConfigurationManager.
File testConfig = MavenTestingUtils.getTargetFile("xml-configured-jetty.properties");
FileOutputStream out = new FileOutputStream(testConfig);
properties.store(out,"Generated by " + XmlConfiguredJetty.class.getName());
}
public void addConfiguration(File xmlConfigFile) throws MalformedURLException
{
xmlConfigurations.add(xmlConfigFile.toURI().toURL());
}
public void addConfiguration(String testConfigName) throws MalformedURLException
{
addConfiguration(MavenTestingUtils.getTestResourceFile(testConfigName));
}
public void addConfiguration(URL xmlConfig)
{
xmlConfigurations.add(xmlConfig);
}
public void assertNoWebAppContexts()
{
List<WebAppContext> contexts = getWebAppContexts();
if (contexts.size() > 0)
{
for (WebAppContext context : contexts)
{
System.out.println("WebAppContext should not exist:\n" + toString(context));
}
Assert.assertEquals("Contexts.size",0,contexts.size());
}
}
public String getResponse(String path) throws IOException
{
URI destUri = getServerURI().resolve(path);
URL url = destUri.toURL();
URLConnection conn = url.openConnection();
InputStream in = null;
try
{
in = conn.getInputStream();
return IO.toString(in);
}
finally
{
IO.close(in);
}
}
public void assertResponseContains(String path, String needle) throws IOException
{
System.out.println("Issuing request to " + path);
String content = getResponse(path);
Assert.assertTrue("Content should contain <" + needle + ">, instead got <" + content + ">",content.contains(needle));
}
public void assertWebAppContextsExists(String... expectedContextPaths)
{
List<WebAppContext> contexts = getWebAppContexts();
if (expectedContextPaths.length != contexts.size())
{
System.out.println("## Expected Contexts");
for (String expected : expectedContextPaths)
{
System.out.println(expected);
}
System.out.println("## Actual Contexts");
for (WebAppContext context : contexts)
{
System.out.printf("%s ## %s%n",context.getContextPath(),context);
}
Assert.assertEquals("Contexts.size",expectedContextPaths.length,contexts.size());
}
for (String expectedPath : expectedContextPaths)
{
boolean found = false;
for (WebAppContext context : contexts)
{
if (context.getContextPath().equals(expectedPath))
{
found = true;
break;
}
}
Assert.assertTrue("Did not find Expected Context Path " + expectedPath,found);
}
}
public void copyContext(String srcName, String destName) throws IOException
{
System.out.printf("Copying Context: %s -> %s%n",srcName,destName);
File srcDir = MavenTestingUtils.getTestResourceDir("contexts");
File destDir = new File(jettyHome,"contexts");
File srcFile = new File(srcDir,srcName);
File destFile = new File(destDir,destName);
copyFile("Context",srcFile,destFile);
}
private void copyFile(String type, File srcFile, File destFile) throws IOException
{
PathAssert.assertFileExists(type + " File",srcFile);
IO.copyFile(srcFile,destFile);
PathAssert.assertFileExists(type + " File",destFile);
System.out.printf("Copy %s: %s%n To %s: %s%n",type,srcFile,type,destFile);
System.out.printf("Destination Exists: %s - %s%n",destFile.exists(),destFile);
}
public void copyWebapp(String srcName, String destName) throws IOException
{
System.out.printf("Copying Webapp: %s -> %s%n",srcName,destName);
File srcDir = MavenTestingUtils.getTestResourceDir("webapps");
File destDir = new File(jettyHome,"webapps");
File srcFile = new File(srcDir,srcName);
File destFile = new File(destDir,destName);
copyFile("Webapp",srcFile,destFile);
}
private void deleteContents(File dir)
{
System.out.printf("Delete (dir) %s/%n",dir);
for (File file : dir.listFiles())
{
// Safety measure. only recursively delete within target directory.
if (file.isDirectory() && file.getAbsolutePath().contains("target" + File.separator))
{
deleteContents(file);
Assert.assertTrue("Delete failed: " + file.getAbsolutePath(),file.delete());
}
else
{
System.out.printf("Delete (file) %s%n",file);
Assert.assertTrue("Delete failed: " + file.getAbsolutePath(),file.delete());
}
}
}
public DeploymentManager getActiveDeploymentManager()
{
List<DeploymentManager> depmans = server.getBeans(DeploymentManager.class);
Assert.assertEquals("DeploymentManager bean count",1,depmans.size());
return depmans.get(0);
}
public File getJettyDir(String name)
{
return new File(jettyHome,name);
}
public File getJettyHome()
{
return jettyHome;
}
public String getScheme()
{
return scheme;
}
public Server getServer()
{
return server;
}
public int getServerPort()
{
return serverPort;
}
public URI getServerURI() throws UnknownHostException
{
StringBuffer uri = new StringBuffer();
uri.append(this.scheme).append("://");
uri.append(InetAddress.getLocalHost().getHostAddress());
uri.append(":").append(this.serverPort);
return URI.create(uri.toString());
}
public List<WebAppContext> getWebAppContexts()
{
List<WebAppContext> contexts = new ArrayList<WebAppContext>();
HandlerCollection handlers = (HandlerCollection)server.getHandler();
System.out.println(server.dump());
Handler children[] = handlers.getChildHandlers();
for (Handler handler : children)
{
if (handler instanceof WebAppContext)
{
WebAppContext context = (WebAppContext)handler;
contexts.add(context);
}
}
return contexts;
}
@SuppressWarnings("unchecked")
public void load() throws Exception
{
XmlConfiguration last = null;
Object[] obj = new Object[this.xmlConfigurations.size()];
// Configure everything
for (int i = 0; i < this.xmlConfigurations.size(); i++)
{
URL configURL = this.xmlConfigurations.get(i);
XmlConfiguration configuration = new XmlConfiguration(configURL);
if (last != null)
{
configuration.getIdMap().putAll(last.getIdMap());
}
configuration.setProperties(properties);
obj[i] = configuration.configure();
last = configuration;
}
// Test for Server Instance.
Server foundServer = null;
int serverCount = 0;
for (int i = 0; i < this.xmlConfigurations.size(); i++)
{
if (obj[i] instanceof Server)
{
if (obj[i].equals(foundServer))
{
// Identical server instance found
break;
}
foundServer = (Server)obj[i];
serverCount++;
}
}
if (serverCount <= 0)
{
throw new Exception("Load failed to configure a " + Server.class.getName());
}
Assert.assertEquals("Server load count",1,serverCount);
this.server = foundServer;
this.server.setGracefulShutdown(10);
}
public void printHandlers(PrintStream out)
{
Handler handler = server.getHandler();
out.println(toString(handler));
}
public void removeContext(String name)
{
File destDir = new File(jettyHome,"contexts");
File contextFile = new File(destDir,name);
if (contextFile.exists())
{
Assert.assertTrue("Delete of Context file: " + contextFile.getAbsolutePath(),contextFile.delete());
}
}
public void setProperty(String key, String value)
{
properties.setProperty(key,value);
}
public void setScheme(String scheme)
{
this.scheme = scheme;
}
public void start() throws Exception
{
Assert.assertNotNull("Server should not be null (failed load?)",server);
server.start();
// Find the active server port.
this.serverPort = (-1);
Connector connectors[] = server.getConnectors();
for (int i = 0; i < connectors.length; i++)
{
Connector connector = connectors[i];
if (connector.getLocalPort() > 0)
{
this.serverPort = connector.getLocalPort();
break;
}
}
Assert.assertTrue("Server Port is between 1 and 65535. Actually <" + serverPort + ">",(1 <= this.serverPort) && (this.serverPort <= 65535));
// Uncomment to have server start and continue to run (without exiting)
// System.out.printf("Listening to port %d%n",this.serverPort);
// server.join();
}
public void stop() throws Exception
{
server.stop();
}
public String toString(Handler handler)
{
if (handler instanceof HandlerCollection)
{
return ((HandlerCollection)handler).dump();
}
if (handler instanceof AbstractHandler)
{
return ((AbstractHandler)handler).dump();
}
return handler.toString();
}
public void waitForDirectoryScan()
{
int ms = 2000;
System.out.printf("Waiting %d milliseconds for AppProvider to process directory scan ...%n",ms);
try
{
Thread.sleep(ms);
}
catch (InterruptedException ignore)
{
/* ignore */
}
}
}