| /* |
| * 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." ); |
| } |
| } |
| } |
| } |