package org.openecomp.mso.bpmn.core; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.HashMap; import java.util.Map; import java.util.Properties; import org.openecomp.mso.logger.MsoLogger; import org.openecomp.mso.bpmn.core.PropertyConfiguration; /** * Sets up mso.bpmn.properties and mso.bpmn.urn.properties for unit tests. */ public class PropertyConfigurationSetup { private static Path msoConfigPath = null; private static Path bpmnPropertiesPath = null; private static Path bpmnUrnPropertiesPath = null; private static boolean modifiedConfiguration = false; private static final MsoLogger LOGGER = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL); /** * Ensures that the the PropertyConfiguration is initialized and that the * property data is reset to initial values. Any extra properties that are * specified will be merged with the initial values. The following example * shows how a test can specify a replacement URN mapping property. *
	 *     Map urnProperties =
	 *         PropertyConfigurationSetup.createBpmnUrnProperties();
	 *     urnProperties.add("mso.po.timeout", "PT1M");
	 *     PropertyConfiguration.init(urnProperties);
	 * 
* @param args one or more maps created with createBpmnProperties() * and/or createBpmnUrnProperties() */ public static synchronized void init(Object ... args) throws IOException { Map extraBpmnProperties = null; Map extraBpmnUrnProperties = null; boolean propertiesSpecified = false; for (Object arg : args) { @SuppressWarnings("unchecked") Map properties = (Map) arg; String type = properties.get("PROPERTIES-TYPE"); if (PropertyConfiguration.MSO_BPMN_PROPERTIES.equals(type)) { if (properties.size() > 1) { extraBpmnProperties = properties; propertiesSpecified = false; } } else if (PropertyConfiguration.MSO_BPMN_URN_PROPERTIES.equals(type)) { if (properties.size() > 1) { extraBpmnUrnProperties = properties; propertiesSpecified = false; } } else { throw new IllegalArgumentException("Not a supported PROPERTIES-TYPE map"); } } // There are three cases in which we need to change the existing configuration: // 1) There is no existing configuration, i.e. first time setup // 2) The existing configuration was modified, i.e. it has non-default values // 3) Non-default values are specified for this initialization if (msoConfigPath == null || modifiedConfiguration || propertiesSpecified) { modifiedConfiguration = propertiesSpecified; Path bpmnPropertiesSourcePath = Paths.get("src", "test", "resources", "mso.bpmn.properties"); Path bpmnUrnPropertiesSourcePath = Paths.get("src", "test", "resources", "mso.bpmn.urn.properties"); if (msoConfigPath == null) { // Initialize from scratch. msoConfigPath = Files.createTempDirectory("mso-config-path-"); System.setProperty("mso.config.path", msoConfigPath.toString()); msoConfigPath.toFile().deleteOnExit(); bpmnPropertiesPath = msoConfigPath.resolve("mso.bpmn.properties"); mergeCopy(bpmnPropertiesSourcePath, extraBpmnProperties, bpmnPropertiesPath); bpmnPropertiesPath.toFile().deleteOnExit(); bpmnUrnPropertiesPath = msoConfigPath.resolve("mso.bpmn.urn.properties"); mergeCopy(bpmnUrnPropertiesSourcePath, extraBpmnUrnProperties, bpmnUrnPropertiesPath); bpmnUrnPropertiesPath.toFile().deleteOnExit(); PropertyConfiguration.getInstance(); } else { // Just reset the data. PropertyConfiguration.getInstance().clearCache(); mergeCopy(bpmnPropertiesSourcePath, extraBpmnProperties, bpmnPropertiesPath); mergeCopy(bpmnUrnPropertiesSourcePath, extraBpmnUrnProperties, bpmnUrnPropertiesPath); } } } /** * Resets the PropertyConfiguration to its initial state, as if it had never * been started. Note that this is a very expensive option and should not * be needed by most unit tests. * @throws IOException */ public static synchronized void nuke() throws IOException { if (msoConfigPath == null) { return; } PropertyConfiguration.getInstance().shutDown(); bpmnUrnPropertiesPath.toFile().delete(); bpmnUrnPropertiesPath = null; bpmnPropertiesPath.toFile().delete(); bpmnPropertiesPath = null; msoConfigPath.toFile().delete(); msoConfigPath = null; System.setProperty("mso.config.path", null); modifiedConfiguration = false; } /** * Create a map to hold properties to be added to mso.bpmn.properties. */ public static Map createBpmnProperties() { Map properties = new HashMap(); properties.put("PROPERTIES-TYPE", PropertyConfiguration.MSO_BPMN_PROPERTIES); return properties; } /** * Create a map to hold properties to be added to mso.bpmn.urn.properties. */ public static Map createBpmnUrnProperties() { Map properties = new HashMap(); properties.put("PROPERTIES-TYPE", PropertyConfiguration.MSO_BPMN_URN_PROPERTIES); return properties; } /** * Adds (or replaces) the specified values in the mso.bpmn.urn.properties file. * Note that properties added this way may take some time to be loaded by the * PropertyConfiguration, just like they do when a property file is updated on * a real MSO system. This method will optionally wait for the new properties * to be loaded. Timeout results in an IOException. * @param values new properties * @param wait maximum amount of time to wait for new properties to be loaded, * in milliseconds. A value of zero means, "Do not wait." * @throws IOException */ public static synchronized void addProperties(Map properties, long wait) throws IOException, InterruptedException { if (msoConfigPath == null) { throw new IllegalStateException(); } String type = properties.get("PROPERTIES-TYPE"); Path path; if (PropertyConfiguration.MSO_BPMN_PROPERTIES.equals(type)) { path = bpmnPropertiesPath; } else if (PropertyConfiguration.MSO_BPMN_URN_PROPERTIES.equals(type)) { path = bpmnUrnPropertiesPath; } else { throw new IllegalArgumentException("Not a supported PROPERTIES-TYPE map"); } String oldTimestamp = PropertyConfiguration.getInstance().getProperties(type) .get(PropertyConfiguration.TIMESTAMP_PROPERTY); modifiedConfiguration = true; addProperties(properties, path); if (wait <= 0) { return; } long endTime = System.currentTimeMillis() + wait; while (true) { Thread.sleep(250); String newTimestamp = PropertyConfiguration.getInstance().getProperties(type) .get(PropertyConfiguration.TIMESTAMP_PROPERTY); if (newTimestamp != oldTimestamp) { return; } long now = System.currentTimeMillis(); if (now >= endTime) { throw new IOException("Timed out after " + wait + "ms waiting for PropertyConfiguration change"); } } } /** * Helper method that adds properties to the specified file. */ private static void addProperties(Map values, Path path) throws IOException { FileReader fileReader = null; FileOutputStream outputStream = null; try { fileReader = new FileReader(path.toFile()); Properties properties = new Properties(); properties.load(fileReader); for (String key : values.keySet()) { if (!key.equals("PROPERTIES-TYPE")) { properties.setProperty(key, values.get(key)); } } outputStream = new FileOutputStream(path.toFile()); properties.store(outputStream, "Custom Test Properties"); } finally { if (fileReader != null) { try { fileReader.close(); } catch (IOException e) { LOGGER.debug("Exception :",e); } } if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { LOGGER.debug("Exception :",e); } } } } /** * Helper method that copies properties from the specified source file, and * optionally merges them with the specified extra values, then writes the * whole mess to the destination file. */ private static void mergeCopy(Path sourcePath, Map extraValues, Path destPath) throws IOException { if (extraValues == null || extraValues.isEmpty()) { Files.copy(sourcePath, destPath, StandardCopyOption.REPLACE_EXISTING); return; } FileReader fileReader = null; FileOutputStream outputStream = null; try { fileReader = new FileReader(sourcePath.toFile()); Properties properties = new Properties(); properties.load(fileReader); for (String key : extraValues.keySet()) { if (!key.equals("PROPERTIES-TYPE")) { properties.setProperty(key, extraValues.get(key)); } } outputStream = new FileOutputStream(destPath.toFile()); properties.store(outputStream, "Custom Test Properties"); } finally { if (fileReader != null) { try { fileReader.close(); } catch (IOException e) { LOGGER.debug("Exception :",e); } } if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { LOGGER.debug("Exception :",e); } } } } }