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
11 * http://www.apache.org/licenses/LICENSE-2.0
\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
19 package org.commscope.tr069adapter.config.parser;
\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
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
37 import org.apache.commons.logging.Log;
\r
38 import org.apache.commons.logging.LogFactory;
\r
39 import org.commscope.tr069adapter.acs.common.dto.ConfigurationData;
\r
40 import org.commscope.tr069adapter.config.constants.ConfigurationServiceConstant;
\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.SAXParseException;
\r
48 import org.xml.sax.helpers.DefaultHandler;
\r
51 public class ConfigurationXMLDataParser extends DefaultHandler {
\r
53 private static final Log logger = LogFactory.getLog(ConfigurationXMLDataParser.class);
\r
55 private List<ConfigurationData> completeConfigurationDataList;
\r
57 private ConfigurationData configurationData;
\r
58 private Map<String, String> parameterMONameValueMap;
\r
60 private String moAttr;
\r
61 private String moValue;
\r
63 public void validateFile(ConfigFileContent configFileContent)
\r
64 throws InvalidConfigurationServiceException {
\r
65 SAXParserFactory factory = SAXParserFactory.newInstance();
\r
66 factory.setValidating(true);
\r
67 factory.setNamespaceAware(true);
\r
69 String xmlFileContent = configFileContent.getFileContent();
\r
73 byteArray = xmlFileContent.getBytes(StandardCharsets.UTF_8);
\r
74 } catch (Exception e) {
\r
75 logger.error("Error while parsing device configuration XML file. {}", e);
\r
76 throw new InvalidConfigurationServiceException(
\r
77 "UnsupportedEncodingException error. " + e.getMessage());
\r
80 ByteArrayInputStream xmlFileContentInputStream = new ByteArrayInputStream(byteArray);
\r
82 logger.debug("Validating XML file");
\r
84 validateXmlWithSchema(xmlFileContentInputStream);
\r
86 logger.debug("XML file validation is successful");
\r
90 public ConfigurationData parseFile(ConfigFileContent configFileContent)
\r
91 throws InvalidConfigurationServiceException {
\r
92 SAXParserFactory factory = SAXParserFactory.newInstance();
\r
93 factory.setValidating(true);
\r
94 factory.setNamespaceAware(true);
\r
97 String xmlFileContent = configFileContent.getFileContent();
\r
98 byte[] byteArray = xmlFileContent.getBytes(StandardCharsets.UTF_8);
\r
99 ByteArrayInputStream xmlFileContentInputStream = new ByteArrayInputStream(byteArray);
\r
101 logger.debug("Validating XML file");
\r
103 validateXmlWithSchema(xmlFileContentInputStream);
\r
105 logger.debug("XML file validation is successful");
\r
107 byteArray = xmlFileContent.getBytes(StandardCharsets.UTF_8);
\r
108 xmlFileContentInputStream = new ByteArrayInputStream(byteArray);
\r
110 SAXParser parser = null;
\r
111 parser = factory.newSAXParser();
\r
112 parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
\r
113 parser.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
\r
116 parser.parse(xmlFileContentInputStream, this);
\r
118 } catch (SAXException e) {
\r
119 logger.error("Error while parsing device configuration XML file. {}", e);
\r
120 throw new InvalidConfigurationServiceException("File parsing error. " + e.getMessage());
\r
121 } catch (Exception e) {
\r
122 logger.error("Unknown error occurred while parsing device configuration XML file. {}", e);
\r
123 throw new InvalidConfigurationServiceException("UNKNOWN ERROR. " + e.getMessage());
\r
126 if (null == completeConfigurationDataList || completeConfigurationDataList.isEmpty()) {
\r
129 return completeConfigurationDataList.get(0);
\r
134 public void startElement(String uri, String localName, String qName, Attributes attributes)
\r
135 throws SAXException {
\r
136 qName = qName.trim();
\r
137 if (qName.equalsIgnoreCase(ConfigurationServiceConstant.CONFIG_DATA_FILE)) {
\r
138 completeConfigurationDataList = new ArrayList<>();
\r
142 if (qName.equalsIgnoreCase(ConfigurationServiceConstant.CONFIG_DATA)) {
\r
144 configurationData = new ConfigurationData();
\r
145 parameterMONameValueMap = new HashMap<>();
\r
147 configurationData.setParameterMONameValueMap(parameterMONameValueMap);
\r
148 } else if (qName.equalsIgnoreCase(ConfigurationServiceConstant.FILE_HEADER)) {
\r
149 logger.debug("File hearder start element parsing started");
\r
151 createAttribute(qName, attributes);
\r
156 public void endElement(String uri, String localName, String qName) throws SAXException {
\r
157 qName = qName.trim();
\r
159 if (qName.equalsIgnoreCase(ConfigurationServiceConstant.CONFIG_DATA_FILE)) {
\r
160 logger.debug("ignoreing the datafile end element");
\r
161 } else if (qName.equalsIgnoreCase(ConfigurationServiceConstant.CONFIG_DATA)) {
\r
162 completeConfigurationDataList.add(configurationData);
\r
163 } else if (qName.equalsIgnoreCase(ConfigurationServiceConstant.MANAGED_ELEMENT)
\r
164 || qName.equalsIgnoreCase(ConfigurationServiceConstant.FILE_HEADER)) {
\r
165 logger.debug("File hearder end element parsing started");
\r
167 if (moValue != null && !moValue.equals("") && !moValue.trim().isEmpty()) {
\r
168 parameterMONameValueMap.put(moAttr, moValue);
\r
172 if (moAttr.lastIndexOf(qName) > 0) {
\r
173 moAttr = moAttr.substring(0, moAttr.lastIndexOf(qName) - 1);
\r
175 } catch (StringIndexOutOfBoundsException e) {
\r
176 logger.error("Error occurred while parshing XML file. Cause: {}", e);
\r
181 private void createAttribute(String attrName, Attributes attributes) {
\r
183 if (attrName.equalsIgnoreCase(ConfigurationServiceConstant.MANAGED_ELEMENT)) {
\r
184 configurationData.setOUI(attributes.getValue("OUI"));
\r
185 configurationData.setProductClass(attributes.getValue("ProductClass"));
\r
186 configurationData.setHardwareVersion(attributes.getValue("hwVersion"));
\r
187 configurationData.setSoftwareVersion(attributes.getValue("swVersion"));
\r
188 configurationData.setLocalDn(attributes.getValue("localDn"));
\r
192 if (moAttr != null) {
\r
193 moAttr = moAttr + "." + attrName;
\r
198 if (attributes.getValue(ConfigurationServiceConstant.TABULAR_INDEX_NAME) != null) {
\r
199 moAttr = moAttr + "." + attributes.getValue(ConfigurationServiceConstant.TABULAR_INDEX_NAME);
\r
205 public void characters(char[] ch, int start, int length) throws SAXException {
\r
206 String tmp = new String(ch, start, length);
\r
207 if (moValue == null) {
\r
208 moValue = tmp.trim();
\r
210 moValue = moValue + tmp.trim();
\r
214 public void validateXmlWithSchema(ByteArrayInputStream xmlFileContentInputStream)
\r
215 throws InvalidConfigurationServiceException {
\r
216 logger.info("Validating the XML file against XSD file: "
\r
217 + ConfigurationServiceConstant.CONFIGURATION_DATA_XSD_PATH);
\r
219 SchemaFactory factory = SchemaFactory.newInstance(ConfigurationServiceConstant.XML_SCHEMA_NS);
\r
220 factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
\r
221 factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
\r
223 InputStream xsdInputStream =
\r
224 getClass().getResourceAsStream(ConfigurationServiceConstant.CONFIGURATION_DATA_XSD_PATH);
\r
225 if (xsdInputStream == null) {
\r
226 throw new InvalidConfigurationServiceException("File parsing error: Unable to find XSD "
\r
227 + ConfigurationServiceConstant.CONFIGURATION_DATA_XSD_PATH);
\r
230 Schema schema = factory.newSchema(new StreamSource(xsdInputStream));
\r
231 Validator validator = schema.newValidator();
\r
233 final StringBuilder exceptions = new StringBuilder();
\r
234 validator.setErrorHandler(new ErrorHandler() {
\r
236 public void warning(SAXParseException exception) {
\r
237 handleMessage(exception);
\r
241 public void error(SAXParseException exception) {
\r
242 handleMessage(exception);
\r
246 public void fatalError(SAXParseException exception) {
\r
247 handleMessage(exception);
\r
250 private void handleMessage(SAXParseException exception) {
\r
251 int lineNumber = exception.getLineNumber();
\r
252 int columnNumber = exception.getColumnNumber();
\r
253 String message = exception.getMessage();
\r
254 exceptions.append("\n" + lineNumber + ":" + columnNumber + ": " + message);
\r
258 validator.validate(new StreamSource(xmlFileContentInputStream));
\r
259 if (exceptions.length() > 0) {
\r
260 throw new SAXException(" Line=" + exceptions);
\r
262 } catch (Exception e) {
\r
263 logger.error("Error while parsing the XML file " + e.toString());
\r
264 throw new InvalidConfigurationServiceException("File parsing error. " + e.toString());
\r
267 logger.debug("File is valid.");
\r
270 protected void setProperty() {
\r
271 logger.debug("property added.");
\r