Author: jsdelfino
Date: Sat Dec 2 13:41:10 2006
New Revision: 481632
URL: http://svn.apache.org/viewvc?view=rev&rev=481632
Log:
Fixed support for command style XML/HTTP to handle multiple input parameters
correctly. Renamed internal wrapper SDO from Body to Wrapper. Changed the
serialization code to always send the XML declaration element including the
encoding.
Modified:
incubator/tuscany/cpp/sca/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceWrapper.cpp
incubator/tuscany/cpp/sca/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/ModREST.cpp
incubator/tuscany/cpp/sca/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/RESTServiceProxy.cpp
Modified:
incubator/tuscany/cpp/sca/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceWrapper.cpp
URL:
http://svn.apache.org/viewvc/incubator/tuscany/cpp/sca/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceWrapper.cpp?view=diff&rev=481632&r1=481631&r2=481632
==============================================================================
---
incubator/tuscany/cpp/sca/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceWrapper.cpp
(original)
+++
incubator/tuscany/cpp/sca/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceWrapper.cpp
Sat Dec 2 13:41:10 2006
@@ -22,6 +22,7 @@
#include "tuscany/sca/util/Logging.h"
#include "tuscany/sca/util/Exceptions.h"
+#include "tuscany/sca/util/Utils.h"
#include "RESTServiceWrapper.h"
#include "tuscany/sca/core/Operation.h"
#include "tuscany/sca/model/Service.h"
@@ -163,11 +164,11 @@
} catch (SDORuntimeException&)
{
dataFactory->addType("http://tempuri.org", "RootType",
false, false, false);
- dataFactory->addType("http://tempuri.org", "Body", false,
true, false);
+ dataFactory->addType("http://tempuri.org", "Wrapper",
false, true, false);
dataFactory->addPropertyToType(
"http://tempuri.org", "RootType",
- "Body",
- "http://tempuri.org", "Body",
+ "Wrapper",
+ "http://tempuri.org", "Wrapper",
false, false, true);
dataFactory->addType("http://tempuri.org", "Part", false,
true, false);
dataFactory->addPropertyToType(
@@ -323,12 +324,16 @@
{
if (responsePayload != "")
{
- // TODO This is a temp hack, clean this up
- // Wrap the returned document inside a part
element
- string part =
- "<Part xmlns=\"http://tempuri.org\"
xmlns:tns=\"http://tempuri.org\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
- + responsePayload
- + "</Part>";
+ //TODO Remove this workaround once SDO
supports loading of open top level content
+ // The workaround is to wrap the open content
in a wrapper element
+ string xmldecl;
+ string xml;
+ Utils::rTokeniseString("?>", responsePayload,
xmldecl, xml);
+ string part = "<?xml version=\"1.0\"
encoding=\"UTF-8\"?>\n";
+ part += "<Part xmlns=\"http://tempuri.org\"
xmlns:tns=\"http://tempuri.org\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n";
+ part += xml;
+ part += "\n</Part>";
+
setReturn(xmlHelper, part, operation);
}
else
@@ -658,9 +663,14 @@
else
{
// Not a REST interface, XML / HTTP command style
+ curl_slist *requestHeaders = NULL;
+ struct curl_httppost *formpost = NULL;
+ ostringstream spayload;
+ string requestPayload;
+ string url;
// If the request contains complex content then we'll use
- // a multipart form POST, otherwise we use a GET
+ // a POST, otherwise we use a GET with a query string
bool complexContent = false;
for (int i=0; i<operation.getNParms(); i++)
{
@@ -670,35 +680,77 @@
break;
}
}
- struct curl_httppost *formpost = NULL;
+
if (complexContent)
{
// Set the target URL
string uri = binding->getURI();
ostringstream os;
os << uri << "/" << opName;
- string url = os.str();
+ url = os.str();
curl_easy_setopt(curl_handle, CURLOPT_URL,
url.c_str());
-
- // Build the input form
- struct curl_httppost *lastptr = NULL;
- for (int i=0; i<operation.getNParms(); i++)
+
+ // Disable the 100 continue handshake
+ requestHeaders = curl_slist_append(requestHeaders,
"Expect:");
+
+ if (operation.getNParms() == 1)
{
- ostringstream pname;
- pname << "param" << (i+1);
+ // Single parameter, send it as the body of the
POST
+
+ // Create the input payload
+ writeParameter(xmlHelper, spayload,
operation.getParameter(0));
+ requestPayload = spayload.str();
+ requestChunk.memory = requestPayload.c_str();
+ requestChunk.size = requestPayload.size();
- ostringstream pvalue;
- writeParameter(xmlHelper, pvalue,
operation.getParameter(i));
+ curl_easy_setopt(curl_handle,
CURLOPT_POSTFIELDSIZE, requestChunk.size);
- curl_formadd(&formpost,
- &lastptr,
- CURLFORM_COPYNAME, pname.str().c_str(),
- CURLFORM_COPYCONTENTS, pvalue.str().c_str(),
- CURLFORM_END);
+ // Read all data using this function
+ curl_easy_setopt(curl_handle,
CURLOPT_READFUNCTION, read_callback);
+
+ // Pass our 'chunk' struct to the callback function
+ curl_easy_setopt(curl_handle, CURLOPT_READDATA,
(void *)&requestChunk);
+
+ // Set the content type
+ requestHeaders = curl_slist_append(requestHeaders,
"Content-Type: text/xml");
+
+ // This will be a POST
+ curl_easy_setopt(curl_handle, CURLOPT_POST, true);
+ }
+ else
+ {
+
+ // Multiple parameters, use a form type POST
+ struct curl_httppost *lastptr = NULL;
+ for (int i=0; i<operation.getNParms(); i++)
+ {
+ ostringstream pname;
+ pname << "param" << (i+1);
+
+ const char* ctype;
+ if (operation.getParameter(i).getType() ==
Operation::DATAOBJECT)
+ {
+ ctype ="text/xml";
+ }
+ else
+ {
+ ctype = "text/plain";
+ }
+
+ ostringstream pvalue;
+ writeParameter(xmlHelper, pvalue,
operation.getParameter(i));
+
+ curl_formadd(&formpost,
+ &lastptr,
+ CURLFORM_CONTENTTYPE, ctype,
+ CURLFORM_COPYNAME, pname.str().c_str(),
+ CURLFORM_COPYCONTENTS,
pvalue.str().c_str(),
+ CURLFORM_END);
+ }
+
+ // Set the form into the request
+ curl_easy_setopt(curl_handle, CURLOPT_HTTPPOST,
formpost);
}
-
- // Set the form into the request
- curl_easy_setopt(curl_handle, CURLOPT_HTTPPOST,
formpost);
}
else
{
@@ -720,7 +772,7 @@
os << "&";
}
- string url = os.str();
+ url = os.str();
curl_easy_setopt(curl_handle, CURLOPT_URL,
url.c_str());
}
@@ -731,9 +783,21 @@
// Pass our 'chunk' struct to the callback function
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void
*)&responseChunk);
+ // Configure the headers
+ if (requestHeaders)
+ {
+ curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER,
requestHeaders);
+ }
+
// Perform the HTTP request
CURLcode rc = curl_easy_perform(curl_handle);
+ // Free any headers
+ if (requestHeaders)
+ {
+ curl_slist_free_all(requestHeaders);
+ }
+
// Cleanup the form
if (complexContent)
{
@@ -747,8 +811,19 @@
if (responseChunk.memory)
{
- string payload((const char*)responseChunk.memory,
responseChunk.size);
- setReturn(xmlHelper, payload, operation);
+ string responsePayload((const
char*)responseChunk.memory, responseChunk.size);
+
+ //TODO Remove this workaround once SDO supports
loading of open top level content
+ // The workaround is to wrap the open content in a
wrapper element
+ string xmldecl;
+ string xml;
+ Utils::rTokeniseString("?>", responsePayload, xmldecl,
xml);
+ string part = "<?xml version=\"1.0\"
encoding=\"UTF-8\"?>\n";
+ part += "<Part xmlns=\"http://tempuri.org\"
xmlns:tns=\"http://tempuri.org\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n";
+ part += xml;
+ part += "\n</Part>";
+
+ setReturn(xmlHelper, part, operation);
}
}
@@ -826,7 +901,6 @@
{
DataObjectPtr dob = *(DataObjectPtr*)parm.getValue();
XMLDocumentPtr doc = xmlHelper->createDocument(dob,
NULL, NULL);
- doc->setXMLDeclaration(false);
xmlHelper->save(doc, os);
break;
}
@@ -843,20 +917,23 @@
logentry();
//TODO Remove this workaround once SDO supports loading of
open top level content
- // The workaround is to wrap the open content in a wrapper
element of type OpenDataObject
- string body =
- "<Body xmlns=\"http://tempuri.org\"
xmlns:tns=\"http://tempuri.org\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
- + payload
- + "</Body>";
+ // The workaround is to wrap the open content in a wrapper
element
+ string xmldecl;
+ string xml;
+ Utils::rTokeniseString("?>", payload, xmldecl, xml);
+ string body = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ body += "<Wrapper xmlns=\"http://tempuri.org\"
xmlns:tns=\"http://tempuri.org\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n";
+ body += xml;
+ body += "\n</Wrapper>";
// Convert the body to an SDO DataObject
- DataObjectPtr outputBodyDataObject = NULL;
+ DataObjectPtr outputWrapperDataObject = NULL;
XMLDocumentPtr theXMLDocument = xmlHelper->load(body.c_str(),
NULL);
if (theXMLDocument != 0)
{
- outputBodyDataObject = theXMLDocument->getRootDataObject();
+ outputWrapperDataObject =
theXMLDocument->getRootDataObject();
}
- if(!outputBodyDataObject)
+ if(!outputWrapperDataObject)
{
ostringstream msg;
msg << "Could not convert received document to SDO: " <<
body;
@@ -865,17 +942,17 @@
// Get the body part
DataObjectPtr outputDataObject = NULL;
- PropertyList bpl =
outputBodyDataObject->getInstanceProperties();
+ PropertyList bpl =
outputWrapperDataObject->getInstanceProperties();
if (bpl.size()!=0)
{
if (bpl[0].isMany())
{
- DataObjectList& parts =
outputBodyDataObject->getList((unsigned int)0);
+ DataObjectList& parts =
outputWrapperDataObject->getList((unsigned int)0);
outputDataObject = parts[0];
}
else
{
- outputDataObject =
outputBodyDataObject->getDataObject(bpl[0]);
+ outputDataObject =
outputWrapperDataObject->getDataObject(bpl[0]);
}
}
if (outputDataObject == NULL)
Modified:
incubator/tuscany/cpp/sca/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/ModREST.cpp
URL:
http://svn.apache.org/viewvc/incubator/tuscany/cpp/sca/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/ModREST.cpp?view=diff&rev=481632&r1=481631&r2=481632
==============================================================================
---
incubator/tuscany/cpp/sca/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/ModREST.cpp
(original)
+++
incubator/tuscany/cpp/sca/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/ModREST.cpp
Sat Dec 2 13:41:10 2006
@@ -515,13 +515,9 @@
DataObjectPtr outputDataObject =
proxy->invoke(wsdlOperation, inputDataObject);
// Send the output DataObject
- char *str;
if (iface!=NULL &&
iface->getInterfaceTypeQName() ==
RESTInterface::typeQName)
{
- // Set the content type
- ap_set_content_type(request, "text/xml");
-
if (outputDataObject == NULL)
{
throwException(ServiceInvocationException,
"Null output from REST create operation");
@@ -539,18 +535,18 @@
resourceDataObject,
resourceDataObject->getType().getURI(),
resourceDataObject->getType().getName());
- doc->setXMLDeclaration(false);
- str = xm->save(doc);
+ char* str = xm->save(doc);
loginfo("Sending response: %s", str);
+ ap_set_content_type(request, "text/xml");
ap_rputs(str, request);
- return OK;
}
else
{
loginfo("REST resource not found, sending
HTTP 404 response code");
request->status = HTTP_NOT_FOUND;
+
return OK;
}
}
@@ -559,30 +555,37 @@
{
// Command style, send the response wrapper element
- // Set the content type
- ap_set_content_type(request, "text/xml");
-
if (outputDataObject == NULL)
{
loginfo("Sending empty response");
- return OK;
+ //request->status = HTTP_NO_CONTENT;
}
else
{
XMLHelperPtr xm =
HelperProvider::getXMLHelper(dataFactory);
- XMLDocumentPtr doc = xm->createDocument(
- outputDataObject,
- wsdlOperation.getOutputTypeUri().c_str(),
- wsdlOperation.getOutputTypeName().c_str());
- doc->setXMLDeclaration(false);
- str = xm->save(doc);
-
- loginfo("Sending response: %s", str);
- ap_rputs(str, request);
-
- return OK;
+ DataObjectList& l =
outputDataObject->getList("return");
+ if (l.size() != 0)
+ {
+ DataObjectPtr resultDataObject = l[0];
+ XMLDocumentPtr doc = xm->createDocument(
+ resultDataObject,
+ resultDataObject->getType().getURI(),
+ resultDataObject->getType().getName());
+ char* str = xm->save(doc);
+
+ loginfo("Sending response: %s", str);
+ ap_set_content_type(request, "text/xml");
+ ap_rputs(str, request);
+ }
+ else
+ {
+ loginfo("Sending empty response");
+ //request->status = HTTP_NO_CONTENT;
+ }
}
}
+
+ return OK;
}
else if (request->method_number == M_POST)
{
@@ -731,9 +734,6 @@
{
// Pure REST, send the location of the created
resource
- // Set the content type
- ap_set_content_type(request, "text/xml");
-
if (outputDataObject == NULL)
{
throwException(ServiceInvocationException,
"Null output from REST create operation");
@@ -762,35 +762,45 @@
const char* loc = ap_construct_url(request->pool,
locuri.c_str(), request);
loginfo("Sending resource location: %s", loc);
apr_table_setn(request->headers_out, "Location",
loc);
+ apr_table_setn(request->headers_out,
"Content-Location", loc);
request->status = HTTP_CREATED;
// Send the created resource entity back to the
client
+ ap_set_content_type(request, "text/xml");
ap_rputs(input.c_str(), request);
}
else
{
- // Command style, send the response wrapper element
+ // Command style, send the response element
- // Set the content type
- ap_set_content_type(request, "text/xml");
-
if (outputDataObject == NULL)
{
loginfo("Sending empty response");
+ //request->status = HTTP_NO_CONTENT;
}
else
{
XMLHelperPtr xm =
HelperProvider::getXMLHelper(dataFactory);
- XMLDocumentPtr doc = xm->createDocument(
- outputDataObject,
- wsdlOperation.getOutputTypeUri().c_str(),
- wsdlOperation.getOutputTypeName().c_str());
- doc->setXMLDeclaration(false);
- char* str = xm->save(doc);
-
- loginfo("Sending response: %s", str);
- ap_rputs(str, request);
+ DataObjectList& l =
outputDataObject->getList("return");
+ if (l.size() != 0)
+ {
+ DataObjectPtr resultDataObject = l[0];
+ XMLDocumentPtr doc = xm->createDocument(
+ resultDataObject,
+ resultDataObject->getType().getURI(),
+ resultDataObject->getType().getName());
+ char* str = xm->save(doc);
+
+ loginfo("Sending response: %s", str);
+ ap_set_content_type(request, "text/xml");
+ ap_rputs(str, request);
+ }
+ else
+ {
+ loginfo("Sending empty response");
+ //request->status = HTTP_NO_CONTENT;
+ }
}
}
@@ -889,10 +899,9 @@
// Dispatch to the REST proxy
DataObjectPtr outputDataObject =
proxy->invoke(wsdlOperation, inputDataObject);
-
- // Send the response back to the client
- ap_set_content_type(request, "text/xml");
-
+
+ // Empty response
+ //request->status = HTTP_NO_CONTENT;
return OK;
}
else if (request->method_number == M_DELETE)
@@ -963,10 +972,9 @@
// Dispatch to the REST proxy
DataObjectPtr outputDataObject =
proxy->invoke(wsdlOperation, inputDataObject);
-
- // Send the response back to the client
- ap_set_content_type(request, "text/xml");
-
+
+ // Empty response
+ //request->status = HTTP_NO_CONTENT;
return OK;
}
else
@@ -1018,7 +1026,7 @@
{
// The input wrapper type is not known, create an open
DataObject
- inputDataObject =
dataFactory->create(Type::SDOTypeNamespaceURI, "OpenDataObject");
+ inputDataObject =
dataFactory->create("http://tempuri.org", "Wrapper");
}
}
@@ -1092,21 +1100,25 @@
{
logentry();
+
//TODO Remove this workaround once SDO supports loading of
open top level content
- // The workaround is to wrap the open content in a wrapper
element of type OpenDataObject
- string body =
- "<Body xmlns=\"http://tempuri.org\"
xmlns:tns=\"http://tempuri.org\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
- + payload
- + "</Body>";
+ // The workaround is to wrap the open content in a wrapper
element
+ string xmldecl;
+ string xml;
+ Utils::rTokeniseString("?>", payload, xmldecl, xml);
+ string body = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ body += "<Wrapper xmlns=\"http://tempuri.org\"
xmlns:tns=\"http://tempuri.org\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n";
+ body += xml;
+ body += "\n</Wrapper>";
// Convert the body to an SDO DataObject
- DataObjectPtr inputBodyDataObject = NULL;
+ DataObjectPtr inputWrapperDataObject = NULL;
XMLDocumentPtr theXMLDocument = xmlHelper->load(body.c_str(),
NULL);
if (theXMLDocument != 0)
{
- inputBodyDataObject = theXMLDocument->getRootDataObject();
+ inputWrapperDataObject =
theXMLDocument->getRootDataObject();
}
- if(!inputBodyDataObject)
+ if(!inputWrapperDataObject)
{
ostringstream msg;
msg << "Could not convert received document to SDO: " <<
body;
@@ -1115,17 +1127,17 @@
// Get the body part
DataObjectPtr inputDataObject = NULL;
- PropertyList bpl =
inputBodyDataObject->getInstanceProperties();
+ PropertyList bpl =
inputWrapperDataObject->getInstanceProperties();
if (bpl.size()!=0)
{
if (bpl[0].isMany())
{
- DataObjectList& parts =
inputBodyDataObject->getList((unsigned int)0);
+ DataObjectList& parts =
inputWrapperDataObject->getList((unsigned int)0);
inputDataObject = parts[0];
}
else
{
- inputDataObject =
inputBodyDataObject->getDataObject(bpl[0]);
+ inputDataObject =
inputWrapperDataObject->getDataObject(bpl[0]);
}
}
if (inputDataObject == NULL)
Modified:
incubator/tuscany/cpp/sca/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/RESTServiceProxy.cpp
URL:
http://svn.apache.org/viewvc/incubator/tuscany/cpp/sca/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/RESTServiceProxy.cpp?view=diff&rev=481632&r1=481631&r2=481632
==============================================================================
---
incubator/tuscany/cpp/sca/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/RESTServiceProxy.cpp
(original)
+++
incubator/tuscany/cpp/sca/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/RESTServiceProxy.cpp
Sat Dec 2 13:41:10 2006
@@ -70,11 +70,11 @@
} catch (SDORuntimeException&)
{
dataFactory->addType("http://tempuri.org", "RootType",
false, false, false);
- dataFactory->addType("http://tempuri.org", "Body", false,
true, false);
+ dataFactory->addType("http://tempuri.org", "Wrapper",
false, true, false);
dataFactory->addPropertyToType(
"http://tempuri.org", "RootType",
- "Body",
- "http://tempuri.org", "Body",
+ "Wrapper",
+ "http://tempuri.org", "Wrapper",
false, false, true);
dataFactory->addType("http://tempuri.org", "Part", false,
true, false);
dataFactory->addPropertyToType(
@@ -340,7 +340,7 @@
catch (SDORuntimeException&)
{
// The output wrapper type is not known, create an
open DataObject
- outputDataObject =
dataFactoryPtr->create(Type::SDOTypeNamespaceURI, "OpenDataObject");
+ outputDataObject =
dataFactoryPtr->create("http://tempuri.org", "Wrapper");
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]