Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

CorbaCall.cpp

Go to the documentation of this file.
00001 
00005 /* --------------------------------------------------------------
00006 Copyright (C) 2001 LifeLine Networks BV <soap2corba@lifeline.nl>
00007 
00008 This program is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU General Public License
00010 as published by the Free Software Foundation; either
00011 version 2 of the License, or (at your option) any later
00012 version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00022 -------------------------------------------------------------- */
00023 #include <iostream.h>
00024 #include <OB/CORBA.h>
00025 #include <OB/CosNaming.h>
00026 #include "BridgeStub.h"
00027 #include "Parser.h"
00028 #include "StdAfx.h"
00029 #include "SoapCorba.h"
00030 #include "DbObjects.h"
00031 #include "ReadIR.h"
00032 #include "SoapBridge.h"
00033 #include "SoapBridge_skel.h"
00034 #include "sbimpl.h"
00035 #include "curl/curl.h"
00036 
00037 CORBA::Boolean AnyInterface::_is_a (const char *name)
00038     throw (CORBA::SystemException)
00039 {
00040     CString idl = "IDL:";
00041     idl += m_Intf;
00042     idl += ":1.0";
00043     CORBA::Boolean _r = idl.Compare (name) == 0;
00044     if (!_r) {
00045         corbaBridgeLog->error ("AnyInterface::_is_a: %s != %s\n", (const char *) idl, name);
00046     }
00047     return _r;
00048 }
00049 
00050 size_t curlWriter (void *ptr, size_t siz, size_t num, void *pStream)
00051 {
00052     CString *pcs = (CString *) pStream;
00053     CString cop ((char *) ptr, siz * num);
00054     *pcs += cop;
00055     return siz * num;
00056 }
00057 
00064 void AnyInterface::ErrorCallback (const char *name, const char *msg)
00065 {
00066     corbaBridgeLog->warn ("CCerr: %s, %s/%s (%s): %s", 
00067         (const char *) m_Addr, (const char *) m_Intf, name, (const char *) m_Ctxk, msg);
00068     if (!CORBA::is_nil (m_cb)) {
00069         try {
00070             m_cb->tellMe (m_Addr, m_Intf, name, m_Ctxk, msg);
00071             corbaBridgeLog->info ("Succesfully informed caller of error");
00072         }
00073         catch (...) {
00074             corbaBridgeLog->warn ("Could not tell caller, failed to invoke callback.");
00075         }
00076     } else {
00077         corbaBridgeLog->warn ("Could not tell caller, no callback was registered.");
00078     }
00079 }
00080 
00092 void AnyInterface::invoke (CORBA::ServerRequest_ptr request) throw ()
00093 {
00094     CORBA::String_var name = request->operation ();
00095     CString mp = "/";
00096     mp += m_Intf;
00097     mp += "/";
00098     mp += (const char *) name;
00099     CString spAct = m_Intf;
00100     spAct += '#';
00101     spAct += (const char *) name;
00102     corbaBridgeLog->info ("CORBACall::invoke (%s)\n", (const char *) mp);
00103     ParList_Holder _plhold;
00104     SCParamList *pParList = NULL;
00105     
00106     {
00107         IRPlus *pIRP = (IRPlus *) irplusHandle;
00108         JTCSynchronized synchronized (pIRP->monitor);
00109         SCInterfaceMethod *pMeth = pIRP->IRC.FindInterfaceMethod (mp);
00110         if (!pMeth) {
00111             ErrorCallback (name, "No such interface/method in the repository");
00112             CORBA::Any exAny;
00113             exAny <<= new CORBA::BAD_OPERATION ();
00114             request -> set_exception(exAny);
00115             return;
00116         }
00117         _plhold.pParList = pParList = new SCParamList (pMeth, dynFact);
00118     }
00119     {
00120         CORBA::NVList_ptr list;
00121         orb->create_list (0, list);
00122         SCParamList::ParamValueIterator iParVal (pParList);
00123         while (++iParVal) {
00124             CORBA::TypeCode_var tc = iParVal->GetDynAnyPtr ()->type ();
00125             if (iParVal->m_prmKind == ioeIn) {
00126                 list->add (CORBA::ARG_IN)->value ()->replace (tc, 0);
00127             }
00128             if (iParVal->m_prmKind == ioeInOut) {
00129                 list->add (CORBA::ARG_INOUT)->value ()->replace (tc, 0);
00130             }
00131         }
00132         request->arguments (list);
00133         iParVal.Reset ();
00134 
00135         DOM_Document doc;
00136         DOM_Element envel;
00137         DOM_Element body;
00138         createEmptySoap (doc, envel, body);
00139         {
00140             DOM_Element hd;
00141             addHeader (doc, envel, hd, 
00142                 NULL, // ll:ObjRef
00143                 m_Ctxk.IsEmpty () ? NULL : (const char *) m_Ctxk, // ll:Context
00144                 (const char *) spAct);
00145         }
00146         DOM_Element methNode = addElement (doc, body, name);
00147         body.setAttribute ("xmlns:m", (const char *) mp);
00148         unsigned int listPtr = 0;
00149         while (++iParVal) {
00150             if (iParVal->m_prmKind == ioeIn || iParVal->m_prmKind == ioeInOut) {
00151                 DOM_Element insNode = addElement (doc, methNode, iParVal->m_prmName);
00152                 CORBA::Any aar (*(list->item (listPtr)->value ()));
00153                 DynamicAny::DynAny_var tmpDa = dynFact->create_dyn_any (aar);
00154                 DynAny2Xml (doc, insNode, iParVal, tmpDa, m_Ctxk);
00155             }
00156             if (iParVal->m_prmKind != ioeException && iParVal->m_prmName.Compare ("return") != 0) {
00157                 listPtr ++;
00158             }
00159         }
00160         unsigned char *outXml = NULL;
00161         unsigned long outXmlSiz = 0;
00162         CString answer;
00163         CURLcode result;
00164         GetXML (outXml, outXmlSiz, (DOM_H) &doc);
00165         {
00166             CURL *curl;
00167             curl = curl_easy_init ();
00168             if (curl) {
00169                 curl_easy_setopt (curl, CURLOPT_URL, (const char *) m_Addr);
00170                 curl_easy_setopt (curl, CURLOPT_TIMEOUT, 10);
00171                 curl_easy_setopt (curl, CURLOPT_POST, 1);
00172                 curl_easy_setopt (curl, CURLOPT_POSTFIELDS, outXml);
00173                 curl_easy_setopt (curl, CURLOPT_POSTFIELDSIZE, outXmlSiz);
00174                 struct curl_slist *pList = NULL;
00175                 CString sa = "SOAPAction: " + spAct;
00176                 pList = curl_slist_append (pList, (const char *) sa);
00177                 curl_easy_setopt (curl, CURLOPT_HTTPHEADER, pList);
00178                 curl_easy_setopt (curl, CURLOPT_FILE, &answer);
00179                 curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, curlWriter);
00180                 corbaBridgeLog->debug ("Calling SOAP Server...\n");
00181                 result = curl_easy_perform (curl);
00182                 curl_easy_cleanup (curl);
00183                 corbaBridgeLog->info ("Call result=%d\n", result);
00184             } else {
00185                 ErrorCallback (name, "Server error: cURL init failed");
00186                 CORBA::Any exAny;
00187                 exAny <<= new CORBA::BAD_OPERATION ();
00188                 request -> set_exception(exAny);
00189                 return;
00190             }
00191         }        
00192         delete outXml;
00193         if (!result) {
00194             try {
00195                 corbaBridgeLog->debug ("Result=%s\n", (const char *) answer);
00196                 DOM_Holder Holder (parseDOM ((const unsigned char *) (const char *) answer, answer.GetLength ()));
00197                 if (Holder.domHdl) {
00198                     DOM_Document Doc = *((DOM_Document *) Holder.domHdl);
00199                     HrefIdMap HrefMap;
00200                     HrefMap.Build (Doc);
00201 
00202                     // First we parse the SOAP for the bits that interest us and to determine its sanety.
00203 
00204                     DOM_Element soapEnvelope;
00205                     {
00206                         DOM_Node sNode = Doc.getFirstChild ();
00207                         DOMTRACE (sNode.getNodeName ());
00208                         while (sNode != NULL && sNode.getNodeType () != DOM_Node::ELEMENT_NODE) {
00209                             sNode = sNode.getNextSibling ();
00210                         }
00211                         DOMString envelopeTag ("Envelope");
00212                         if (sNode == NULL || !envelopeTag.equals (sNode.getLocalName ())) {
00213                             ErrorCallback (name, "SOAP response error: No SOAP Envelope");
00214                             CORBA::Any exAny;
00215                             exAny <<= new CORBA::BAD_OPERATION ();
00216                             request -> set_exception(exAny);
00217                             return;
00218                         }
00219                         HrefMap.RealNode (soapEnvelope, sNode);
00220                     }
00221                     DOM_Element soapBody;
00222                     {
00223                         DOM_Node sNode = soapEnvelope.getFirstChild ();
00224                         DOMTRACE (sNode.getLocalName ());
00225                         while (sNode != NULL && sNode.getNodeType () != DOM_Node::ELEMENT_NODE) {
00226                             sNode = sNode.getNextSibling ();
00227                         }
00228                         DOMString headerTag ("Header");
00229                         if (sNode != NULL && headerTag.equals (sNode.getLocalName ())) {
00230                             sNode = sNode.getNextSibling ();
00231                         }
00232                         DOMTRACE (sNode.getNodeName ());
00233                         while (sNode != NULL && sNode.getNodeType () != DOM_Node::ELEMENT_NODE) {
00234                             sNode = sNode.getNextSibling ();
00235                         }
00236                         DOMString bodyTag ("Body");
00237                         if (sNode == NULL || !bodyTag.equals (sNode.getLocalName ())) {
00238                             ErrorCallback (name, "SOAP response error: No SOAP Body");
00239                             CORBA::Any exAny;
00240                             exAny <<= new CORBA::BAD_OPERATION ();
00241                             request -> set_exception(exAny);
00242                             return;
00243                         }
00244                         HrefMap.RealNode (soapBody, sNode);
00245                     }
00246                     
00247                     // Check for response or fault
00248                     DOM_Element soapResp;
00249                     {
00250                         DOM_Node sNode = soapBody.getFirstChild ();
00251                         while (sNode != NULL && sNode.getNodeType () != DOM_Node::ELEMENT_NODE) {
00252                             sNode = sNode.getNextSibling ();
00253                         }
00254                         DOMString responseTag (name);
00255                         responseTag += "Response";
00256                         DOMString faultTag ("SOAP-ENV:Fault");
00257                         if (sNode != NULL && responseTag.equals (sNode.getLocalName ())) {
00258                             DOM_Node parNode = sNode.getFirstChild ();
00259                             while (parNode != NULL && parNode.getNodeType () != DOM_Node::ELEMENT_NODE) {
00260                                 parNode = parNode.getNextSibling ();
00261                             }
00262                             iParVal.Reset ();
00263                             listPtr = 0;
00264                             while (++iParVal) {
00265                                 if (iParVal->m_prmKind == ioeOut && iParVal->m_prmName.Compare ("return") == 0) {
00266                                     DOMString returnTag ("return");
00267                                     if (parNode != NULL && returnTag.equals (parNode.getLocalName ())) {
00268                                         // return value
00269                                         DOM_Element methodParm;
00270                                         HrefMap.RealNode (methodParm, parNode);
00271                                         if (parNode != NULL) {
00272                                             do {
00273                                                 parNode = parNode.getNextSibling ();
00274                                             } while (parNode != NULL && parNode.getNodeType () != DOM_Node::ELEMENT_NODE);
00275                                         }
00276                                         try {
00277                                             FillInDynAny (HrefMap, iParVal, iParVal->GetDynAnyPtr (), methodParm);
00278                                         }
00279                                         catch (DOM_Document &) {
00280                                             ErrorCallback (name, "SOAP Fault thrown from FillInDynAny");
00281                                             CORBA::Any exAny;
00282                                             exAny <<= new CORBA::BAD_OPERATION ();
00283                                             request -> set_exception(exAny);
00284                                             return;
00285                                         }
00286                                         catch (...) {
00287                                             soapBridgeLog->crit ("Unknown Exception in FillInDynAny\n");
00288                                             abort ();
00289                                         }
00290                                         CORBA::Any_var an = iParVal->GetDynAnyPtr ()->to_any ();
00291                                         request -> set_result(an);
00292                                     }
00293                                 } else if (iParVal->m_prmKind == ioeOut || iParVal->m_prmKind == ioeInOut) {
00294                                     if (parNode != NULL) {
00295                                         DOM_Element methodParm;
00296                                         HrefMap.RealNode (methodParm, parNode);
00297                                         if (parNode != NULL) {
00298                                             do {
00299                                                 parNode = parNode.getNextSibling ();
00300                                             } while (parNode != NULL && parNode.getNodeType () != DOM_Node::ELEMENT_NODE);
00301                                         }
00302                                         try {
00303                                             FillInDynAny (HrefMap, iParVal, iParVal->GetDynAnyPtr (), methodParm);
00304                                         }
00305                                         catch (DOM_Document &) {
00306                                             ErrorCallback (name, "SOAP Fault thrown from FillInDynAny");
00307                                             CORBA::Any exAny;
00308                                             exAny <<= new CORBA::BAD_OPERATION ();
00309                                             request -> set_exception(exAny);
00310                                             return;
00311                                         }
00312                                         catch (...) {
00313                                             soapBridgeLog->crit ("Unknown Exception in FillInDynAny\n");
00314                                             abort ();
00315                                         }
00316                                         CORBA::Any_var an = iParVal->GetDynAnyPtr ()->to_any ();
00317                                         CORBA::Any *pAny = list->item (listPtr)->value ();
00318                                         *pAny = an;
00319                                     } else {
00320                                         CString misPar;
00321                                         misPar.Format ("Missing parameter '%s' in SOAP response", 
00322                                             (const char *) iParVal->m_prmName);
00323                                         ErrorCallback (name, misPar);
00324                                         CORBA::Any exAny;
00325                                         exAny <<= new CORBA::BAD_OPERATION ();
00326                                         request -> set_exception(exAny);
00327                                         return;
00328                                     }
00329                                     listPtr ++;
00330                                 } else if (iParVal->m_prmKind == ioeIn) {
00331                                     listPtr ++;
00332                                 }
00333                             }
00334                         } else if (sNode != NULL && faultTag.equals (sNode.getNodeName ())) {
00335                             // we have a fault
00336                             GetXML (outXml, outXmlSiz, (DOM_H) &sNode);
00337                             CString cs ((const char *) outXml, outXmlSiz);
00338                             delete outXml;
00339                             ErrorCallback (name, (const char *) cs);
00340                             CORBA::Any exAny;
00341                             exAny <<= new CORBA::BAD_OPERATION ();
00342                             request -> set_exception(exAny);
00343                             return;
00344                         } else {
00345                             ErrorCallback (name, "SOAP response error: Neither a response nor a Fault was returned");
00346                             CORBA::Any exAny;
00347                             exAny <<= new CORBA::BAD_OPERATION ();
00348                             request -> set_exception(exAny);
00349                             return;
00350                         }
00351                     }
00352 
00353                 } else {
00354                     ErrorCallback (name, "Failed to parse SOAP response.");
00355                     CORBA::Any exAny;
00356                     exAny <<= new CORBA::BAD_OPERATION ();
00357                     request -> set_exception(exAny);
00358                     return;
00359                 }
00360             }
00361             catch (...) {
00362                 ErrorCallback (name, "An exception occured while processing the SOAP response.");
00363                 CORBA::Any exAny;
00364                 exAny <<= new CORBA::BAD_OPERATION ();
00365                 request -> set_exception(exAny);
00366                 return;
00367             }
00368         } else {
00369             ErrorCallback (name, "Failed to call SOAP server.");
00370             CORBA::Any exAny;
00371             exAny <<= new CORBA::BAD_OPERATION ();
00372             request -> set_exception(exAny);
00373             return;
00374         }
00375     }
00376 }
00377 
00378 CORBA::RepositoryId AnyInterface::_primary_interface (
00379     const PortableServer::ObjectId &oid,
00380     PortableServer::POA_ptr pPoa)
00381 {
00382     CString idl = "IDL:";
00383     idl += m_Intf;
00384     idl += ":1.0";
00385     return CORBA::string_dup ((const char *) idl);
00386 }
00387 
00388 //
00389 // IDL:SOAPBridge/CORBACall:1.0
00390 //
00391 SOAPBridge::CORBACall_impl::CORBACall_impl(PortableServer::POA_ptr poa)
00392     : poa_(PortableServer::POA::_duplicate(poa))
00393 {
00394 }
00395 
00396 SOAPBridge::CORBACall_impl::~CORBACall_impl()
00397 {
00398 }
00399 
00400 PortableServer::POA_ptr SOAPBridge::CORBACall_impl::_default_POA()
00401 {
00402     return PortableServer::POA::_duplicate(poa_);
00403 }
00404 
00405 //
00406 // IDL:SOAPBridge/CORBACall/contextKey:1.0
00407 //
00408 char* SOAPBridge::CORBACall_impl::contextKey()
00409     throw(CORBA::SystemException)
00410 {
00411     // TODO: Implementation
00412     char* _r = CORBA::string_dup(ctxKey);
00413     return _r;
00414 }
00415 
00416 void SOAPBridge::CORBACall_impl::contextKey(const char* a)
00417     throw(CORBA::SystemException)
00418 {
00419     ctxKey = a;
00420 }
00421 
00422 //
00423 // IDL:SOAPBridge/CORBACall/CreateSession:1.0
00424 //
00425 CORBA::Object_ptr SOAPBridge::CORBACall_impl::CreateSession(const char* soapAddress,
00426                                           const char* intfName,
00427                                           CORBA::Boolean obtainContextKey,
00428                                           SOAPBridge::CORBACallback_ptr cb)
00429     throw(CORBA::SystemException)
00430 {
00431     corbaBridgeLog->info ("SOAPBridge::CORBACall_impl::CreateSession:%s/%s\n", soapAddress, intfName);
00432     if (obtainContextKey) {
00433         // let's hope their SOAP server will give me one
00434         AnyInterface cki (soapAddress, "SOAPBridge/ContextManager", "", SOAPBridge::CORBACallback::_nil());
00435         PortableServer::ObjectId_var ckid = poa_ -> activate_object (&cki);
00436         CORBA::Object_var obj = poa_ -> id_to_reference (ckid);
00437         SOAPBridge::ContextManager_var man = SOAPBridge::ContextManager::_narrow (obj);
00438         CString userId = soapAddress;
00439         userId += intfName;
00440         SOAPBridge::ContextManager::SOAPContext_var tmp = man->allocateContext (1800, userId);
00441         ctxKey = (char *) tmp->contextKey;
00442     }
00443     AnyInterface *pi = new AnyInterface (soapAddress, intfName, ctxKey, cb);
00444     PortableServer::ObjectId_var id = poa_ -> activate_object (pi);
00445     return poa_ -> id_to_reference (id);
00446 }
00447 
00448 //
00449 // IDL:SOAPBridge/CORBACall/DestroySession:1.0
00450 //
00451 void SOAPBridge::CORBACall_impl::DestroySession(CORBA::Object_ptr sessionObject)
00452     throw(CORBA::SystemException)
00453 {
00454     CORBA::release (sessionObject);
00455 }
00456 

This documentation is part of the "SOAP to CORBA bridge" project
Copyright © 2000 by Lifeline Networks bv.
All rights are reserved.