Java tutorial
/******************************************************************************* * Educational Online Test Delivery System * Copyright (c) 2014 American Institutes for Research * * Distributed under the AIR Open Source License, Version 1.0 * See accompanying file AIR-License-1_0.txt or at * http://www.smarterapp.org/documents/American_Institutes_for_Research_Open_Source_Software_License.pdf ******************************************************************************/ package org.opentestsystem.shared.test.standalone; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.InvalidPropertiesFormatException; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.GnuParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.opentestsystem.shared.test.api.InteractionContext; import org.opentestsystem.shared.test.api.cooperation.Chorus; import org.opentestsystem.shared.test.api.user.FirstPersonInteractiveUser; import org.opentestsystem.shared.test.listener.LifecycleResourceCombiner; import org.opentestsystem.shared.test.statistics.InteractionTimingRecord; import org.opentestsystem.shared.test.statistics.TimingRecordSummarizer; import org.opentestsystem.shared.test.statistics.TimingRecordSummarizerImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import org.slf4j.bridge.SLF4JBridgeHandler; import org.springframework.context.ApplicationContext; import org.springframework.context.support.GenericXmlApplicationContext; import org.springframework.core.env.PropertiesPropertySource; import org.springframework.util.StringUtils; public class LoadTestPackageRunner { public static final String OPTION_NAME_HELP = "help"; public static final String OPTION_NAME_CONTEXT_CONFIG = "context-config"; public static final String OPTION_DEFAULT_CONTEXT_CONFIG = "classpath://load-test-context.xml"; public static final String OPTION_NAME_CONTEXT_PROPERTIES = "context-properties"; public static final String OPTION_DEFAULT_CONTEXT_PROPERTIES = ""; public static final String OPTION_NAME_SPRING_PROFILES = "spring-profiles"; public static final String OPTION_DEFAULT_SPRING_PROFILES = ""; private static final Logger _logger = LoggerFactory.getLogger(LoadTestPackageRunner.class); private ApplicationContext _applicationContext = null; private LifecycleResourceCombiner _lifecycleResources = null; private Map<String, FirstPersonInteractiveUser<?, ?>> _users = null; public void setApplicationContext(ApplicationContext applicationContext) { _applicationContext = applicationContext; } public ApplicationContext getApplicationContext() { return _applicationContext; } public static void main(String[] args) { new LoadTestPackageRunner().main_(args); } private void main_(String[] args) { // Bridge the JUL logging into SLF4J SLF4JBridgeHandler.removeHandlersForRootLogger(); // (since SLF4J 1.6.5) SLF4JBridgeHandler.install(); MDC.put("interestingThreadId", "main"); // Parse arguments Options options = new Options(); options.addOption("h", OPTION_NAME_HELP, false, "Print this message"); options.addOption("p", OPTION_NAME_CONTEXT_CONFIG, true, "URL of Spring context-configuration file that defines the test to run"); options.addOption("c", OPTION_NAME_CONTEXT_PROPERTIES, true, "URL of a file defining properties for the test"); options.addOption("d", OPTION_NAME_SPRING_PROFILES, true, "Names of active Spring profiles, separated by spaces"); CommandLineParser cliParser = new GnuParser(); CommandLine cli = null; try { cli = cliParser.parse(options, args); } catch (ParseException e) { _logger.error("Unable to parse command line parameters", e); System.exit(1); } if (cli.hasOption(OPTION_NAME_HELP)) { new HelpFormatter().printHelp("java -jar shared-test.jar", options); System.exit(0); } String contextConfigUrl = cli.getOptionValue(OPTION_NAME_CONTEXT_CONFIG, OPTION_DEFAULT_CONTEXT_CONFIG); String contextPropertiesUrl = cli.getOptionValue(OPTION_NAME_CONTEXT_PROPERTIES, OPTION_DEFAULT_CONTEXT_PROPERTIES); String springProfilesString = cli.getOptionValue(OPTION_NAME_SPRING_PROFILES, OPTION_DEFAULT_SPRING_PROFILES); // Configure the Spring context GenericXmlApplicationContext context = new GenericXmlApplicationContext(); if (!StringUtils.isEmpty(springProfilesString)) { String[] springProfiles = springProfilesString.split(" "); context.getEnvironment().setActiveProfiles(springProfiles); } if (!StringUtils.isEmpty(contextPropertiesUrl)) { Properties p = new Properties(); try { p.loadFromXML(new URL(contextPropertiesUrl).openStream()); } catch (InvalidPropertiesFormatException e) { MDC.put("close", "true"); _logger.error("Error parsing properties file {}", contextPropertiesUrl, e); System.exit(1); } catch (MalformedURLException e) { MDC.put("close", "true"); _logger.error("Illegal URL for properties file {}", contextPropertiesUrl, e); System.exit(1); } catch (IOException e) { MDC.put("close", "true"); _logger.error("IO error reading properties file {}", contextPropertiesUrl, e); System.exit(1); } context.getEnvironment().getPropertySources().addFirst(new PropertiesPropertySource("cmdline", p)); } context.load(contextConfigUrl); context.refresh(); setApplicationContext(context); // Get the lifecycle resources _lifecycleResources = new LifecycleResourceCombiner(); _lifecycleResources.setApplicationContext(context); // Start lifecycle resources try { _lifecycleResources.startupBeforeDependencies(); _lifecycleResources.startupAfterDependencies(); } catch (Exception e) { MDC.put("close", "true"); _logger.error("Error starting lifecycle resources", e); System.exit(1); } // Get the first-person users _users = new HashMap<>(); for (@SuppressWarnings("rawtypes") Entry<String, FirstPersonInteractiveUser> entry_i : context.getBeansOfType(FirstPersonInteractiveUser.class) .entrySet()) { _users.put(entry_i.getKey(), entry_i.getValue()); } // Start first-person scripts for (FirstPersonInteractiveUser<?, ?> user_i : _users.values()) { user_i.startScript(); } // Wait for conclusion for (FirstPersonInteractiveUser<?, ?> user_i : _users.values()) { try { user_i.join(); } catch (InterruptedException e) { _logger.error("Interrupted running test"); } } // Expand any "chorus" users to get the actual users int i = 0; List<FirstPersonInteractiveUser<?, ?>> allUsers = new ArrayList<>(_users.values()); while (i < allUsers.size()) { FirstPersonInteractiveUser<?, ?> user_i = allUsers.get(i); if (user_i instanceof Chorus) { allUsers.remove(i); for (FirstPersonInteractiveUser<?, ?> user_j : ((Chorus<?, ?>) user_i)) { allUsers.add(user_j); } } else { i++; } } // Log summary interaction statistics TimingRecordSummarizer summarizer = new TimingRecordSummarizerImpl(); for (FirstPersonInteractiveUser<?, ?> user_i : allUsers) { for (InteractionContext<?> context_j : user_i.getInteractionContexts()) { for (InteractionTimingRecord record_k : context_j.getTimingRecordHistory()) { summarizer.addObservation(record_k); } } } _logger.info("Latency summary:\r\n\r\n" + summarizer.getSummaryAsString()); // Shut down lifecycle resources try { _lifecycleResources.shutdownBeforeDependencies(); _lifecycleResources.shutdownAfterDependencies(); } catch (Exception e) { MDC.put("close", "true"); _logger.error("Error stopping lifecycle resources", e); System.exit(1); } MDC.put("close", "true"); System.exit(0); } }