org.terracotta.management.embedded.StandaloneServer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ehcache Show documentation
Show all versions of ehcache Show documentation
Ehcache is an open source, standards-based cache used to boost performance,
offload the database and simplify scalability. Ehcache is robust, proven and full-featured and
this has made it the most widely-used Java-based cache.
The newest version!
/* All content copyright (c) 2003-2012 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.*/
package org.terracotta.management.embedded;
import java.util.EnumSet;
import java.util.EventListener;
import java.util.List;
import javax.net.ssl.SSLContext;
import javax.servlet.DispatcherType;
import javax.servlet.ServletContextListener;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.glassfish.jersey.servlet.ServletContainer;
/**
* A standalone server implementation for agents embedded at the Terracotta monitorable entity.
*
* @author Ludovic Orban
* @author brandony
*/
public final class StandaloneServer implements StandaloneServerInterface {
public static final String EMBEDDED_CTXT = "/tc-management-api";
private final List filterDetails;
private final List servletListeners;
private volatile Server server;
private final String applicationClassName;
private final String host;
private final int port;
private final SSLContext sslCtxt;
private final boolean needClientAuth;
/**
* Create a standalone management server.
* @param filterDetails a list of {@link FilterDetail} to add. Can be null;
* @param servletListeners a list of {@link ServletContextListener} to add. Can be null.
* @param applicationClassName the {@link javax.ws.rs.core.Application} implementation to deploy.
* @param host the host or IP address to bind. Mandatory unless port is < 0.
* @param port the port to bind. Can be < 0 to mean do not bind.
* @param sslCtxt the {@link SSLContext} to use. Can be null if no SSL is desired.
* @param needClientAuth true to mandate client SSL auth, false otherwise.
*/
public StandaloneServer(List filterDetails, List servletListeners, String applicationClassName,
String host, int port, SSLContext sslCtxt, boolean needClientAuth) {
super();
this.filterDetails = filterDetails;
this.servletListeners = servletListeners;
this.applicationClassName = applicationClassName;
this.host = host;
this.port = port;
this.sslCtxt = sslCtxt;
this.needClientAuth = needClientAuth;
}
@Override
public void start() throws Exception {
if (port < 0) {
return;
}
if (port == 0) {
throw new IllegalArgumentException("port must be set");
}
if (applicationClassName == null) {
throw new IllegalArgumentException("applicationClassName must be set");
}
if (server != null) {
throw new IllegalStateException("server already started");
}
try {
// Create a basic jetty server object without declaring the port. Since we are configuring connectors
// directly we'll be setting ports on those connectors.
server = new Server();
// HttpConfiguration is a collection of configuration information appropriate for http and https. The default
// scheme for http is http
of course, as the default for secured http is https
but
// we show setting the scheme to show it can be done. The port for secured communication is also set here.
HttpConfiguration httpConfig = new HttpConfiguration();
httpConfig.setSecureScheme("https");
httpConfig.setSecurePort(port);
httpConfig.setBlockingTimeout(0); // make it same as idleTime (defaults to 30s.)
ServerConnector connector;
if (sslCtxt != null) {
// A new HttpConfiguration object is needed for the next connector and you can pass the old one as an
// argument to effectively clone the contents. On this HttpConfiguration object we add a
// SecureRequestCustomizer which is how a new connector is able to resolve the https connection before
// handing control over to the Jetty Server.
HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig);
httpsConfig.addCustomizer(new SecureRequestCustomizer());
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setSslContext(sslCtxt);
sslContextFactory.setNeedClientAuth(needClientAuth);
// HTTPS connector
// We create a second ServerConnector, passing in the http configuration we just made along with the
// previously created ssl context factory. Next we set the port and a longer idle timeout.
connector = new ServerConnector(server,
new SslConnectionFactory(sslContextFactory, "http/1.1"),
new HttpConnectionFactory(httpsConfig));
} else {
// HTTP connector
// The first server connector we create is the one for http, passing in the http configuration we configured
// above so it can get things like the output buffer size, etc. We also set the port (8080) and configure an
// idle timeout.
connector = new ServerConnector(server, new HttpConnectionFactory(httpConfig));
}
connector.setHost(host);
connector.setPort(port);
server.setConnectors(new Connector[]{connector});
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath(EMBEDDED_CTXT);
server.setHandler(context);
ServletHolder servletHolder = new ServletHolder(new ServletContainer());
// make sure com.sun.jersey.core.util.FeaturesAndProperties.FEATURE_XMLROOTELEMENT_PROCESSING is set to true
// so that a list of @XmlRootElement(name = "configuration") is
servletHolder.setInitParameter("com.sun.jersey.config.feature.XmlRootElementProcessing", "true");
servletHolder.setInitParameter("javax.ws.rs.Application", applicationClassName);
// not needed anymore thanks to the jackson-jaxrs-json-provider
// servletHolder.setInitParameter("com.sun.jersey.api.json.POJOMappingFeature", "true");
servletHolder.setInitParameter("com.sun.jersey.spi.container.ContainerRequestFilters",
"com.sun.jersey.api.container.filter.GZIPContentEncodingFilter");
servletHolder.setInitParameter("com.sun.jersey.spi.container.ContainerResponseFilters",
"com.sun.jersey.api.container.filter.GZIPContentEncodingFilter");
context.addServlet(servletHolder, "/*");
if (servletListeners != null) {
context.setEventListeners(servletListeners.toArray(new EventListener[] {}));
}
if (filterDetails != null) {
for (FilterDetail f : filterDetails) {
FilterHolder filterHolder = new FilterHolder(f.getFilter());
EnumSet dTypes = null;
if (f.getDispatcherNames() != null) {
dTypes = EnumSet.noneOf(DispatcherType.class);
for (String dn : f.getDispatcherNames()) {
dTypes.add(DispatcherType.valueOf(dn));
}
}
context.addFilter(filterHolder, f.getPathSpec(), dTypes);
}
}
server.start();
} catch (Exception e) {
server.stop();
server = null;
throw e;
}
}
@Override
public void stop() throws Exception {
if (server == null || port < 0) {
return;
}
try {
server.stop();
server.join();
} finally {
server = null;
}
}
}