/** * Copyright (C) 2008 Mathieu Carbou <mathieu.carbou@gmail.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.mycila.testing.plugins.jetty; import static com.jayway.awaitility.Awaitility.await; import static org.hamcrest.CoreMatchers.equalTo; import java.io.File; import java.net.URISyntaxException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.webapp.WebAppContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.mycila.testing.core.api.TestExecution; import com.mycila.testing.plugins.jetty.config.Config; public class ServerWebappActions { public ServerWebappActions() { this.context.set(new HashMap()); } public void createServer( final TestExecution testExecution, final Config config) { this.logger.debug("server creation..."); this.setServer(new Server(config.getServerPort())); this.getServer().addLifeCycleListener(new AbstractLifeCycle.AbstractLifeCycleListener() { @Override public void lifeCycleFailure( final LifeCycle event, final Throwable cause) { testExecution.setThrowable(cause); } @Override public void lifeCycleStarted( final LifeCycle event) { ServerWebappActions.this.ready.set(true); } }); final HandlerCollection handlerCollection = new HandlerCollection(); this.setContextHandlerCollection(new ContextHandlerCollection()); handlerCollection.addHandler(this.getContextHandlerCollection()); this.getServer().setHandler(handlerCollection); this.logger.debug("server created"); } public void startServer( final Config config) throws Exception { final String serverPortStr = (config == null) ? "<null>" : Integer.toString(config.getServerPort()); this.logger.info("server starting on localhost:{}", serverPortStr); if (config != null) { config.getServerLifeCycleListener(this.context.get()).beforeServerStart(this.getServer()); } this.getServer().start(); final Callable<Boolean> isReady = new WaitUntilReadyCallable(this.ready); await().until(isReady, equalTo(true)); if (config != null) { config.getServerLifeCycleListener(this.context.get()).afterServerStart(this.getServer()); } this.logger.info("server started"); } public void stopServer( final Config config) throws Exception { this.logger.info("server stopping"); if (config != null) { config.getServerLifeCycleListener(this.context.get()).beforeServerStop(this.getServer()); } this.getContextHandlerCollection().stop(); this.getServer().stop(); if (config != null) { config.getServerLifeCycleListener(this.context.get()).afterServerStop(this.getServer()); } this.logger.info("server stopped"); this.getServer().destroy(); this.setContextHandlerCollection(null); this.setServer(null); } public boolean hasServer() { return (this.getServer() != null); } public Server getServer() { return this.server.get(); } public void setServer( final Server server) { this.server.set(server); } private ContextHandlerCollection getContextHandlerCollection() { return this.contextHandlerCollection.get(); } private void setContextHandlerCollection( final ContextHandlerCollection contextHandlerCollection) { this.contextHandlerCollection.set(contextHandlerCollection); } public void createWebAppContext( final Config config) throws URISyntaxException { this.logger.debug("webapp creation..."); final File warFile = new File(config.getWarLocationUrl().toURI()); if (!warFile.exists()) { throw new AssertionError("non-existent WAR : " + warFile.getAbsolutePath()); } if (!"/".equals(config.getContextPath()) && (!config.getContextPath().startsWith("/") || config.getContextPath().endsWith("/"))) { throw new AssertionError("contextPath must starts with a slash '/' but doesn't end with one"); } this.setWebAppContext(new WebAppContext()); this.getWebAppContext().setWar(config.getWarLocationUrl().getFile()); this.getWebAppContext().setContextPath(config.getContextPath()); this.getWebAppContext().setCopyWebDir(false); this.getWebAppContext().setExtractWAR(false); this.getWebAppContext().setLogUrlOnStart(true); this.logger.info("webapp created on localhost:{}{} with WAR:{}", new Object[] { Integer.valueOf(config.getServerPort()), config.getContextPath(), config.getWarLocation() }); } public void startWebApp( final Config config) throws Exception { this.logger.info("webapp starting"); if (config != null) { config.getServerLifeCycleListener(this.context.get()).beforeWebappStart(this.getServer(), this.getWebAppContext()); } this.getContextHandlerCollection().addHandler(this.getWebAppContext()); this.getWebAppContext().start(); if (config != null) { config.getServerLifeCycleListener(this.context.get()).afterWebappStart(this.getServer(), this.getWebAppContext()); } this.logger.info("webapp started"); } public void stopWebapp( final Config config) throws Exception { this.logger.info("webapp stopping"); if (config != null) { config.getServerLifeCycleListener(this.context.get()).beforeWebappStop(this.getServer(), this.getWebAppContext()); } this.getWebAppContext().stop(); if (config != null) { config.getServerLifeCycleListener(this.context.get()).afterWebappStop(this.getServer(), this.getWebAppContext()); } this.getContextHandlerCollection().removeHandler(this.getWebAppContext()); this.getWebAppContext().destroy(); this.getWebAppContext().setServer(null); this.logger.info("webapp stopped"); this.setWebAppContext(null); } public boolean hasWebAppContext() { return (this.getWebAppContext() != null); } public WebAppContext getWebAppContext() { return this.webapp.get(); } public void setWebAppContext( final WebAppContext webAppContext) { this.webapp.set(webAppContext); } private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final AtomicBoolean ready = new AtomicBoolean(); private final AtomicReference<Server> server = new AtomicReference<Server>(); private final AtomicReference<ContextHandlerCollection> contextHandlerCollection = new AtomicReference<ContextHandlerCollection>(); private final AtomicReference<WebAppContext> webapp = new AtomicReference<WebAppContext>(); private final AtomicReference<Map> context = new AtomicReference<Map>(); private static class WaitUntilReadyCallable implements Callable<Boolean> { public WaitUntilReadyCallable( final AtomicBoolean ready) { this.ready = ready; } public Boolean call() throws Exception { return this.ready.get(); } private final AtomicBoolean ready; } }