blob: 498068a454e1f78e03841a0b326ab1c15bac0749 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.usergrid.rest;
import java.io.File;
import org.junit.rules.ExternalResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.startup.Tomcat;
import org.apache.commons.lang.math.RandomUtils;
import org.apache.usergrid.cassandra.AvailablePortFinder;
import org.apache.usergrid.setup.ConcurrentProcessSingleton;
import com.google.common.io.Files;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
/**
* Start and stop embedded Tomcat.
*/
public class TomcatRuntime extends ExternalResource {
private static final Logger log = LoggerFactory.getLogger( TomcatRuntime.class );
private static final String WEBAPP_PATH = System.getProperty("webapp.directory");
private static TomcatRuntime instance;
public final TomcatInstance tomcat;
private TomcatRuntime() {
//before we run tomcat, we need to cleanup our data
ConcurrentProcessSingleton.getInstance();
tomcat = new TomcatInstance( WEBAPP_PATH );
tomcat.startTomcat();
//stop on JVM shutdown
Runtime.getRuntime().addShutdownHook( new Thread() {
@Override
public void run() {
tomcat.stopTomcat();
}
} );
}
/**
* Get the instance of the tomcat runtime and starts the tomcat singleton. Starts tomcat once per JVM
* @return
*/
public static synchronized TomcatRuntime getInstance() {
if ( instance == null ) {
instance = new TomcatRuntime();
}
return instance;
}
/**
* Get the port tomcat is running on
*/
public int getPort() {
return tomcat.getPort();
}
/**
* Inner class of tomcat runtime
*/
private static class TomcatInstance {
public static final int THREADS_PERPROC = 25;
private final String webAppsPath;
private Tomcat tomcat = null;
private int port;
private boolean started = false;
private TomcatInstance( final String webAppsPath ) {this.webAppsPath = webAppsPath;}
/**
* Start the tomcat instance
*/
public void startTomcat() {
try {
//we don't want to use all our threads, we'll kill the box
final int availableProcessors = Runtime.getRuntime().availableProcessors();
final int usedProcs = Math.min( 2, availableProcessors );
final int threads = usedProcs * THREADS_PERPROC;
File dataDir = Files.createTempDir();
dataDir.deleteOnExit();
port = AvailablePortFinder.getNextAvailable( 9998 + RandomUtils.nextInt( 10 ) );
tomcat = new Tomcat();
tomcat.setBaseDir( dataDir.getAbsolutePath() );
tomcat.setPort( port );
tomcat.getConnector().setAttribute( "maxThreads", "" + threads );
tomcat.addWebapp( "/", new File( webAppsPath ).getAbsolutePath() );
log.info( "-----------------------------------------------------------------" );
log.info( "Starting Tomcat embedded port {} dir {}", port, dataDir.getAbsolutePath() );
log.info( "-----------------------------------------------------------------" );
tomcat.start();
waitForTomcat();
}
catch ( Exception e ) {
throw new RuntimeException( "Couldn't start tomcat", e );
}
}
/**
* Stop the embedded tomcat process
*/
public void stopTomcat() {
try {
tomcat.stop();
}
catch ( LifecycleException e ) {
throw new RuntimeException( "Unable to stop tomcat", e );
}
}
public int getPort() {
return port;
}
private void waitForTomcat() throws RuntimeException {
String url = "http://localhost:" + port + "/status";
int count = 0;
while ( count++ < 30 ) {
try {
Thread.sleep( 1000 );
Client c = Client.create();
WebResource wr = c.resource( url );
wr.get( String.class );
log.info( "Tomcat is started." );
started = true;
break;
}
catch ( Exception e ) {
log.info( "Waiting for Tomcat on url {}", url );
}
}
if ( !started ) {
throw new RuntimeException( "Tomcat process never started." );
}
}
}
}