Skip to content

Instantly share code, notes, and snippets.

@impl
Created October 26, 2015 23:43
Show Gist options
  • Save impl/6b7f48f6326b4abcab0d to your computer and use it in GitHub Desktop.
Save impl/6b7f48f6326b4abcab0d to your computer and use it in GitHub Desktop.
package com.example.test;
import ch.qos.logback.access.jetty.RequestLogImpl;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.util.StatusPrinter;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.resource.Resource;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.XmlWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import java.io.File;
import java.net.URI;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
public final class TestServer implements Runnable
{
public static final class Arguments
{
@Parameter(names = { "--help", "-h", "-?" }, description = "Display usage information", help = true)
private boolean help;
@Parameter(names = { "--log-configuration", "-l" }, description = "Logback classic configuration file for main logging")
private File logConfiguration;
@Parameter(names = { "--access-log-configuration", "-a" }, description = "Logback access configuration file for access logging")
private File accessLogConfiguration;
@Parameter(names = { "--port", "-p" }, description = "Port for the administrative interface to listen on")
private int port = 8080;
@Parameter(names = { "--bind", "-b" }, description = "Local address for the administrative interface to listen on")
private String bind;
@Parameter(names = { "--config", "-c" }, description = "Additional Spring Framework bean definitions to load")
private List<String> configs = Collections.emptyList();
public boolean isHelp()
{
return help;
}
public File getLogConfiguration ()
{
return logConfiguration;
}
public File getAccessLogConfiguration ()
{
return accessLogConfiguration;
}
public int getPort()
{
return port;
}
public String getBind()
{
return bind;
}
public List<String> getConfigs()
{
return configs;
}
}
private final Arguments arguments;
private final Server server;
public TestServer(Arguments arguments) throws Exception
{
this.arguments = arguments;
setUpLogging(); // Set up logging as early as possible!
server = new Server();
setUpConnector();
HandlerCollection handlers = new HandlerCollection();
handlers.addHandler(createServletContextHandler());
handlers.addHandler(createRequestLogHandler());
server.setHandler(handlers);
}
protected void setUpLogging ()
{
LoggerContext context = (LoggerContext)LoggerFactory.getILoggerFactory();
try {
JoranConfigurator configurator = new JoranConfigurator();
configurator.setContext(context);
context.reset();
if (arguments.getLogConfiguration() != null) {
configurator.doConfigure(arguments.getLogConfiguration());
} else {
// We must not use Jetty's Resource class here, as it will prematurely set up the
// logging framework.
configurator.doConfigure(getClass().getResource("/META-INF/test/conf/logback.xml"));
}
} catch (JoranException je) {}
StatusPrinter.printInCaseOfErrorsOrWarnings(context);
}
protected void setUpConnector()
{
ServerConnector connector = new ServerConnector(server);
if (arguments.getBind() != null) {
connector.setHost(arguments.getBind());
}
connector.setPort(arguments.getPort());
server.addConnector(connector);
}
protected Handler createServletContextHandler()
{
ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
contextHandler.setContextPath("/");
contextHandler.setBaseResource(Resource.newClassPathResource("/META-INF/test"));
XmlWebApplicationContext applicationContext = new XmlWebApplicationContext();
// Build configurations.
int configSize = arguments.getConfigs().size() + 1, i = 0;
String[] configLocations = new String[configSize];
configLocations[i++] = "classpath:/META-INF/test/conf/test-context.xml";
for (String configLocation : arguments.getConfigs()) {
URI path = Paths.get(configLocation).toUri().normalize();
configLocations[i++] = path.toString();
}
applicationContext.setConfigLocations(configLocations);
// Add the context loader listener so additional Spring components will find our application
// context.
contextHandler.addEventListener(new ContextLoaderListener(applicationContext));
// Add the main dispatcher servlet for Spring's Web MVC framework.
ServletHolder dispatcherServletHolder = new ServletHolder("test", new DispatcherServlet(applicationContext));
dispatcherServletHolder.setAsyncSupported(true);
contextHandler.addServlet(dispatcherServletHolder, "/");
return contextHandler;
}
protected Handler createRequestLogHandler ()
{
RequestLogImpl requestLog = new RequestLogImpl();
requestLog.setQuiet(true);
if (arguments.getAccessLogConfiguration() != null) {
requestLog.setFileName(arguments.getAccessLogConfiguration().getAbsolutePath());
} else {
requestLog.setResource("/META-INF/test/conf/logback-access.xml");
}
RequestLogHandler requestLogHandler = new RequestLogHandler();
requestLogHandler.setRequestLog(requestLog);
return requestLogHandler;
}
@Override
public void run()
{
try {
server.start();
} catch (Exception e) {
e.printStackTrace();
}
try {
server.join();
} catch (InterruptedException ie) {
try {
server.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws Exception
{
Arguments arguments = new Arguments();
JCommander jc = new JCommander(arguments);
jc.parse(args);
if (arguments.isHelp()) {
jc.usage();
System.exit(1);
} else {
new TestServer(arguments).run();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment