Files
alfresco-community-repo/source/test-java/org/alfresco/repo/web/util/AbstractJettyComponent.java
Alan Davis 3e1e1edbaa Merged 5.2.N (5.2.1) to HEAD (5.2)
125788 rmunteanu: Merged 5.1.N (5.1.2) to 5.2.N (5.2.1)
      125606 rmunteanu: Merged 5.1.1 (5.1.1) to 5.1.N (5.1.2)
         125515 slanglois: MNT-16155 Update source headers - add new Copyrights for Java and JSP source files + automatic check in the build


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@127810 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
2016-06-03 17:08:06 +00:00

265 lines
8.2 KiB
Java

/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.web.util;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.util.BaseApplicationContextHelper;
import org.alfresco.util.TempFileProvider;
import org.alfresco.util.WebApplicationContextLoader;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.WebAppContext;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.GenericWebApplicationContext;
/**
* Manages an embedded jetty server, hooking it up to the repository spring context.
*
* @author steveglover
*
*/
public abstract class AbstractJettyComponent implements JettyComponent
{
protected static final Log logger = LogFactory.getLog(AbstractJettyComponent.class);
public static final int JETTY_STOP_PORT = 8079;
public static final String JETTY_LOCAL_IP = "127.0.0.1";
protected int port = 8081;
protected String contextPath = "/alfresco";
protected String publicApiServletName = "api";
protected String[] configLocations;
protected String[] classLocations;
protected static Server server;
private WebAppContext webAppContext;
public AbstractJettyComponent(int port, String contextPath, String[] configLocations, String[] classLocations)
{
this.configLocations = configLocations;
this.classLocations = classLocations;
this.port = port;
this.contextPath = contextPath;
server = new Server(port);
}
public int getPort()
{
return port;
}
/*
* Creates a web application context wrapping a Spring application context (adapted from core spring code in
* org.springframework.web.context.ContextLoader)
*/
protected WebApplicationContext createWebApplicationContext(ServletContext sc, ApplicationContext parent)
{
GenericWebApplicationContext wac = (GenericWebApplicationContext) BeanUtils.instantiateClass(GenericWebApplicationContext.class);
// Assign the best possible id value.
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + contextPath);
wac.setParent(parent);
wac.setServletContext(sc);
wac.refresh();
return wac;
}
public ConfigurableApplicationContext getApplicationContext()
{
return (ConfigurableApplicationContext)webAppContext.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
}
protected abstract void configureWebAppContext(WebAppContext webAppContext);
public void start()
{
if(logger.isDebugEnabled())
{
logger.debug("["+new Date()+"] startJetty: starting embedded Jetty server ...");
}
try
{
if(logger.isDebugEnabled())
{
logger.debug("["+new Date()+"] startJetty");
}
this.webAppContext = new WebAppContext();
webAppContext.setContextPath(contextPath);
configure(webAppContext);
server.setHandler(webAppContext);
// for clean shutdown, add monitor thread
// from: http://ptrthomas.wordpress.com/2009/01/24/how-to-start-and-stop-jetty-revisited/
// adapted from: http://jetty.codehaus.org/jetty/jetty-6/xref/org/mortbay/start/Monitor.html
Thread monitor = new MonitorThread();
monitor.start();
configureWebAppContext(webAppContext);
server.start();
if(logger.isDebugEnabled())
{
logger.debug("["+new Date()+"] startJetty: ... embedded Jetty server started on port " + port);
}
}
catch (Exception e)
{
logger.error("["+new Date()+"] startJetty: ... failed to start embedded Jetty server on port " + port + ", " + e);
}
}
protected void configure(WebAppContext webAppContext)
{
try
{
ClassLoader classLoader = BaseApplicationContextHelper.buildClassLoader(classLocations);
webAppContext.setClassLoader(classLoader);
}
catch (IOException e)
{
throw new ExceptionInInitializerError(e);
}
webAppContext.addEventListener(new ServletContextListener()
{
public void contextInitialized(ServletContextEvent sce)
{
// create a Spring web application context, wrapping and providing access to
// the application context
try
{
ServletContext servletContext = sce.getServletContext();
// initialise web application context
WebApplicationContextLoader.getApplicationContext(servletContext, configLocations, classLocations);
if(logger.isDebugEnabled())
{
logger.debug("contextInitialized "+sce);
}
}
catch(Throwable t)
{
logger.error("Failed to start Jetty server: " + t);
throw new AlfrescoRuntimeException("Failed to start Jetty server", t);
}
}
public void contextDestroyed(ServletContextEvent sce)
{
if(logger.isDebugEnabled())
{
logger.debug("contextDestroyed "+sce);
}
}
});
// with a login-config in web.xml, jetty seems to require this in order to start successfully
webAppContext.getSecurityHandler().setLoginService(new HashLoginService());
// arbitrary temporary file location
File tmp = new File(TempFileProvider.getSystemTempDir(), String.valueOf(System.currentTimeMillis()));
webAppContext.setResourceBase(tmp.getAbsolutePath());
}
public void shutdown()
{
try
{
server.stop();
}
catch(Exception e)
{
throw new AlfrescoRuntimeException("", e);
}
}
private static class MonitorThread extends Thread
{
private ServerSocket socket;
public MonitorThread()
{
setDaemon(true);
setName("StopMonitor");
try
{
socket = new ServerSocket(JETTY_STOP_PORT, 1, InetAddress.getByName(JETTY_LOCAL_IP));
}
catch(Exception e)
{
throw new RuntimeException(e);
}
}
@Override
public void run()
{
Socket accept;
try
{
accept = socket.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
reader.readLine();
server.stop();
accept.close();
socket.close();
}
catch(Exception e)
{
throw new RuntimeException(e);
}
}
}
}