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