/******************************************************************************* * Copyright (C) 2014, International Business Machines Corporation * All Rights Reserved *******************************************************************************/ package com.ibm.streamsx.messaging.mqtt; import java.io.IOException; import java.io.InputStream; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Set; import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; import org.apache.log4j.Logger; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import com.ibm.streams.operator.log4j.LogLevel; import com.ibm.streams.operator.log4j.LoggerNames; import com.ibm.streams.operator.log4j.TraceLevel; import com.ibm.streamsx.messaging.mqtt.Messages; //This class parses and validates the connections document class ConnectionDocumentHelper { private static Logger TRACE = Logger.getLogger(ConnectionDocumentHelper.class); private static final Logger LOG = Logger.getLogger(LoggerNames.LOG_FACILITY + "." + ConnectionDocumentHelper.class.getName()); //$NON-NLS-1$ private static final String EMPTY_STRING = ""; //$NON-NLS-1$ LinkedHashMap<String, ConnectionSpecification> connSpecMap = new LinkedHashMap<String, ConnectionSpecification>(); public void parseAndValidateConnectionDocument(String connectionDocument) throws Exception, SAXException, IOException, ParserConfigurationException { try { // validate the connections document against the xsd validateConnectionsXML(connectionDocument); // create document builder Element docEle = createDocumentBuilder(connectionDocument); // parse validate the connection_specification tag in connections // document parseConnectionSpecifications(docEle); } catch (Exception e) { TRACE.log(TraceLevel.ERROR, Messages.getString("INVALID_CONNECTION_DOC"), e); //$NON-NLS-1$ LOG.log(LogLevel.ERROR, Messages.getString("INVALID_CONNECTION_DOC"), e); //$NON-NLS-1$ throw e; } } // subroutine to validate the connections document against the xsd public void validateConnectionsXML(String connectionDocument) throws SAXException, IOException { // validate against the xsd, if validation error occurs, it throws the // error and aborts at runtime SchemaFactory factory = SchemaFactory .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); // read schema from classpath InputStream resourceAsStream = getClass().getResourceAsStream( "mqttconnection.xsd"); //$NON-NLS-1$ Source streamSource = new StreamSource(resourceAsStream); // create new schema Schema schema = factory.newSchema(streamSource); Validator validator = schema.newValidator(); Source source = new StreamSource(connectionDocument); validator.validate(source); } // subroutine to create document builder private Element createDocumentBuilder(String connectionDocument) throws ParserConfigurationException, IOException, SAXException { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(connectionDocument); Element docEle = doc.getDocumentElement(); return docEle; } private void parseConnectionSpecifications(Element element) { NodeList connectionSpecs = element .getElementsByTagName("connection_specification"); //$NON-NLS-1$ int length = connectionSpecs.getLength(); for (int i = 0; i < length; i++) { Node spec = connectionSpecs.item(i); NodeList childNodes = spec.getChildNodes(); String name = getAttributeValue(spec.getAttributes(), "name"); //$NON-NLS-1$ if (name != null) { int numChildren = childNodes.getLength(); for (int j = 0; j < numChildren; j++) { Node connElement = childNodes.item(j); if (connElement.getNodeName().equals("MQTT")) { //$NON-NLS-1$ NamedNodeMap attributes = connElement.getAttributes(); if (attributes != null) { String serverUriStr = getAttributeValue(attributes, "serverURI"); //$NON-NLS-1$ String trustStore = getAttributeValue(attributes, "trustStore"); //$NON-NLS-1$ String keyStore = getAttributeValue(attributes, "keyStore"); //$NON-NLS-1$ String keyStorePassword = getAttributeValue( attributes, "keyStorePassword"); //$NON-NLS-1$ String trustStorePassword = getAttributeValue(attributes, "trustStorePassword"); //$NON-NLS-1$ String userID = getAttributeValue(attributes, "userID"); //$NON-NLS-1$ String password = getAttributeValue(attributes, "password"); //$NON-NLS-1$ int keepAliveInterval; try { keepAliveInterval = Integer.parseInt(getAttributeValue(attributes, "keepAliveInterval")); //$NON-NLS-1$ } catch (NumberFormatException e) { keepAliveInterval = IMqttConstants.UNINITIALIZED_KEEP_ALIVE_INTERVAL; } long commandTimeout; try { commandTimeout = Long.parseLong(getAttributeValue(attributes, "commandTimeout")); //$NON-NLS-1$ } catch (NumberFormatException e) { commandTimeout = IMqttConstants.UNINITIALIZED_COMMAND_TIMEOUT; } if (!serverUriStr.isEmpty()) { ConnectionSpecification specObj = new ConnectionSpecification(); specObj.setServerUri(serverUriStr) .setTrustStore(trustStore) .setKeyStore(keyStore) .setKeyStorePassword(keyStorePassword) .setTrustStorePassword(trustStorePassword) .setUserID(userID) .setPassword(password) .setKeepAliveInterval(keepAliveInterval) .setCommandTimeout(commandTimeout); connSpecMap.put(name, specObj); } } } } } } } private String getAttributeValue(NamedNodeMap attributes, String attrName) { Node attribute = attributes.getNamedItem(attrName); if (attribute != null) { return attribute.getNodeValue(); } return EMPTY_STRING; } public ConnectionSpecification getConnectionSpecification(String name) { if (name == null) { // return the first connection if (!connSpecMap.isEmpty()) { Set<String> keySet = connSpecMap.keySet(); Iterator<String> keyIterator = keySet.iterator(); if (keyIterator.hasNext()) { return connSpecMap.get(keyIterator.next()); } } } return connSpecMap.get(name); } }