package mil.nga.giat.geowave.test.service; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.concurrent.TimeUnit; import org.apache.commons.io.FileUtils; import org.mortbay.jetty.Connector; import org.mortbay.jetty.Server; import org.mortbay.jetty.bio.SocketConnector; import org.mortbay.jetty.webapp.WebAppClassLoader; import org.mortbay.jetty.webapp.WebAppContext; import org.mortbay.xml.XmlConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import mil.nga.giat.geowave.test.GeoWaveITRunner; import mil.nga.giat.geowave.test.TestEnvironment; import mil.nga.giat.geowave.test.TestUtils; import mil.nga.giat.geowave.test.mapreduce.MapReduceTestEnvironment; public class ServicesTestEnvironment implements TestEnvironment { private static final Logger LOGGER = LoggerFactory.getLogger(ServicesTestEnvironment.class); private static ServicesTestEnvironment singletonInstance = null; public static synchronized ServicesTestEnvironment getInstance() { if (singletonInstance == null) { singletonInstance = new ServicesTestEnvironment(); } return singletonInstance; } private static String[] PARENT_CLASSLOADER_LIBRARIES = new String[] { "hbase", "hadoop", "protobuf" }; protected static final int JETTY_PORT = 9011; protected static final String JETTY_BASE_URL = "http://localhost:" + JETTY_PORT; protected static final int ACCEPT_QUEUE_SIZE = 100; protected static final int MAX_IDLE_TIME = (int) TimeUnit.HOURS.toMillis(1); protected static final int SO_LINGER_TIME = -1; protected static final int MAX_FORM_CONTENT_SIZE = 1024 * 1024 * 2; protected static final String GEOSERVER_USER = "admin"; protected static final String GEOSERVER_PASS = "geoserver"; protected static final String TEST_WORKSPACE = "geowave_test"; protected static final String GEOSERVER_WAR_DIR = "target/geoserver"; protected static final String GEOSERVER_CONTEXT_PATH = "/geoserver"; protected static final String GEOSERVER_BASE_URL = JETTY_BASE_URL + GEOSERVER_CONTEXT_PATH; protected static final String GEOSERVER_REST_PATH = GEOSERVER_BASE_URL + "/rest"; protected static final String GEOWAVE_WAR_DIR = "target/geowave-services"; protected static final String GEOWAVE_CONTEXT_PATH = "/geowave-services"; protected static final String GEOWAVE_BASE_URL = JETTY_BASE_URL + GEOWAVE_CONTEXT_PATH; protected static final String GEOWAVE_WORKSPACE_PATH = GEOSERVER_WAR_DIR + "/data/workspaces/" + TEST_WORKSPACE; protected static final String TEST_STYLE_NAME_NO_DIFFERENCE = "SubsamplePoints-2px"; protected static final String TEST_STYLE_NAME_MINOR_SUBSAMPLE = "SubsamplePoints-10px"; protected static final String TEST_STYLE_NAME_MAJOR_SUBSAMPLE = "SubsamplePoints-100px"; protected static final String TEST_STYLE_NAME_DISTRIBUTED_RENDER = "DistributedRender"; protected static final String TEST_STYLE_PATH = "src/test/resources/sld/"; protected static final String TEST_GEOSERVER_LOGGING_PATH = "src/test/resources/logging.xml"; protected static final String TEST_LOG_PROPERTIES_PATH = "src/test/resources/log4j-test.properties"; protected static final String TEST_GEOSERVER_LOG_PROPERTIES_PATH = GEOSERVER_WAR_DIR + "/data/logs/log4j-test.properties"; protected static final String EXISTING_GEOSERVER_LOGGING_PATH = GEOSERVER_WAR_DIR + "/data/logging.xml"; protected static final String TEST_SLD_NO_DIFFERENCE_FILE = TEST_STYLE_PATH + TEST_STYLE_NAME_NO_DIFFERENCE + ".sld"; protected static final String TEST_SLD_MINOR_SUBSAMPLE_FILE = TEST_STYLE_PATH + TEST_STYLE_NAME_MINOR_SUBSAMPLE + ".sld"; protected static final String TEST_SLD_MAJOR_SUBSAMPLE_FILE = TEST_STYLE_PATH + TEST_STYLE_NAME_MAJOR_SUBSAMPLE + ".sld"; protected static final String TEST_SLD_DISTRIBUTED_RENDER_FILE = TEST_STYLE_PATH + TEST_STYLE_NAME_DISTRIBUTED_RENDER + ".sld"; private Server jettyServer; @SuppressFBWarnings(value = { "SWL_SLEEP_WITH_LOCK_HELD" }, justification = "Jetty must be started before releasing the lock") @Override public void setup() throws Exception { synchronized (GeoWaveITRunner.MUTEX) { // Setup activities delegated to private function // to satisfy HP Fortify doSetup(); } } private void doSetup() { if (jettyServer == null) { try { // Prevent "Unauthorized class found" error System.setProperty( "GEOSERVER_XSTREAM_WHITELIST", "org.geoserver.wfs.**;org.geoserver.wms.**"); // delete old workspace configuration if it's still there jettyServer = new Server(); final SocketConnector conn = new SocketConnector(); conn.setPort(JETTY_PORT); conn.setAcceptQueueSize(ACCEPT_QUEUE_SIZE); conn.setMaxIdleTime(MAX_IDLE_TIME); conn.setSoLingerTime(SO_LINGER_TIME); jettyServer.setConnectors(new Connector[] { conn }); FileUtils.copyFile( new File( TEST_GEOSERVER_LOGGING_PATH), new File( EXISTING_GEOSERVER_LOGGING_PATH)); FileUtils.copyFile( new File( TEST_LOG_PROPERTIES_PATH), new File( TEST_GEOSERVER_LOG_PROPERTIES_PATH)); final WebAppContext gsWebapp = new WebAppContext(); gsWebapp.setContextPath(GEOSERVER_CONTEXT_PATH); gsWebapp.setWar(GEOSERVER_WAR_DIR); final WebAppClassLoader classLoader = AccessController .doPrivileged(new PrivilegedAction<WebAppClassLoader>() { @Override public WebAppClassLoader run() { try { return new WebAppClassLoader( gsWebapp); } catch (final IOException e) { LOGGER.error( "Unable to create new classloader", e); return null; } } }); if (classLoader == null) { throw new IOException( "Unable to create classloader"); } final String classpath = System.getProperty( "java.class.path").replace( ":", ";"); final String[] individualEntries = classpath.split(";"); final StringBuffer str = new StringBuffer(); for (final String e : individualEntries) { // HBase has certain static initializers that use reflection // to get annotated values // because Class instances are not equal if they are loaded // by different class loaders this HBase initialization // fails // furthermore HBase's runtime dependencies need to // be loaded by the same classloader, the webapp's parent // class loader // but geowave hbase datastore implementation must be loaded // by the same classloader as geotools or the SPI loader // won't work boolean addLibraryToWebappContext = true; if (!e.contains("geowave")) { for (final String parentLoaderLibrary : PARENT_CLASSLOADER_LIBRARIES) { if (e.contains(parentLoaderLibrary)) { addLibraryToWebappContext = false; break; } } } if (addLibraryToWebappContext) { str.append( e).append( ";"); } } classLoader.addClassPath(str.toString()); gsWebapp.setClassLoader(classLoader); // this has to be false for geoserver to load the correct guava // classes (until hadoop updates guava support to a later // version, slated for hadoop 3.x) gsWebapp.setParentLoaderPriority(false); final File warDir = new File( GEOWAVE_WAR_DIR); // update the config file ServicesTestUtils.writeConfigFile(new File( warDir, "/WEB-INF/config.properties")); final WebAppContext gwWebapp = new WebAppContext(); gwWebapp.setContextPath(GEOWAVE_CONTEXT_PATH); gwWebapp.setWar(warDir.getAbsolutePath()); jettyServer.setHandlers(new WebAppContext[] { gsWebapp, gwWebapp }); gsWebapp.setTempDirectory(TestUtils.TEMP_DIR); // this allows to send large SLD's from the styles form gsWebapp.getServletContext().getContextHandler().setMaxFormContentSize( MAX_FORM_CONTENT_SIZE); final String jettyConfigFile = System.getProperty("jetty.config.file"); if (jettyConfigFile != null) { LOGGER.info("Loading Jetty config from file: " + jettyConfigFile); (new XmlConfiguration( new FileInputStream( jettyConfigFile))).configure(jettyServer); } jettyServer.start(); while (!jettyServer.isRunning() && !jettyServer.isStarted()) { Thread.sleep(1000); } } catch (final RuntimeException e) { throw e; } catch (final Exception e) { LOGGER.error( "Could not start the Jetty server: " + e.getMessage(), e); if (jettyServer.isRunning()) { try { jettyServer.stop(); } catch (final Exception e1) { LOGGER.error( "Unable to stop the Jetty server", e1); } } } } } @Override public void tearDown() throws Exception { synchronized (GeoWaveITRunner.MUTEX) { if (!GeoWaveITRunner.DEFER_CLEANUP.get()) { if (jettyServer != null) { try { jettyServer.stop(); jettyServer = null; } catch (final Exception e) { LOGGER.error( "Unable to stop the Jetty server", e); } } } } } @Override public TestEnvironment[] getDependentEnvironments() { return new TestEnvironment[] { MapReduceTestEnvironment.getInstance() }; } }