Initial OpenECOMP MSO commit
[so.git] / bpmn / MSOCoreBPMN / src / main / java / org / openecomp / mso / bpmn / test / PropertyConfigurationSetup.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * OPENECOMP - MSO
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.mso.bpmn.test;
22
23 import java.io.FileOutputStream;
24 import java.io.FileReader;
25 import java.io.IOException;
26 import java.nio.file.Files;
27 import java.nio.file.Path;
28 import java.nio.file.Paths;
29 import java.nio.file.StandardCopyOption;
30 import java.util.HashMap;
31 import java.util.Map;
32 import java.util.Properties;
33
34 import org.openecomp.mso.bpmn.core.PropertyConfiguration;
35
36 /**
37  * Sets up mso.bpmn.properties and mso.bpmn.urn.properties for unit tests.
38  */
39 public class PropertyConfigurationSetup {
40
41         private static Path msoConfigPath = null;
42         private static Path bpmnPropertiesPath = null;
43         private static Path bpmnUrnPropertiesPath = null;
44         private static boolean modifiedConfiguration = false;
45
46         /**
47          * Ensures that the the PropertyConfiguration is initialized and that the
48          * property data is reset to initial values.  Any extra properties that are
49          * specified will be merged with the initial values.  The following example
50          * shows how a test can specify a replacement URN mapping property.
51          * <pre>
52          *     Map<String, String> urnProperties =
53          *         PropertyConfigurationSetup.createBpmnUrnProperties();
54          *     urnProperties.add("mso.po.timeout", "PT1M");
55          *     PropertyConfiguration.init(urnProperties);
56          * </pre>
57          * @param args one or more maps created with createBpmnProperties()
58          *        and/or createBpmnUrnProperties()
59          */
60         public static synchronized void init(Object ... args) throws IOException {
61
62                 Map<String, String> extraBpmnProperties = null;
63                 Map<String, String> extraBpmnUrnProperties = null;
64                 
65                 boolean propertiesSpecified = false;
66
67                 for (Object arg : args) {
68                         @SuppressWarnings("unchecked")
69                         Map<String, String> properties = (Map<String, String>) arg;
70
71                         String type = properties.get("PROPERTIES-TYPE");
72
73                         if (PropertyConfiguration.MSO_BPMN_PROPERTIES.equals(type)) {
74                                 if (properties.size() > 1) {
75                                         extraBpmnProperties = properties;
76                                         propertiesSpecified = false;
77                                 }
78                         } else if (PropertyConfiguration.MSO_BPMN_URN_PROPERTIES.equals(type)) {
79                                 if (properties.size() > 1) {
80                                         extraBpmnUrnProperties = properties;
81                                         propertiesSpecified = false;
82                                 }
83                         } else {
84                                 throw new IllegalArgumentException("Not a supported PROPERTIES-TYPE map");
85                         }
86                 }
87
88                 // There are three cases in which we need to change the existing configuration:
89                 //     1) There is no existing configuration, i.e. first time setup
90                 //     2) The existing configuration was modified, i.e. it has non-default values
91                 //     3) Non-default values are specified for this initialization
92
93                 if (msoConfigPath == null || modifiedConfiguration || propertiesSpecified) {
94                         modifiedConfiguration = propertiesSpecified;
95
96                         Path bpmnPropertiesSourcePath = Paths.get("src", "test", "resources", "mso.bpmn.properties");
97                         Path bpmnUrnPropertiesSourcePath = Paths.get("src", "test", "resources", "mso.bpmn.urn.properties");
98
99                         if (msoConfigPath == null) {
100                                 // Initialize from scratch.
101                                 msoConfigPath = Files.createTempDirectory("mso-config-path-");
102                                 System.setProperty("mso.config.path", msoConfigPath.toString());
103                                 msoConfigPath.toFile().deleteOnExit();
104
105                                 bpmnPropertiesPath = msoConfigPath.resolve("mso.bpmn.properties");
106                                 mergeCopy(bpmnPropertiesSourcePath, extraBpmnProperties, bpmnPropertiesPath);
107                                 bpmnPropertiesPath.toFile().deleteOnExit();
108
109                                 bpmnUrnPropertiesPath = msoConfigPath.resolve("mso.bpmn.urn.properties");
110                                 mergeCopy(bpmnUrnPropertiesSourcePath, extraBpmnUrnProperties, bpmnUrnPropertiesPath);
111                                 bpmnUrnPropertiesPath.toFile().deleteOnExit();
112
113                                 PropertyConfiguration.getInstance();
114                         } else {
115                                 // Just reset the data.
116                                 PropertyConfiguration.getInstance().clearCache();
117                                 mergeCopy(bpmnPropertiesSourcePath, extraBpmnProperties, bpmnPropertiesPath);
118                                 mergeCopy(bpmnUrnPropertiesSourcePath, extraBpmnUrnProperties, bpmnUrnPropertiesPath);
119                         }
120                 }
121         }
122
123         /**
124          * Resets the PropertyConfiguration to its initial state, as if it had never
125          * been started. Note that this is a very expensive option and should not
126          * be needed by most unit tests.
127          * @throws IOException
128          */
129         public static synchronized void nuke() throws IOException {
130                 if (msoConfigPath == null) {
131                         return;
132                 }
133
134                 PropertyConfiguration.getInstance().shutDown();
135
136                 bpmnUrnPropertiesPath.toFile().delete();
137                 bpmnUrnPropertiesPath = null;
138                 
139                 bpmnPropertiesPath.toFile().delete();
140                 bpmnPropertiesPath = null;
141
142                 msoConfigPath.toFile().delete();
143                 msoConfigPath = null;
144                 
145                 System.setProperty("mso.config.path", null);
146
147                 modifiedConfiguration = false;
148         }
149         
150         /**
151          * Create a map to hold properties to be added to mso.bpmn.properties.
152          */
153         public static Map<String, String> createBpmnProperties() {
154                 Map<String, String> properties = new HashMap<String, String>();
155                 properties.put("PROPERTIES-TYPE", PropertyConfiguration.MSO_BPMN_PROPERTIES);
156                 return properties;
157         }
158
159         /**
160          * Create a map to hold properties to be added to mso.bpmn.urn.properties.
161          */
162         public static Map<String, String> createBpmnUrnProperties() {
163                 Map<String, String> properties = new HashMap<String, String>();
164                 properties.put("PROPERTIES-TYPE", PropertyConfiguration.MSO_BPMN_URN_PROPERTIES);
165                 return properties;
166         }
167
168         /**
169          * Adds (or replaces) the specified values in the mso.bpmn.urn.properties file.
170          * Note that properties added this way may take some time to be loaded by the
171          * PropertyConfiguration, just like they do when a property file is updated on
172          * a real MSO system. This method will optionally wait for the new properties
173          * to be loaded.  Timeout results in an IOException.
174          * @param values new properties
175          * @param wait maximum amount of time to wait for new properties to be loaded,
176          *             in milliseconds.  A value of zero means, "Do not wait."
177          * @throws IOException
178          */
179         public static synchronized void addProperties(Map<String, String> properties, long wait)
180                         throws IOException, InterruptedException {
181
182                 if (msoConfigPath == null) {
183                         throw new IllegalStateException();
184                 }
185
186                 String type = properties.get("PROPERTIES-TYPE");
187                 Path path;
188
189                 if (PropertyConfiguration.MSO_BPMN_PROPERTIES.equals(type)) {
190                         path = bpmnPropertiesPath;
191                 } else if (PropertyConfiguration.MSO_BPMN_URN_PROPERTIES.equals(type)) {
192                         path = bpmnUrnPropertiesPath;
193                 } else {
194                         throw new IllegalArgumentException("Not a supported PROPERTIES-TYPE map");
195                 }
196
197                 String oldTimestamp = PropertyConfiguration.getInstance().getProperties(type)
198                         .get(PropertyConfiguration.TIMESTAMP_PROPERTY);
199
200                 modifiedConfiguration = true;
201                 addProperties(properties, path);
202
203                 if (wait <= 0) {
204                         return;
205                 }
206
207                 long endTime = System.currentTimeMillis() + wait;
208
209                 while (true) {
210                         Thread.sleep(250);
211
212                         String newTimestamp = PropertyConfiguration.getInstance().getProperties(type)
213                                 .get(PropertyConfiguration.TIMESTAMP_PROPERTY);
214
215                         if (newTimestamp != oldTimestamp) {
216                                 return;
217                         }
218
219                         long now = System.currentTimeMillis();
220
221                         if (now >= endTime) {
222                                 throw new IOException("Timed out after " + wait
223                                         + "ms waiting for PropertyConfiguration change");
224                         }
225                 }
226         }
227
228         /**
229          * Helper method that adds properties to the specified file.
230          */
231         private static void addProperties(Map<String, String> values, Path path)
232                         throws IOException {
233
234                 FileReader fileReader = null;
235                 FileOutputStream outputStream = null;
236
237                 try {
238                         fileReader = new FileReader(path.toFile());
239                         Properties properties = new Properties();
240                         properties.load(fileReader);
241
242                         for (String key : values.keySet()) {
243                                 if (!key.equals("PROPERTIES-TYPE")) {
244                                         properties.setProperty(key, values.get(key));
245                                 }
246                         }
247
248                         outputStream = new FileOutputStream(path.toFile());
249                         properties.store(outputStream, "Custom Test Properties");
250                 } finally {
251                         if (fileReader != null) {
252                                 try {
253                                         fileReader.close();
254                                 } catch (IOException e) {
255                                         // Ignore
256                                 }
257                         }
258
259                         if (outputStream != null) {
260                                 try {
261                                         outputStream.close();
262                                 } catch (IOException e) {
263                                         // Ignore
264                                 }
265                         }
266                 }
267         }
268
269         /**
270          * Helper method that copies properties from the specified source file, and
271          * optionally merges them with the specified extra values, then writes the
272          * whole mess to the destination file.
273          */
274         private static void mergeCopy(Path sourcePath, Map<String, String> extraValues, Path destPath)
275                         throws IOException {
276                 if (extraValues == null || extraValues.isEmpty()) {
277                         Files.copy(sourcePath, destPath, StandardCopyOption.REPLACE_EXISTING);
278                         return;
279                 }
280
281                 FileReader fileReader = null;
282                 FileOutputStream outputStream = null;
283
284                 try {
285                         fileReader = new FileReader(sourcePath.toFile());
286                         Properties properties = new Properties();
287                         properties.load(fileReader);
288
289                         for (String key : extraValues.keySet()) {
290                                 if (!key.equals("PROPERTIES-TYPE")) {
291                                         properties.setProperty(key, extraValues.get(key));
292                                 }
293                         }
294
295                         outputStream = new FileOutputStream(destPath.toFile());
296                         properties.store(outputStream, "Custom Test Properties");
297                 } finally {
298                         if (fileReader != null) {
299                                 try {
300                                         fileReader.close();
301                                 } catch (IOException e) {
302                                         // Ignore
303                                 }
304                         }
305
306                         if (outputStream != null) {
307                                 try {
308                                         outputStream.close();
309                                 } catch (IOException e) {
310                                         // Ignore
311                                 }
312                         }
313                 }
314         }
315 }