/pkginfo
/stamp-h1
/xmltooling.spec
+/.settings
io/AbstractXMLObjectUnmarshaller.cpp \
signature/impl/KeyInfoImpl.cpp \
signature/impl/KeyInfoSchemaValidators.cpp \
+ soap/impl/SOAPClient.cpp \
soap/impl/SOAPImpl.cpp \
soap/impl/SOAPSchemaValidators.cpp \
soap/impl/CURLSOAPTransport.cpp \
#ifndef __xmltooling_soap11client_h__
#define __xmltooling_soap11client_h__
-#include <xmltooling/soap/SOAP.h>
+#include <xmltooling/security/KeyInfoSource.h>
#include <xmltooling/soap/SOAPTransport.h>
namespace soap11 {
-
+
+ class XMLTOOL_API Envelope;
+
/**
* Implements SOAP 1.1 messaging over a transport.
*
* In the abstract, this can be a one-way exchange, or use asynchronous
- * transports, but this is mostly theoretical.
+ * transports, but this is mostly theoretical at this point.
*/
class XMLTOOL_API SOAPClient
{
MAKE_NONCOPYABLE(SOAPClient);
public:
- SOAPClient() : m_response(NULL) {}
+ SOAPClient() : m_validate(false), m_transport(NULL) {}
virtual ~SOAPClient();
/**
- * Sends the supplied envelope to the identified recipient/endpoint.
+ * Controls schema validation of incoming XML messages.
+ * This is separate from other forms of programmatic validation of objects,
+ * but can detect a much wider range of syntax errors.
*
- * <p>The caller is responsible for freeing the outgoing envelope.
+ * @param validate true iff the client should use a validating XML parser
+ */
+ void setValidating(bool validate=true) {
+ m_validate = validate;
+ }
+
+ /**
+ * Sends the supplied envelope to the identified recipient/endpoint.
*
* <p>The client object will instantiate a transport layer object
* appropriate for the endpoint URL provided and supply it to the
* prepareTransport() method below.
*
* @param env SOAP envelope to send
- * @param to identifier/name of party to send message to
+ * @param peer peer to send message to, expressed in TrustEngine terms
* @param endpoint URL of endpoint to recieve message
*/
- virtual void send(const Envelope* env, const char* to, const char* endpoint);
+ virtual void send(const Envelope* env, const xmltooling::KeyInfoSource& peer, const char* endpoint);
/**
* Returns the response message, if any. As long as a response is
* "expected" but not available, NULL will be returned. If no response
* will be forthcoming, an exception is raised.
*
- * <p>The caller is responsible for freeing the incoming envelope.
+ * <p>The caller is responsible for freeing the returned envelope.
+ *
+ * <p>Once a response is returned, the object will be reset for a subsequent call.
*/
virtual Envelope* receive();
+
+ /**
+ * Resets the object for another call.
+ */
+ virtual void reset();
protected:
/**
* Allows client to supply transport-layer settings prior to sending message.
*
* @param transport reference to transport layer
- * @return true iff transport preparation was successful
*/
- virtual bool prepareTransport(const xmltooling::SOAPTransport& transport) {}
+ virtual void prepareTransport(const xmltooling::SOAPTransport& transport) {}
+ /** Flag controlling schema validation. */
+ bool m_validate;
+
/** Holds response until retrieved by caller. */
- Envelope* m_response;
+ xmltooling::SOAPTransport* m_transport;
};
};
#endif
/**
- * Sends a stream of data over the transport, and writes the results into another.
+ * Sends a stream of data over the transport. The function may return without
+ * having received any data, depending on the nature of the transport.
*
* @param in input stream to send
- * @param out output stream to write result into
*/
- virtual size_t send(std::istream& in, std::ostream& out)=0;
+ virtual void send(std::istream& in)=0;
+
+ /**
+ * Returns reference to response stream. The resulting stream must be
+ * checked directly to determine whether data is available.
+ *
+ * @return reference to a stream containing the response, if any
+ */
+ virtual std::istream& receive()=0;
/**
* Returns the MIME type of the response, if any.
curl_easy_setopt(m_handle,CURLOPT_HTTPAUTH,0);
curl_easy_setopt(m_handle,CURLOPT_USERPWD,NULL);
curl_easy_setopt(m_handle,CURLOPT_HEADERDATA,this);
+ m_headers=curl_slist_append(m_headers,"Content-Type: text/xml");
}
virtual ~CURLSOAPTransport() {
return true;
}
- size_t send(istream& in, ostream& out);
+ void send(istream& in);
+
+ istream& receive() {
+ return m_stream;
+ }
string getContentType() const;
const KeyInfoSource& m_peer;
string m_endpoint;
CURL* m_handle;
+ stringstream m_stream;
mutable struct curl_slist* m_headers;
map<string,vector<string> > m_response_headers;
mutable const OpenSSLCredentialResolver* m_credResolver;
return content_type ? content_type : "";
}
-size_t CURLSOAPTransport::send(istream& in, ostream& out)
+void CURLSOAPTransport::send(istream& in)
{
#ifdef _DEBUG
xmltooling::NDC ndc("send");
// caller should have executed any set functions to manipulate it.
// Setup standard per-call curl properties.
- size_t content_length=0;
- pair<ostream*,size_t*> output = make_pair(&out,&content_length);
curl_easy_setopt(m_handle,CURLOPT_POST,1);
curl_easy_setopt(m_handle,CURLOPT_READDATA,&in);
- curl_easy_setopt(m_handle,CURLOPT_FILE,&output);
+ curl_easy_setopt(m_handle,CURLOPT_FILE,&m_stream);
curl_easy_setopt(m_handle,CURLOPT_DEBUGDATA,&log_curl);
char curl_errorbuf[CURL_ERROR_SIZE];
string("CURLSOAPTransport::send() failed while contacting SOAP responder: ") +
(curl_errorbuf[0] ? curl_errorbuf : "no further information available"));
}
-
- return content_length;
}
// callback to buffer headers from server
// callback to buffer data from server
size_t xmltooling::curl_write_hook(void* ptr, size_t size, size_t nmemb, void* stream)
{
- pair<ostream*,size_t*>* output = reinterpret_cast<pair<ostream*,size_t*>*>(stream);
size_t len = size*nmemb;
- output->first->write(reinterpret_cast<const char*>(ptr),len);
- *(output->second) += len;
+ reinterpret_cast<stringstream*>(stream)->write(reinterpret_cast<const char*>(ptr),len);
return len;
}
--- /dev/null
+/*
+ * Copyright 2001-2006 Internet2
+ *
+ * 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
+ *
+ * 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.
+ */
+
+/**
+ * SOAPClient.cpp
+ *
+ * Implements SOAP 1.1 messaging over a transport.
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "soap/SOAP.h"
+#include "soap/SOAPClient.h"
+#include "util/XMLHelper.h"
+
+#include <sstream>
+
+using namespace soap11;
+using namespace xmltooling;
+using namespace std;
+
+SOAPClient::~SOAPClient()
+{
+ reset();
+}
+
+void SOAPClient::reset()
+{
+ delete m_transport;
+ m_transport=NULL;
+}
+
+void SOAPClient::send(const Envelope* env, const KeyInfoSource& peer, const char* endpoint)
+{
+ // Prepare a transport object.
+ const char* pch = strchr(endpoint,':');
+ if (!pch)
+ throw IOException("SOAP endpoint was not a URL.");
+ string scheme(endpoint, pch-endpoint);
+ m_transport = XMLToolingConfig::getConfig().SOAPTransportManager.newPlugin(scheme.c_str(), make_pair(&peer,endpoint));
+ prepareTransport(*m_transport);
+
+ // Serialize envelope.
+ stringstream s;
+ XMLHelper::serialize(env->marshall(), s);
+
+ // Send to peer.
+ m_transport->send(s);
+}
+
+Envelope* SOAPClient::receive()
+{
+ if (!m_transport)
+ throw IOException("No call is active.");
+
+ // If we can get the stream, then the call is still active.
+ istream& out = m_transport->receive();
+ if (!out)
+ return NULL; // nothing yet
+
+ // Parse and bind the document into an XMLObject.
+ DOMDocument* doc = (m_validate ? XMLToolingConfig::getConfig().getValidatingParser()
+ : XMLToolingConfig::getConfig().getParser()).parse(out);
+ XercesJanitor<DOMDocument> janitor(doc);
+ auto_ptr<XMLObject> xmlObject(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(), true));
+ janitor.release();
+
+ Envelope* env = dynamic_cast<Envelope*>(xmlObject.get());
+ if (!env)
+ throw IOException("Response was not a SOAP 1.1 Envelope.");
+ reset();
+ xmlObject.release();
+ return env;
+}
>\r
</File>\r
<File\r
+ RelativePath=".\soap\impl\SOAPClient.cpp"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath=".\soap\impl\SOAPImpl.cpp"\r
>\r
</File>\r