Add o-ran-sc/ prefix to ves-agent image name
[oam/tr069-adapter.git] / config-data / src / main / java / org / commscope / tr069adapter / config / parser / ConfigurationXMLDataParser.java
1 /*\r
2  * ============LICENSE_START========================================================================\r
3  * ONAP : tr-069-adapter\r
4  * =================================================================================================\r
5  * Copyright (C) 2020 CommScope Inc Intellectual Property.\r
6  * =================================================================================================\r
7  * This tr-069-adapter software file is distributed by CommScope Inc under the Apache License,\r
8  * Version 2.0 (the "License"); you may not use this file except in compliance with the License. You\r
9  * may obtain a copy of the License at\r
10  *\r
11  * http://www.apache.org/licenses/LICENSE-2.0\r
12  *\r
13  * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,\r
14  * either express or implied. See the License for the specific language governing permissions and\r
15  * limitations under the License.\r
16  * ===============LICENSE_END=======================================================================\r
17  */\r
18 \r
19 package org.commscope.tr069adapter.config.parser;\r
20 \r
21 import java.io.ByteArrayInputStream;\r
22 import java.io.InputStream;\r
23 import java.nio.charset.StandardCharsets;\r
24 import java.util.ArrayList;\r
25 import java.util.HashMap;\r
26 import java.util.List;\r
27 import java.util.Map;\r
28 \r
29 import javax.xml.XMLConstants;\r
30 import javax.xml.parsers.SAXParser;\r
31 import javax.xml.parsers.SAXParserFactory;\r
32 import javax.xml.transform.stream.StreamSource;\r
33 import javax.xml.validation.Schema;\r
34 import javax.xml.validation.SchemaFactory;\r
35 import javax.xml.validation.Validator;\r
36 \r
37 import org.apache.commons.logging.Log;\r
38 import org.apache.commons.logging.LogFactory;\r
39 import org.commscope.tr069adapter.config.constants.ConfigurationServiceConstant;\r
40 import org.commscope.tr069adapter.config.dto.ConfigurationData;\r
41 import org.commscope.tr069adapter.config.exceptions.InvalidConfigurationServiceException;\r
42 import org.commscope.tr069adapter.config.model.ConfigFileContent;\r
43 import org.springframework.stereotype.Component;\r
44 import org.xml.sax.Attributes;\r
45 import org.xml.sax.ErrorHandler;\r
46 import org.xml.sax.SAXException;\r
47 import org.xml.sax.SAXNotRecognizedException;\r
48 import org.xml.sax.SAXNotSupportedException;\r
49 import org.xml.sax.SAXParseException;\r
50 import org.xml.sax.helpers.DefaultHandler;\r
51 \r
52 @Component\r
53 public class ConfigurationXMLDataParser extends DefaultHandler {\r
54 \r
55   private static final Log logger = LogFactory.getLog(ConfigurationXMLDataParser.class);\r
56 \r
57   private List<ConfigurationData> completeConfigurationDataList;\r
58 \r
59   private ConfigurationData configurationData;\r
60   private Map<String, String> parameterMONameValueMap;\r
61 \r
62   private String moAttr;\r
63   private String moValue;\r
64 \r
65   public void validateFile(ConfigFileContent configFileContent)\r
66       throws InvalidConfigurationServiceException {\r
67     SAXParserFactory factory = SAXParserFactory.newInstance();\r
68     factory.setValidating(true);\r
69     factory.setNamespaceAware(true);\r
70 \r
71     String xmlFileContent = configFileContent.getFileContent();\r
72     byte[] byteArray;\r
73 \r
74     try {\r
75       byteArray = xmlFileContent.getBytes(StandardCharsets.UTF_8);\r
76     } catch (Exception e) {\r
77       logger.error("Error while parsing device configuration XML file. {}", e);\r
78       throw new InvalidConfigurationServiceException(\r
79           "UnsupportedEncodingException error. " + e.getMessage());\r
80     }\r
81 \r
82     ByteArrayInputStream xmlFileContentInputStream = new ByteArrayInputStream(byteArray);\r
83 \r
84     logger.debug("Validating XML file");\r
85 \r
86     validateXmlWithSchema(xmlFileContentInputStream);\r
87 \r
88     logger.debug("XML file validation is successful");\r
89 \r
90   }\r
91 \r
92   public ConfigurationData parseFile(ConfigFileContent configFileContent)\r
93       throws InvalidConfigurationServiceException {\r
94     SAXParserFactory factory = SAXParserFactory.newInstance();\r
95     factory.setValidating(true);\r
96     factory.setNamespaceAware(true);\r
97 \r
98     try {\r
99       String xmlFileContent = configFileContent.getFileContent();\r
100       byte[] byteArray = xmlFileContent.getBytes(StandardCharsets.UTF_8);\r
101       ByteArrayInputStream xmlFileContentInputStream = new ByteArrayInputStream(byteArray);\r
102 \r
103       logger.debug("Validating XML file");\r
104 \r
105       validateXmlWithSchema(xmlFileContentInputStream);\r
106 \r
107       logger.debug("XML file validation is successful");\r
108 \r
109       byteArray = xmlFileContent.getBytes(StandardCharsets.UTF_8);\r
110       xmlFileContentInputStream = new ByteArrayInputStream(byteArray);\r
111 \r
112       SAXParser parser = null;\r
113       parser = factory.newSAXParser();\r
114       parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");\r
115       parser.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");\r
116       setProperty(parser);\r
117 \r
118       parser.parse(xmlFileContentInputStream, this);\r
119 \r
120     } catch (SAXException e) {\r
121       logger.error("Error while parsing device configuration XML file. {}", e);\r
122       throw new InvalidConfigurationServiceException("File parsing error. " + e.getMessage());\r
123     } catch (Exception e) {\r
124       logger.error("Unknown error occurred while parsing device configuration XML file. {}", e);\r
125       throw new InvalidConfigurationServiceException("UNKNOWN ERROR. " + e.getMessage());\r
126     }\r
127 \r
128     if (null == completeConfigurationDataList || completeConfigurationDataList.isEmpty()) {\r
129       return null;\r
130     } else {\r
131       return completeConfigurationDataList.get(0);\r
132     }\r
133   }\r
134 \r
135   @Override\r
136   public void startElement(String uri, String localName, String qName, Attributes attributes)\r
137       throws SAXException {\r
138     qName = qName.trim();\r
139     if (qName.equalsIgnoreCase(ConfigurationServiceConstant.CONFIG_DATA_FILE)) {\r
140       completeConfigurationDataList = new ArrayList<>();\r
141       return;\r
142     }\r
143 \r
144     if (qName.equalsIgnoreCase(ConfigurationServiceConstant.CONFIG_DATA)) {\r
145       moAttr = null;\r
146       configurationData = new ConfigurationData();\r
147       parameterMONameValueMap = new HashMap<>();\r
148 \r
149       configurationData.setParameterMONameValueMap(parameterMONameValueMap);\r
150     } else if (qName.equalsIgnoreCase(ConfigurationServiceConstant.FILE_HEADER)) {\r
151       logger.debug("File hearder start element parsing started");\r
152     } else {\r
153       createAttribute(qName, attributes);\r
154     }\r
155   }\r
156 \r
157   @Override\r
158   public void endElement(String uri, String localName, String qName) throws SAXException {\r
159     qName = qName.trim();\r
160 \r
161     if (qName.equalsIgnoreCase(ConfigurationServiceConstant.CONFIG_DATA_FILE)) {\r
162       logger.debug("ignoreing the datafile end element");\r
163     } else if (qName.equalsIgnoreCase(ConfigurationServiceConstant.CONFIG_DATA)) {\r
164       completeConfigurationDataList.add(configurationData);\r
165     } else if (qName.equalsIgnoreCase(ConfigurationServiceConstant.MANAGED_ELEMENT)\r
166         || qName.equalsIgnoreCase(ConfigurationServiceConstant.FILE_HEADER)) {\r
167       logger.debug("File hearder end element parsing started");\r
168     } else {\r
169       if (moValue != null && !moValue.equals("") && !moValue.trim().isEmpty()) {\r
170         parameterMONameValueMap.put(moAttr, moValue);\r
171         moValue = null;\r
172       }\r
173       try {\r
174         if (moAttr.lastIndexOf(qName) > 0) {\r
175           moAttr = moAttr.substring(0, moAttr.lastIndexOf(qName) - 1);\r
176         }\r
177       } catch (StringIndexOutOfBoundsException e) {\r
178         logger.error("Error occurred while parshing XML file. Cause: {}", e);\r
179       }\r
180     }\r
181   }\r
182 \r
183   private void createAttribute(String attrName, Attributes attributes) {\r
184 \r
185     if (attrName.equalsIgnoreCase(ConfigurationServiceConstant.MANAGED_ELEMENT)) {\r
186       configurationData.setOUI(attributes.getValue("OUI"));\r
187       configurationData.setProductClass(attributes.getValue("ProductClass"));\r
188       configurationData.setHardwareVersion(attributes.getValue("hwVersion"));\r
189       configurationData.setSoftwareVersion(attributes.getValue("swVersion"));\r
190       configurationData.setLocalDn(attributes.getValue("localDn"));\r
191 \r
192       return;\r
193     }\r
194     if (moAttr != null) {\r
195       moAttr = moAttr + "." + attrName;\r
196     } else {\r
197       moAttr = attrName;\r
198     }\r
199 \r
200     if (attributes.getValue(ConfigurationServiceConstant.TABULAR_INDEX_NAME) != null) {\r
201       moAttr = moAttr + "." + attributes.getValue(ConfigurationServiceConstant.TABULAR_INDEX_NAME);\r
202     }\r
203 \r
204   }\r
205 \r
206   @Override\r
207   public void characters(char[] ch, int start, int length) throws SAXException {\r
208     String tmp = new String(ch, start, length);\r
209     if (moValue == null) {\r
210       moValue = tmp.trim();\r
211     } else {\r
212       moValue = moValue + tmp.trim();\r
213     }\r
214   }\r
215 \r
216   public void validateXmlWithSchema(ByteArrayInputStream xmlFileContentInputStream)\r
217       throws InvalidConfigurationServiceException {\r
218     logger.info("Validating the XML file against XSD file: "\r
219         + ConfigurationServiceConstant.CONFIGURATION_DATA_XSD_PATH);\r
220     try {\r
221       SchemaFactory factory = SchemaFactory.newInstance(ConfigurationServiceConstant.XML_SCHEMA_NS);\r
222       factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");\r
223       factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");\r
224 \r
225       InputStream xsdInputStream =\r
226           getClass().getResourceAsStream(ConfigurationServiceConstant.CONFIGURATION_DATA_XSD_PATH);\r
227       if (xsdInputStream == null) {\r
228         throw new InvalidConfigurationServiceException("File parsing error: Unable to find XSD "\r
229             + ConfigurationServiceConstant.CONFIGURATION_DATA_XSD_PATH);\r
230       }\r
231 \r
232       Schema schema = factory.newSchema(new StreamSource(xsdInputStream));\r
233       Validator validator = schema.newValidator();\r
234 \r
235       final StringBuilder exceptions = new StringBuilder();\r
236       validator.setErrorHandler(new ErrorHandler() {\r
237         @Override\r
238         public void warning(SAXParseException exception) {\r
239           handleMessage(exception);\r
240         }\r
241 \r
242         @Override\r
243         public void error(SAXParseException exception) {\r
244           handleMessage(exception);\r
245         }\r
246 \r
247         @Override\r
248         public void fatalError(SAXParseException exception) {\r
249           handleMessage(exception);\r
250         }\r
251 \r
252         private void handleMessage(SAXParseException exception) {\r
253           int lineNumber = exception.getLineNumber();\r
254           int columnNumber = exception.getColumnNumber();\r
255           String message = exception.getMessage();\r
256           exceptions.append("\n" + lineNumber + ":" + columnNumber + ": " + message);\r
257         }\r
258       });\r
259 \r
260       validator.validate(new StreamSource(xmlFileContentInputStream));\r
261       if (exceptions.length() > 0) {\r
262         throw new SAXException(" Line=" + exceptions);\r
263       }\r
264     } catch (Exception e) {\r
265       logger.error("Error while parsing the XML file " + e.toString());\r
266       throw new InvalidConfigurationServiceException("File parsing error. " + e.toString());\r
267     }\r
268 \r
269     logger.debug("File is valid.");\r
270   }\r
271 \r
272   protected void setProperty(SAXParser parser)\r
273       throws SAXNotRecognizedException, SAXNotSupportedException {\r
274       logger.debug("property added.");\r
275   }\r
276 \r
277 }\r