Author: jsdelfino
Date: Fri Dec  1 08:35:53 2006
New Revision: 481281

URL: http://svn.apache.org/viewvc?view=rev&rev=481281
Log:
Client side support for creation of REST resources using POST

Modified:
    
incubator/tuscany/cpp/sca/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceWrapper.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=481281&r1=481280&r2=481281
==============================================================================
--- 
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
 Fri Dec  1 08:35:53 2006
@@ -44,11 +44,17 @@
 
 extern "C"
 {
-    struct Chunk {
+    struct ResponseChunk {
         char *memory;
         size_t size;
     };
 
+    struct RequestChunk {
+        const char *memory;
+        size_t size;
+        size_t read;
+    };
+
     static void *my_realloc(void *ptr, size_t size)
     {
         if (ptr)
@@ -60,16 +66,43 @@
     static size_t write_callback(void *ptr, size_t size, size_t nmemb, void 
*data)
     {
         size_t realsize = size * nmemb;
-        struct Chunk *mem = (struct Chunk *)data;
+        struct ResponseChunk *mem = (struct ResponseChunk *)data;
 
         mem->memory = (char *)my_realloc(mem->memory, mem->size + realsize + 
1);
-        if (mem->memory) {
-            memcpy(&(mem->memory[mem->size]), ptr, realsize);
-            mem->size += realsize;
-            mem->memory[mem->size] = 0;
-        }
+        memcpy(&(mem->memory[mem->size]), ptr, realsize);
+        mem->size += realsize;
+        mem->memory[mem->size] = 0;
         return realsize;
     }
+    
+    static size_t read_callback(void *ptr, size_t size, size_t nmemb, void 
*data)
+    {
+        size_t realsize = size * nmemb;
+        struct RequestChunk *mem = (struct RequestChunk *)data;
+
+        if (realsize < mem->size - mem->read)
+        {
+            realsize = mem->size - mem->read;
+        }
+        if (realsize != 0)
+        {
+            memcpy(ptr, &(mem->memory[mem->read]), realsize);
+        }
+        return realsize; 
+    }    
+ 
+    static size_t header_callback(void *ptr, size_t size, size_t nmemb, void 
*data)
+    {
+        size_t realsize = size * nmemb;
+        char* str = (char*)malloc(realsize + 1);
+        memcpy(str, ptr, realsize);
+        str[realsize] = 0;
+        
+        printf("Header: %s", str);
+        free(str);
+
+        return realsize; 
+    }    
  
  }
 
@@ -145,9 +178,14 @@
                 
                 // Init the curl session
                 CURL *curl_handle = curl_easy_init();
-                Chunk chunk;
-                chunk.memory=NULL;
-                chunk.size = 0;
+
+                RequestChunk requestChunk;
+                requestChunk.memory=NULL;
+                requestChunk.size = 0;
+                requestChunk.read = 0;
+                ResponseChunk responseChunk;
+                responseChunk.memory=NULL;
+                responseChunk.size = 0;
                 
                 // Some servers don't like requests that are made without a 
user-agent
                 curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, 
"libcurl-agent/1.0");
@@ -197,31 +235,57 @@
                         curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, 
write_callback);
      
                         // Pass our 'chunk' struct to the callback function
-                        curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void 
*)&chunk);
+                        curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void 
*)&responseChunk);
+     
+                        // Send all headers to this function
+                        curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, 
header_callback);
+     
+                        // Pass our 'chunk' struct to the callback function
+                        curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, 
(void *)0);
      
                         // Perform the HTTP get
                         CURLcode rc = curl_easy_perform(curl_handle);
                         
                         if (rc)
                         {
-                            if (chunk.memory)
-                                free(chunk.memory);
+                            if (responseChunk.memory)
+                                free(responseChunk.memory);
                             throwException(ServiceInvocationException, 
curl_easy_strerror(rc)); 
                         }
     
-                        // Get the output data out of the returned document 
-                        if (chunk.memory)
+                        // Get the output data out of the returned document
+                        long httprc;
+                        curl_easy_getinfo (curl_handle, 
CURLINFO_RESPONSE_CODE, &httprc);
+
+                        string responsePayload = ""; 
+                        if (responseChunk.memory)
                         {
-                            string payload((const char*)chunk.memory, 
chunk.size);
-                            free(chunk.memory);
-    
-                            // 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\";>"
-                            + payload
-                            + "</Part>";
-                            setReturn(xmlHelper, part, operation);
+                            responsePayload = string((const 
char*)responseChunk.memory, responseChunk.size);
+                            free(responseChunk.memory);
+                        }
+        
+                        if (httprc == 200)
+                        {
+                            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>";
+                                setReturn(xmlHelper, part, operation);
+                            }
+                        }
+                        else
+                        {
+                            ostringstream msg;
+                            msg << "Failed to retrieve REST resource, HTTP 
code: " << httprc;
+                            if (responsePayload != "")
+                            {
+                                msg << ", payload: " << responsePayload;
+                            } 
+                            throwException(ServiceInvocationException, 
msg.str().c_str());
                         }
                     }
                     else if (opName == "create")
@@ -232,91 +296,78 @@
                         string url = binding->getURI();  
                         curl_easy_setopt(curl_handle, CURLOPT_URL, 
url.c_str());
     
-                        // If the request contains complex content then we'll 
use
-                        // a multipart form POST, otherwise we use a simpler
-                        // url-encoded POST
-                        bool complexContent = false; 
+                        // Create the input payload     
+                        ostringstream spayload;
                         for (int i=0; i<operation.getNParms(); i++)
                         {
-                            if (operation.getParameter(i).getType() == 
Operation::DATAOBJECT)
-                            {
-                                complexContent = true;
-                                break;
-                            }
-                        }
-                        struct curl_httppost *formpost = NULL;
-                        if (complexContent)
-                        {
-                            // Build the input form
-                            struct curl_httppost *lastptr = NULL;
-                            for (int i=0; i<operation.getNParms(); i++)
-                            {
-                                ostringstream pname;
-                                pname << "param" << (i+1);
-                                
-                                ostringstream pvalue;
-                                writeParameter(xmlHelper, pvalue, 
operation.getParameter(i));
-                                
-                                curl_formadd(&formpost,
-                                    &lastptr,
-                                    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);
+                            writeParameter(xmlHelper, spayload, 
operation.getParameter(i));
                         }
-                        else
-                        {
-                            // Build the request string
-                            // Add the parameters in the form // param=value&
-                            ostringstream os;
-                            for (int i=0; i<operation.getNParms(); i++)
-                            {
-                                os << "param" << (i + 1) << "=";
-                                writeParameter(xmlHelper, os, 
operation.getParameter(i));
-                                if (i < operation.getNParms()-1)
-                                    os << "&";
-                            }
-                            curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, 
os.str().c_str());
-                        }                    
-                            
+                        const string& requestPayload = spayload.str(); 
+                        requestChunk.memory = requestPayload.c_str();
+                        requestChunk.size = requestPayload.size();
+                        
+                        curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, 
requestChunk.size);
+                        
+                        // 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);
+                        
                         // Send all data to this function
                         curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, 
write_callback);
      
                         // Pass our 'chunk' struct to the callback function
-                        curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void 
*)&chunk);
+                        curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void 
*)&responseChunk);
+     
+                        // Send all headers to this function
+                        curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, 
header_callback);
      
+                        // Pass our 'chunk' struct to the callback function
+                        curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, 
(void *)0);
+
+                        // Configure headers
+                        curl_slist *requestHeaders = NULL;
+                        requestHeaders = curl_slist_append(requestHeaders, 
"Content-Type: text/xml");
+                        requestHeaders = curl_slist_append(requestHeaders, 
"Expect:");
+                        curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, 
requestHeaders);
+                                                
                         // Perform the HTTP post
+                        curl_easy_setopt(curl_handle, CURLOPT_POST, true);
                         CURLcode rc = curl_easy_perform(curl_handle);
                         
-                        // Cleanup the form
-                        if (complexContent)
-                        {
-                            curl_formfree(formpost);
-                        }                    
+                        curl_slist_free_all(requestHeaders);
                         
                         if (rc)
                         {
-                            if (chunk.memory)
-                                free(chunk.memory);
                             throwException(ServiceInvocationException, 
curl_easy_strerror(rc)); 
                         }
-    
-                        // Get the output data out of the returned document 
-                        if (chunk.memory)
+                        
+                        // Get the output and location of the created resource
+                        string responsePayload = "";
+                        if (responseChunk.memory)
                         {
-                            string payload((const char*)chunk.memory, 
chunk.size);
-                            free(chunk.memory);
-    
-                            // 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\";>"
-                            + payload
-                            + "</Part>";
-                            setReturn(xmlHelper, part, operation);
+                            responsePayload = string((const 
char*)responseChunk.memory, responseChunk.size);
+                            free(responseChunk.memory);
+                        }
+                        
+                        long httprc;
+                        curl_easy_getinfo (curl_handle, 
CURLINFO_RESPONSE_CODE, &httprc);
+                        if (httprc == 201)
+                        {
+                            string* location = new string;
+                            *location = "http://wherever.org";;
+                            operation.setReturnValue(location);
+                        }
+                        else
+                        {
+                            ostringstream msg;
+                            msg << "Failed to create REST resource, HTTP code: 
" << httprc;
+                            if (responsePayload != "")
+                            {
+                                msg << ", payload: " << responsePayload;
+                            } 
+                            throwException(ServiceInvocationException, 
msg.str().c_str());
                         }
                     }
                     else if (opName == "update")
@@ -408,7 +459,7 @@
                     curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, 
write_callback);
  
                     // Pass our 'chunk' struct to the callback function
-                    curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void 
*)&chunk);
+                    curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void 
*)&responseChunk);
  
                     // Perform the HTTP request
                     CURLcode rc = curl_easy_perform(curl_handle);
@@ -421,15 +472,15 @@
                     
                     if (rc)
                     {
-                        if (chunk.memory)
-                            free(chunk.memory);
+                        if (responseChunk.memory)
+                            free(responseChunk.memory);
                         throwException(ServiceInvocationException, 
curl_easy_strerror(rc)); 
                     }
  
-                    if (chunk.memory)
+                    if (responseChunk.memory)
                     {
-                        string payload((const char*)chunk.memory, chunk.size);
-                        free(chunk.memory);
+                        string payload((const char*)responseChunk.memory, 
responseChunk.size);
+                        free(responseChunk.memory);
                         
                         setReturn(xmlHelper, payload, operation);
                     }
@@ -509,6 +560,7 @@
                     {
                         DataObjectPtr dob = *(DataObjectPtr*)parm.getValue(); 
                         XMLDocumentPtr doc = xmlHelper->createDocument(dob, 
NULL, NULL);
+                        doc->setXMLDeclaration(false);
                         xmlHelper->save(doc, os);
                         break;
                     }
@@ -542,8 +594,9 @@
                 }
                 if(!outputBodyDataObject)
                 {
-                    logerror("Could not convert received document to SDO: %s", 
body.c_str());
-                    return;
+                    ostringstream msg;
+                    msg << "Could not convert received document to SDO: " << 
body;
+                    throwException(ServiceDataException, msg.str().c_str());
                 }                    
 
                 // Get the body part
@@ -563,8 +616,9 @@
                 }
                 if (outputDataObject == NULL)
                 {
-                    logerror("Could not convert body part to SDO: %s", 
body.c_str());
-                    return;
+                    ostringstream msg;
+                    msg << "Could not convert body part to SDO: " << body;
+                    throwException(ServiceDataException, msg.str().c_str());
                 }
                  
                 PropertyList pl = outputDataObject->getInstanceProperties();



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to