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

SoapCall.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 
00036 static time_t gmt_offset;
00037 static time_t gmt_checked = 0;
00038 
00039 static void calc_gmt_offset (time_t now)
00040 {
00041     gmt_checked = now;
00042     // get as GMT
00043     struct tm t2 = *gmtime (&now);
00044     // mktime thinks t2 is localtime
00045     time_t t3 = mktime (&t2);
00046     // store the inverse in gmt_offset for doing conversions
00047     gmt_offset = -t3;
00048 }
00049 
00074 void SOAPBridge_SOAPCall_i::soapFault(DOM_Document &doc, FaultCode fCode, const char *fSubCode, const char *fString)
00075 {
00076     soapBridgeLog->error ("Fault: %d.%s (%s)\n", fCode, fSubCode, fString);
00077     DOM_Element envel, body;
00078     createEmptySoap (doc, envel, body);
00079     DOM_Element fault = addElement (doc, body, "SOAP-ENV:Fault");
00080     {
00081         DOM_Element code = addElement (doc, fault, "faultcode");
00082         CString txt = "SOAP-ENV:";
00083         switch (fCode) {
00084         case sfVersion: txt += "VersionMismatch."; break;
00085         case sfUnderstand: txt += "MustUnderstand."; break;
00086         case sfClient: txt += "Client."; break;
00087         case sfServer: txt += "Server."; break;
00088         }
00089         txt += fSubCode;
00090         addText (doc, code, txt);
00091     }
00092     {
00093         DOM_Element str = addElement (doc, fault, "faultstring");
00094         addText (doc, str, fString);
00095     }
00096 }
00097 
00099 void SOAPBridge_SOAPCall_i::soapFault(DOM_Document &doc, FaultCode fCode, const char *fSubCode, const char *fString, DynamicAny::DynAny_ptr da)
00100 {
00101     soapBridgeLog->error ("Fault: %d.%s (%s)\n", fCode, fSubCode, fString);
00102     DOM_Element envel, body;
00103     createEmptySoap (doc, envel, body);
00104     DOM_Element fault = addElement (doc, body, "SOAP-ENV:Fault");
00105     {
00106         DOM_Element code = addElement (doc, fault, "faultcode");
00107         CString txt = "SOAP-ENV:";
00108         switch (fCode) {
00109         case sfVersion: txt += "VersionMismatch."; break;
00110         case sfUnderstand: txt += "MustUnderstand."; break;
00111         case sfClient: txt += "Client."; break;
00112         case sfServer: txt += "Server."; break;
00113         }
00114         txt += fSubCode;
00115         addText (doc, code, txt);
00116     }
00117     {
00118         DOM_Element str = addElement (doc, fault, "faultstring");
00119         addText (doc, str, fString);
00120     }
00121     {
00122         DOM_Element det = addElement (doc, fault, "m:detail");
00123         det.setAttribute ("xmlns:m", "http://www.lifeline.nl/SOAPBridge/SoapFault/detail");
00124         // needOuter is true here to obtain the NAME of the exception we've gotten.
00125         DynAny2Xml (doc, det, NULL, da, NULL, true);
00126     }
00127 }
00128 
00141 bool CorbaSoap::TypeConversion (DynamicAny::DynAny_ptr da, DOM_Document &doc, DOM_Node &node, 
00142         SCParamValue *pParVal, CORBA::TCKind kind) throw (DOM_Document &)
00143 {
00144     switch (pParVal->m_convId) {
00145     case 1:
00146     case 2:
00147     case 6:
00148         {
00149             CString msg;
00150             msg.Format ("The conversion %s specified for OUT parameter '%s' is not implemented (yet)",
00151                 (const char *) pParVal->m_convInfo, (const char *) pParVal->m_prmName);
00152             aFault (sfClient, "BadConversion", msg);
00153         }
00154         break;
00155     case 3:
00156         {
00157             bool doConv = false;
00158             time_t t = 0;
00159             if (kind == CORBA::tk_long) {
00160                 t = (time_t) da->get_long ();
00161                 doConv = true;
00162             }
00163             if (kind == CORBA::tk_ulong) {
00164                 t = (time_t) da->get_ulong ();
00165                 doConv = true;
00166             }
00167             if (doConv) {
00168                 JTCSynchronized synchronized (*p_struct_tm_monitor);
00169                 struct tm *t2 = gmtime (&t);
00170                 if (t2 == NULL) {
00171                     // some (commercial!) C runtimes actually return NULL on negative time values.
00172                     return false; // return the original number, maybe the caller can figure it out.
00173                 }
00174                 CString t3;
00175                 t3.Format ("%04d-%02d-%02d %02d:%02d:%02d",
00176                     t2->tm_year + 1900,
00177                     t2->tm_mon + 1,
00178                     t2->tm_mday,
00179                     t2->tm_hour,
00180                     t2->tm_min,
00181                     t2->tm_sec);
00182                 addText (doc, node, (const char *) t3);
00183             }
00184             return doConv;
00185         }
00186         break;
00187     case 4:
00188         {
00189             bool doConv = false;
00190             time_t t = 0;
00191             if (kind == CORBA::tk_long) {
00192                 t = (time_t) da->get_long ();
00193                 doConv = true;
00194             }
00195             if (kind == CORBA::tk_ulong) {
00196                 t = (time_t) da->get_ulong ();
00197                 doConv = true;
00198             }
00199             if (doConv) {
00200                 JTCSynchronized synchronized (*p_struct_tm_monitor);
00201                 struct tm *t2 = localtime (&t);
00202                 if (t2 == NULL) {
00203                     // some (commercial!) C runtimes actually return NULL on negative time values.
00204                     return false; // return the original number, maybe the caller can figure it out.
00205                 }
00206                 CString t3;
00207                 t3.Format ("%04d-%02d-%02d %02d:%02d:%02d",
00208                     t2->tm_year + 1900,
00209                     t2->tm_mon + 1,
00210                     t2->tm_mday,
00211                     t2->tm_hour,
00212                     t2->tm_min,
00213                     t2->tm_sec);
00214                 addText (doc, node, (const char *) t3);
00215             }
00216             return doConv;
00217         }
00218         break;
00219     case 5: 
00220         // ignore, will be handled by the caller
00221         break;
00222     case 7:
00223         if (kind == CORBA::tk_string) {
00224             CORBA::String_var s = da->get_string ();
00225             CString cs = (char *) s;
00226             addText (doc, node, (const char *) cs.Left (atoi (pParVal->m_convInfo)));
00227             return true;
00228         }
00229         break;
00230     case 8:
00231         if (kind == CORBA::tk_string) {
00232             CORBA::String_var s = da->get_string ();
00233             if (strlen (s) > (size_t) atoi (pParVal->m_convInfo)) {
00234                 CString msg;
00235                 msg.Format ("The string '%s' returned for OUT parameter '%s' is exceeds the specified maximum length %s.",
00236                     (char *) s, (const char *) pParVal->m_prmName, (const char *) pParVal->m_convInfo);
00237                 aFault (sfServer, "BadStringLength", msg);
00238             }
00239             addText (doc, node, (char *) s);
00240             return true;
00241         }
00242         break;
00243     case 9:
00244         if (kind == CORBA::tk_objref) {
00245             CORBA::String_var sior = orb->object_to_string (da->get_reference ());
00246             addText (doc, node, (char *) sior);
00247             return true;
00248         }
00249         break;
00250     default:
00251         {
00252             CString msg;
00253             msg.Format ("The conversion %s specified for OUT parameter '%s' is not a SoapBridge internal conversion",
00254                 (const char *) pParVal->m_convInfo, (const char *) pParVal->m_prmName);
00255             aFault (sfClient, "BadConversion", msg);
00256         }
00257         break;
00258     }
00259     return false;
00260 }
00261 
00268 static struct tm *ParseTimeString (CString &cs)
00269 {
00270     static struct tm t;
00271     time_t now = time (NULL);
00272     if (now - gmt_checked > 3600) {
00273         calc_gmt_offset (now);
00274     }
00275     t = *localtime (&now);
00276     char *dup = strdup (cs);
00277     char *tok = strtok (dup, " -:/.,\t");
00278     if (tok) {
00279         int y = atoi (tok);
00280         if (y >= 1970) {
00281             t.tm_year = y - 1900;
00282         } else {
00283             tok = NULL;
00284         }
00285         if (tok) tok = strtok (NULL, " -:/.,\t");
00286     }
00287     if (tok) {
00288         int m = atoi (tok);
00289         if (m >= 1 && m <= 12) {
00290             t.tm_mon = m - 1;
00291         } else {
00292             tok = NULL;
00293         }
00294         if (tok) tok = strtok (NULL, " -:/.,\t");
00295     }
00296     if (tok) {
00297         int md = atoi (tok);
00298         if (md >= 1 && md <= 31) {
00299             t.tm_mday = md;
00300         } else {
00301             tok = NULL;
00302         }
00303         if (tok) tok = strtok (NULL, " -:/.,\t");
00304     }
00305     if (tok) {
00306         int h = atoi (tok);
00307         if (h >= 0 && h <= 23) {
00308             t.tm_hour = h;
00309         } else {
00310             tok = NULL;
00311         }
00312         if (tok) tok = strtok (NULL, " -:/.,\t");
00313     }
00314     if (tok) {
00315         int m = atoi (tok);
00316         if (m >= 0 && m <= 59) {
00317             t.tm_min = m;
00318         } else {
00319             tok = NULL;
00320         }
00321         if (tok) tok = strtok (NULL, " -:/.,\t");
00322     }
00323     if (tok) {
00324         int s = atoi (tok);
00325         if (s >= 0 && s <= 59) {
00326             t.tm_sec = s;
00327         } else {
00328             tok = NULL;
00329         }
00330     }
00331     free (dup);
00332     if (tok) return &t;
00333     return NULL;
00334 }
00335 
00349 bool CorbaSoap::TypeConversion (DynamicAny::DynAny_ptr da, DOM_Element &elm, CString &Value, 
00350     SCParamValue *pParVal, CORBA::TCKind kind) throw (DOM_Document &)
00351 {
00352     switch (pParVal->m_convId) {
00353     case 1:
00354     case 2:
00355     case 6:
00356         {
00357             CString msg;
00358             msg.Format ("The conversion %s specified for IN parameter '%s' is not implemented (yet)",
00359                 (const char *) pParVal->m_convInfo, (const char *) pParVal->m_prmName);
00360             aFault (sfClient, "BadConversion", msg);
00361         }
00362         break;
00363     default:
00364         {
00365             CString msg;
00366             msg.Format ("The conversion %s specified for IN parameter '%s' is not a SoapBridge internal conversion",
00367                 (const char *) pParVal->m_convInfo, (const char *) pParVal->m_prmName);
00368             aFault (sfClient, "BadConversion", msg);
00369         }
00370         break;
00371     case 3:
00372         if (kind == CORBA::tk_long || kind == CORBA::tk_ulong) {
00373             time_t t2;
00374             JTCSynchronized synchronized (*p_struct_tm_monitor);
00375             struct tm *t1 = ParseTimeString (Value);
00376             if (t1) {
00377                 t2 = mktime (t1);
00378                 t2 += gmt_offset;
00379             } else {
00380                 CString msg;
00381                 msg.Format ("The value '%s' for parameter '%s' could not be interpreted as a date/time value.",
00382                     (const char *) Value, (const char *) pParVal->m_prmName);
00383                 aFault (sfClient, "BadDateTimeValue", msg);
00384             }
00385             Value.Format ("%ld", t2);
00386             return false;
00387         }
00388         break;
00389     case 4:
00390         if (kind == CORBA::tk_long || kind == CORBA::tk_ulong) {
00391             time_t t2;
00392             JTCSynchronized synchronized (*p_struct_tm_monitor);
00393             struct tm *t1 = ParseTimeString (Value);
00394             if (t1) {
00395                 t2 = mktime (t1);
00396             } else {
00397                 CString msg;
00398                 msg.Format ("The value '%s' for parameter '%s' could not be interpreted as a date/time value.",
00399                     (const char *) Value, (const char *) pParVal->m_prmName);
00400                 aFault (sfClient, "BadDateTimeValue", msg);
00401             }
00402             Value.Format ("%ld", t2);
00403             return false;
00404         }
00405         break;
00406     case 5: // ignore for IN
00407         break;
00408     case 7:
00409         if (kind == CORBA::tk_string && Value.GetLength () > atoi (pParVal->m_convInfo)) {
00410             Value = Value.Left (atoi (pParVal->m_convInfo));
00411         }
00412         break;
00413     case 8:
00414         if (kind == CORBA::tk_string && Value.GetLength () > atoi (pParVal->m_convInfo)) {
00415             CString msg;
00416             msg.Format ("The string '%s' passed for IN parameter '%s' exceeded the specified maximum length of %s characters",
00417                 (const char *) Value, (const char *) pParVal->m_prmName, (const char *) pParVal->m_convInfo);
00418             aFault (sfClient, "StringLengthExceeded", msg);
00419         }
00420         break;
00421     case 9:
00422         if (kind == CORBA::tk_objref) {
00423             CORBA::Object_var obj = orb->string_to_object ((const char *) Value);
00424             da->insert_reference (obj);
00425             return true;
00426         }
00427         break;
00428     }
00429     return false;
00430 }
00431 
00442 void CorbaSoap::DynAny2Xml (DOM_Document &doc, DOM_Node &node, SCParamValue *pParVal, 
00443                                         DynamicAny::DynAny_ptr da, const char *ctxKey, bool needOuter)
00444                                         throw (DOM_Document &)
00445 {
00446     CORBA::TypeCode_var tc (da->type ());
00447     if (needOuter) {
00448         CORBA::String_var outerHint;
00449         switch (tc->kind ()) {
00450         case CORBA::tk_objref:
00451         case CORBA::tk_enum:
00452         case CORBA::tk_alias:
00453         case CORBA::tk_struct:
00454         case CORBA::tk_except:
00455         case CORBA::tk_union:
00456             outerHint = tc->name ();
00457             break;
00458         default:
00459             outerHint = CORBA::string_dup ("elm");
00460             break;
00461         }
00462         DOM_Node insNod = addElement (doc, node, (char *) outerHint);
00463         DynAny2Xml (doc, insNod, pParVal, da, ctxKey);
00464         return;
00465     }
00466     while (tc->kind () == CORBA::tk_alias) {
00467         tc = tc->content_type ();
00468     }
00469     if (pParVal && pParVal->m_convId && TypeConversion (da, doc, node, pParVal, tc->kind ())) return; 
00470     switch (tc->kind ()) {
00471     case CORBA::tk_null:      addComment (doc, node, "tk_null?");      break;
00472     case CORBA::tk_void:      addComment (doc, node, "tk_void?");      break;
00473     case CORBA::tk_short:     addTextI (doc, node, da->get_short ());  break;
00474     case CORBA::tk_long:      addTextI (doc, node, da->get_long ());   break;
00475     case CORBA::tk_ushort:    addTextU (doc, node, da->get_ushort ()); break;
00476     case CORBA::tk_ulong:     addTextU (doc, node, da->get_ulong ());  break;
00477     case CORBA::tk_float:     addTextD (doc, node, da->get_float ());  break;
00478     case CORBA::tk_double:    addTextD (doc, node, da->get_double ()); break;
00479     case CORBA::tk_char:      addTextC (doc, node, da->get_char ());   break;
00480     case CORBA::tk_wchar:     addTextC (doc, node, da->get_wchar ());  break;
00481     case CORBA::tk_octet:     addTextC (doc, node, da->get_octet ());  break;
00482     case CORBA::tk_TypeCode:  addComment (doc, node, "tk_TypeCode?");  break;
00483     case CORBA::tk_Principal: addComment (doc, node, "tk_Principal?"); break;
00484     case CORBA::tk_boolean:   addTextC (doc, node, da->get_boolean () ? '1' : '0'); break;
00485     case CORBA::tk_any:
00486         {
00487             CORBA::Any *tmpAny = da->get_any ();
00488             DynamicAny::DynAny_var tmpDa = dynFact->create_dyn_any (*tmpAny);
00489             DynAny2Xml (doc, node, pParVal, tmpDa, ctxKey);
00490             tmpDa->destroy ();
00491         }
00492         break;
00493     case CORBA::tk_objref:
00494         {
00495             if (ctxKey != NULL) {
00496                 soapBridgeLog->debug ("Object reference, ctxKey = %lX", ctxKey);
00497                 CORBA::String_var theKey = CORBA::string_dup (ctxKey);
00498                 try {
00499                     soapBridgeLog->debug ("ObjCtxMan = %lX\n", (void *) ObjCtxMan);
00500                     CORBA::String_var objRef (ObjCtxMan->storeObjectReference (theKey, da->get_reference ()));
00501                     addText (doc, node, (char *) objRef);
00502                 }
00503                 catch (...) {
00504                     addComment (doc, node, "Sorry, ObjectContentManager went Splat!");
00505                 }
00506             } else {
00507                 addComment (doc, node, "No context key in effect at this point, cannot return object reference.");
00508             }
00509         }
00510         break;
00511     case CORBA::tk_string:
00512         {
00513             CORBA::String_var sv (da->get_string ());
00514             addText (doc, node, (char *) sv);
00515         }
00516         break;
00517     case CORBA::tk_wstring:
00518         {
00519             CORBA::WString_var sv (da->get_wstring ());
00520             addText (doc, node, (unsigned short *) ((CORBA::WChar *) sv));
00521         }
00522         break;
00523     case CORBA::tk_fixed:
00524         {
00525             DynamicAny::DynFixed_var df = DynamicAny::DynFixed::_narrow (da);
00526             CORBA::String_var sv (df->get_value ());
00527             addText (doc, node, (char *) sv);
00528         }
00529         break;
00530     case CORBA::tk_struct:
00531     case CORBA::tk_except:
00532         {
00533             DynamicAny::DynStruct_var ds = DynamicAny::DynStruct::_narrow (da);
00534             for (unsigned int i = 0; i < ds->component_count (); i ++) {
00535                 DynamicAny::DynAny_var cm (ds->current_component ());
00536                 CORBA::String_var mem (ds->current_member_name ());
00537                 DOM_Element nInner = addElement (doc, node, (char *) mem);
00538                 DynAny2Xml (doc, nInner, pParVal, cm, ctxKey);
00539                 ds->next ();
00540             }
00541         }
00542         break;
00543     case CORBA::tk_sequence:
00544         {
00545             DynamicAny::DynSequence_var ds = DynamicAny::DynSequence::_narrow (da);
00546             CORBA::TypeCode_var sqct = tc->content_type ();
00547             if (pParVal->m_convId != 5 && sqct->kind () == CORBA::tk_octet) {
00548                 // special case, unless explicitely requested otherwise we encode this as BASE64
00549                 DynamicAny::AnySeq_var as = ds->get_elements ();
00550                 CORBA::Octet *buf = new CORBA::Octet [as->length ()];
00551                 for (unsigned int i = 0; i < as->length (); i ++) {
00552                     as [i] >>= CORBA::Any::to_octet (buf [i]);
00553                 }
00554                 CString str;
00555                 EncodeBase64 (buf, as->length (), str, false);
00556                 delete buf;
00557                 addText (doc, node, (const char *) str);
00558                 DOM_Element elm = (DOM_Element &) node;
00559                 elm.setAttribute ("xsi:type", "SOAP-ENC:base64");
00560             } else {
00561                 for (unsigned int i = 0; i < ds->get_length (); i ++) {
00562                     DynamicAny::DynAny_var cm (ds->current_component ());
00563                     DynAny2Xml (doc, node, pParVal, cm, ctxKey, true);
00564                     ds->next ();
00565                 }
00566             }
00567         }
00568         break;
00569     case CORBA::tk_array:
00570         {
00571             DynamicAny::DynArray_var ds = DynamicAny::DynArray::_narrow (da);
00572             for (unsigned int i = 0; i < ds->component_count (); i ++) {
00573                 DynamicAny::DynAny_var cm (ds->current_component ());
00574                 DynAny2Xml (doc, node, pParVal, cm, ctxKey, true);
00575                 ds->next ();
00576             }
00577         }
00578         break;
00579     case CORBA::tk_enum:
00580         {
00581             DynamicAny::DynEnum_var ds = DynamicAny::DynEnum::_narrow (da);
00582             CORBA::String_var val (ds->get_as_string ());
00583             addText (doc, node, (char *) val);
00584         }
00585         break;
00586     case CORBA::tk_union:
00587         {
00588             DynamicAny::DynUnion_var du = DynamicAny::DynUnion::_narrow (da);
00589             DynamicAny::DynAny_var disc = du->get_discriminator ();
00590             DOM_Element nDisc = addElement (doc, node, "discriminator");
00591             DynAny2Xml (doc, nDisc, pParVal, disc, ctxKey);
00592             if (!du->has_no_active_member ()) {
00593                 DynamicAny::DynAny_var cm (du->member ());
00594                 CORBA::String_var mem (du->member_name ());
00595                 DOM_Element nInner = addElement (doc, node, (char *) mem);
00596                 DynAny2Xml (doc, nInner, pParVal, cm, ctxKey);
00597             }
00598         }
00599         break;
00600     default:
00601         {
00602             CString msg;
00603             msg = "We are sorry but an unimplemented CORBA type was encountered in DynAny2Xml(). ";
00604             msg += "This is either a bug or might mean that the SoapBridge ";
00605             msg += "cannot handle the IDL for this interface method. ";
00606             msg += "A work-around might be to substitute your own CORBA server for this interface to ";
00607             msg += "do a custom conversion, that in turn calls the original service.";
00608             aFault (sfServer, "NotImplemented", msg);
00609         }
00610         break;
00611     }
00612 }
00613 
00614 CorbaSoap::CorbaSoap ()
00615 {
00616     CORBA::Object_var obj = orb->string_to_object (ObjCtxMan_SIOR);
00617     ObjCtxMan = SOAPBridge::ObjectContextManager::_narrow (obj);
00618 }
00619 
00625 SOAPBridge_SOAPCall_i::SOAPBridge_SOAPCall_i(CosNaming::NamingContext_ptr inc)
00626     : CorbaSoap ()
00627 {
00628     useSupplied = false;
00629     suppliedObject = NULL;
00630     m_inc = inc;
00631 }
00632 
00634 SOAPBridge_SOAPCall_i::~SOAPBridge_SOAPCall_i()
00635 {
00636 }
00637 
00646 SOAPBridge::SOAPCall::XMLData * SOAPBridge_SOAPCall_i::Fault(FaultCode fCode, const char *fSubCode, const char *fString)
00647 {
00648     DOM_Document doc;
00649     soapFault (doc, fCode, fSubCode, fString);
00650     unsigned char *out;
00651     unsigned long siz;
00652     GetXML (out, siz, &doc);
00653     CORBA::Octet *pBuf = SOAPBridge::SOAPCall::XMLData::allocbuf (siz);
00654     memcpy (pBuf, out, siz);
00655     delete out;
00656     return new SOAPBridge::SOAPCall::XMLData (siz, siz, pBuf, 1);
00657 }
00658 
00668 void SOAPBridge_SOAPCall_i::CheckTag (char *cNam, DOM_Node &node) throw (DOM_Document &)
00669 {
00670     if (node == NULL) {
00671         CString msg;
00672         msg.Format ("Expected an element named '%s' but found nothing.", cNam);
00673         DOM_Document doc;
00674         soapFault (doc, sfClient, "MissingData", msg);
00675         throw (doc);
00676     }
00677     DOMTRACE (node.getNodeName ());
00678     DOMString dsCName (cNam);
00679     DOMString dsNName (node.getLocalName ());
00680     if (dsCName.equals (dsNName)) return;
00681     CString msg;
00682     char *del = dsNName.transcode ();
00683     msg.Format ("Expected an element named '%s' but found '%s'", cNam, del);
00684     delete del;
00685     DOM_Document doc;
00686     soapFault (doc, sfClient, "WrongElement", msg);
00687     throw (doc);
00688 }
00689 
00703 void CorbaSoap::FillInDynAny (HrefIdMap &Map, 
00704                                           SCParamValue *pParVal, 
00705                                           DynamicAny::DynAny_ptr da, 
00706                                           DOM_Element &elm)
00707     throw (DOM_Document &)
00708 {
00709     if (elm == NULL) {
00710         CString msg;
00711         msg.Format ("Missing data for parameter '%s'", (const char *) pParVal->m_prmName);
00712         aFault (sfClient, "MissingData", msg);
00713     }
00714     CORBA::TypeCode_var tc (da->type ());
00715     while (tc->kind () == CORBA::tk_alias) {
00716         tc = tc->content_type ();
00717     }
00718     CString cs = DOM2CS (elm);
00719 #if TRACEDOM
00720     soapBridgeLog->debug ("[%s] --> %s", (const char *) cs, (const char *) pParVal->m_prmName);
00721     DOMTRACE (elm.getNodeName ());
00722 #endif
00723     if (pParVal->m_convId && TypeConversion (da, elm, cs, pParVal, tc->kind ())) return;
00724     switch (tc->kind ()) {
00725     case CORBA::tk_null:
00726         {
00727             aFault (sfServer, "Internal", "Found a tk_null TypeCode while filling in the parameters");
00728         }
00729         break;
00730     case CORBA::tk_void:
00731         {
00732             aFault (sfServer, "Internal", "Found a tk_void TypeCode while filling in the parameters");
00733         }
00734         break;
00735     case CORBA::tk_short:
00736         da->insert_short ((CORBA::Short) atoi (cs));
00737         break;
00738     case CORBA::tk_long:
00739         da->insert_long ((CORBA::Long) atoi (cs));
00740         break;
00741     case CORBA::tk_ushort:
00742         da->insert_ushort ((CORBA::UShort) strtoul (cs, NULL, 10));
00743         break;
00744     case CORBA::tk_ulong:
00745         da->insert_ulong ((CORBA::ULong) strtoul (cs, NULL, 10));
00746         break;
00747     case CORBA::tk_float:
00748         da->insert_float ((CORBA::Float) strtod (cs, NULL));
00749         break;
00750     case CORBA::tk_double:
00751         da->insert_double ((CORBA::Double) strtod (cs, NULL));
00752         break;
00753     case CORBA::tk_boolean:
00754         {
00755             CORBA::Boolean b;
00756             if (cs.GetLength () > 0) {
00757                 switch (cs.GetAt (0)) {
00758                 case 'N': case 'n':
00759                     // no, nein, non, nee, njet, negative.
00760                     // Fortunately "NO" in most European languages starts with a N"
00761                 case 'F': case 'f': // "false"
00762                 case '0': // zero
00763                     b = false;
00764                     break;
00765                 default:
00766                     // anything else is either a numeric value other than zero or text that we do
00767                     // not recognize as being "NO" (si/yes, jawoll, oui, ja, da, positive).
00768                     b = true;
00769                     break;
00770                 }
00771             } else {    // "NULL" values are false
00772                 b = false;
00773             }
00774             da->insert_boolean (b);
00775         }
00776         break;
00777     case CORBA::tk_wchar:
00778     case CORBA::tk_char:
00779         if (cs.GetLength () > 1) {
00780             int i = atoi (cs);
00781             if (i) {
00782                 da->insert_char ((CORBA::Char) i);
00783             } else {
00784                 da->insert_char ((CORBA::Char) cs.GetAt (0));
00785             }
00786         } else {
00787             da->insert_char ((CORBA::Char) cs.GetAt (0));
00788         }
00789         break;
00790     case CORBA::tk_octet:
00791         if (cs.GetLength () > 1) {
00792             int i = atoi (cs);
00793             if (i) {
00794                 da->insert_octet ((CORBA::Octet) i);
00795             } else {
00796                 da->insert_octet ((CORBA::Octet) cs.GetAt (0));
00797             }
00798         } else {
00799             da->insert_octet ((CORBA::Char) cs.GetAt (0));
00800         }
00801         break;
00802     case CORBA::tk_any:
00803         {
00804             aFault (sfClient, "MustSpecify",
00805                 "Found an ANY in or inout parameter without type conversion specification.");
00806         }
00807         break;
00808     case CORBA::tk_TypeCode:
00809         {
00810             aFault (sfServer, "Internal", "Found a tk_TypeCode TypeCode while filling in the parameters");
00811         }
00812         break;
00813     case CORBA::tk_Principal:
00814         {
00815             aFault (sfServer, "Internal", "Found a tk_Principal TypeCode while filling in the parameters");
00816         }
00817         break;
00818     case CORBA::tk_objref:
00819         {
00820             CORBA::Object_var anObj;
00821             CORBA::String_var objref = CORBA::string_dup ((const char *) cs);
00822             try {
00823                 anObj = ObjCtxMan->resolveStoredObjectReference (objref);
00824             }
00825             catch (...) {
00826                 CString msg;
00827                 msg.Format ("Failed to locate '%s' as a valid object reference in the ObjectContextManager.",
00828                     (const char *) cs);
00829                 aFault (sfClient, "ObjectNotFound", msg);
00830             }
00831             da->insert_reference (anObj);
00832         }
00833         break;
00834     case CORBA::tk_struct:
00835         {
00836             DynamicAny::DynStruct_var ds = DynamicAny::DynStruct::_narrow (da);
00837             DOM_Node node = elm.getFirstChild ();
00838             while (node != NULL && node.getNodeType () != DOM_Node::ELEMENT_NODE) {
00839                 node = node.getNextSibling ();
00840             }
00841             for (unsigned int i = 0; i < ds->component_count (); i ++) {
00842                 DynamicAny::DynAny_var cm (ds->current_component ());
00843                 DOM_Element nElm;
00844                 Map.RealNode (nElm, node);
00845                 CORBA::String_var mem (ds->current_member_name ());
00846                 CheckTag (mem, nElm);
00847                 FillInDynAny (Map, pParVal, cm, nElm);
00848                 ds->next ();
00849                 node = node.getNextSibling ();
00850                 while (node != NULL && node.getNodeType () != DOM_Node::ELEMENT_NODE) {
00851                     node = node.getNextSibling ();
00852                 }
00853             }
00854         }
00855         break;
00856     case CORBA::tk_union:
00857         {
00858             DynamicAny::DynUnion_var du = DynamicAny::DynUnion::_narrow (da);
00859             // Grab the first child element node as the union's discriminator
00860             DOM_Node node = elm.getFirstChild ();
00861             while (node != NULL && node.getNodeType () != DOM_Node::ELEMENT_NODE) {
00862                 node = node.getNextSibling ();
00863             }
00864             DynamicAny::DynAny_var tmpDa = du->get_discriminator ();
00865             DOM_Element nElm;
00866             Map.RealNode (nElm, node);
00867             FillInDynAny (Map, pParVal, tmpDa, nElm);
00868             // whatever follows should match the now active member
00869             node = node.getNextSibling ();
00870             while (node != NULL && node.getNodeType () != DOM_Node::ELEMENT_NODE) {
00871                 node = node.getNextSibling ();
00872             }
00873             tmpDa = du->member ();
00874             Map.RealNode (nElm, node);
00875             FillInDynAny (Map, pParVal, tmpDa, nElm);
00876         }
00877         break;
00878     case CORBA::tk_enum:
00879         {
00880             DynamicAny::DynEnum_var de = DynamicAny::DynEnum::_narrow (da);
00881             try {
00882                 de->set_as_string ((const char *) cs);
00883             }
00884             catch (...) {
00885                 CString msg;
00886                 CORBA::String_var nam (tc->name ());
00887                 msg.Format ("Parameter '%s': Failed to set '%s' as the value of enum '%s'.",
00888                     (const char *) pParVal->m_prmName, (const char *) cs, (char *) nam);
00889                 aFault (sfClient, "WrongElement", msg);
00890             }
00891         }
00892         break;
00893     case CORBA::tk_wstring:
00894         {
00895             aFault (sfServer, "NotImplemented", "Cannot handle Wstring");
00896         }
00897         break;
00898     case CORBA::tk_string:
00899         da->insert_string (CORBA::string_dup ((const char *) cs));
00900         break;
00901     case CORBA::tk_fixed:
00902         {
00903             DynamicAny::DynFixed_var df = DynamicAny::DynFixed::_narrow (da);
00904             df->set_value (CORBA::string_dup ((const char *) cs));
00905         }
00906         break;
00907     case CORBA::tk_sequence:
00908         {
00909             DynamicAny::DynSequence_var ds = DynamicAny::DynSequence::_narrow (da);
00910             DOM_Node node = elm.getFirstChild ();
00911             // we'll start by counting the number of elements here
00912             unsigned int numElm = 0;
00913             while (node != NULL) {
00914                 if (node.getNodeType () == DOM_Node::ELEMENT_NODE) numElm ++; 
00915                 node = node.getNextSibling ();
00916             }
00917             ds->set_length (numElm);
00918             node = elm.getFirstChild ();
00919             while (node != NULL && node.getNodeType () != DOM_Node::ELEMENT_NODE) {
00920                 node = node.getNextSibling ();
00921             }
00922             for (unsigned int i = 0; i < ds->component_count (); i ++) {
00923                 DynamicAny::DynAny_var cm (ds->current_component ());
00924                 DOM_Element nElm;
00925                 Map.RealNode (nElm, node);
00926                 // can we check a name here?
00927                 {
00928                     CORBA::TypeCode_var tc2 (cm->type ());
00929                     while (tc2->kind () == CORBA::tk_alias) {
00930                         tc2 = tc2->content_type ();
00931                     }
00932                     switch (tc2->kind ()) {
00933                     case CORBA::tk_objref:
00934                     case CORBA::tk_struct:
00935                     case CORBA::tk_union:
00936                     case CORBA::tk_enum:
00937                     case CORBA::tk_except:
00938                         {
00939                             CORBA::String_var mem (tc2->name ());
00940                             CheckTag (mem, nElm);
00941                         }
00942                     default:
00943                         // no way to obtain a name, accept anything as valid
00944                         break;
00945                     }
00946                 }
00947                 FillInDynAny (Map, pParVal, cm, nElm);
00948                 ds->next ();
00949                 node = node.getNextSibling ();
00950                 while (node != NULL && node.getNodeType () != DOM_Node::ELEMENT_NODE) {
00951                     node = node.getNextSibling ();
00952                 }
00953             }
00954         }
00955         break;
00956     case CORBA::tk_array:
00957         {
00958             DynamicAny::DynArray_var ds = DynamicAny::DynArray::_narrow (da);
00959             DOM_Node node = elm.getFirstChild ();
00960             while (node != NULL && node.getNodeType () != DOM_Node::ELEMENT_NODE) {
00961                 node = node.getNextSibling ();
00962             }
00963             for (unsigned int i = 0; i < ds->component_count (); i ++) {
00964                 DynamicAny::DynAny_var cm (ds->current_component ());
00965                 DOM_Element nElm;
00966                 Map.RealNode (nElm, node);
00967                 FillInDynAny (Map, pParVal, cm, nElm);
00968                 ds->next ();
00969                 node = node.getNextSibling ();
00970                 while (node != NULL && node.getNodeType () != DOM_Node::ELEMENT_NODE) {
00971                     node = node.getNextSibling ();
00972                 }
00973             }
00974         }
00975         break;
00976     default:
00977         {
00978             CString msg;
00979             msg = "We are sorry but an unimplemented CORBA type was encountered in FillInDynAny(). ";
00980             msg += "This is either a bug or might mean that the SoapBridge ";
00981             msg += "cannot handle the IDL for this interface method. ";
00982             msg += "A work-around might be to substitute your own CORBA server for this interface to ";
00983             msg += "do a custom conversion, that in turn calls the original service.";
00984             aFault (sfServer, "NotImplemented", msg);
00985         }
00986         break;
00987     }
00988 }
00989 
00999 SOAPBridge::SOAPCall::XMLData* SOAPBridge_SOAPCall_i::invokeAction(const char* action, const SOAPBridge::SOAPCall::XMLData& data)
01000 throw (CORBA::SystemException, SOAPBridge::SOAPCall::InvocationFailed)
01001 {
01002     double start_time = sec_u ();
01003     DOM_Holder Holder (parseDOM (data.get_buffer (), data.length ()));
01004     if (!Holder.domHdl) {
01005         return Fault (sfClient, "MissingData", "Bad SOAP XML encountered.");
01006     }
01007     IRPlus *pIRP = (IRPlus *) irplusHandle;
01008     DOM_Document Doc = *((DOM_Document *) Holder.domHdl);
01009     HrefIdMap HrefMap;
01010     HrefMap.Build (Doc);
01011     CString scope, method;
01012     unsigned char *outXml = NULL;
01013     unsigned long outXmlSiz = 0;
01014 
01015     // First we parse the SOAP for the bits that interest us and to determine its sanety.
01016 
01017     DOM_Element soapEnvelope;
01018     {
01019         DOM_Node sNode = Doc.getFirstChild ();
01020         DOMTRACE (sNode.getNodeName ());
01021         while (sNode != NULL && sNode.getNodeType () != DOM_Node::ELEMENT_NODE) {
01022             sNode = sNode.getNextSibling ();
01023         }
01024         DOMString envelopeTag ("Envelope");
01025         if (sNode == NULL || !envelopeTag.equals (sNode.getLocalName ())) {
01026             return Fault (sfClient, "MissingData", "No SOAP Envelope");
01027         }
01028         HrefMap.RealNode (soapEnvelope, sNode);
01029     }
01030     DOM_Element soapHeader;
01031     DOM_Element soapBody;
01032     {
01033         DOM_Node sNode = soapEnvelope.getFirstChild ();
01034         DOMTRACE (sNode.getLocalName ());
01035         while (sNode != NULL && sNode.getNodeType () != DOM_Node::ELEMENT_NODE) {
01036             sNode = sNode.getNextSibling ();
01037         }
01038         DOMString headerTag ("Header");
01039         if (sNode != NULL && headerTag.equals (sNode.getLocalName ())) {
01040             HrefMap.RealNode (soapHeader, sNode);
01041             sNode = sNode.getNextSibling ();
01042         }
01043         DOMTRACE (sNode.getNodeName ());
01044         while (sNode != NULL && sNode.getNodeType () != DOM_Node::ELEMENT_NODE) {
01045             sNode = sNode.getNextSibling ();
01046         }
01047         DOMString bodyTag ("Body");
01048         if (sNode == NULL || !bodyTag.equals (sNode.getLocalName ())) {
01049             return Fault (sfClient, "MissingData", "No SOAP Body");
01050         }
01051         HrefMap.RealNode (soapBody, sNode);
01052     }
01053     DOM_Element headObjRef, headAction, headCtxKey;
01054     CString theCtxKey;
01055     if (soapHeader != NULL) {
01056         DOM_Node sNode = soapHeader.getFirstChild ();
01057         DOMString soapObjRefTag ("ObjRef");
01058         DOMString soapCtxKeyTag ("Context");
01059         DOMString soapActionTag ("Action");
01060         while (sNode != NULL) {
01061             if (sNode.getNodeType () == DOM_Node::ELEMENT_NODE) {
01062                 if (soapObjRefTag.equals (sNode.getLocalName ())) {
01063                     HrefMap.RealNode (headObjRef, sNode);
01064                 } else if (soapCtxKeyTag.equals (sNode.getLocalName ())) {
01065                     HrefMap.RealNode (headCtxKey, sNode);
01066                     theCtxKey = DOM2CS (headCtxKey);
01067                 } else if (soapActionTag.equals (sNode.getLocalName ())) {
01068                     HrefMap.RealNode (headAction, sNode);
01069                 }
01070             }
01071             sNode = sNode.getNextSibling ();
01072         }
01073     }
01074     
01075     // We should now have everything we need. Next thing to do is to obtain an object
01076     // reference and method identification.
01077 
01078     scope = action;
01079     if (scope.Find ('#') < 1) {
01080         // That rules out the HTTP SOAP Action.
01081         if (headAction != NULL) {
01082             scope = DOM2CS (headAction);
01083         }
01084     } else {
01085         // HTTP SOAP Action must match any SOAP Header Action
01086         if (headAction != NULL) {
01087             CString cs = DOM2CS (headAction);
01088             if (cs.Compare (scope)) {
01089                 CString msg;
01090                 msg.Format ("HTTP SOAP Action '%s' does NOT match SOAP Header action '%s'",
01091                     (const char *) scope, (const char *) cs);
01092                 return Fault (sfClient, "ActionMismatch", msg);
01093             }
01094         }
01095     }
01096     int pound = scope.Find ('#');
01097     if (pound < 1) {
01098         // never found a valid SOAP action
01099         CString msg;
01100         msg.Format ("The action found ('%s') cannot be interpreted.", (const char *) scope);
01101         return Fault (sfClient, "InvalidAction", msg);
01102     }
01103 
01104     // Parse the SOAP action into the scope and the method
01105 
01106     CString soapAction = scope;
01107     method = scope.Mid (pound + 1);
01108     scope = scope.Left (pound);
01109     CString methKey;
01110     methKey = "/";
01111     methKey += scope;
01112     methKey += "/";
01113     methKey += method;
01114 
01115     try {
01116         // We will now attempt to locate the call information in the IRPlus
01117 
01118         ParList_Holder _plhold;
01119         SCParamList *pParList = NULL;
01120         
01121         {
01122             JTCSynchronized synchronized (pIRP->monitor);
01123             SCInterfaceMethod *pMeth = pIRP->IRC.FindInterfaceMethod (methKey);
01124             if (!pMeth) {
01125                 CString msg;
01126                 msg.Format ("There is no match for '%s' in the InterfaceRepository", (const char *) soapAction);
01127                 return Fault (sfClient, "UnknownMethod", msg);
01128             }
01129             if (pMeth->m_convId) {
01130                 CString msg;
01131                 msg.Format ("The called method (%s,convId=%d) must be preprocessed before calling the SoapBridge", 
01132                     (const char *) soapAction, pMeth->m_convId);
01133                 return Fault (sfClient, "ConvertedMethod", msg);
01134             }
01135             _plhold.pParList = pParList = new SCParamList (pMeth, dynFact);
01136         }
01137 
01138         // Last check, are we referring to the right method?
01139 
01140         DOM_Element methodCall;
01141         {
01142             DOM_Node sNode = soapBody.getFirstChild ();
01143             while (sNode != NULL && sNode.getNodeType () != DOM_Node::ELEMENT_NODE) {
01144                 sNode = sNode.getNextSibling ();
01145             }
01146             HrefMap.RealNode (methodCall, sNode);
01147         }
01148         {
01149             DOMString expected ((const char *) method);
01150             if (!methodCall.getLocalName ().equals (expected)) {
01151                 CString msg;
01152                 char *del = methodCall.getLocalName ().transcode ();
01153                 msg.Format ("Expected element '%s' to follow SOAP Body, not '%s'.",
01154                     (const char *) method, del);
01155                 delete del;
01156                 return Fault (sfClient, "WrongMethod", msg);
01157             }
01158         }
01159 
01160         // set up for the parameters
01161 
01162         DOM_Node methodParmList = methodCall.getFirstChild ();
01163         while (methodParmList != NULL && methodParmList.getNodeType () != DOM_Node::ELEMENT_NODE) {
01164             methodParmList = methodParmList.getNextSibling ();
01165         }
01166         DOM_Node saveList = methodParmList;
01167 
01168         // we'll have to obtain the various object references now
01169 
01170         soapBridgeLog->debug ("Input parsing done at %lg seconds\n", sec_u () - start_time);
01171         CORBA::Object_var theObj;
01172         if (!useSupplied) {
01173             if (headObjRef != NULL) {
01174                 CString ref = DOM2CS (headObjRef);
01175                 CORBA::String_var objref = CORBA::string_dup ((const char *) ref);
01176                 try {
01177                     theObj = ObjCtxMan->resolveStoredObjectReference (objref);
01178                 }
01179                 catch (...) {
01180                 }
01181                 if (CORBA::is_nil (theObj)) {
01182                     return Fault (sfServer, "ObjectNotFound", "Object reference passed in SOAP Header is invalid");
01183                 }
01184             } else {
01185                 CString corbaname = "corbaname:rir:#";
01186                 corbaname += scope;
01187                 try {
01188                     theObj = orb->string_to_object (corbaname);
01189                 }
01190                 catch (...) {
01191                 }
01192                 if (CORBA::is_nil (theObj)) {
01193                     return Fault (sfServer, "ObjectNotFound", corbaname);
01194                 }
01195             }
01196             soapBridgeLog->debug ("Object obtained at %lg seconds\n", sec_u () - start_time);
01197         }
01198 
01199         // process the parameters
01200 
01201         try {
01202             SCParamList::ParamValueIterator iParVal (pParList);
01203             while (++iParVal) {
01204                 if (iParVal->m_prmKind == ioeIn || iParVal->m_prmKind == ioeInOut) {
01205                     DOM_Element methodParm;
01206                     HrefMap.RealNode (methodParm, methodParmList);
01207                     if (methodParmList != NULL) {
01208                         do {
01209                             methodParmList = methodParmList.getNextSibling ();
01210                         } while (methodParmList != NULL && methodParmList.getNodeType () != DOM_Node::ELEMENT_NODE);
01211                     }
01212                     try {
01213                         FillInDynAny (HrefMap, iParVal, iParVal->GetDynAnyPtr (), methodParm);
01214                     }
01215                     catch (DOM_Document &doc) {
01216                         soapBridgeLog->error ("SOAP Fault thrown from FillInDynAny\n");
01217                         throw (doc);
01218                     }
01219                     catch (...) {
01220                         soapBridgeLog->crit ("Unknown Exception in FillInDynAny\n");
01221                         abort ();
01222                     }
01223                 }
01224             }
01225 
01226             // ======================================================================
01227             // if we get here we've got everything we need to do the CORBA invocation
01228             // ======================================================================
01229 
01230             CORBA::Request_var req;
01231             if (useSupplied) {
01232                 req = suppliedObject->_request (method);
01233             } else {
01234                 req = theObj->_request (method);
01235             }
01236             CORBA::NVList_ptr args = req->arguments ();
01237             CORBA::NamedValue_ptr result = req->result ();
01238             CORBA::Any *resultAny;
01239             resultAny = result->value ();
01240             CORBA::ExceptionList_ptr exlst = req->exceptions ();
01241             iParVal.Reset ();
01242             while (++iParVal) {
01243                 if (iParVal->m_prmName == "return") {
01244                     CORBA::TypeCode_var tc = iParVal->GetDynAnyPtr ()->type ();
01245                     try {
01246                         resultAny->replace (tc, &result);
01247                     }
01248                     catch (...) {
01249                         soapBridgeLog->info ("ORB bug: resultAny->replace() cannot have failed. We'll continue.\n");
01250                     }
01251                 } else {
01252                     CORBA::Any_var an = iParVal->GetDynAnyPtr ()->to_any ();
01253                     switch (iParVal->m_prmKind) {
01254                     case ioeIn: args->add_value (iParVal->m_prmName, an, CORBA::ARG_IN); break;
01255                     case ioeOut: args->add_value (iParVal->m_prmName, an, CORBA::ARG_OUT); break;
01256                     case ioeInOut: args->add_value (iParVal->m_prmName, an, CORBA::ARG_INOUT); break;
01257                     case ioeException:
01258                         {
01259                             CORBA::TypeCode_var tc = iParVal->GetDynAnyPtr ()->type ();
01260                             exlst->add (tc);
01261                         }
01262                         break;
01263                     }
01264                 }
01265             }
01266 
01267             // ====================
01268             // The CORBA invocation
01269             // ====================
01270 
01271             try {
01272                 soapBridgeLog->debug ("Parameters parsed at %lg seconds\n", sec_u () - start_time);
01273                 req->invoke ();
01274                 soapBridgeLog->debug ("Invocation done at %lg seconds\n", sec_u () - start_time);
01275             }
01276             catch (...) {
01277                 soapBridgeLog->crit ("DcOperation::Execute -> Failed to perform dynamic invocation\n");
01278             }
01279 
01280             // Handle any exception that were thrown.
01281 
01282             CORBA::Exception *pEx = req->env()->exception ();
01283             if (pEx) {
01284                 CORBA::UnknownUserException *puex = CORBA::UnknownUserException::_downcast (pEx);
01285                 CORBA::SystemException *psex = CORBA::SystemException::_downcast (pEx);
01286                 CORBA::Any tmp;
01287                 const char *exType= "UnknownException";
01288                 if (puex != NULL) {
01289                     soapBridgeLog->error ("CORBA invocation caused an UnknownUserException\n");
01290                     DynamicAny::DynAny_var tmpDa = dynFact->create_dyn_any (puex->exception ());
01291                     DOM_Document doc;
01292                     soapFault (doc, sfServer, "Exception", "UserException", tmpDa);
01293                     tmpDa->destroy ();
01294                     throw (doc);
01295                 } else if (psex != NULL) {
01296                     soapBridgeLog->error ("CORBA invocation caused a SystemException\n");
01297                     tmp <<= *psex;
01298                     exType = "SystemException";
01299                 } else {
01300                     soapBridgeLog->error ("CORBA invocation caused an Exception\n");
01301                     tmp <<= *pEx;
01302                 }
01303                 DynamicAny::DynAny_var tmpDa = dynFact->create_dyn_any (tmp);
01304                 DOM_Document doc;
01305                 soapFault (doc, sfServer, "Exception", exType, tmpDa);
01306                 tmpDa->destroy ();
01307                 throw (doc);
01308             } else {
01309 
01310                 // ================
01311                 // Build the result
01312                 // ================
01313 
01314                 DOM_Document doc;
01315                 DOM_Element envel, body;
01316                 createEmptySoap (doc, envel, body);
01317                 importHeader (doc, envel, soapHeader);
01318                 DOM_Element methNode = addElement (doc, body, method + "Response");
01319                 body.setAttribute ("xmlns:m", (const char *) methKey);
01320             
01321                 iParVal.Reset ();
01322                 args = req->arguments ();
01323                 int argNum = 0;
01324                 while (++iParVal) {
01325                     if (iParVal->m_prmName == "return") {
01326                         DynamicAny::DynAny_var tmpDa = dynFact->create_dyn_any (req->return_value ());
01327                         CORBA::TypeCode_var _tc = tmpDa->type ();
01328                         if (_tc->kind () != CORBA::tk_void) {
01329                             DOM_Node retNode = addElement (doc, methNode, "m:return");
01330                             DynAny2Xml (doc, retNode, iParVal, tmpDa, theCtxKey.IsEmpty () ? NULL : (const char *) theCtxKey);
01331                         }
01332                         tmpDa->destroy ();
01333                     } else if (iParVal->m_prmKind != ioeException) {
01334                         CORBA::NamedValue_ptr ar = args->item (argNum ++);
01335                         CORBA::Any aar (*(ar->value ()));
01336                         switch (iParVal->m_prmKind) {
01337                         case ioeIn: break;
01338                         case ioeOut:   
01339                         case ioeInOut: 
01340                             {
01341                                 DynamicAny::DynAny_var tmpDa = dynFact->create_dyn_any (aar);
01342                                 CString argNam = "m:";
01343                                 argNam += iParVal->m_prmName;
01344                                 DOM_Node argNode = addElement (doc, methNode, argNam);
01345                                 DynAny2Xml (doc, argNode, iParVal, tmpDa, theCtxKey.IsEmpty () ? NULL : (const char *) theCtxKey);
01346                                 tmpDa->destroy ();
01347                             }
01348                             break;
01349                         }
01350                     }
01351                 }
01352 
01353                 GetXML (outXml, outXmlSiz, (DOM_H) &doc);
01354             }
01355         }
01356         catch (DOM_Document &doc) {
01357             GetXML (outXml, outXmlSiz, &doc);
01358         }
01359     }
01360     catch (...) {
01361         return Fault (sfServer, "Exception", "Unknown exception occurred while handling the SOAP request.");
01362     }
01363     soapBridgeLog->debug ("Call handled in %lg seconds\n", sec_u () - start_time);
01364     CORBA::Octet *pBuf = SOAPBridge::SOAPCall::XMLData::allocbuf (outXmlSiz);
01365     if (outXml) memcpy (pBuf, outXml, outXmlSiz);
01366     delete outXml;
01367     return new SOAPBridge::SOAPCall::XMLData (outXmlSiz, outXmlSiz, pBuf, 1);
01368 }
01369 
01380 SOAPBridge::SOAPCall::XMLData* SOAPBridge_SOAPCall_i::invokeInstance(CORBA::Object_ptr objRef, const char* action, const SOAPBridge::SOAPCall::XMLData& data)
01381 throw (CORBA::SystemException, SOAPBridge::SOAPCall::InvocationFailed)
01382 {
01383     suppliedObject = objRef;
01384     useSupplied = true;
01385     return invokeAction (action, data);
01386 }
01387 
01392 SOAPBridge::SOAPCall::SOAPActionSeq* SOAPBridge_SOAPCall_i::listActions ()
01393 throw (CORBA::SystemException)
01394 {
01395     SOAPBridge::SOAPCall::SOAPActionSeq_var result = new SOAPBridge::SOAPCall::SOAPActionSeq;
01396     IRP_ITEM_H itm = NULL;
01397     const char *ccp;
01398     CORBA::ULong na = 0;
01399     while ((ccp = iterIRPlus (irplusHandle, &itm)) != NULL) {
01400         CString action = ccp;
01401         int lastSlash = action.ReverseFind ('/');
01402         if (lastSlash > 0) {
01403             CString funcName = action.Mid (lastSlash + 1);
01404             action = action.Left (lastSlash);
01405             action += '#';
01406             action += funcName;
01407         } else {
01408             action += "#BAD_METHOD_FOUND";
01409         }
01410         result->length (na + 1);
01411         result [na] = (const char *) action;
01412         na ++;
01413     }
01414     return result._retn ();
01415 }
01416 
01425 CORBA::Boolean SOAPBridge_SOAPCall_i::fetchSample (const char* action, SOAPBridge::SOAPCall::XMLData_out request, SOAPBridge::SOAPCall::XMLData_out respons)
01426 throw (CORBA::SystemException)
01427 {
01428     request = new SOAPBridge::SOAPCall::XMLData;
01429     respons = new SOAPBridge::SOAPCall::XMLData;
01430     CString xmlin;
01431     CString xmlout;
01432     if (!GetSOAP (xmlin, xmlout, irplusHandle, action)) {
01433         soapBridgeLog->error ("fetchSample: GetSOAP(%s) failed\n", action);
01434         return false;
01435     }
01436     soapBridgeLog->debug ("GetSoap(%s)=\n\t%s\n\t%s\n", action, (const char *) xmlin, (const char *) xmlout);
01437     CORBA::Octet *buf;
01438     buf = SOAPBridge::SOAPCall::XMLData::allocbuf (xmlin.GetLength ());
01439     memcpy (buf, (const char *) xmlin, xmlin.GetLength ());
01440     request->replace (xmlin.GetLength (), xmlin.GetLength (), buf, true);
01441     buf = SOAPBridge::SOAPCall::XMLData::allocbuf (xmlout.GetLength ());
01442     memcpy (buf, (const char *) xmlout, xmlout.GetLength ());
01443     respons->replace (xmlout.GetLength (), xmlout.GetLength (), buf, true);
01444     return true;
01445 }
01446 

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