Add cache handling to SOAP transport layer.
authorcantor <cantor@de75baf8-a10c-0410-a50a-987c0e22f00f>
Fri, 8 Jan 2010 00:50:38 +0000 (00:50 +0000)
committercantor <cantor@de75baf8-a10c-0410-a50a-987c0e22f00f>
Fri, 8 Jan 2010 00:50:38 +0000 (00:50 +0000)
git-svn-id: https://svn.middleware.georgetown.edu/cpp-xmltooling/branches/REL_1@706 de75baf8-a10c-0410-a50a-987c0e22f00f

xmltooling/soap/SOAPTransport.h
xmltooling/soap/impl/CURLSOAPTransport.cpp
xmltooling/soap/impl/SOAPClient.cpp

index 3a5c345..cf5cb41 100644 (file)
@@ -24,6 +24,8 @@
 #define __xmltooling_soaptrans_h__
 
 #include <xmltooling/base.h>
+
+#include <string>
 #include <iostream>
 
 namespace xmltooling {
@@ -156,6 +158,15 @@ namespace xmltooling {
 #endif
 
         /**
+         * Installs (or clears) a pointer to an object used for cache management of the
+         * content being accessed. The lifetime of the object must be longer than the lifetime
+         * of this object.
+         *
+         * @param cacheTag  optional pointer to string used for cache management
+         */
+        virtual bool setCacheTag(std::string* cacheTag=NULL);
+
+        /**
          * Sets an implementation-specific transport provider option.
          *
          * <p>Requires knowledge of the underlying SOAPTransport implementation.
@@ -211,6 +222,13 @@ namespace xmltooling {
          * @return  MIME type of response, or an empty string
          */
         virtual std::string getContentType() const=0;
+
+        /**
+         * Returns the status code of the response.
+         *
+         * @return  transport status code, or 0 if unknown
+         */
+        virtual long getStatusCode() const;
     };
 
 #ifndef XMLTOOLING_NO_XMLSEC
index af06fbb..e7a1b1e 100644 (file)
@@ -72,7 +72,7 @@ namespace xmltooling {
 #ifndef XMLTOOLING_NO_XMLSEC
                     m_cred(NULL), m_trustEngine(NULL), m_peerResolver(NULL), m_mandatory(false),
 #endif
-                    m_ssl_callback(NULL), m_ssl_userptr(NULL), m_chunked(true), m_authenticated(false) {
+                    m_ssl_callback(NULL), m_ssl_userptr(NULL), m_chunked(true), m_authenticated(false), m_cacheTag(NULL) {
             m_handle = g_CURLPool->get(addr);
             curl_easy_setopt(m_handle,CURLOPT_URL,addr.m_endpoint);
             curl_easy_setopt(m_handle,CURLOPT_CONNECTTIMEOUT,15);
@@ -147,6 +147,11 @@ namespace xmltooling {
             return true;
         }
 
+        bool setCacheTag(string* cacheTag) {
+            m_cacheTag = cacheTag;
+            return true;
+        }
+
         bool setProviderOption(const char* provider, const char* option, const char* value) {
             if (!provider || strcmp(provider, "CURL"))
                 return false;
@@ -196,6 +201,7 @@ namespace xmltooling {
         }
 
         string getContentType() const;
+        long getStatusCode() const;
 
         bool setRequestHeader(const char* name, const char* val) {
             string temp(name);
@@ -231,6 +237,7 @@ namespace xmltooling {
         void* m_ssl_userptr;
         bool m_chunked;
         bool m_authenticated;
+        string* m_cacheTag;
 
         friend size_t XMLTOOL_DLLLOCAL curl_header_hook(void* ptr, size_t size, size_t nmemb, void* stream);
         friend CURLcode XMLTOOL_DLLLOCAL xml_ssl_ctx_callback(CURL* curl, SSL_CTX* ssl_ctx, void* userptr);
@@ -428,6 +435,14 @@ string CURLSOAPTransport::getContentType() const
     return content_type ? content_type : "";
 }
 
+long CURLSOAPTransport::getStatusCode() const
+{
+    long code=200;
+    if (curl_easy_getinfo(m_handle, CURLINFO_RESPONSE_CODE, &code) != CURLE_OK)
+        code = 200;
+    return code;
+}
+
 void CURLSOAPTransport::send(istream* in)
 {
 #ifdef _DEBUG
@@ -475,6 +490,13 @@ void CURLSOAPTransport::send(istream* in)
     if (log_curl.isDebugEnabled())
         curl_easy_setopt(m_handle,CURLOPT_VERBOSE,1);
 
+    // Check for cache tag.
+    if (m_cacheTag && !m_cacheTag->empty()) {
+        string hdr("If-None-Match: ");
+        hdr += *m_cacheTag;
+        m_headers = curl_slist_append(m_headers, hdr.c_str());
+    }
+
     // Set request headers.
     curl_easy_setopt(m_handle,CURLOPT_HTTPHEADER,m_headers);
 
@@ -505,6 +527,13 @@ void CURLSOAPTransport::send(istream* in)
             string("CURLSOAPTransport failed while contacting SOAP endpoint (") + m_endpoint + "): " +
                 (curl_errorbuf[0] ? curl_errorbuf : "no further information available"));
     }
+
+    // Check for outgoing cache tag.
+    if (m_cacheTag) {
+        const vector<string>& tags = getResponseHeader("ETag");
+        if (!tags.empty())
+            *m_cacheTag = tags.front();
+    }
 }
 
 // callback to buffer headers from server
index 1978e28..a3898a5 100644 (file)
@@ -50,6 +50,23 @@ bool SOAPTransport::setProviderOption(const char* provider, const char* option,
     return false;
 }
 
+bool SOAPTransport::setCacheTag(string* cacheTag)
+{
+    return false;
+}
+
+void SOAPTransport::send(istream* in)
+{
+    if (!in)
+        throw IOException("SOAP transport does not support an empty request body.");
+    return send(*in);
+}
+
+long SOAPTransport::getStatusCode() const
+{
+    return 0;
+}
+
 HTTPSOAPTransport::HTTPSOAPTransport()
 {
 }
@@ -78,13 +95,6 @@ void SOAPClient::reset()
     m_transport=NULL;
 }
 
-void SOAPTransport::send(istream* in)
-{
-    if (!in)
-        throw IOException("SOAP transport does not support an empty request body.");
-    return send(*in);
-}
-
 void SOAPClient::send(const Envelope& env, const SOAPTransport::Address& addr)
 {
     // Prepare a transport object.