Java tutorial
/* * Copyright (c) Mirth Corporation. All rights reserved. * * http://www.mirthcorp.com * * The software in this package is published under the terms of the MPL license a copy of which has * been included with this distribution in the LICENSE.txt file. */ package com.mirth.connect.model.util; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.commons.lang3.StringUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import com.mirth.connect.donkey.util.DonkeyElement; import com.mirth.connect.model.converters.DocumentSerializer; import com.mirth.connect.model.converters.ObjectXMLSerializer; import com.mirth.connect.util.CharsetUtils; import com.mirth.connect.util.MigrationUtil; public class ImportConverter { private static final String HL7V2 = "HL7V2"; private static final String XML = "XML"; private static Pattern matchVersion = Pattern.compile("<version>([\\.0-9]+?)<\\/version>"); private enum Direction { INBOUND, OUTBOUND } /** * Manually change the any old package XML to the new package * * @param xml * @return updated xml */ private static String convertPackageNames(String xml) { return xml.replaceAll("com.webreach.mirth", "com.mirth.connect"); } public static Document convertServerConfiguration(String serverConfiguration) throws Exception { serverConfiguration = convertPackageNames(serverConfiguration); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); Document document; DocumentBuilder builder; builder = factory.newDocumentBuilder(); document = builder.parse(new InputSource(new StringReader(serverConfiguration))); // Remove users from the server configuration file if they were there. Element documentElement = document.getDocumentElement(); NodeList users = documentElement.getElementsByTagName("users"); if (users != null && users.getLength() > 0) { documentElement.removeChild(users.item(0)); } Element channelsRoot = (Element) document.getElementsByTagName("channels").item(0); NodeList channels = getElements(document, "channel", "com.mirth.connect.model.Channel"); List<Element> channelList = new ArrayList<Element>(); int length = channels.getLength(); for (int i = 0; i < length; i++) { // Must get node 0 because the first channel is removed each // iteration Element channel = (Element) channels.item(0); TransformerFactory tf = TransformerFactory.newInstance(); Transformer trans = tf.newTransformer(); trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); StringWriter sw = new StringWriter(); trans.transform(new DOMSource(channel), new StreamResult(sw)); String channelDocXML = sw.toString(); channelList.add(new DonkeyElement(convertChannelString(channelDocXML)).getElement()); channelsRoot.removeChild(channel); } for (Element channel : channelList) { channelsRoot.appendChild(document.importNode(channel, true)); } NodeList codeTemplates = documentElement.getElementsByTagName("codeTemplates"); int codeTemplateCount = codeTemplates.getLength(); for (int i = 0; i < codeTemplateCount; i++) { Element codeTemplate = (Element) codeTemplates.item(i); Element convertedCodeTemplate = convertCodeTemplates(new DonkeyElement(codeTemplate).toXml()) .getDocumentElement(); documentElement.replaceChild(document.importNode(convertedCodeTemplate, true), codeTemplate); } return document; } public static Document convertCodeTemplates(String codeTemplatesXML) throws Exception { codeTemplatesXML = convertPackageNames(codeTemplatesXML); codeTemplatesXML = runStringConversions(codeTemplatesXML); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); Document document; DocumentBuilder builder; builder = factory.newDocumentBuilder(); document = builder.parse(new InputSource(new StringReader(codeTemplatesXML))); NodeList codeTemplates = getElements(document, "codeTemplate", "com.mirth.connect.model.CodeTemplate"); int length = codeTemplates.getLength(); for (int i = 0; i < length; i++) { Element codeTemplate = (Element) codeTemplates.item(i); codeTemplate.getOwnerDocument().renameNode(codeTemplate, codeTemplate.getNamespaceURI(), "codeTemplate"); NodeList versions = codeTemplate.getElementsByTagName("version"); // If there is no version, then this is a migration to 2.0 and the // scope should be incremented by 1 if its value is not currently 0 // (global map). Global Channel Map was added in position 1 for 2.0. if (versions.getLength() == 0) { Element scope = (Element) codeTemplate.getElementsByTagName("scope").item(0); int scopeValue = Integer.parseInt(scope.getTextContent()); if (scopeValue != 0) { scopeValue++; scope.setTextContent(Integer.toString(scopeValue)); } } } return document; } public static String convertChannelString(String channel) throws Exception { channel = convertPackageNames(channel); channel = runStringConversions(channel); String contents = removeInvalidHexChar(channel); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); Document document; DocumentBuilder builder; builder = factory.newDocumentBuilder(); document = builder.parse(new InputSource(new StringReader(contents))); return convertChannel(document); } /** * Run string conversions based on the version number. These conversions can * apply to anything that contains a version element. * * @param xmlData * @return updated xmlData */ private static String runStringConversions(String xmlData) { /* * Set the default version to 1.8.2 so that anything passed in without a * version will run all conversions. */ String versionData = getComponentVersion(xmlData, "1.8.2"); if (MigrationUtil.compareVersions(versionData, "2.0.0") < 0) { // Run any string replacements for 2.0.0 here. } return xmlData; } /** * Gets the value of the first version node in the xml being passed in. If * there isn't a version node, the defaultVersion passed in is returned. * * @param xmlData * @param defaultVersion * @return */ private static String getComponentVersion(String xmlData, String defaultVersion) { Matcher matcher = matchVersion.matcher(xmlData); // Anything passed in without a version will return the default. if (matcher.find()) { return matcher.group(1); } else { return defaultVersion; } } /* * Upgrade pre-1.4 channels to work with 1.4+ */ private static String convertChannel(Document document) throws Exception { String channelXML = ""; Element channelRoot = document.getDocumentElement(); String version = channelRoot.getElementsByTagName("version").item(0).getTextContent(); int majorVersion = Integer.parseInt(version.split("\\.")[0]); int minorVersion = Integer.parseInt(version.split("\\.")[1]); int patchVersion = Integer.parseInt(version.split("\\.")[2]); if (majorVersion < 2) { if (minorVersion < 4) { Direction direction = null; Element sourceConnectorRoot = (Element) document.getDocumentElement() .getElementsByTagName("sourceConnector").item(0); Element destinationConnectorRoot = (Element) document.getDocumentElement() .getElementsByTagName("destinationConnectors").item(0); NodeList destinationsConnectors = getElements(destinationConnectorRoot, "connector", "com.mirth.connect.model.Connector"); Node channelDirection = channelRoot.getElementsByTagName("direction").item(0); if (channelDirection.getTextContent().equals("INBOUND")) direction = Direction.INBOUND; else if (channelDirection.getTextContent().equals("OUTBOUND")) direction = Direction.OUTBOUND; channelRoot.removeChild(channelDirection); NodeList modeElements = channelRoot.getElementsByTagName("mode"); for (int i = 0; i < modeElements.getLength(); i++) { if (((Element) modeElements.item(i)).getParentNode() == channelRoot) { channelRoot.removeChild(modeElements.item(i)); } } channelRoot.removeChild(channelRoot.getElementsByTagName("protocol").item(0)); NodeList transportNames = channelRoot.getElementsByTagName("transportName"); for (int i = 0; i < transportNames.getLength(); i++) { if (transportNames.item(i).getTextContent().equals("PDF Writer")) { transportNames.item(i).setTextContent("Document Writer"); } } NodeList properyNames = channelRoot.getElementsByTagName("property"); for (int i = 0; i < properyNames.getLength(); i++) { Node nameAttribute = properyNames.item(i).getAttributes().getNamedItem("name"); if (properyNames.item(i).getAttributes().getLength() > 0 && nameAttribute != null) { if (nameAttribute.getNodeValue().equals("DataType")) { if (properyNames.item(i).getTextContent().equals("PDF Writer")) { properyNames.item(i).setTextContent("Document Writer"); } } } } Element modeElement = document.createElement("mode"); modeElement.setTextContent("SOURCE"); sourceConnectorRoot.appendChild(modeElement); updateFilterFor1_4((Element) sourceConnectorRoot.getElementsByTagName("filter").item(0)); if (direction == Direction.OUTBOUND) updateTransformerFor1_4(document, (Element) sourceConnectorRoot.getElementsByTagName("transformer").item(0), XML, XML); else updateTransformerFor1_4(document, (Element) sourceConnectorRoot.getElementsByTagName("transformer").item(0), HL7V2, HL7V2); for (int i = 0; i < destinationsConnectors.getLength(); i++) { modeElement = document.createElement("mode"); modeElement.setTextContent("DESTINATION"); Element destinationsConnector = (Element) destinationsConnectors.item(i); destinationsConnector.appendChild(modeElement); updateFilterFor1_4((Element) destinationsConnector.getElementsByTagName("filter").item(0)); if (direction == Direction.OUTBOUND) updateTransformerFor1_4(document, (Element) destinationsConnector.getElementsByTagName("transformer").item(0), XML, HL7V2); else updateTransformerFor1_4(document, (Element) destinationsConnector.getElementsByTagName("transformer").item(0), HL7V2, HL7V2); } } if (minorVersion < 5) { updateTransformerFor1_5(document); } if (minorVersion < 6) { // Go through each connector and set it to enabled if that // property doesn't exist. Element sourceConnectorRoot = (Element) document.getDocumentElement() .getElementsByTagName("sourceConnector").item(0); Element destinationConnectorRoot = (Element) document.getDocumentElement() .getElementsByTagName("destinationConnectors").item(0); NodeList destinationsConnectors = getElements(destinationConnectorRoot, "connector", "com.mirth.connect.model.Connector"); // Check SOURCE CONNECTOR node for "enabled" element which is // added by migration automatically. Add it if not found. if (!nodeChildrenContains(sourceConnectorRoot, "enabled")) { Element enabledSource = document.createElement("enabled"); enabledSource.setTextContent("true"); sourceConnectorRoot.appendChild(enabledSource); } else { // set it anyway, in case xstream auto set it to false. setBooleanNode(sourceConnectorRoot, "enabled", true); } // Check CONNECTOR node for "enabled" element which is added by // migration automatically. Add it if not found. for (int i = 0; i < destinationsConnectors.getLength(); i++) { Element destinationConnector = (Element) destinationsConnectors.item(i); if (!nodeChildrenContains(destinationConnector, "enabled")) { Element enabledDestination = document.createElement("enabled"); enabledDestination.setTextContent("true"); destinationConnector.appendChild(enabledDestination); } else { // set it anyway, in case xstream auto set it to false. setBooleanNode(destinationConnector, "enabled", true); } } if (!nodeChildrenContains(channelRoot, "deployScript")) { Element deployScript = document.createElement("deployScript"); deployScript.setTextContent( "// This script executes once when the channel is deployed\n// You only have access to the globalMap and globalChannelMap here to persist data\nreturn;"); channelRoot.appendChild(deployScript); } if (!nodeChildrenContains(channelRoot, "shutdownScript")) { Element shutdownScript = document.createElement("shutdownScript"); shutdownScript.setTextContent( "// This script executes once when the channel is undeployed\n// You only have access to the globalMap and globalChannelMap here to persist data\nreturn;"); channelRoot.appendChild(shutdownScript); } if (!nodeChildrenContains(channelRoot, "postprocessingScript")) { Element postprocessorScript = document.createElement("postprocessingScript"); postprocessorScript.setTextContent( "// This script executes once after a message has been processed\nreturn;"); channelRoot.appendChild(postprocessorScript); } } if (minorVersion < 7) { if (!nodeChildrenContains(channelRoot, "lastModified")) { Element lastModified = document.createElement("lastModified"); Element time = document.createElement("time"); Element timezone = document.createElement("timezone"); Calendar calendar = Calendar.getInstance(); time.setTextContent(calendar.getTimeInMillis() + ""); timezone.setTextContent(calendar.getTimeZone().getDisplayName()); lastModified.appendChild(time); lastModified.appendChild(timezone); channelRoot.appendChild(lastModified); } updateFilterFor1_7(document); updateTransformerFor1_7(document); } if (minorVersion < 8) { // Run for all versions prior to 1.7.1 if (minorVersion < 7 || (minorVersion == 7 && patchVersion < 1)) { updateTransformerFor1_7_1(document); } convertChannelConnectorsFor1_8(document, channelRoot); } // Run for all versions prior to 1.8.2 if (minorVersion < 8 || (minorVersion == 8 && patchVersion < 1)) { updateTransformerFor1_8_1(document); } // Run for all versions prior to 2.0 // MIRTH-1402 - Fix old channels from oracle that did not have // description because they were blank if (channelRoot.getElementsByTagName("description").getLength() == 0) { Element descriptionElement = document.createElement("description"); channelRoot.appendChild(descriptionElement); } convertChannelConnectorsFor2_0(document, channelRoot); updateFilterFor2_0(document); } // Run for all versions prior to 3.x if (majorVersion < 3) { // Run for all versions prior to 2.2 if (minorVersion < 2) { convertChannelConnectorsFor2_2(document, channelRoot); } } DocumentSerializer docSerializer = new DocumentSerializer(); channelXML = docSerializer.toXML(document); return updateLocalAndGlobalVariables(channelXML); } /** * Convert the source and destination connectors for the channel from * pre-1.8 to 1.8 */ private static void convertChannelConnectorsFor1_8(Document document, Element channelRoot) throws Exception { Element sourceConnectorRoot = (Element) channelRoot.getElementsByTagName("sourceConnector").item(0); Element destinationConnectorRoot = (Element) channelRoot.getElementsByTagName("destinationConnectors") .item(0); NodeList destinationsConnectors = getElements(destinationConnectorRoot, "connector", "com.mirth.connect.model.Connector"); // Convert the source connector convertOneConnectorFor1_8(document, sourceConnectorRoot); // Convert all destination connectors for (int i = 0; i < destinationsConnectors.getLength(); i++) { Element destinationConnector = (Element) destinationsConnectors.item(i); convertOneConnectorFor1_8(document, destinationConnector); } } /** * Update the child property elements of a properties element * * @param document * The document to use to generate new Elements. * @param properties * The properties element to be modified. * @param defaultProperties * Properties to be added only if they are missing. * @param changeProperties * Properties to be added if missing, or changed if already * present. */ private static void updateProperties(Document document, Element properties, Map<String, String> defaultProperties, Map<String, String> changeProperties) throws Exception { // Make a working copy of the properies so we can remove existing // properties Map<String, String> missingProperties = new HashMap<String, String>(); missingProperties.putAll(defaultProperties); missingProperties.putAll(changeProperties); // Removes all existing properties from the working copy, and changes // the value of any // change properties NodeList existingProperties = properties.getElementsByTagName("property"); for (int i = 0; i < existingProperties.getLength(); i++) { Node existingProperty = existingProperties.item(i); Node existingPropertyNameAttribute = existingProperty.getAttributes().getNamedItem("name"); String existingPropertyName = existingPropertyNameAttribute.getNodeValue(); if (missingProperties.containsKey(existingPropertyName)) { if (changeProperties.containsKey(existingPropertyName)) { existingProperty.setTextContent(changeProperties.get(existingPropertyName)); } missingProperties.remove(existingPropertyName); } } // And any remaining default or change properties for (Map.Entry<String, String> thisEntry : missingProperties.entrySet()) { Element newProperty = document.createElement("property"); newProperty.setAttribute("name", thisEntry.getKey()); newProperty.setTextContent(thisEntry.getValue()); properties.appendChild(newProperty); } } /** Get the child transport node of a connector */ private static Node getConnectorTransportNode(Element connectorRoot) throws Exception { // There will be exactly one. NodeList transportNames = connectorRoot.getElementsByTagName("transportName"); return transportNames.item(0); } /** Get the child properties element of a connector */ private static Element getPropertiesElement(Element connectorRoot) throws Exception { NodeList propertiesElements = connectorRoot.getElementsByTagName("properties"); return (Element) propertiesElements.item(0); } /** Convert a single source or destination connector from pre-1.8 to 1.8 */ private static void convertOneConnectorFor1_8(Document document, Element connectorRoot) throws Exception { Node transportNode = getConnectorTransportNode(connectorRoot); String transportNameText = transportNode.getTextContent(); Element propertiesElement = getPropertiesElement(connectorRoot); // Properties to be added if they're missing. Map<String, String> propertyDefaults = new HashMap<String, String>(); propertyDefaults.put("charsetEncoding", "DEFAULT_ENCODING"); propertyDefaults.put("FTPAnonymous", "1"); propertyDefaults.put("outputAppend", "0"); propertyDefaults.put("passive", "1"); propertyDefaults.put("password", "anonymous"); propertyDefaults.put("username", "anonymous"); propertyDefaults.put("validateConnections", "1"); // Properties to be added if missing, or reset if present Map<String, String> propertyChanges = new HashMap<String, String>(); if (transportNameText.equals("File Reader")) { propertyDefaults.put("scheme", "file"); updateProperties(document, propertiesElement, propertyDefaults, propertyChanges); } else if (transportNameText.equals("File Writer")) { propertyDefaults.put("scheme", "file"); updateProperties(document, propertiesElement, propertyDefaults, propertyChanges); } else if (transportNameText.equals("FTP Reader")) { transportNode.setTextContent("File Reader"); propertyDefaults.put("scheme", "ftp"); propertyChanges.put("DataType", "File Reader"); updateProperties(document, propertiesElement, propertyDefaults, propertyChanges); } else if (transportNameText.equals("FTP Writer")) { transportNode.setTextContent("File Writer"); propertyDefaults.put("scheme", "ftp"); propertyChanges.put("DataType", "File Writer"); updateProperties(document, propertiesElement, propertyDefaults, propertyChanges); } else if (transportNameText.equals("SFTP Reader")) { transportNode.setTextContent("File Reader"); propertyDefaults.put("scheme", "sftp"); propertyDefaults.put("FTPAnonymous", "0"); propertyChanges.put("DataType", "File Reader"); updateProperties(document, propertiesElement, propertyDefaults, propertyChanges); } else if (transportNameText.equals("SFTP Writer")) { transportNode.setTextContent("File Writer"); propertyDefaults.put("scheme", "sftp"); propertyDefaults.put("FTPAnonymous", "0"); propertyChanges.put("DataType", "File Writer"); updateProperties(document, propertiesElement, propertyDefaults, propertyChanges); } } private static void convertChannelConnectorsFor2_0(Document document, Element channelRoot) throws Exception { Element sourceConnectorRoot = (Element) channelRoot.getElementsByTagName("sourceConnector").item(0); Element destinationConnectorRoot = (Element) channelRoot.getElementsByTagName("destinationConnectors") .item(0); NodeList destinationsConnectors = getElements(destinationConnectorRoot, "connector", "com.mirth.connect.model.Connector"); // Convert the source connector convertSoapConnectorFor2_0(document, sourceConnectorRoot); convertHttpConnectorFor2_0(document, sourceConnectorRoot); // Convert all destination connectors for (int i = 0; i < destinationsConnectors.getLength(); i++) { Element destinationConnector = (Element) destinationsConnectors.item(i); convertSoapConnectorFor2_0(document, destinationConnector); convertHttpConnectorFor2_0(document, destinationConnector); } } /** Convert soap connector and destination settings */ private static void convertSoapConnectorFor2_0(Document document, Element connectorRoot) throws Exception { // convert SOAP reader and SOAP writer to the new formats Node transportNode = getConnectorTransportNode(connectorRoot); String transportNameText = transportNode.getTextContent(); String attribute = ""; String value = ""; Element propertiesElement = getPropertiesElement(connectorRoot); // Default Properties Map<String, String> propertyDefaults = new HashMap<String, String>(); // Properties to be added if missing, or reset if present Map<String, String> propertyChanges = new HashMap<String, String>(); // logic to deal with SOAP listener settings if (transportNameText.equals("SOAP Listener")) { NodeList properties = connectorRoot.getElementsByTagName("property"); // set defaults propertyDefaults.put("DataType", "Web Service Listener"); propertyDefaults.put("host", "0.0.0.0"); propertyDefaults.put("port", "8081"); propertyDefaults.put("receiverClassName", "com.mirth.connect.connectors.ws.DefaultAcceptMessage"); propertyDefaults.put("receiverServiceName", "Mirth"); propertyDefaults.put("receiverResponseValue", "None"); ObjectXMLSerializer serializer = ObjectXMLSerializer.getInstance(); propertyDefaults.put("receiverUsernames", serializer.serialize(new ArrayList<String>())); propertyDefaults.put("receiverPasswords", serializer.serialize(new ArrayList<String>())); // rename properties for (int i = 0; i < properties.getLength(); i++) { // get the current attribute and current value attribute = properties.item(i).getAttributes().item(0).getTextContent(); value = properties.item(i).getTextContent(); // Now rename attributes if (attribute.equals("externalAddress")) { propertyChanges.put("host", value); } if (attribute.equals("responseValue")) { propertyChanges.put("receiverResponseValue", value); } if (attribute.equals("serviceName")) { propertyChanges.put("receiverServiceName", value); } } // set changes propertyChanges.put("DataType", "Web Service Listener"); // set new name of transport node transportNode.setTextContent("Web Service Listener"); // update properties updateProperties(document, propertiesElement, propertyDefaults, propertyChanges); } else if (transportNameText.equals("SOAP Sender")) { // get properties NodeList properties = connectorRoot.getElementsByTagName("property"); // disable connector document.getElementsByTagName("enabled").item(0).setTextContent("false"); // set defaults propertyDefaults.put("DataType", "Web Service Sender"); propertyDefaults.put("host", ""); propertyDefaults.put("dispatcherWsdlCacheId", ""); propertyDefaults.put("dispatcherWsdlUrl", ""); propertyDefaults.put("dispatcherService", ""); propertyDefaults.put("dispatcherPort", ""); propertyDefaults.put("dispatcherOperation", "Press Get Operations"); propertyDefaults.put("dispatcherUseAuthentication", "0"); propertyDefaults.put("dispatcherUsername", ""); propertyDefaults.put("dispatcherPassword", ""); propertyDefaults.put("dispatcherEnvelope", ""); propertyDefaults.put("dispatcherOneWay", "0"); propertyDefaults.put("dispatcherUseMtom", "0"); propertyDefaults.put("dispatcherReplyChannelId", "sink"); ObjectXMLSerializer serializer = ObjectXMLSerializer.getInstance(); ArrayList<String> defaultOperations = new ArrayList<String>(); defaultOperations.add("Press Get Operations"); propertyDefaults.put("dispatcherWsdlOperations", serializer.serialize(defaultOperations)); propertyDefaults.put("dispatcherAttachmentNames", serializer.serialize(new ArrayList<String>())); propertyDefaults.put("dispatcherAttachmentContents", serializer.serialize(new ArrayList<String>())); propertyDefaults.put("dispatcherAttachmentTypes", serializer.serialize(new ArrayList<String>())); // Add new queue property propertyDefaults.put("queuePollInterval", "200"); for (int i = 0; i < properties.getLength(); i++) { // get the current attribute and current value attribute = properties.item(i).getAttributes().item(0).getTextContent(); value = properties.item(i).getTextContent(); // Now rename attributes if (attribute.equals("attachmentNames")) { propertyChanges.put("dispatcherAttachmentNames", value); if (StringUtils.isNotBlank(value) && !value.trim().equals("<list/>")) { propertyChanges.put("dispatcherUseMtom", "1"); } } if (attribute.equals("wsdlUrl")) { propertyChanges.put("dispatcherWsdlUrl", value); } if (attribute.equals("soapActionURI")) { propertyChanges.put("dispatcherSoapAction", value); } if (attribute.equals("method")) { propertyChanges.put("dispatcherOperation", value); if (StringUtils.isNotBlank(value)) { defaultOperations.clear(); defaultOperations.add(value); propertyChanges.put("dispatcherWsdlOperations", serializer.serialize(defaultOperations)); } } if (attribute.equals("replyChannelId")) { propertyChanges.put("dispatcherReplyChannelId", value); } if (attribute.equals("attachmentContents")) { propertyChanges.put("dispatcherAttachmentContents", value); } if (attribute.equals("soapEnvelope")) { propertyChanges.put("dispatcherEnvelope", value); } if (attribute.equals("attachmentTypes")) { propertyChanges.put("dispatcherAttachmentTypes", value); } } propertyChanges.put("DataType", "Web Service Sender"); // set new name of transport node transportNode.setTextContent("Web Service Sender"); updateProperties(document, propertiesElement, propertyDefaults, propertyChanges); } } /** Convert http connector and destination settings */ private static void convertHttpConnectorFor2_0(Document document, Element connectorRoot) throws Exception { // convert HTTP Listener and HTTP writer to the new formats Node transportNode = getConnectorTransportNode(connectorRoot); String transportNameText = transportNode.getTextContent(); String attribute = ""; String value = ""; Element propertiesElement = getPropertiesElement(connectorRoot); // Default Properties Map<String, String> propertyDefaults = new HashMap<String, String>(); // Properties to be added if missing, or reset if present Map<String, String> propertyChanges = new HashMap<String, String>(); // logic to deal with HTTP listener settings if (transportNameText.equals("HTTP Listener") || transportNameText.equals("HTTPS Listener")) { NodeList properties = connectorRoot.getElementsByTagName("property"); // set defaults propertyDefaults.put("DataType", "HTTP Listener"); propertyDefaults.put("host", "0.0.0.0"); propertyDefaults.put("port", "80"); propertyDefaults.put("receiverResponse", "None"); propertyDefaults.put("receiverBodyOnly", "1"); propertyDefaults.put("HTTP_RESPONSE_CONTENT_TYPE", "text/plain"); // rename properties for (int i = 0; i < properties.getLength(); i++) { // get the current attribute and current value attribute = properties.item(i).getAttributes().item(0).getTextContent(); value = properties.item(i).getTextContent(); // Now rename attributes if (attribute.equals("responseValue")) { propertyChanges.put("receiverResponse", value); } if (attribute.equals("appendPayload")) { // The old property value needs to be flipped // If appendPayload was 1, set bodyOnly to 0 // If appendPayload was 0 or null, set bodyOnly to 1 propertyChanges.put("receiverBodyOnly", ("1".equals(value) ? "0" : "1")); } } // set changes propertyChanges.put("host", "0.0.0.0"); propertyChanges.put("DataType", "HTTP Listener"); // set new name of transport node transportNode.setTextContent("HTTP Listener"); // update properties updateProperties(document, propertiesElement, propertyDefaults, propertyChanges); } else if (transportNameText.equals("HTTP Sender") || transportNameText.equals("HTTPS Sender")) { // get properties NodeList properties = connectorRoot.getElementsByTagName("property"); // disable connector // document.getElementsByTagName("enabled").item(0).setTextContent("false"); // set defaults ObjectXMLSerializer serializer = ObjectXMLSerializer.getInstance(); propertyDefaults.put("DataType", "HTTP Sender"); propertyDefaults.put("host", ""); propertyDefaults.put("dispatcherMethod", "POST"); propertyDefaults.put("dispatcherHeaders", serializer.serialize(new Properties())); propertyDefaults.put("dispatcherParameters", serializer.serialize(new Properties())); propertyDefaults.put("dispatcherReplyChannelId", "sink"); propertyDefaults.put("dispatcherIncludeHeadersInResponse", "0"); propertyDefaults.put("dispatcherMultipart", "0"); propertyDefaults.put("dispatcherUseAuthentication", "0"); propertyDefaults.put("dispatcherAuthenticationType", "Basic"); propertyDefaults.put("dispatcherUsername", ""); propertyDefaults.put("dispatcherPassword", ""); propertyDefaults.put("dispatcherContent", ""); propertyDefaults.put("dispatcherContentType", "text/plain"); propertyDefaults.put("dispatcherCharset", "UTF-8"); propertyDefaults.put("dispatcherSocketTimeout", "30000"); // Add new queue property propertyDefaults.put("queuePollInterval", "200"); for (int i = 0; i < properties.getLength(); i++) { // get the current attribute and current value attribute = properties.item(i).getAttributes().item(0).getTextContent(); value = properties.item(i).getTextContent(); // Now rename attributes if (attribute.equals("method")) { propertyChanges.put("dispatcherMethod", value); } if (attribute.equals("requestVariables")) { // get the properties object for the variables Properties tempProps = serializer.deserialize(value, Properties.class); // set the content of 2.0 to be $payload of 1.8.2 propertyChanges.put("dispatcherContent", tempProps.getProperty("$payload", "")); // remove $payload as we dont need it tempProps.remove("$payload"); // set the params propertyChanges.put("dispatcherParameters", serializer.serialize(tempProps)); } if (attribute.equals("replyChannelId")) { propertyChanges.put("dispatcherReplyChannelId", value); } if (attribute.equals("headerVariables")) { propertyChanges.put("dispatcherHeaders", value); } if (attribute.equals("excludeHeaders")) { if (value.equals("0")) { propertyChanges.put("dispatcherIncludeHeadersInResponse", "1"); } else { propertyChanges.put("dispatcherIncludeHeadersInResponse", "0"); } } if (attribute.equals("multipart")) { propertyChanges.put("dispatcherMultipart", value); } } // If we have a post/put message and blank content, then disable String requestMethod = propertyChanges.get("dispatcherMethod") == null ? propertyDefaults.get("dispatcherMethod") : propertyChanges.get("dispatcherMethod"); String requestContent = propertyChanges.get("dispatcherContent") == null ? propertyDefaults.get("dispatcherContent") : propertyChanges.get("dispatcherContent"); if (requestContent.length() == 0 && (requestMethod.equalsIgnoreCase("POST") || requestMethod.equalsIgnoreCase("PUT"))) { document.getElementsByTagName("enabled").item(0).setTextContent("false"); } propertyChanges.put("DataType", "HTTP Sender"); // set new name of transport node transportNode.setTextContent("HTTP Sender"); updateProperties(document, propertiesElement, propertyDefaults, propertyChanges); } } private static void convertFileConnectorFor2_2(Document document, Element connectorRoot) throws Exception { Node transportNode = getConnectorTransportNode(connectorRoot); String transportNameText = transportNode.getTextContent(); Element propertiesElement = getPropertiesElement(connectorRoot); // Default Properties Map<String, String> propertyDefaults = new HashMap<String, String>(); // Properties to be added if missing, or reset if present Map<String, String> propertyChanges = new HashMap<String, String>(); if (transportNameText.equals("File Reader")) { // set defaults propertyDefaults.put("ignoreDot", "0"); // update properties updateProperties(document, propertiesElement, propertyDefaults, propertyChanges); } } private static void convertEmailConnectorFor2_2(Document document, Element connectorRoot) throws Exception { // convert Email Sender to the new SMTP Sender Node transportNode = getConnectorTransportNode(connectorRoot); String transportNameText = transportNode.getTextContent(); String attribute = ""; String value = ""; Element propertiesElement = getPropertiesElement(connectorRoot); // Default Properties Map<String, String> propertyDefaults = new HashMap<String, String>(); // Properties to be added if missing, or reset if present Map<String, String> propertyChanges = new HashMap<String, String>(); // logic to deal with SMTP Sender settings if (transportNameText.equals("Email Sender")) { // get properties NodeList properties = connectorRoot.getElementsByTagName("property"); // set defaults ObjectXMLSerializer serializer = ObjectXMLSerializer.getInstance(); propertyDefaults.put("DataType", "SMTP Sender"); propertyDefaults.put("smtpHost", ""); propertyDefaults.put("smtpPort", "25"); propertyDefaults.put("timeout", "5000"); propertyDefaults.put("encryption", "none"); propertyDefaults.put("authentication", "0"); propertyDefaults.put("username", ""); propertyDefaults.put("password", ""); propertyDefaults.put("to", ""); propertyDefaults.put("from", ""); propertyDefaults.put("headers", serializer.serialize(new LinkedHashMap<String, String>())); propertyDefaults.put("subject", ""); propertyDefaults.put("charsetEncoding", CharsetUtils.DEFAULT_ENCODING); propertyDefaults.put("html", "0"); propertyDefaults.put("body", ""); propertyDefaults.put("attachments", "<list/>"); List<String> attachmentNames = null; List<String> attachmentContents = null; List<String> attachmentTypes = null; for (int i = 0; i < properties.getLength(); i++) { // get the current attribute and current value attribute = properties.item(i).getAttributes().item(0).getTextContent(); value = properties.item(i).getTextContent(); // Now rename attributes if (attribute.equals("hostname")) { propertyChanges.put("smtpHost", value); } else if (attribute.equals("emailSecure")) { propertyChanges.put("encryption", value); } else if (attribute.equals("useAuthentication")) { propertyChanges.put("authentication", value); } else if (attribute.equals("toAddresses")) { propertyChanges.put("to", value); } else if (attribute.equals("fromAddress")) { propertyChanges.put("from", value); } else if (attribute.equals("contentType")) { if (value.equalsIgnoreCase("text/plain")) { propertyChanges.put("html", "0"); } else { propertyChanges.put("html", "1"); } } else if (attribute.equals("attachmentNames")) { attachmentNames = serializer.deserializeList(value, String.class); } else if (attribute.equals("attachmentContents")) { attachmentContents = serializer.deserializeList(value, String.class); } else if (attribute.equals("attachmentTypes")) { attachmentTypes = serializer.deserializeList(value, String.class); } else if (attribute.equals("useServerSettings")) { // Disable the channel or connector if useServerSettings was set if (value.equalsIgnoreCase("1")) { document.getElementsByTagName("enabled").item(0).setTextContent("false"); } } } DonkeyElement attachmentList = new DonkeyElement("<list/>"); if (attachmentNames != null) { for (int i = 0; i < attachmentNames.size(); i++) { DonkeyElement attachment = attachmentList .addChildElement("com.mirth.connect.connectors.smtp.Attachment"); attachment.addChildElement("name", attachmentNames.get(i)); attachment.addChildElement("content", attachmentContents.get(i)); attachment.addChildElement("mimeType", attachmentTypes.get(i)); } } propertyChanges.put("attachments", attachmentList.toXml()); propertyChanges.put("DataType", "SMTP Sender"); // set new name of transport node transportNode.setTextContent("SMTP Sender"); updateProperties(document, propertiesElement, propertyDefaults, propertyChanges); } } private static void convertChannelConnectorsFor2_2(Document document, Element channelRoot) throws Exception { Element sourceConnectorRoot = (Element) channelRoot.getElementsByTagName("sourceConnector").item(0); Element destinationConnectorRoot = (Element) channelRoot.getElementsByTagName("destinationConnectors") .item(0); NodeList destinationsConnectors = getElements(destinationConnectorRoot, "connector", "com.mirth.connect.model.Connector"); // Convert the source connector convertFileConnectorFor2_2(document, sourceConnectorRoot); // Convert all destination connectors for (int i = 0; i < destinationsConnectors.getLength(); i++) { Element destinationConnector = (Element) destinationsConnectors.item(i); convertEmailConnectorFor2_2(document, destinationConnector); } } public static String convertFilter(String filterXml) throws Exception { filterXml = convertPackageNames(filterXml); filterXml = runStringConversions(filterXml); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); Document document; DocumentBuilder builder; try { builder = factory.newDocumentBuilder(); document = builder.parse(new InputSource(new StringReader(filterXml))); updateFilterFor1_4(document.getDocumentElement()); updateFilterFor1_7(document); updateFilterFor2_0(document); DocumentSerializer docSerializer = new DocumentSerializer(); filterXml = docSerializer.toXML(document); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return updateLocalAndGlobalVariables(filterXml); } /** * Convert a connector. Added in 1.8 and shouldn't be called on pre-1.8 * connectors. * * @param connector * @return * @throws Exception */ public static String convertConnector(String connectorXml) throws Exception { connectorXml = convertPackageNames(connectorXml); connectorXml = runStringConversions(connectorXml); connectorXml = removeInvalidHexChar(connectorXml); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); Document document; DocumentBuilder builder; builder = factory.newDocumentBuilder(); document = builder.parse(new InputSource(new StringReader(connectorXml))); Element connectorRoot = document.getDocumentElement(); Node transportNode = getConnectorTransportNode(connectorRoot); String transportNameText = transportNode.getTextContent(); // SOAP connectors only existed before 2.0, so convert it for 2.0 if (transportNameText.equals("SOAP Sender") || transportNameText.equals("SOAP Listener")) { convertSoapConnectorFor2_0(document, connectorRoot); } // Convert HTTP and HTTPS connectors if (transportNameText.equals("HTTP Sender") || transportNameText.equals("HTTP Listener") || transportNameText.equals("HTTPS Sender") || transportNameText.equals("HTTPS Listener")) { /* * Set the default version to 1.8.2 so that anything passed in * without a version will run all conversions. */ String versionData = getComponentVersion(connectorXml, "1.8.2"); if (MigrationUtil.compareVersions(versionData, "2.0.0") < 0) { convertHttpConnectorFor2_0(document, connectorRoot); } } // Conversions for 2.2.0 String versionData = getComponentVersion(connectorXml, "2.1.1"); if (MigrationUtil.compareVersions(versionData, "2.2.0") < 0) { convertFileConnectorFor2_2(document, connectorRoot); convertEmailConnectorFor2_2(document, connectorRoot); } DocumentSerializer docSerializer = new DocumentSerializer(); connectorXml = docSerializer.toXML(document); return connectorXml; } public static String convertTransformer(String transformerXml, String incoming, String outgoing) throws Exception { transformerXml = convertPackageNames(transformerXml); transformerXml = runStringConversions(transformerXml); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); Document document; DocumentBuilder builder; builder = factory.newDocumentBuilder(); document = builder.parse(new InputSource(new StringReader(transformerXml))); Element transformerRoot = document.getDocumentElement(); updateTransformerFor1_4(document, transformerRoot, incoming, outgoing); updateTransformerFor1_5(document); updateTransformerFor1_7(document); updateTransformerFor1_7_1(document); DocumentSerializer docSerializer = new DocumentSerializer(); transformerXml = docSerializer.toXML(document); return updateLocalAndGlobalVariables(transformerXml); } private static void updateFilterFor1_4(Element filterElement) { Element filterTemplate = null; if (filterElement.getElementsByTagName("template").getLength() > 0) { filterTemplate = (Element) filterElement.getElementsByTagName("template").item(0); if (filterTemplate != null) filterElement.removeChild(filterElement.getElementsByTagName("template").item(0)); } } /* * Upgrade pre-1.4 channels' transformers and filters to work with 1.4+ */ private static void updateTransformerFor1_4(Document document, Element transformerRoot, String incoming, String outgoing) { String template = ""; Element transformerTemplate = null; if (transformerRoot.getElementsByTagName("template").getLength() > 0) { transformerTemplate = (Element) transformerRoot.getElementsByTagName("template").item(0); if (transformerTemplate != null) template = transformerTemplate.getTextContent(); } Element inboundTemplateElement = null, outboundTemplateElement = null, inboundProtocolElement = null, outboundProtocolElement = null; if (transformerRoot.getElementsByTagName("inboundTemplate").getLength() == 0) inboundTemplateElement = document.createElement("inboundTemplate"); if (transformerRoot.getElementsByTagName("outboundTemplate").getLength() == 0) outboundTemplateElement = document.createElement("outboundTemplate"); if (transformerRoot.getElementsByTagName("inboundProtocol").getLength() == 0) { inboundProtocolElement = document.createElement("inboundProtocol"); inboundProtocolElement.setTextContent(incoming.toString()); } if (transformerRoot.getElementsByTagName("outboundProtocol").getLength() == 0) { outboundProtocolElement = document.createElement("outboundProtocol"); outboundProtocolElement.setTextContent(outgoing.toString()); } if (transformerTemplate != null) { if (incoming.equals(HL7V2) && outgoing.equals(HL7V2)) { inboundTemplateElement.setTextContent(template); } else if (outgoing.equals(HL7V2)) { outboundTemplateElement.setTextContent(template); } } if (transformerRoot.getElementsByTagName("inboundTemplate").getLength() == 0) transformerRoot.appendChild(inboundTemplateElement); if (transformerRoot.getElementsByTagName("outboundTemplate").getLength() == 0) transformerRoot.appendChild(outboundTemplateElement); if (transformerRoot.getElementsByTagName("inboundProtocol").getLength() == 0) transformerRoot.appendChild(inboundProtocolElement); if (transformerRoot.getElementsByTagName("outboundProtocol").getLength() == 0) transformerRoot.appendChild(outboundProtocolElement); // replace HL7 Message builder with Message Builder NodeList steps = getElements(transformerRoot, "step", "com.mirth.connect.model.Step"); for (int i = 0; i < steps.getLength(); i++) { Element step = (Element) steps.item(i); NodeList stepTypesList = step.getElementsByTagName("type"); if (stepTypesList.getLength() > 0) { Element stepType = (Element) stepTypesList.item(0); if (stepType.getTextContent().equals("HL7 Message Builder")) { stepType.setTextContent("Message Builder"); } if (stepType.getTextContent().equals("Message Builder") || stepType.getTextContent().equals("Mapper")) { boolean foundRegex = false, foundDefaultValue = false; Element data = (Element) step.getElementsByTagName("data").item(0); NodeList entries = data.getElementsByTagName("entry"); for (int j = 0; j < entries.getLength(); j++) { NodeList strings = ((Element) entries.item(j)).getElementsByTagName("string"); if (strings.getLength() > 0) { if (strings.item(0).getTextContent().equals("RegularExpressions")) foundRegex = true; else if (strings.item(0).getTextContent().equals("DefaultValue")) foundDefaultValue = true; if (strings.item(0).getTextContent().equals("isGlobal")) { if (strings.item(1).getTextContent().equals("0")) strings.item(1).setTextContent("channel"); else if (strings.item(1).getTextContent().equals("1")) strings.item(1).setTextContent("global"); } } } if (!foundRegex) data.appendChild(createRegexElement(document)); if (!foundDefaultValue) data.appendChild(createDefaultValueElement(document)); } } } if (transformerTemplate != null) transformerRoot.removeChild(transformerTemplate); } private static void updateTransformerFor1_5(Document document) { Element inboundPropertiesElement, outboundPropertiesElement; NodeList transformers = document.getElementsByTagName("transformer"); for (int i = 0; i < transformers.getLength(); i++) { Element transformerRoot = (Element) transformers.item(i); if (transformerRoot.getElementsByTagName("inboundProtocol").item(0).getTextContent().equals("HL7V2") && transformerRoot.getElementsByTagName("inboundProperties").getLength() == 0) { inboundPropertiesElement = document.createElement("inboundProperties"); Element handleRepetitionsProperty = document.createElement("property"); handleRepetitionsProperty.setAttribute("name", "handleRepetitions"); handleRepetitionsProperty.setTextContent("false"); Element useStrictValidationProperty = document.createElement("property"); useStrictValidationProperty.setAttribute("name", "useStrictValidation"); useStrictValidationProperty.setTextContent("false"); Element useStrictParserProperty = document.createElement("property"); useStrictParserProperty.setAttribute("name", "useStrictParser"); useStrictParserProperty.setTextContent("false"); inboundPropertiesElement.appendChild(handleRepetitionsProperty); inboundPropertiesElement.appendChild(useStrictValidationProperty); inboundPropertiesElement.appendChild(useStrictParserProperty); transformerRoot.appendChild(inboundPropertiesElement); } if (transformerRoot.getElementsByTagName("outboundProtocol").item(0).getTextContent().equals("HL7V2") && transformerRoot.getElementsByTagName("outboundProperties").getLength() == 0) { outboundPropertiesElement = document.createElement("outboundProperties"); Element handleRepetitionsProperty = document.createElement("property"); handleRepetitionsProperty.setAttribute("name", "handleRepetitions"); handleRepetitionsProperty.setTextContent("false"); Element useStrictValidationProperty = document.createElement("property"); useStrictValidationProperty.setAttribute("name", "useStrictValidation"); useStrictValidationProperty.setTextContent("false"); Element useStrictParserProperty = document.createElement("property"); useStrictParserProperty.setAttribute("name", "useStrictParser"); useStrictParserProperty.setTextContent("false"); outboundPropertiesElement.appendChild(handleRepetitionsProperty); outboundPropertiesElement.appendChild(useStrictValidationProperty); outboundPropertiesElement.appendChild(useStrictParserProperty); transformerRoot.appendChild(outboundPropertiesElement); } } } private static void updateFilterFor1_7(Document document) { // add data element to Rules NodeList rules = getElements(document, "rule", "com.mirth.connect.model.Rule"); for (int i = 0; i < rules.getLength(); i++) { Element rule = (Element) rules.item(i); if (rule.getElementsByTagName("type").getLength() == 0) { Element typeElement = document.createElement("type"); typeElement.setTextContent("JavaScript"); rule.appendChild(typeElement); } if (rule.getElementsByTagName("data").getLength() == 0) { Element dataElement = document.createElement("data"); dataElement.setAttribute("class", "map"); Element entryElement = document.createElement("entry"); Element keyElement = document.createElement("string"); Element valueElement = document.createElement("string"); keyElement.setTextContent("Script"); valueElement.setTextContent(rule.getElementsByTagName("script").item(0).getTextContent()); entryElement.appendChild(keyElement); entryElement.appendChild(valueElement); dataElement.appendChild(entryElement); rule.appendChild(dataElement); } } } private static void updateTransformerFor1_7(Document document) { Element inboundPropertiesElement, outboundPropertiesElement; NodeList transformers = document.getElementsByTagName("transformer"); for (int i = 0; i < transformers.getLength(); i++) { Element transformerRoot = (Element) transformers.item(i); // Update the inbound protocol properties. if (transformerRoot.getElementsByTagName("inboundProtocol").item(0).getTextContent().equals("HL7V2")) { if (transformerRoot.getElementsByTagName("inboundProperties").getLength() != 0) { inboundPropertiesElement = (Element) transformerRoot.getElementsByTagName("inboundProperties") .item(0); // Find out if encodeEntities already exists. If it was 1.5 // it won't. boolean hasEncodeEntities = false; NodeList propertyNames = inboundPropertiesElement.getElementsByTagName("property"); for (int j = 0; j < propertyNames.getLength(); j++) { Node nameAttribute = propertyNames.item(j).getAttributes().getNamedItem("name"); if (propertyNames.item(j).getAttributes().getLength() > 0 && nameAttribute != null) { if (nameAttribute.getNodeValue().equals("encodeEntities")) { hasEncodeEntities = true; } } } // Add encodeEntities if it doesn't exist. if (!hasEncodeEntities) { Element encodeEntities = document.createElement("property"); encodeEntities.setAttribute("name", "encodeEntities"); encodeEntities.setTextContent("true"); inboundPropertiesElement.appendChild(encodeEntities); } Element convertLFtoCRProperty = document.createElement("property"); convertLFtoCRProperty.setAttribute("name", "convertLFtoCR"); convertLFtoCRProperty.setTextContent("true"); inboundPropertiesElement.appendChild(convertLFtoCRProperty); } else { inboundPropertiesElement = document.createElement("inboundProperties"); Element convertLFtoCRProperty = document.createElement("property"); convertLFtoCRProperty.setAttribute("name", "convertLFtoCR"); convertLFtoCRProperty.setTextContent("true"); Element encodeEntitiesProperty = document.createElement("property"); encodeEntitiesProperty.setAttribute("name", "encodeEntities"); encodeEntitiesProperty.setTextContent("true"); Element handleRepetitionsProperty = document.createElement("property"); handleRepetitionsProperty.setAttribute("name", "handleRepetitions"); handleRepetitionsProperty.setTextContent("false"); Element useStrictValidationProperty = document.createElement("property"); useStrictValidationProperty.setAttribute("name", "useStrictValidation"); useStrictValidationProperty.setTextContent("false"); Element useStrictParserProperty = document.createElement("property"); useStrictParserProperty.setAttribute("name", "useStrictParser"); useStrictParserProperty.setTextContent("false"); inboundPropertiesElement.appendChild(convertLFtoCRProperty); inboundPropertiesElement.appendChild(encodeEntitiesProperty); inboundPropertiesElement.appendChild(handleRepetitionsProperty); inboundPropertiesElement.appendChild(useStrictValidationProperty); inboundPropertiesElement.appendChild(useStrictParserProperty); transformerRoot.appendChild(inboundPropertiesElement); } } // Update the outbound protocol properties. if (transformerRoot.getElementsByTagName("outboundProtocol").item(0).getTextContent().equals("HL7V2")) { if (transformerRoot.getElementsByTagName("outboundProperties").getLength() != 0) { outboundPropertiesElement = (Element) transformerRoot.getElementsByTagName("outboundProperties") .item(0); // Find out if encodeEntities already exists. If it was 1.5 // it won't. boolean hasEncodeEntities = false; NodeList propertyNames = outboundPropertiesElement.getElementsByTagName("property"); for (int j = 0; j < propertyNames.getLength(); j++) { Node nameAttribute = propertyNames.item(j).getAttributes().getNamedItem("name"); if (propertyNames.item(j).getAttributes().getLength() > 0 && nameAttribute != null) { if (nameAttribute.getNodeValue().equals("encodeEntities")) { hasEncodeEntities = true; } } } // Add encodeEntities if it doesn't exist. if (!hasEncodeEntities) { Element encodeEntities = document.createElement("property"); encodeEntities.setAttribute("name", "encodeEntities"); encodeEntities.setTextContent("true"); outboundPropertiesElement.appendChild(encodeEntities); } Element convertLFtoCRProperty = document.createElement("property"); convertLFtoCRProperty.setAttribute("name", "convertLFtoCR"); convertLFtoCRProperty.setTextContent("true"); outboundPropertiesElement.appendChild(convertLFtoCRProperty); } else { outboundPropertiesElement = document.createElement("outboundProperties"); Element convertLFtoCRProperty = document.createElement("property"); convertLFtoCRProperty.setAttribute("name", "convertLFtoCR"); convertLFtoCRProperty.setTextContent("true"); Element encodeEntitiesProperty = document.createElement("property"); encodeEntitiesProperty.setAttribute("name", "encodeEntities"); encodeEntitiesProperty.setTextContent("true"); Element handleRepetitionsProperty = document.createElement("property"); handleRepetitionsProperty.setAttribute("name", "handleRepetitions"); handleRepetitionsProperty.setTextContent("false"); Element useStrictValidationProperty = document.createElement("property"); useStrictValidationProperty.setAttribute("name", "useStrictValidation"); useStrictValidationProperty.setTextContent("false"); Element useStrictParserProperty = document.createElement("property"); useStrictParserProperty.setAttribute("name", "useStrictParser"); useStrictParserProperty.setTextContent("false"); outboundPropertiesElement.appendChild(convertLFtoCRProperty); outboundPropertiesElement.appendChild(encodeEntitiesProperty); outboundPropertiesElement.appendChild(handleRepetitionsProperty); outboundPropertiesElement.appendChild(useStrictValidationProperty); outboundPropertiesElement.appendChild(useStrictParserProperty); transformerRoot.appendChild(outboundPropertiesElement); } } } } private static void updateTransformerFor1_7_1(Document document) { Element inboundPropertiesElement, outboundPropertiesElement; NodeList transformers = document.getElementsByTagName("transformer"); for (int i = 0; i < transformers.getLength(); i++) { Element transformerRoot = (Element) transformers.item(i); // Update the inbound protocol properties. if (transformerRoot.getElementsByTagName("inboundProtocol").item(0).getTextContent().equals("HL7V2") || transformerRoot.getElementsByTagName("inboundProtocol").item(0).getTextContent() .equals("EDI")) { if (transformerRoot.getElementsByTagName("inboundProperties").getLength() != 0) { inboundPropertiesElement = (Element) transformerRoot.getElementsByTagName("inboundProperties") .item(0); // Remove encode entities if it exists. NodeList propertyNames = inboundPropertiesElement.getElementsByTagName("property"); for (int j = 0; j < propertyNames.getLength(); j++) { Node nameAttribute = propertyNames.item(j).getAttributes().getNamedItem("name"); if (propertyNames.item(j).getAttributes().getLength() > 0 && nameAttribute != null) { if (nameAttribute.getNodeValue().equals("encodeEntities")) { inboundPropertiesElement.removeChild(propertyNames.item(j)); } } } // Override convertLFtoCR and set it to "true". propertyNames = inboundPropertiesElement.getElementsByTagName("property"); for (int j = 0; j < propertyNames.getLength(); j++) { Node nameAttribute = propertyNames.item(j).getAttributes().getNamedItem("name"); if (propertyNames.item(j).getAttributes().getLength() > 0 && nameAttribute != null) { if (nameAttribute.getNodeValue().equals("convertLFtoCR")) { propertyNames.item(j).setTextContent("true"); } } } } } // Update the outbound protocol properties. if (transformerRoot.getElementsByTagName("outboundProtocol").item(0).getTextContent().equals("HL7V2") || transformerRoot.getElementsByTagName("outboundProtocol").item(0).getTextContent() .equals("EDI")) { if (transformerRoot.getElementsByTagName("outboundProperties").getLength() != 0) { outboundPropertiesElement = (Element) transformerRoot.getElementsByTagName("outboundProperties") .item(0); // Remove encode entities if it exists. NodeList propertyNames = outboundPropertiesElement.getElementsByTagName("property"); for (int j = 0; j < propertyNames.getLength(); j++) { Node nameAttribute = propertyNames.item(j).getAttributes().getNamedItem("name"); if (propertyNames.item(j).getAttributes().getLength() > 0 && nameAttribute != null) { if (nameAttribute.getNodeValue().equals("encodeEntities")) { outboundPropertiesElement.removeChild(propertyNames.item(j)); } } } // Override convertLFtoCR and set it to "true". propertyNames = outboundPropertiesElement.getElementsByTagName("property"); for (int j = 0; j < propertyNames.getLength(); j++) { Node nameAttribute = propertyNames.item(j).getAttributes().getNamedItem("name"); if (propertyNames.item(j).getAttributes().getLength() > 0 && nameAttribute != null) { if (nameAttribute.getNodeValue().equals("convertLFtoCR")) { propertyNames.item(j).setTextContent("true"); } } } } } } } private static void updateTransformerFor1_8_1(Document document) { Element inboundPropertiesElement, outboundPropertiesElement; NodeList transformers = document.getElementsByTagName("transformer"); for (int i = 0; i < transformers.getLength(); i++) { Element transformerRoot = (Element) transformers.item(i); // Update the inbound protocol properties. if (transformerRoot.getElementsByTagName("inboundProtocol").item(0).getTextContent().equals("XML") || transformerRoot.getElementsByTagName("inboundProtocol").item(0).getTextContent() .equals("HL7V2") || transformerRoot.getElementsByTagName("inboundProtocol").item(0).getTextContent() .equals("HL7V3")) { if (transformerRoot.getElementsByTagName("inboundProperties").getLength() == 0) { inboundPropertiesElement = document.createElement("inboundProperties"); transformerRoot.appendChild(inboundPropertiesElement); } inboundPropertiesElement = (Element) transformerRoot.getElementsByTagName("inboundProperties") .item(0); Element stripNamespacesProperty = document.createElement("property"); stripNamespacesProperty.setAttribute("name", "stripNamespaces"); stripNamespacesProperty.setTextContent("true"); // Override stripNamespaces on inbound if the old // removeNamespace was set to false NodeList propertyNames = document.getElementsByTagName("property"); for (int j = 0; j < propertyNames.getLength(); j++) { Node nameAttribute = propertyNames.item(j).getAttributes().getNamedItem("name"); if (propertyNames.item(j).getAttributes().getLength() > 0 && nameAttribute != null) { if (nameAttribute.getNodeValue().equals("removeNamespace")) { stripNamespacesProperty.setTextContent(propertyNames.item(j).getTextContent()); } } } inboundPropertiesElement.appendChild(stripNamespacesProperty); } // Update the outbound protocol properties. if (transformerRoot.getElementsByTagName("outboundProtocol").item(0).getTextContent().equals("XML") || transformerRoot.getElementsByTagName("outboundProtocol").item(0).getTextContent() .equals("HL7V2") || transformerRoot.getElementsByTagName("outboundProtocol").item(0).getTextContent() .equals("HL7V3")) { if (transformerRoot.getElementsByTagName("outboundProperties").getLength() == 0) { outboundPropertiesElement = document.createElement("outboundProperties"); transformerRoot.appendChild(outboundPropertiesElement); } outboundPropertiesElement = (Element) transformerRoot.getElementsByTagName("outboundProperties") .item(0); Element stripNamespacesProperty = document.createElement("property"); stripNamespacesProperty.setAttribute("name", "stripNamespaces"); stripNamespacesProperty.setTextContent("true"); outboundPropertiesElement.appendChild(stripNamespacesProperty); } } } private static void updateFilterFor2_0(Document document) { // Convert Rule Builder steps using "Reject" to JavaScript steps NodeList rules = getElements(document, "rule", "com.mirth.connect.model.Rule"); for (int i = 0; i < rules.getLength(); i++) { Element rule = (Element) rules.item(i); if (rule.getElementsByTagName("type").item(0).getTextContent().equalsIgnoreCase("Rule Builder")) { boolean reject = false; NodeList entries = rule.getElementsByTagName("entry"); for (int j = 0; j < entries.getLength(); j++) { NodeList entry = ((Element) entries.item(j)).getElementsByTagName("string"); if ((entry.getLength() == 2) && entry.item(0).getTextContent().equalsIgnoreCase("Accept") && entry.item(1).getTextContent().equalsIgnoreCase("0")) { reject = true; } } if (reject) { rule.getElementsByTagName("type").item(0).setTextContent("JavaScript"); rule.removeChild(rule.getElementsByTagName("data").item(0)); Element dataElement = document.createElement("data"); dataElement.setAttribute("class", "map"); Element entryElement = document.createElement("entry"); Element keyElement = document.createElement("string"); Element valueElement = document.createElement("string"); keyElement.setTextContent("Script"); valueElement.setTextContent(rule.getElementsByTagName("script").item(0).getTextContent()); entryElement.appendChild(keyElement); entryElement.appendChild(valueElement); dataElement.appendChild(entryElement); rule.appendChild(dataElement); } } } } private static Element createRegexElement(Document document) { Element entryElement = document.createElement("entry"); Element regexElement = document.createElement("string"); // Element stringArrayElement = document.createElement("string-array"); Element listElement = document.createElement("list"); regexElement.setTextContent("RegularExpressions"); entryElement.appendChild(regexElement); entryElement.appendChild(listElement); return entryElement; } private static Element createDefaultValueElement(Document document) { Element entryElement = document.createElement("entry"); Element defaultValueElement = document.createElement("string"); Element defaultValueValueElement = document.createElement("string"); defaultValueElement.setTextContent("DefaultValue"); entryElement.appendChild(defaultValueElement); entryElement.appendChild(defaultValueValueElement); return entryElement; } private static String updateLocalAndGlobalVariables(String xml) throws Exception { xml = xml.replaceAll("localMap.put", "channelMap.put"); xml = xml.replaceAll("localMap.get", "channelMap.get"); return xml; } /** * Removes certain invalid characters */ private static String removeInvalidHexChar(String string) { String result = string; for (char i = 0x0; i <= 0x8; i++) { result = result.replace(i, ' '); } for (char i = 0xB; i <= 0xC; i++) { result = result.replace(i, ' '); } for (char i = 0xE; i <= 0x1F; i++) { result = result.replace(i, ' '); } return result; } private static boolean nodeChildrenContains(Node parent, String elementName) { NodeList children = parent.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); if (child.getNodeName().equals(elementName)) { return true; } } return false; } private static void setBooleanNode(Node parent, String elementName, boolean value) { NodeList children = parent.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); if (child.getNodeName().equals(elementName)) { child.setTextContent(Boolean.toString(value)); } } } /** * Gets elements by the tag name passed in and returns the NodeList from * the first tagName that returns results. If there are no results from * any of the tagNames an empty list is returned. * * @param document * @param tagName * @param oldTagNames * @return */ private static NodeList getElements(Document document, String tagName, String... oldTagNames) { NodeList elements = document.getElementsByTagName(tagName); // loop through the oldTagNames while there are still no results for (int i = 0; (elements.getLength() == 0) && (i < oldTagNames.length); i++) { elements = document.getElementsByTagName(oldTagNames[i]); } return elements; } /** * Gets elements by the tag name passed in and returns the NodeList from * the first tagName that returns results. If there are no results from * any of the tagNames an empty list is returned. * * @param element * @param tagName * @param oldTagNames * @return */ private static NodeList getElements(Element element, String tagName, String... oldTagNames) { NodeList elements = element.getElementsByTagName(tagName); // loop through the oldTagNames while there are still no results for (int i = 0; (elements.getLength() == 0) && (i < oldTagNames.length); i++) { elements = element.getElementsByTagName(oldTagNames[i]); } return elements; } }