summaryrefslogtreecommitdiffstats
path: root/sca-cpp/branches/cpp-contrib/contrib/runtime/core/src/tuscany/sca/model/WSDLDefinition.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sca-cpp/branches/cpp-contrib/contrib/runtime/core/src/tuscany/sca/model/WSDLDefinition.cpp')
-rw-r--r--sca-cpp/branches/cpp-contrib/contrib/runtime/core/src/tuscany/sca/model/WSDLDefinition.cpp633
1 files changed, 633 insertions, 0 deletions
diff --git a/sca-cpp/branches/cpp-contrib/contrib/runtime/core/src/tuscany/sca/model/WSDLDefinition.cpp b/sca-cpp/branches/cpp-contrib/contrib/runtime/core/src/tuscany/sca/model/WSDLDefinition.cpp
new file mode 100644
index 0000000000..53971b5a17
--- /dev/null
+++ b/sca-cpp/branches/cpp-contrib/contrib/runtime/core/src/tuscany/sca/model/WSDLDefinition.cpp
@@ -0,0 +1,633 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* $Rev$ $Date$ */
+
+#include <sstream>
+#include <set>
+
+#include "tuscany/sca/model/WSDLDefinition.h"
+#include "tuscany/sca/model/WSDLOperation.h"
+#include "tuscany/sca/util/Logging.h"
+#include "tuscany/sca/util/Utils.h"
+#include "tuscany/sca/core/Exceptions.h"
+
+using namespace std;
+using namespace commonj::sdo;
+using namespace tuscany::sca::util;
+
+namespace tuscany
+{
+ namespace sca
+ {
+ namespace model
+ {
+
+ // Constructor
+ WSDLDefinition::WSDLDefinition(DataObjectPtr wsdlModel)
+ {
+ logentry();
+
+ wsdlModels.insert(wsdlModels.end(), wsdlModel);
+ mapOperations( wsdlModel );
+ }
+
+ WSDLDefinition::~WSDLDefinition()
+ {
+ logentry();
+ }
+
+ ///
+ /// The namespace of the service and other definitions defined in this wsdl definition
+ string WSDLDefinition::getNamespace()
+ {
+ logentry();
+ return wsdlModels[0]->getCString("targetNamespace");
+ }
+
+ void WSDLDefinition::addWSDLModel(DataObjectPtr wsdlModel)
+ {
+ logentry();
+ wsdlModels.insert(wsdlModels.end(), wsdlModel);
+ mapOperations( wsdlModel );
+ }
+
+ ///
+ /// Find the operation defined in this wsdl
+ ///
+ const WSDLOperation& WSDLDefinition::findOperation(const string& serviceName,
+ const string& portName,
+ const string& operationName)
+ {
+ logentry();
+
+ string operationKey = serviceName+"#"+portName;
+ STR_OPERATION_MAP::const_iterator spIter = servicePortMap.find(operationKey);
+ if( spIter == servicePortMap.end() )
+ {
+ stringstream errMessage;
+ errMessage
+ << "Unable to find Service and Port: \""
+ << serviceName << "," << portName
+ << "\" in the WSDL definition";
+ throwException(SystemConfigurationException, errMessage.str().c_str());
+ }
+
+ OPERATION_MAP::const_iterator opIter = spIter->second.find(operationName);
+
+ if (opIter != spIter->second.end())
+ {
+ return opIter->second;
+ }
+ else
+ {
+ stringstream errMessage;
+ errMessage
+ << "Unable to find operation \""
+ << serviceName << ":" << portName << ":" << operationName
+ << "\" in the WSDL definition";
+
+ throwException(SystemConfigurationException, errMessage.str().c_str());
+ }
+ }
+
+ ///
+ /// Find the operation defined in this wsdl
+ ///
+ const WSDLOperation& WSDLDefinition::findOperation(const string& portTypeName,
+ const string& operationName)
+ {
+ logentry();
+
+ STR_OPERATION_MAP::const_iterator ptIter = portTypeMap.find(portTypeName);
+ if( ptIter == portTypeMap.end() )
+ {
+ stringstream errMessage;
+ errMessage
+ << "Unable to find PortType: \""
+ << portTypeName
+ << "\" in the WSDL definition";
+ throwException(SystemConfigurationException, errMessage.str().c_str());
+ }
+
+ OPERATION_MAP::const_iterator opIter = ptIter->second.find(operationName);
+
+ if (opIter != ptIter->second.end())
+ {
+ return opIter->second;
+ }
+ else
+ {
+ stringstream errMessage;
+ errMessage
+ << "Unable to find Operation \""
+ << portTypeName << ":" << operationName
+ << "\" in the WSDL definition";
+ throwException(SystemConfigurationException, errMessage.str().c_str());
+ }
+ }
+
+ std::list<std::string> WSDLDefinition::getPortTypes()
+ {
+ logentry();
+
+ std::list<std::string> ptList;
+ STR_OPERATION_MAP::const_iterator ptIter = portTypeMap.begin();
+ STR_OPERATION_MAP::const_iterator ptIterEnd = portTypeMap.end();
+
+ for( ; ptIter != ptIterEnd; ++ptIter )
+ {
+ ptList.push_back( ptIter->first );
+ }
+
+ return ptList;
+ }
+
+ std::list<std::string> WSDLDefinition::getOperations( const std::string &portTypeName )
+ {
+ logentry();
+
+ std::list<std::string> ptOpList;
+ STR_OPERATION_MAP::const_iterator ptIter = portTypeMap.find( portTypeName );
+
+ if( ptIter == portTypeMap.end() )
+ {
+ stringstream errMessage;
+ errMessage
+ << "Unable to find PortType: \""
+ << portTypeName
+ << "\" in the WSDL definition";
+ throwException(SystemConfigurationException, errMessage.str().c_str());
+ }
+
+ OPERATION_MAP::const_iterator opIter = ptIter->second.begin();
+ OPERATION_MAP::const_iterator opIterEnd = ptIter->second.end();
+
+ for( ; opIter != opIterEnd; ++opIter )
+ {
+ ptOpList.push_back( opIter->first );
+ }
+
+ return ptOpList;
+ }
+
+ ///
+ /// Find a service
+ ///
+ DataObjectPtr WSDLDefinition::findService(const string& serviceName)
+ {
+ logentry();
+
+ DataObjectPtr service = 0;
+
+ // Find the binding
+ for (unsigned int m = 0; m < wsdlModels.size(); m++)
+ {
+ DataObjectList& serviceList = wsdlModels[m]->getList("service");
+ for (unsigned int i=0; i<serviceList.size(); i++)
+ {
+ string name(serviceList[i]->getCString("name"));
+
+ if (name.compare(serviceName) == 0)
+ {
+ return serviceList[i];
+ }
+ }
+ }
+
+ return service;
+ }
+
+
+ ///
+ /// Find a named binding
+ ///
+ DataObjectPtr WSDLDefinition::findBinding(const string& bindingName)
+ {
+ logentry();
+
+ DataObjectPtr binding = 0;
+ string uri;
+ string name;
+
+ Utils::rTokeniseString("#", bindingName, uri, name);
+
+ // Find the binding
+ for (unsigned int m = 0; m < wsdlModels.size(); m++)
+ {
+ DataObjectList& bindingList = wsdlModels[m]->getList("binding");
+ for (unsigned int i=0; i<bindingList.size(); i++)
+ {
+ string nameBinding(bindingList[i]->getCString("name"));
+
+ if (nameBinding.compare(name) == 0)
+ {
+ return bindingList[i];
+ }
+ }
+ }
+
+ return binding;
+ }
+
+ ///
+ /// Find a named portType
+ ///
+ DataObjectPtr WSDLDefinition::findPortType(const string& portTypeName)
+ {
+ logentry();
+
+ DataObjectPtr portType = 0;
+ string uri;
+ string name;
+
+ Utils::rTokeniseString("#", portTypeName, uri, name);
+
+ // Find the binding
+ for (unsigned int m = 0; m < wsdlModels.size(); m++)
+ {
+ DataObjectList& portTypeList = wsdlModels[m]->getList("portType");
+ for (unsigned int i=0; i<portTypeList.size(); i++)
+ {
+ string namePortType(portTypeList[i]->getCString("name"));
+
+ if (namePortType.compare(name) == 0)
+ {
+ return portTypeList[i];
+ }
+ }
+ }
+
+ return portType;
+ }
+
+ ///
+ /// Find a named message
+ ///
+ DataObjectPtr WSDLDefinition::findMessage(const string& messageName)
+ {
+ logentry();
+
+ DataObjectPtr message = 0;
+ string uri;
+ string name;
+
+ Utils::rTokeniseString("#", messageName, uri, name);
+
+ // Find the binding
+ for (unsigned int m = 0; m < wsdlModels.size(); m++)
+ {
+ DataObjectList& messageList = wsdlModels[m]->getList("message");
+ for (unsigned int i=0; i<messageList.size(); i++)
+ {
+ string nameMessage(messageList[i]->getCString("name"));
+
+ if (nameMessage.compare(name) == 0)
+ {
+ return messageList[i];
+ }
+ }
+ }
+
+ return message;
+ }
+
+ ///
+ /// Traverse the WSDL SDO and insert operations into the operationMap
+ ///
+ void WSDLDefinition::mapOperations( DataObjectPtr wsdlModel )
+ {
+ logentry();
+
+ // check for duplicate message/binding/PortType/Service
+ // with equal name attributes. This cant be enforced by
+ // the schema, so it has to be enforced at the app level
+ checkForDuplicates( wsdlModel );
+
+ DataObjectList& serviceList = wsdlModel->getList("service");
+
+ // Iterate through the WSDL services
+ for (unsigned int i=0; i < serviceList.size(); i++)
+ {
+ string serviceName( serviceList[i]->getCString("name") );
+
+ // Iterate through the WSDL service ports
+ DataObjectList& portList = serviceList[i]->getList("port");
+ for (unsigned int j=0; j < portList.size();j++)
+ {
+ string portName( portList[j]->getCString("name") );
+ string wsBindingName(portList[j]->getCString("binding"));
+
+ // There can only be one soap address and the check must be made
+ // at the application level since it cant be specified in the xsd
+/*
+ DataObjectList& soapAddressList = portList[j]->getList("address");
+ if( soapAddressList.size() != 1 )
+ {
+ // Invalid WSDL
+ stringstream errMessage;
+ errMessage
+ << "service/port/address: \""
+ << portName
+ << "\" cannot be duplicated in the WSDL definition";
+ throwException(SystemConfigurationException, errMessage.str().c_str());
+ }
+*/
+
+ string targetAddress(portList[j]->getCString("address/location"));
+
+ // get the binding specified in the WSDL service port
+ DataObjectPtr wsBinding = findBinding(wsBindingName);
+ if (!wsBinding)
+ {
+ // Invalid WSDL
+ stringstream errMessage;
+ errMessage
+ << "Unable to find binding \""
+ << wsBindingName
+ << "\" in the WSDL definition";
+ throwException(SystemConfigurationException, errMessage.str().c_str());
+ }
+
+ // Check if its a SOAP binding, if not go on to the next binding
+ // doing a find like this will work for SOAP11 and SOAP12
+ DataObjectPtr wsBindingSubBinding = wsBinding->getDataObject("binding");
+ string bindingURI(wsBindingSubBinding->getType().getURI());
+ if (bindingURI.find("http://schemas.xmlsoap.org/wsdl/soap") == string::npos)
+ {
+ loginfo("Discarding non-SOAP Binding %s", wsBindingName.c_str() );
+ continue;
+ }
+
+ // Get the port type specified the WSDL binding
+ string wsBindingPortTypeName(wsBinding->getCString("type"));
+ DataObjectPtr portType = findPortType(wsBindingPortTypeName);
+ if (!portType)
+ {
+ // Invalid WSDL
+ stringstream errMessage;
+ errMessage
+ << "Unable to find PortType \""
+ << wsBindingPortTypeName
+ << "\" in the WSDL definition";
+ throwException(SystemConfigurationException, errMessage.str().c_str());
+ }
+ string portTypeName( portType->getCString("name") );
+
+ // Fill in this map with operation names to WSDLOperations
+ // then after iterating through the operations, add the map
+ // to the portTypeMap, keyed off of the portTypeName
+ OPERATION_MAP operationMap;
+
+ // For each binding and portType operation:
+ // - get the soap action, style, and use from the binding
+ // - get the input and/or output message types
+ // its ok if not all of the PortType operations are not defined in the binding
+ DataObjectList& bindingOperationList = wsBinding->getList("operation");
+ DataObjectList& portTypeOperationList = portType->getList("operation");
+ for (unsigned int k=0; k < bindingOperationList.size(); k++)
+ {
+ DataObjectPtr bindingOp = bindingOperationList[k];
+ string operationName = bindingOp->getCString("name");
+
+ // Get the corresponding PortType operation
+ // I know this may not be very efficient, but its a necessary evil
+ bool foundPortType = false;
+ DataObjectPtr portTypeOp;
+ for (unsigned int l=0;
+ (!foundPortType && l < portTypeOperationList.size());
+ l++)
+ {
+ //portTypeOp = portTypeOperationList[l]->getDataObject("operation");
+ portTypeOp = portTypeOperationList[l];
+ if (operationName == portTypeOp->getCString("name") )
+ {
+ foundPortType = true;
+ }
+ }
+
+ if( !foundPortType )
+ {
+ // Invalid WSDL
+ stringstream errMessage;
+ errMessage
+ << "Unable to find PortType operation for binding operation: \""
+ << operationName
+ << "\" in the WSDL definition";
+ throwException(SystemConfigurationException, errMessage.str().c_str());
+ }
+
+ string soapAction = "";
+ bool documentStyle = true;
+ bool wrappedStyle = true;
+ bool useEncodedInput = false;
+ bool useEncodedOutput = false;
+ WSDLOperation::soapVersion soapVer = WSDLOperation::SOAP11;
+
+ string opType = bindingOp->getType().getURI();
+ if (opType == "http://schemas.xmlsoap.org/wsdl/soap12/")
+ {
+ soapVer = WSDLOperation::SOAP12;
+ }
+
+ // Get the soapAction
+ soapAction = bindingOp->getCString("operation/soapAction");
+
+ // Get the style
+ string style = bindingOp->getCString("operation/style");
+ if (style == "")
+ {
+ style = wsBinding->getCString("binding/style");
+ }
+ if (style != "document")
+ {
+ documentStyle = false;
+ wrappedStyle = false;
+ }
+
+ // get the use
+ string use = bindingOp->getCString("input/body/use");
+ if (use == "encoded")
+ {
+ useEncodedInput = true;
+ }
+
+ use = bindingOp->getCString("output/body/use");
+ if (use == "encoded")
+ {
+ useEncodedOutput = true;
+ }
+
+ // Get the request message type from the PortType
+ DataObjectPtr wsMessageIn =
+ findMessage(portTypeOp->getCString("input/message"));
+ if (!wsMessageIn)
+ {
+ stringstream errMessage;
+ errMessage
+ << "unable to find PortType input message \""
+ << portTypeOp->getCString("input/message")
+ << "\" in the wsdl definition";
+ throwException(SystemConfigurationException, errMessage.str().c_str());
+ }
+ string inputMessageType( wsMessageIn->getCString("name") );
+ // If it doesnt have a namespace prefix, add the target namespace
+ if (inputMessageType.find("#") == string::npos)
+ {
+ inputMessageType.insert(0, (getNamespace() + "#") );
+ }
+
+ // Get the response message type from the PortType
+ DataObjectPtr wsMessageOut =
+ findMessage(portTypeOp->getCString("output/message"));
+ if (!wsMessageOut)
+ {
+ // TODO this is ok for one way operations, right?
+ stringstream errMessage;
+ errMessage
+ << "unable to find PortType output message \""
+ << portTypeOp->getCString("output/message")
+ << "\" in the wsdl definition";
+ throwException(SystemConfigurationException, errMessage.str().c_str());
+ }
+ string outputMessageType( wsMessageOut->getCString("name") );
+ // If it doesnt have a namespace prefix, add the target namespace
+ if (outputMessageType.find("#") == string::npos)
+ {
+ outputMessageType.insert(0, (getNamespace() + "#") );
+ }
+
+ WSDLOperation wsdlOp;
+ wsdlOp.setOperationName(operationName);
+ wsdlOp.setSoapAction(soapAction);
+ wsdlOp.setEndpoint(targetAddress);
+ wsdlOp.setSoapVersion(soapVer);
+ wsdlOp.setDocumentStyle(documentStyle);
+ wsdlOp.setWrappedStyle(wrappedStyle);
+ wsdlOp.setInputEncoded(useEncodedInput);
+ wsdlOp.setOutputEncoded(useEncodedOutput);
+ wsdlOp.setInputMessageType(inputMessageType);
+ wsdlOp.setOutputMessageType(outputMessageType);
+ wsdlOp.setInputMessage(wsMessageIn);
+ wsdlOp.setOutputMessage(wsMessageOut);
+
+ operationMap[ operationName ] = wsdlOp;
+
+ } // end bindingOperationList
+
+ portTypeMap[portTypeName] = operationMap;
+ servicePortMap[(serviceName+"#"+portName)] = operationMap;
+
+ } // end portTypeList
+ } // end serviceList
+ } // end method mapOperations
+
+ void WSDLDefinition::checkForDuplicates( DataObjectPtr wsdlModel )
+ {
+ logentry();
+
+ // check for duplicate message/binding/PortType/service
+ // with equal name attributes. This cant be enforced by
+ // the schema, so it has to be enforced at the app level
+
+ std::set<string> namesSet;
+
+ DataObjectList &messageList = wsdlModel->getList("message");
+ for( unsigned int i = 0; i < messageList.size(); i++ )
+ {
+ if( namesSet.find( messageList[i]->getCString("name") ) == namesSet.end() )
+ {
+ namesSet.insert( messageList[i]->getCString("name") );
+ }
+ else
+ {
+ // Invalid WSDL
+ stringstream errMessage;
+ errMessage
+ << "message/name: \""
+ << messageList[i]->getCString("name")
+ << "\" cannot be duplicated in the WSDL definition";
+ throwException(SystemConfigurationException, errMessage.str().c_str());
+ }
+ }
+
+ namesSet.clear();
+ DataObjectList &bindingList = wsdlModel->getList("binding");
+ for( unsigned int i = 0; i < bindingList.size(); i++ )
+ {
+ if( namesSet.find( bindingList[i]->getCString("name") ) == namesSet.end() )
+ {
+ namesSet.insert( bindingList[i]->getCString("name") );
+ }
+ else
+ {
+ // Invalid WSDL
+ stringstream errMessage;
+ errMessage
+ << "binding/name: \""
+ << bindingList[i]->getCString("name")
+ << "\" cannot be duplicated in the WSDL definition";
+ throwException(SystemConfigurationException, errMessage.str().c_str());
+ }
+ }
+
+ namesSet.clear();
+ DataObjectList &portTypeList = wsdlModel->getList("portType");
+ for( unsigned int i = 0; i < portTypeList.size(); i++ )
+ {
+ if( namesSet.find( portTypeList[i]->getCString("name") ) == namesSet.end() )
+ {
+ namesSet.insert( portTypeList[i]->getCString("name") );
+ }
+ else
+ {
+ // Invalid WSDL
+ stringstream errMessage;
+ errMessage
+ << "portType/name: \""
+ << portTypeList[i]->getCString("name")
+ << "\" cannot be duplicated in the WSDL definition";
+ throwException(SystemConfigurationException, errMessage.str().c_str());
+ }
+ }
+
+ namesSet.clear();
+ DataObjectList &serviceList = wsdlModel->getList("service");
+ for( unsigned int i = 0; i < serviceList.size(); i++ )
+ {
+ if( namesSet.find( serviceList[i]->getCString("name") ) == namesSet.end() )
+ {
+ namesSet.insert( serviceList[i]->getCString("name") );
+ }
+ else
+ {
+ // Invalid WSDL
+ stringstream errMessage;
+ errMessage
+ << "service/name: \""
+ << serviceList[i]->getCString("name")
+ << "\" cannot be duplicated in the WSDL definition";
+ throwException(SystemConfigurationException, errMessage.str().c_str());
+ }
+ }
+ }
+
+ } // end namespace model
+ } // end namespace sca
+} // End namespace tuscany