Sync Integ to Master
[sdc.git] / common-app-api / src / main / java / org / openecomp / sdc / common / util / YamlToObjectConverter.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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.sdc.common.util;
22
23 import java.io.ByteArrayInputStream;
24 import java.io.File;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.nio.file.Files;
28 import java.nio.file.Paths;
29 import java.util.HashMap;
30 import java.util.Map;
31
32 import org.apache.commons.codec.binary.Base64;
33 import org.openecomp.sdc.be.config.Configuration.ApplicationL1CacheConfig;
34 import org.openecomp.sdc.be.config.Configuration.ApplicationL2CacheConfig;
35 import org.openecomp.sdc.be.config.Configuration.ArtifactTypeConfig;
36 import org.openecomp.sdc.be.config.Configuration.BeMonitoringConfig;
37 import org.openecomp.sdc.be.config.Configuration.EcompPortalConfig;
38 import org.openecomp.sdc.be.config.Configuration.ElasticSearchConfig;
39 import org.openecomp.sdc.be.config.Configuration.ElasticSearchConfig.IndicesTimeFrequencyEntry;
40 import org.openecomp.sdc.be.config.Configuration.OnboardingConfig;
41 import org.openecomp.sdc.be.config.Configuration.SwitchoverDetectorConfig;
42 import org.openecomp.sdc.be.config.Configuration.ToscaValidatorsConfig;
43 import org.openecomp.sdc.be.config.DistributionEngineConfiguration;
44 import org.openecomp.sdc.be.config.DistributionEngineConfiguration.ComponentArtifactTypesConfig;
45 import org.openecomp.sdc.be.config.DistributionEngineConfiguration.CreateTopicConfig;
46 import org.openecomp.sdc.be.config.DistributionEngineConfiguration.DistributionNotificationTopicConfig;
47 import org.openecomp.sdc.be.config.DistributionEngineConfiguration.DistributionStatusTopicConfig;
48 import org.openecomp.sdc.be.config.validation.DeploymentArtifactHeatConfiguration;
49 import org.openecomp.sdc.fe.config.Configuration.FeMonitoringConfig;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52 import org.yaml.snakeyaml.TypeDescription;
53 import org.yaml.snakeyaml.Yaml;
54 import org.yaml.snakeyaml.error.YAMLException;
55 import org.yaml.snakeyaml.introspector.PropertyUtils;
56 import org.yaml.snakeyaml.nodes.Node;
57
58 public class YamlToObjectConverter {
59
60         private static Logger log = LoggerFactory.getLogger(YamlToObjectConverter.class.getName());
61
62         private static HashMap<String, Yaml> yamls = new HashMap<String, Yaml>();
63
64         private static Yaml defaultYaml = new Yaml();
65
66         static {
67
68                 org.yaml.snakeyaml.constructor.Constructor deConstructor = new org.yaml.snakeyaml.constructor.Constructor(
69                                 DistributionEngineConfiguration.class);
70                 TypeDescription deDescription = new TypeDescription(DistributionEngineConfiguration.class);
71                 deDescription.putListPropertyType("distributionStatusTopic", DistributionStatusTopicConfig.class);
72                 deDescription.putListPropertyType("distribNotifServiceArtifactTypes", ComponentArtifactTypesConfig.class);
73                 deDescription.putListPropertyType("distribNotifResourceArtifactTypes", ComponentArtifactTypesConfig.class);
74                 deDescription.putListPropertyType("createTopic", CreateTopicConfig.class);
75                 deDescription.putListPropertyType("distributionNotificationTopic", DistributionNotificationTopicConfig.class);
76                 deConstructor.addTypeDescription(deDescription);
77                 Yaml yaml = new Yaml(deConstructor);
78                 yamls.put(DistributionEngineConfiguration.class.getName(), yaml);
79
80                 // FE conf
81                 org.yaml.snakeyaml.constructor.Constructor feConfConstructor = new org.yaml.snakeyaml.constructor.Constructor(
82                                 org.openecomp.sdc.fe.config.Configuration.class);
83                 TypeDescription feConfDescription = new TypeDescription(org.openecomp.sdc.fe.config.Configuration.class);
84                 feConfDescription.putListPropertyType("systemMonitoring", FeMonitoringConfig.class);
85                 feConfConstructor.addTypeDescription(feConfDescription);
86                 yamls.put(org.openecomp.sdc.fe.config.Configuration.class.getName(), new Yaml(feConfConstructor));
87
88                 // BE conf
89                 org.yaml.snakeyaml.constructor.Constructor beConfConstructor = new org.yaml.snakeyaml.constructor.Constructor(
90                                 org.openecomp.sdc.be.config.Configuration.class);
91                 TypeDescription beConfDescription = new TypeDescription(org.openecomp.sdc.be.config.Configuration.class);
92                 beConfConstructor.addTypeDescription(beConfDescription);
93
94                 // systemMonitoring
95                 beConfDescription.putListPropertyType("systemMonitoring", BeMonitoringConfig.class);
96
97                 // elasticSearch
98                 beConfDescription.putListPropertyType("elasticSearch", ElasticSearchConfig.class);
99                 TypeDescription esDescription = new TypeDescription(ElasticSearchConfig.class);
100                 esDescription.putListPropertyType("indicesTimeFrequency", IndicesTimeFrequencyEntry.class);
101                 beConfConstructor.addTypeDescription(esDescription);
102
103                 // resourceDeploymentArtifacts and serviceDeploymentArtifacts
104                 beConfDescription.putMapPropertyType("resourceDeploymentArtifacts", String.class,
105                                 ArtifactTypeConfig.class);
106                 beConfDescription.putMapPropertyType("serviceDeploymentArtifacts", String.class,
107                                 ArtifactTypeConfig.class);
108
109                 // onboarding
110                 beConfDescription.putListPropertyType("onboarding", OnboardingConfig.class);
111
112                 // ecompPortal
113                 beConfDescription.putListPropertyType("ecompPortal", EcompPortalConfig.class);
114                 // switchoverDetector
115                 beConfDescription.putListPropertyType("switchoverDetector", SwitchoverDetectorConfig.class);
116
117                 // ApplicationL1Cache
118                 beConfDescription.putListPropertyType("applicationL1Cache", ApplicationL1CacheConfig.class);
119
120                 // ApplicationL2Cache
121                 beConfDescription.putListPropertyType("applicationL2Cache", ApplicationL2CacheConfig.class);
122
123                 // tosca validators config
124                 beConfDescription.putListPropertyType("toscaValidators", ToscaValidatorsConfig.class);
125
126                 yamls.put(org.openecomp.sdc.be.config.Configuration.class.getName(), new Yaml(beConfConstructor));
127
128                 // HEAT deployment artifact
129                 org.yaml.snakeyaml.constructor.Constructor depArtHeatConstructor = new org.yaml.snakeyaml.constructor.Constructor(
130                                 DeploymentArtifactHeatConfiguration.class);
131                 PropertyUtils propertyUtils = new PropertyUtils();
132                 // Skip properties which are found in YAML but not found in POJO
133                 propertyUtils.setSkipMissingProperties(true);
134                 depArtHeatConstructor.setPropertyUtils(propertyUtils);
135                 yamls.put(org.openecomp.sdc.be.config.validation.DeploymentArtifactHeatConfiguration.class.getName(),
136                                 new Yaml(depArtHeatConstructor));
137
138         }
139
140         private static <T> Yaml getYamlByClassName(Class<T> className) {
141
142                 Yaml yaml = yamls.get(className.getName());
143                 if (yaml == null) {
144                         yaml = defaultYaml;
145                 }
146
147                 return yaml;
148         }
149
150         public <T> T convert(String dirPath, Class<T> className, String configFileName) {
151
152                 T config = null;
153
154                 try {
155
156                         String fullFileName = dirPath + File.separator + configFileName;
157
158                         config = convert(fullFileName, className);
159
160                 } catch (Exception e) {
161                         log.error("Failed to convert yaml file {} to object.", configFileName,e);
162                 }
163
164                 return config;
165         }
166
167         public class MyYamlConstructor extends org.yaml.snakeyaml.constructor.Constructor {
168                 private HashMap<String, Class<?>> classMap = new HashMap<String, Class<?>>();
169
170                 public MyYamlConstructor(Class<? extends Object> theRoot) {
171                         super(theRoot);
172                         classMap.put(DistributionEngineConfiguration.class.getName(), DistributionEngineConfiguration.class);
173                         classMap.put(DistributionStatusTopicConfig.class.getName(), DistributionStatusTopicConfig.class);
174                 }
175
176                 /*
177                  * This is a modified version of the Constructor. Rather than using a
178                  * class loader to get external classes, they are already predefined
179                  * above. This approach works similar to the typeTags structure in the
180                  * original constructor, except that class information is pre-populated
181                  * during initialization rather than runtime.
182                  *
183                  * @see
184                  * org.yaml.snakeyaml.constructor.Constructor#getClassForNode(org.yaml.
185                  * snakeyaml.nodes.Node)
186                  */
187                 protected Class<?> getClassForNode(Node node) {
188                         String name = node.getTag().getClassName();
189                         Class<?> cl = classMap.get(name);
190                         if (cl == null)
191                                 throw new YAMLException("Class not found: " + name);
192                         else
193                                 return cl;
194                 }
195         }
196
197         public <T> T convert(String fullFileName, Class<T> className) {
198
199                 T config = null;
200
201                 Yaml yaml = getYamlByClassName(className);
202
203                 InputStream in = null;
204                 try {
205
206                         File f = new File(fullFileName);
207                         if (false == f.exists()) {
208                                 log.warn("The file " + fullFileName + " cannot be found. Ignore reading configuration.");
209                                 return null;
210                         }
211                         in = Files.newInputStream(Paths.get(fullFileName));
212
213                         config = yaml.loadAs(in, className);
214
215                         // System.out.println(config.toString());
216                 } catch (Exception e) {
217                         log.error("Failed to convert yaml file {} to object.", fullFileName, e);
218                 } finally {
219                         if (in != null) {
220                                 try {
221                                         in.close();
222                                 } catch (IOException e) {
223                                         log.debug("Failed to close input stream {} ", e.getMessage(), e);
224                                         e.printStackTrace();
225                                 }
226                         }
227                 }
228
229                 return config;
230         }
231
232         public <T> T convert(byte[] fileContents, Class<T> className) {
233
234                 T config = null;
235
236                 Yaml yaml = getYamlByClassName(className);
237
238                 InputStream in = null;
239                 try {
240
241                         in = new ByteArrayInputStream(fileContents);
242
243                         config = yaml.loadAs(in, className);
244
245                 } catch (Exception e) {
246                         log.error("Failed to convert yaml file to object", e);
247                 } finally {
248                         if (in != null) {
249                                 try {
250                                         in.close();
251                                 } catch (IOException e) {
252                                         log.debug("Failed to close input stream {} ", e.getMessage(), e);
253                                         e.printStackTrace();
254                                 }
255                         }
256                 }
257
258                 return config;
259         }
260
261         public boolean isValidYamlEncoded64(byte[] fileContents) {
262                 log.trace("Received Base64 data - decoding before validating...");
263                 byte[] decodedFileContents = Base64.decodeBase64(fileContents);
264                 
265                 return isValidYaml(decodedFileContents);
266         }
267         
268         public boolean isValidYaml(byte[] fileContents) {
269                 try {
270                         
271                         Iterable<Object> mappedToscaTemplateIt =  defaultYaml.loadAll(new ByteArrayInputStream(fileContents));
272                         
273                          for (Object o : mappedToscaTemplateIt) {
274                         System.out.println("Loaded object type:" + o.getClass());
275                         Map<String, Object> map = (Map<String, Object>) o;
276                          }
277                         
278                 } catch (Exception e) {
279                         log.error("Failed to convert yaml file to object - yaml is invalid", e);
280                         return false;
281                 }
282                 return true;
283         }
284 }