/* * 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$ */ #ifndef tuscany_webservice_hpp #define tuscany_webservice_hpp /** * Web service invocation functions using Axis2. */ #include "config.hpp" // Ignore redundant declarations in Axiom headers #ifdef WANT_MAINTAINER_WARNINGS #pragma GCC diagnostic ignored "-Wredundant-decls" #endif #include #include #include #include #include #include #include #ifdef WANT_MAINTAINER_WARNINGS #pragma GCC diagnostic warning "-Wredundant-decls" #endif #include "string.hpp" #include "sstream.hpp" #include "list.hpp" #include "value.hpp" #include "xml.hpp" #include "monad.hpp" namespace tuscany { namespace webservice { /** * Represents an Axis2 runtime context. */ class Axis2Context { public: Axis2Context() : env(axutil_env_create_all("axis2.log", AXIS2_LOG_LEVEL_WARNING)), owner(true) { debug("webservice::axis2context"); } Axis2Context(const Axis2Context& ax) : env(ax.env), owner(false) { debug("webservice::axis2context::copy"); } const Axis2Context& operator=(const Axis2Context& ax) { debug("webservice::axis2context::operator="); if(this == &ax) return *this; env = ax.env; owner = false; return *this; } Axis2Context(const axutil_env_t* env) : env(const_cast(env)), owner(false) { debug("webservice::axis2context::env"); } ~Axis2Context() { debug("webservice::~axis2context"); if (!owner || env == NULL) return; axutil_env_free(env); } private: axutil_env_t* env; bool owner; friend const axutil_env_t* env(const Axis2Context& ax); }; const axutil_env_t* env(const Axis2Context& ax) { return ax.env; } /** * Return the latest Axis2 error in an Axis2 context. */ const string axis2Error(const Axis2Context& ax) { ostringstream os; os << env(ax)->error->error_number << " : " << AXIS2_ERROR_GET_MESSAGE(env(ax)->error); return str(os); } /** * Convert a string to an Axiom node. */ const failable stringToAxiomNode(const string& s, const Axis2Context& ax) { axiom_node_t* node = axiom_node_create_from_buffer(env(ax), const_cast(c_str(s))); if (node == NULL) return mkfailure(string("Couldn't convert XML to Axiom node: ") + axis2Error(ax)); return node; } /** * Convert a list of values representing XML elements to an Axiom node. */ const failable valuesToAxiomNode(const list& l, const Axis2Context& ax) { const failable > xml = writeXML(valuesToElements(l), false); if (!hasContent(xml)) return mkfailure(xml); ostringstream os; write(content(xml), os); return stringToAxiomNode(str(os), ax); } /** * Convert an axiom node to a string. */ const failable axiomNodeToString(axiom_node_t* node, const Axis2Context& ax) { const char* c = axiom_node_to_string(node, env(ax)); if (c == NULL) return mkfailure(string("Couldn't convert Axiom node to XML: ") + axis2Error(ax)); const string s(c); AXIS2_FREE(env(ax)->allocator, const_cast(c)); return s; } /** * Convert an axiom node to a list of values representing XML elements. */ const failable > axiomNodeToValues(axiom_node_t* node, const Axis2Context& ax) { const failable s = axiomNodeToString(node, ax); if (!hasContent(s)) return mkfailure >(s); istringstream is(content(s)); const failable > l = readXML(streamList(is)); if (!hasContent(l)) return l; return elementsToValues(content(l)); } /** * Evaluate an expression in the form (soap-action-string, document, uri). Send the * SOAP action and document to the Web Service at the given URI using Axis2. */ const failable evalExpr(const value& expr, const Axis2Context& ax) { debug(expr, "webservice::evalExpr::input"); // Extract func name and single argument const value func(car(expr)); const list param(cadr(expr)); const value uri(caddr(expr)); // Create Axis2 client axis2_svc_client_t *client = axis2_svc_client_create(env(ax), getenv("AXIS2C_HOME")); if (client == NULL) return mkfailure("Couldn't create Axis2 client: " + axis2Error(ax)); axis2_endpoint_ref_t *epr = axis2_endpoint_ref_create(env(ax), c_str(uri)); axis2_options_t *opt = axis2_options_create(env(ax)); axis2_options_set_to(opt, env(ax), epr); axis2_options_set_action(opt, env(ax), (const axis2_char_t*)c_str(func)); axis2_svc_client_set_options(client, env(ax), opt); axis2_svc_client_engage_module(client, env(ax), AXIS2_MODULE_ADDRESSING); // Construct request Axiom node const failable req = valuesToAxiomNode(param, ax); if (!hasContent(req)) return mkfailure(req); // Call the Web service axiom_node_t* res = axis2_svc_client_send_receive(client, env(ax), content(req)); if (res == NULL) { axis2_svc_client_free(client, env(ax)); return mkfailure("Couldn't invoke Axis2 service: " + axis2Error(ax)); } // Parse result Axiom node const failable > lval = axiomNodeToValues(res, ax); if (!hasContent(lval)) return mkfailure(lval); const value rval = content(lval); debug(rval, "webservice::evalExpr::result"); // Cleanup axis2_svc_client_free(client, env(ax)); return rval; } } } #endif /* tuscany_webservice_hpp */