/**
Copyright (c) 2014 Delcyon, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.delcyon.capo.server.jetty;
import java.security.KeyStore;
import java.util.logging.Level;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.NCSARequestLog;
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.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.webapp.WebAppContext;
import com.delcyon.capo.CapoApplication;
import com.delcyon.capo.Configuration.PREFERENCE;
import com.delcyon.capo.server.CapoServer;
import com.delcyon.capo.webapp.servlets.CapoWebWTServlet;
import com.delcyon.capo.webapp.servlets.resource.WebResourcesServlet;
import eu.webtoolkit.jwt.ServletInit;
/**
* @author jeremiah
*
*/
public class CapoJettyServer implements Runnable
{
private KeyStore keyStore = null;
private String keyStorePassowrd = null;
private Server server = null;
private int port;
public CapoJettyServer(KeyStore keyStore, String keyStorePassowrd, int port)
{
this.keyStore = keyStore;
this.keyStorePassowrd = keyStorePassowrd;
this.port = port;
}
@Override
public void run()
{
//mostly copied from http://www.eclipse.org/jetty/documentation/current/embedding-jetty.html
// === jetty.xml ===
// Setup Threadpool
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMaxThreads(500);
// Server
this.server = new Server();
// Extra options
//server.setDumpAfterStart(true);
//server.setDumpBeforeStop(true);
server.setStopAtShutdown(true);
//Handler Structure
HandlerCollection handlers = new HandlerCollection();
NCSARequestLog requestLog = new NCSARequestLog();
requestLog.setFilename("request.log");
requestLog.setFilenameDateFormat("yyyy_MM_dd");
requestLog.setRetainDays(90);
requestLog.setAppend(true);
requestLog.setExtended(true);
requestLog.setLogCookies(false);
requestLog.setLogTimeZone("GMT");
RequestLogHandler requestLogHandler = new RequestLogHandler();
requestLogHandler.setRequestLog(requestLog);
handlers.addHandler(requestLogHandler);
// === jetty-https.xml ===
// SSL Context Factory
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStore(keyStore);
sslContextFactory.setKeyStorePassword(keyStorePassowrd);
sslContextFactory.setKeyManagerPassword(keyStorePassowrd);
sslContextFactory.setTrustStore(keyStore);
sslContextFactory.setTrustStorePassword(keyStorePassowrd);
// sslContextFactory.setExcludeCipherSuites(
// "SSL_RSA_WITH_DES_CBC_SHA",
// "SSL_DHE_RSA_WITH_DES_CBC_SHA",
// "SSL_DHE_DSS_WITH_DES_CBC_SHA",
// "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
// "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
// "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
// "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
// SSL HTTP Configuration
HttpConfiguration https_config = new HttpConfiguration();
https_config.setSecureScheme("https");
https_config.setSecurePort(port);
https_config.setOutputBufferSize(32768);
https_config.setRequestHeaderSize(8192);
https_config.setResponseHeaderSize(8192);
https_config.setSendServerVersion(true);
https_config.setSendDateHeader(false);
https_config.addCustomizer(new SecureRequestCustomizer());
// SSL Connector
ServerConnector sslConnector = new ServerConnector(server, new SslConnectionFactory(sslContextFactory,"http/1.1"),new HttpConnectionFactory(https_config));
sslConnector.setPort(port);
server.setConnectors(new Connector[]{sslConnector});
// The WebAppContext is the entity that controls the environment in which a web application lives and
// breathes. In this example the context path is being set to "/" so it is suitable for serving root context
// requests and then we see it setting the location of the war. A whole host of other configurations are
// available, ranging from configuring to support annotation scanning in the webapp (through
// PlusConfiguration) to choosing where the webapp will unpack itself.
WebAppContext webapp = new WebAppContext();//"capo/server/webapp","/");
webapp.setContextPath("/");
webapp.addServlet(WebResourcesServlet.class, "/wr/*");
webapp.addServlet(DefaultServlet.class, "/public/*");
webapp.addServlet(CapoWebWTServlet.class, "/*");
webapp.setResourceBase(CapoApplication.getDataManager().getResourceDirectory(PREFERENCE.WEB_DIR.toString()).getResourceURI().getResourceURIString());
webapp.getSessionHandler().getSessionManager().setMaxInactiveInterval(CapoApplication.getConfiguration().getIntValue(CapoServer.Preferences.WEB_SESSION_TIMEOUT));
webapp.addEventListener(new ServletInit());
// A WebAppContext is a ContextHandler as well so it needs to be set to the server so it is aware of where to
// send the appropriate requests.
handlers.addHandler(webapp);
try
{
server.setHandler(handlers);
// Start the server
server.start();
server.join();
} catch (Exception exception)
{
exception.printStackTrace();
}
}
public void start() throws Exception
{
Thread jettyServerThread = new Thread(this, "JettyServerThread");
jettyServerThread.start();
CapoApplication.logger.log(Level.INFO, "Waiting for jetty to start");
while (server == null || server.isRunning() == false)
{
Thread.sleep(1000);
}
CapoApplication.logger.log(Level.INFO, "Jetty Started on port "+port);
}
public void shutdown() throws Exception
{
server.stop();
}
}