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.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
53 public class ConfigurationXMLDataParser extends DefaultHandler {
\r
55 private static final Log logger = LogFactory.getLog(ConfigurationXMLDataParser.class);
\r
57 private List<ConfigurationData> completeConfigurationDataList;
\r
59 private ConfigurationData configurationData;
\r
60 private Map<String, String> parameterMONameValueMap;
\r
62 private String moAttr;
\r
63 private String moValue;
\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
71 String xmlFileContent = configFileContent.getFileContent();
\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
82 ByteArrayInputStream xmlFileContentInputStream = new ByteArrayInputStream(byteArray);
\r
84 logger.debug("Validating XML file");
\r
86 validateXmlWithSchema(xmlFileContentInputStream);
\r
88 logger.debug("XML file validation is successful");
\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
99 String xmlFileContent = configFileContent.getFileContent();
\r
100 byte[] byteArray = xmlFileContent.getBytes(StandardCharsets.UTF_8);
\r
101 ByteArrayInputStream xmlFileContentInputStream = new ByteArrayInputStream(byteArray);
\r
103 logger.debug("Validating XML file");
\r
105 validateXmlWithSchema(xmlFileContentInputStream);
\r
107 logger.debug("XML file validation is successful");
\r
109 byteArray = xmlFileContent.getBytes(StandardCharsets.UTF_8);
\r
110 xmlFileContentInputStream = new ByteArrayInputStream(byteArray);
\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
118 parser.parse(xmlFileContentInputStream, this);
\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
128 if (null == completeConfigurationDataList || completeConfigurationDataList.isEmpty()) {
\r
131 return completeConfigurationDataList.get(0);
\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
144 if (qName.equalsIgnoreCase(ConfigurationServiceConstant.CONFIG_DATA)) {
\r
146 configurationData = new ConfigurationData();
\r
147 parameterMONameValueMap = new HashMap<>();
\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
153 createAttribute(qName, attributes);
\r
158 public void endElement(String uri, String localName, String qName) throws SAXException {
\r
159 qName = qName.trim();
\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
169 if (moValue != null && !moValue.equals("") && !moValue.trim().isEmpty()) {
\r
170 parameterMONameValueMap.put(moAttr, moValue);
\r
174 if (moAttr.lastIndexOf(qName) > 0) {
\r
175 moAttr = moAttr.substring(0, moAttr.lastIndexOf(qName) - 1);
\r
177 } catch (StringIndexOutOfBoundsException e) {
\r
178 logger.error("Error occurred while parshing XML file. Cause: {}", e);
\r
183 private void createAttribute(String attrName, Attributes attributes) {
\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
194 if (moAttr != null) {
\r
195 moAttr = moAttr + "." + attrName;
\r
200 if (attributes.getValue(ConfigurationServiceConstant.TABULAR_INDEX_NAME) != null) {
\r
201 moAttr = moAttr + "." + attributes.getValue(ConfigurationServiceConstant.TABULAR_INDEX_NAME);
\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
212 moValue = moValue + tmp.trim();
\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
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
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
232 Schema schema = factory.newSchema(new StreamSource(xsdInputStream));
\r
233 Validator validator = schema.newValidator();
\r
235 final StringBuilder exceptions = new StringBuilder();
\r
236 validator.setErrorHandler(new ErrorHandler() {
\r
238 public void warning(SAXParseException exception) {
\r
239 handleMessage(exception);
\r
243 public void error(SAXParseException exception) {
\r
244 handleMessage(exception);
\r
248 public void fatalError(SAXParseException exception) {
\r
249 handleMessage(exception);
\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
260 validator.validate(new StreamSource(xmlFileContentInputStream));
\r
261 if (exceptions.length() > 0) {
\r
262 throw new SAXException(" Line=" + exceptions);
\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
269 logger.debug("File is valid.");
\r
272 protected void setProperty(SAXParser parser)
\r
273 throws SAXNotRecognizedException, SAXNotSupportedException {
\r
274 logger.debug("property added.");
\r