/******************************************************************************* * Copyright (c) 2006-2010 eBay Inc. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 *******************************************************************************/ package org.ebayopensource.turmeric.runtime.common.impl.internal.config; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.wsdl.Definition; import javax.xml.XMLConstants; import javax.xml.namespace.QName; import org.ebayopensource.turmeric.runtime.binding.BindingConstants; import org.ebayopensource.turmeric.runtime.common.exceptions.ErrorDataFactory; import org.ebayopensource.turmeric.runtime.common.exceptions.ServiceCreationException; import org.ebayopensource.turmeric.runtime.common.types.SOAConstants; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.ebayopensource.turmeric.runtime.errorlibrary.ErrorConstants; public class TypeMappingConfigMapper { private static final String TRUE = "TRUE"; private static final String ATTR_PACKAGE_NAME = "name"; private static final String ATTR_PACKAGE_XML_NS = "xml-namespace"; private static final String BASIC_XML_TYPE_JAVA_PACKAGE = "java.lang"; private static final String ATTR_METHOD_NAME = "methodName"; public static void map(String filename, Element topLevel, TypeMappingConfigHolder dst) throws ServiceCreationException { String enforceSingleNS = topLevel.getAttribute("enable-namespace-folding"); dst.setEnableNamespaceFolding((enforceSingleNS != null && TRUE.equals(enforceSingleNS)) ? true : false); Element operationList = (Element) DomParseUtils.getSingleNode(filename, topLevel, SOAConstants.XML_NODE_OPERATIONLIST); NodeList operations = DomParseUtils.getImmediateChildrenByTagName(operationList, SOAConstants.XML_NODE_OPERATION); List<String> operationsInWsdl = new ArrayList<String>(); for (int i = 0; i < operations.getLength(); i++) { Element inOperation = (Element) operations.item(i); String name = inOperation.getAttribute("name"); operationsInWsdl.add(name); } if(!operationsInWsdl.contains(SOAConstants.OP_GET_VERSION)){ addOperation(filename, topLevel); dst.setOperationAdded(true); } addCachePolicyOperation(filename, topLevel); // dst.setOperationAdded(true); // only needed for getVersion calls Element packageMap = (Element) DomParseUtils.getSingleNode(filename, topLevel, SOAConstants.XML_NODE_PACKAGEMAP); NodeList packages = DomParseUtils.getImmediateChildrenByTagName(packageMap, SOAConstants.XML_NODE_PACKAGE); Map<String,String> pkgToNs = new HashMap<String,String>(); for (int i = 0; i < packages.getLength(); i++) { Element onePackage = (Element) packages.item(i); String javaPackage = onePackage.getAttribute("name"); String xmlNamespace = onePackage.getAttribute("xml-namespace"); // TODO - temporary hack for backward compatibility - need to find all instances of the old typemappings and fix them. // if (SOAConstants.OLD_DEFAULT_SERVICE_NAMESPACE.equals(xmlNamespace)) { // xmlNamespace = SOAConstants.DEFAULT_SERVICE_NAMESPACE; // } pkgToNs.put(javaPackage, xmlNamespace); dst.setXmlNamespaceFromJavaPackage(javaPackage, xmlNamespace); } operations = DomParseUtils.getImmediateChildrenByTagName(operationList, SOAConstants.XML_NODE_OPERATION); for (int i = 0; i < operations.getLength(); i++) { Element inOperation = (Element) operations.item(i); String name = inOperation.getAttribute("name"); OperationConfig outOperation = new OperationConfig(); outOperation.setName(name); if(inOperation.hasAttribute(ATTR_METHOD_NAME)) { outOperation.setMethodName(inOperation.getAttribute(ATTR_METHOD_NAME)); } else { outOperation.setMethodName(name); } MessageTypeConfig messageTypeConfig = parseMessageTypeConfig(filename, pkgToNs, inOperation, SOAConstants.XML_NODE_REQUEST_MESSAGE); if (messageTypeConfig != null) { outOperation.setRequestMessage(messageTypeConfig); } messageTypeConfig = parseMessageTypeConfig(filename, pkgToNs, inOperation, SOAConstants.XML_NODE_RESPONSE_MESSAGE); if (messageTypeConfig != null) { outOperation.setResponseMessage(messageTypeConfig); } messageTypeConfig = parseMessageTypeConfig(filename, pkgToNs, inOperation, SOAConstants.XML_NODE_ERROR_MESSAGE); if (messageTypeConfig != null) { outOperation.setErrorMessage(messageTypeConfig); } parseMessageHeaderList(filename, pkgToNs, outOperation.getRequestHeader(), inOperation, SOAConstants.XML_NODE_REQUEST_HEADER); parseMessageHeaderList(filename, pkgToNs, outOperation.getResponseHeader(), inOperation, SOAConstants.XML_NODE_RESPONSE_HEADER); dst.setOperation(name, outOperation); } Element javaTypeList = (Element) DomParseUtils.getSingleNode(filename, topLevel, "java-type-list"); if ( javaTypeList != null ) { NodeList javaTypes = DomParseUtils.getImmediateChildrenByTagName(javaTypeList, SOAConstants.XML_NODE_JAVA_TYPE_NAME); if ( javaTypes != null ) { for (int i = 0; i < javaTypes.getLength(); i++) { Element javaClass = (Element) javaTypes.item(i); String name = javaClass.getTextContent(); dst.addJavaTypes( name ); } } } } private static void parseMessageHeaderList(String filename, Map<String, String> pkgToNs, List<MessageHeaderConfig> headerList, Element inOperation, String headerName) throws ServiceCreationException { NodeList headerElements = DomParseUtils.getImmediateChildrenByTagName(inOperation, headerName); for (int i = 0; i < headerElements.getLength(); i++) { Element headerElement = (Element) headerElements.item(i); MessageHeaderConfig messageHeaderConfig = parseMessageHeaderConfig(filename, pkgToNs, headerElement); headerList.add(messageHeaderConfig); } } private static MessageHeaderConfig parseMessageHeaderConfig(String filename, Map<String, String> pkgToNs, Element headerElement) throws ServiceCreationException { MessageHeaderConfig messageHeaderConfig = new MessageHeaderConfig(); String javaType = DomParseUtils.getElementText(filename, headerElement, SOAConstants.XML_NODE_JAVA_TYPE_NAME); messageHeaderConfig.setJavaTypeName(javaType); String xmlLocalTypeName = DomParseUtils.getElementText(filename, headerElement, SOAConstants.XML_NODE_XML_TYPE_NAME); messageHeaderConfig.setXmlTypeName(qualifyXmlName(pkgToNs, javaType, xmlLocalTypeName)); String xmlLocalElementName = DomParseUtils.getElementText(filename, headerElement, SOAConstants.XML_NODE_XML_ELEMENT_NAME); QName xmlElementName = QName.valueOf(xmlLocalElementName); messageHeaderConfig.setXmlElementName(xmlElementName); return messageHeaderConfig; } private static MessageTypeConfig parseMessageTypeConfig(String filename, Map<String, String> pkgToNs, Element operation, String name) throws ServiceCreationException { Element oneMessage = (Element) DomParseUtils.getSingleNode(filename, operation, name); if (oneMessage == null) { return null; } MessageTypeConfig messageTypeConfig = new MessageTypeConfig(); String javaType = DomParseUtils.getElementText(filename, oneMessage, SOAConstants.XML_NODE_JAVA_TYPE_NAME); messageTypeConfig.setJavaTypeName(javaType); String xmlLocalTypeName = DomParseUtils.getElementText(filename, oneMessage, SOAConstants.XML_NODE_XML_TYPE_NAME); messageTypeConfig.setXmlTypeName(qualifyXmlName(pkgToNs, javaType, xmlLocalTypeName)); String xmlLocalElementName = DomParseUtils.getElementText(filename, oneMessage, SOAConstants.XML_NODE_XML_ELEMENT_NAME); QName xmlElementName = QName.valueOf(xmlLocalElementName); if( XMLConstants.NULL_NS_URI.equals(xmlElementName.getNamespaceURI()) ) { xmlElementName = qualifyXmlName(pkgToNs, javaType, xmlLocalElementName); } messageTypeConfig.setXmlElementName(xmlElementName); Boolean hasAttachment = DomParseUtils.getElementBoolean(filename, oneMessage, SOAConstants.XML_NODE_HAS_ATTACHMENT); if (hasAttachment != null && hasAttachment.booleanValue()) { messageTypeConfig.setHasAttachment(true); } else { messageTypeConfig.setHasAttachment(false); } return messageTypeConfig; } private static QName qualifyXmlName(Map<String, String> pkgToNs, String javaType, String localpart) throws ServiceCreationException { if (localpart == null) { return null; } String packageName = getPackageName(javaType); String namespace = null; if (packageName != null) { namespace = pkgToNs.get(packageName); if (namespace == null) { throw new ServiceCreationException(ErrorDataFactory.createErrorData(ErrorConstants.CFG_TYPEMAP_JAVA_NO_PACKAGE_MATCH, ErrorConstants.ERRORDOMAIN, new Object[] {javaType})); } } return new QName(namespace, localpart); } private static String getPackageName(String javaType) throws ServiceCreationException { if (javaType == null) { return null; } int lastDot = javaType.lastIndexOf("."); if (lastDot == -1) { // Typically this is a primitive like integer. For now, we'll assume java.lang since typemappings // is an auto-generated file. return BASIC_XML_TYPE_JAVA_PACKAGE; } return javaType.substring(0, lastDot); } private static void addOperation(String filename, Element topLevel) throws ServiceCreationException{ Element packageMap = (Element) DomParseUtils.getSingleNode(filename, topLevel, SOAConstants.XML_NODE_PACKAGEMAP); NodeList packages = DomParseUtils.getImmediateChildrenByTagName(packageMap, SOAConstants.XML_NODE_PACKAGE); if(packages != null && packages.getLength() > 0){ Element onePackage = (Element) packages.item(0); Element newPackageMapping = (Element)onePackage.cloneNode(false); newPackageMapping.setAttribute(ATTR_PACKAGE_NAME, BASIC_XML_TYPE_JAVA_PACKAGE); newPackageMapping.setAttribute(ATTR_PACKAGE_XML_NS, BindingConstants.XMLSCHEMA_URI); packageMap.appendChild(newPackageMapping); } Element operationList = (Element) DomParseUtils.getSingleNode(filename, topLevel, SOAConstants.XML_NODE_OPERATIONLIST); NodeList operations = DomParseUtils.getImmediateChildrenByTagName(operationList, SOAConstants.XML_NODE_OPERATION); if(operations != null && operations.getLength() > 0){ Element firstOperation = (Element) operations.item(0); Element newOperation = (Element) firstOperation.cloneNode(true); newOperation.setAttribute("name", SOAConstants.OP_GET_VERSION); NodeList newOperationParams = newOperation.getChildNodes(); int numberOfParams = newOperationParams.getLength(); int notRemoved = 0; for (int i = 0; i < numberOfParams; i++) { Node childNode = newOperationParams.item(notRemoved); if(childNode.getNodeName() == SOAConstants.XML_NODE_RESPONSE_MESSAGE){ NodeList respParams = childNode.getChildNodes(); for (int j = 0; j < respParams.getLength(); j++) { Node respParam = respParams.item(j); if(respParam.getNodeName() == SOAConstants.XML_NODE_JAVA_TYPE_NAME && respParam.getFirstChild() != null) respParam.getFirstChild().setNodeValue("java.lang.String"); else if(respParam.getNodeName() == SOAConstants.XML_NODE_XML_TYPE_NAME && respParam.getFirstChild() != null) respParam.getFirstChild().setNodeValue("VersionString"); else if(respParam.getNodeName() == SOAConstants.XML_NODE_XML_ELEMENT_NAME && respParam.getFirstChild() != null) respParam.getFirstChild().setNodeValue("version"); else if(respParam.getNodeName() == SOAConstants.XML_NODE_HAS_ATTACHMENT && respParam.getFirstChild() != null) respParam.getFirstChild().setNodeValue("false"); } notRemoved++; }else newOperation.removeChild(childNode); } operationList.appendChild(newOperation); } } private static void addCachePolicyOperation(String filename, Element topLevel) throws ServiceCreationException{ Element packageMap = (Element) DomParseUtils.getSingleNode(filename, topLevel, SOAConstants.XML_NODE_PACKAGEMAP); NodeList packages = DomParseUtils.getImmediateChildrenByTagName(packageMap, SOAConstants.XML_NODE_PACKAGE); if(packages != null && packages.getLength() > 0){ Element onePackage = (Element) packages.item(0); Element newPackageMapping = (Element)onePackage.cloneNode(false); newPackageMapping.setAttribute(ATTR_PACKAGE_NAME, BASIC_XML_TYPE_JAVA_PACKAGE); newPackageMapping.setAttribute(ATTR_PACKAGE_XML_NS, BindingConstants.XMLSCHEMA_URI); packageMap.appendChild(newPackageMapping); } Element operationList = (Element) DomParseUtils.getSingleNode(filename, topLevel, SOAConstants.XML_NODE_OPERATIONLIST); NodeList operations = DomParseUtils.getImmediateChildrenByTagName(operationList, SOAConstants.XML_NODE_OPERATION); if(operations != null && operations.getLength() > 0){ Element firstOperation = (Element) operations.item(0); Element newOperation = (Element) firstOperation.cloneNode(true); newOperation.setAttribute("name", SOAConstants.OP_GET_CACHE_POLICY); NodeList newOperationParams = newOperation.getChildNodes(); int numberOfParams = newOperationParams.getLength(); int notRemoved = 0; for (int i = 0; i < numberOfParams; i++) { Node childNode = newOperationParams.item(notRemoved); if(childNode.getNodeName() == SOAConstants.XML_NODE_RESPONSE_MESSAGE){ NodeList respParams = childNode.getChildNodes(); for (int j = 0; j < respParams.getLength(); j++) { Node respParam = respParams.item(j); if(respParam.getNodeName() == SOAConstants.XML_NODE_JAVA_TYPE_NAME && respParam.getFirstChild() != null) respParam.getFirstChild().setNodeValue("java.lang.String"); else if(respParam.getNodeName() == SOAConstants.XML_NODE_XML_TYPE_NAME && respParam.getFirstChild() != null) respParam.getFirstChild().setNodeValue("CachePolicy"); else if(respParam.getNodeName() == SOAConstants.XML_NODE_XML_ELEMENT_NAME && respParam.getFirstChild() != null) respParam.getFirstChild().setNodeValue("cachepolicy"); else if(respParam.getNodeName() == SOAConstants.XML_NODE_HAS_ATTACHMENT && respParam.getFirstChild() != null) respParam.getFirstChild().setNodeValue("false"); } notRemoved++; }else newOperation.removeChild(childNode); } operationList.appendChild(newOperation); } } public static void map(String filename, Element topLevel, QName oldSvcQName, QName svcQName, Definition wsdlDef, TypeMappingConfigHolder dst) throws ServiceCreationException { changeNameSpace(filename, topLevel, oldSvcQName, svcQName, wsdlDef); map(filename, topLevel, dst); } private static void changeNameSpace(String fileName, Element typeMapping, QName oldSvcQName, QName svcQName, Definition wsdlDef) throws ServiceCreationException { String targetWSDLNS = wsdlDef != null ? wsdlDef.getTargetNamespace() : svcQName.getNamespaceURI(); Element operationList = (Element) DomParseUtils.getSingleNode(fileName, typeMapping, SOAConstants.XML_NODE_OPERATIONLIST); NodeList operations = DomParseUtils.getImmediateChildrenByTagName( operationList, SOAConstants.XML_NODE_OPERATION); HashMap<String, String> oldToNewNameSpace = new HashMap<String, String>(); changeNameSpaceMessages(fileName, wsdlDef, oldSvcQName, svcQName, targetWSDLNS, operations, oldToNewNameSpace); changeNameSpaceForPackageMap(fileName, typeMapping, oldToNewNameSpace); } private static void changeNameSpaceForPackageMap(String fileName, Element typeMapping, HashMap<String, String> oldToNewNameSpace) throws ServiceCreationException { Element packageMapList = (Element) DomParseUtils.getSingleNode( fileName, typeMapping, SOAConstants.XML_NODE_PACKAGEMAP); NodeList packages = DomParseUtils.getImmediateChildrenByTagName( packageMapList, SOAConstants.XML_NODE_PACKAGE); HashMap<String, String> nsToResplace = new HashMap<String, String>(); // Replace ns for packages for (int i = 0; i < packages.getLength(); i++) { // Get the package Element inPackage = (Element) packages.item(i); String javaPackage = inPackage.getAttribute(ATTR_PACKAGE_NAME); String newXMLNs = oldToNewNameSpace.get(javaPackage); if (newXMLNs != null) { nsToResplace.put(inPackage.getAttribute(ATTR_PACKAGE_XML_NS), newXMLNs); inPackage.setAttribute(ATTR_PACKAGE_XML_NS, newXMLNs); } } // Relace other NS mappings for (int i = 0; i < packages.getLength(); i++) { // Get the package Element inPackage = (Element) packages.item(i); String XMLSNs = inPackage.getAttribute(ATTR_PACKAGE_XML_NS); String newXMLNs = nsToResplace.get(XMLSNs); if (newXMLNs != null) { inPackage.setAttribute(ATTR_PACKAGE_XML_NS, newXMLNs); } } } private static void changeNameSpaceMessages(String fileName, Definition wsdlDef, QName oldSvcQName, QName svcQName, String targetWSDLNS, NodeList operations, HashMap<String, String> oldToNewNameSpace) throws ServiceCreationException { for (int i = 0; i < operations.getLength(); i++) { // Get the operation Element inOperation = (Element) operations.item(i); changeNameSpaceMessage(fileName, wsdlDef, oldSvcQName, svcQName, targetWSDLNS, oldToNewNameSpace, inOperation); } } private static void changeNameSpaceMessage(String fileName, Definition wsdlDef, QName oldSvcQName, QName svcQName, String targetWSDLNS, HashMap<String, String> oldToNewNameSpace, Element inOperation) throws ServiceCreationException { changeNameSpaceInnerMessage(fileName, wsdlDef, oldSvcQName, svcQName, targetWSDLNS, oldToNewNameSpace, inOperation, SOAConstants.XML_NODE_REQUEST_MESSAGE, false); changeNameSpaceInnerMessage(fileName, wsdlDef, oldSvcQName, svcQName, targetWSDLNS, oldToNewNameSpace, inOperation, SOAConstants.XML_NODE_RESPONSE_MESSAGE, false); changeNameSpaceInnerMessage(fileName, wsdlDef, oldSvcQName, svcQName, targetWSDLNS, oldToNewNameSpace, inOperation, SOAConstants.XML_NODE_ERROR_MESSAGE, true); } private static void changeNameSpaceInnerMessage(String fileName, Definition wsdlDef, QName oldSvcQName, QName svcQName, String targetWSDLNS, HashMap<String, String> oldToNewNameSpace, Element inOperation, String xmlMessageName, boolean ignoreMismatch) throws ServiceCreationException { // Get Request Message Element reqMessage = (Element) DomParseUtils.getSingleNode(fileName, inOperation, xmlMessageName); if (reqMessage == null) { return; } // Get XML-element-Name Element Element xmlTypeElement = DomParseUtils.getSingleElement(fileName, reqMessage, SOAConstants.XML_NODE_XML_ELEMENT_NAME); Element javaTypeElement = DomParseUtils.getSingleElement(fileName, reqMessage, SOAConstants.XML_NODE_JAVA_TYPE_NAME); if (xmlTypeElement == null || javaTypeElement == null) { return; } // Get XML Element Name content String xmlTypeElementStr = xmlTypeElement.getTextContent(); // Get Java type Name String javaTypeName = javaTypeElement.getTextContent(); // Get QName out of it QName qNameTM = QName.valueOf(xmlTypeElementStr); // First check if the WSDL can get this message //Raghu: Turning off the wsdl mismatch validation. As we need to plugin // wsdl schema parsing for doing the same. /* if (wsdlDef != null) { retroFitQName(wsdlDef, svcQName, targetWSDLNS, oldToNewNameSpace, xmlTypeElement, javaTypeName, qNameTM, ignoreMismatch); } else {*/ retroFitQName(oldSvcQName.getNamespaceURI(), targetWSDLNS, oldToNewNameSpace, xmlTypeElement, javaTypeName, qNameTM); /*}*/ } private static void retroFitQName(String oldNS, String targetWSDLNS, HashMap<String, String> oldToNewNameSpace, Element xmlTypeElement, String javaTypeName, QName qNameTM) throws ServiceCreationException { if (oldNS.equals(qNameTM.getNamespaceURI()) || qNameTM.getNamespaceURI().isEmpty()) { QName qNameWSDLNS = new QName(targetWSDLNS, qNameTM.getLocalPart()); // Retro-fit the element xmlTypeElement.setTextContent(qNameWSDLNS.toString()); String packageName = getPackageName(javaTypeName); if (packageName != null) { oldToNewNameSpace.put(packageName, targetWSDLNS); } } } /* private static void retroFitQName(Definition wsdlDef, QName svcQName, String targetWSDLNS, HashMap<String, String> oldToNewNameSpace, Element xmlTypeElement, String javaTypeName, QName qNameTM, boolean ignoreMismatch) throws ServiceCreationException { Message message = wsdlDef.getMessage(qNameTM); if (message == null) { // Try QName with QName qNameWSDLNS = new QName(targetWSDLNS, qNameTM.getLocalPart()); message = wsdlDef.getMessage(qNameWSDLNS); if (message == null) { if (!ignoreMismatch) { throw new ServiceCreationException( ErrorDataFactory.createErrorData(ErrorConstants.CFG_GENERIC_ERROR, ErrorConstants.ERRORDOMAIN, new Object[] { qNameTM.toString(), svcQName.toString() })); } return; } // Retro-fit the element xmlTypeElement.setTextContent(qNameWSDLNS.toString()); String packageName = getPackageName(javaTypeName); if (packageName != null) { oldToNewNameSpace.put(packageName, targetWSDLNS); } } } */ }