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