XmlBlasterManaged.cpp

Go to the documentation of this file.
00001 /*----------------------------------------------------------------------------
00002 Name:      XmlBlasterManaged.cpp
00003 Project:   xmlBlaster.org
00004 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
00005 Author:    "Marcel Ruff" <xmlBlaster@marcelruff.info>
00006 Note:      Managed C++ wrapper around unmanaged C xmlBlaster client library DLL
00007 Todo:      Currently only works for one connection as i don't know how to pass
00008            'XmlBlasterAccessM^ xmlBlasterAccess' to myUpdate() function
00009 -----------------------------------------------------------------------------*/
00010 #ifdef _MANAGED // If /clr flag is set
00011 
00012 #include <iostream>
00013 #include "XmlBlasterManaged.h"
00014 #include "XmlBlasterAccessUnparsed.h"
00015 
00016 using namespace System;
00017 using namespace System::Text;
00018 using namespace System::Collections;
00019 
00020 using namespace org::xmlBlaster::client;
00021 
00022 /* Which multibyte string conversion to use, "toAnsi()" or "toUtf8()" */
00023 #define TO_MBS toAnsi
00024 #define FROM_MBS fromUtf8
00025 
00026 
00027 static void MarshalString(System::String^ s, std::string& os, const char *prefix=0) {
00028    if (prefix != 0) os = prefix;
00029    using namespace System::Runtime::InteropServices;
00030    const char* chars = 
00031       (const char*)(Marshal::StringToHGlobalAnsi(s)).ToPointer();
00032    os += chars;
00033    Marshal::FreeHGlobal(IntPtr((void*)chars));
00034 }
00035 
00039 static char *toAnsi(System::String^ s, const char *prefix=0) {
00040    std::string os;
00041    MarshalString(s, os, prefix);
00042    return strcpyAlloc(os.c_str());
00043 }
00044 
00045 static System::String^ fromUtf8(const char *encodedBytes) {
00046    std::string s(encodedBytes);
00047    String ^str= gcnew String(s.c_str());
00048 
00049    //System::String^ str;
00050    //str = encodedBytes;
00051    return str;
00052    /*
00053    //System::String^ str(p);
00054    UTF8Encoding^ utf8 = gcnew UTF8Encoding;
00055    const int len = (int)strlen(encodedBytes);
00056    array<Byte>^ arr;
00057    for (int i=0; (encodedBytes+i) != 0; i++)
00058    arr[i] = (Byte)encodedBytes[i];
00059    System::String^ decodedString = utf8->GetString(arr);
00060    return decodedString;
00061    */
00062 }
00063 
00064 
00068 static char *toUtf8(String^ unicodeString, const char *prefix=0) {
00069    UTF8Encoding^ utf8 = gcnew UTF8Encoding;
00070    Console::WriteLine("original=" + unicodeString );
00071    array<Byte>^encodedBytes = utf8->GetBytes( unicodeString );
00072    //Console::WriteLine();
00073    Console::WriteLine( "Encoded bytes:" );
00074 
00075    int prefixLen = (prefix == 0) ? 0 : (int)strlen(prefix);
00076    int len = prefixLen + encodedBytes->Length + 1;
00077 
00078    char *mbs = (char *)malloc(len);
00079    *(mbs+len-1) = 0;
00080    if (prefixLen > 0)
00081       strncpy0(mbs, prefix, prefixLen+1);
00082 
00083    int i=prefixLen;
00084    IEnumerator^ myEnum = encodedBytes->GetEnumerator();
00085    while ( myEnum->MoveNext() )
00086    {
00087       Byte b = safe_cast<Byte>(myEnum->Current);
00088       mbs[i] = b;
00089       Console::Write( "[{0}]", b );
00090    }
00091    return mbs;
00092 }
00093 
00094 
00103 static bool myUpdate(::MsgUnitArr *msgUnitArr, void *userData,
00104                      ::XmlBlasterException *exception)
00105 {
00106    size_t i;
00107    bool testException = false;
00108    ::XmlBlasterAccessUnparsed *connection_ = (::XmlBlasterAccessUnparsed *)userData;
00109    //Cannot convert an unmanaged type to a managed type
00110    //XmlBlasterAccessM^ xmlBlasterAccess = static_cast<XmlBlasterAccessM^>(connection_->userObject);
00111 
00112    for (i=0; i<msgUnitArr->len; i++) {
00113       char *xml = ::messageUnitToXml(&msgUnitArr->msgUnitArr[i]);
00114       printf("[client] CALLBACK update(): Asynchronous message update arrived:%s\n",
00115          xml);
00116       ::xmlBlasterFree(xml);
00117       msgUnitArr->msgUnitArr[i].responseQos = 
00118          strcpyAlloc("<qos><state id='OK'/></qos>");
00119       /* Return QoS: Everything is OK */
00120    }
00121    return true;
00122 }
00123 
00124    XmlBlasterAccessM::XmlBlasterAccessM(Hashtable ^props) {
00125       System::Console::WriteLine("Hello from xmlBlasterClientC CLR");
00126 
00127       int argc = (2*props->Count)+1;
00128       const char ** ptr = (const char **)malloc(argc*sizeof(char *));
00129       ptr[0] = strcpyAlloc("someClientName"); // TODO
00130       IDictionaryEnumerator^ myEnumerator = props->GetEnumerator();
00131       int i=1;
00132       while (myEnumerator->MoveNext()) {
00133          //System::Console::WriteLine("\t{0}:\t{1}", myEnumerator->Key, myEnumerator->Value);
00134          ptr[i] = TO_MBS((System::String ^)myEnumerator->Key, "-");
00135          printf("key='%s'\n", ptr[i]);
00136          i++;
00137          ptr[i] = TO_MBS((System::String ^)myEnumerator->Value);
00138          printf("value='%s'\n", ptr[i]);
00139          //std::cout << "UTF8 result is " << ptr[i] << std::endl;
00140          i++;
00141       }
00142 
00143       this->connection_ = getXmlBlasterAccessUnparsed(argc, (const char* const*)ptr);
00144       // Cannot convert a managed type to an unmanaged type
00145       //this->connection_->userObject = (void *)this; // Transports us to the myUpdate() method
00146       // this->connection_->log = myLogger;    // Register our own logging function
00147       // this->connection_->logUserP = this;   // Pass ourself to myLogger()
00148    }
00149 
00150    XmlBlasterAccessM::~XmlBlasterAccessM() {
00151       shutdown();
00152    }
00153 
00154    String ^XmlBlasterAccessM::connect(String ^connectQos) {
00155       ::XmlBlasterException xmlBlasterException;
00156       check();
00157       if (connection_->initialize(connection_, (UpdateFp)myUpdate, &xmlBlasterException) == false) {
00158          printf("[client] Connection to xmlBlaster failed,"
00159             " please start the server or check your configuration\n");
00160          shutdown();
00161          throw gcnew XmlBlasterExceptionM(FROM_MBS(xmlBlasterException.errorCode), FROM_MBS(xmlBlasterException.message));
00162       }
00163 
00164       char *retQos = connection_->connect(connection_, TO_MBS(connectQos),
00165          (UpdateFp)myUpdate, &xmlBlasterException);
00166       if (*xmlBlasterException.errorCode != 0) {
00167          printf("[client] Caught exception during connect errorCode=%s, message=%s\n",
00168             xmlBlasterException.errorCode, xmlBlasterException.message);
00169          shutdown();
00170          throw gcnew XmlBlasterExceptionM(FROM_MBS(xmlBlasterException.errorCode), FROM_MBS(xmlBlasterException.message));
00171       }
00172       String^ ret = FROM_MBS(retQos);
00173       xmlBlasterFree(retQos);
00174       printf("[client] Connected to xmlBlaster ...\n");
00175       return ret;
00176    }
00177 
00178    System::Boolean XmlBlasterAccessM::disconnect(String ^qos) {
00179       
00180       ::XmlBlasterException xmlBlasterException;
00181       check();
00182       if (this->connection_->disconnect(this->connection_, TO_MBS(qos), &xmlBlasterException) == false) {
00183          printf("[client] Caught exception in disconnect, errorCode=%s, message=%s\n",
00184                xmlBlasterException.errorCode, xmlBlasterException.message);
00185          shutdown();
00186          return false;
00187       }
00188       return true;
00189    }
00190 
00191    void XmlBlasterAccessM::check() {
00192       if (this->connection_ == 0) {
00193          throw gcnew XmlBlasterExceptionM(L"user.illegalArgument", L"The connection is shutdown, please create another XmlBlasterAccessM instance");
00194       }
00195    }
00196 
00197    void XmlBlasterAccessM::shutdown() {
00198       freeXmlBlasterAccessUnparsed(this->connection_);
00199       this->connection_ = 0;
00200    }
00201 
00202    String ^XmlBlasterAccessM::getVersion() {
00203       check();
00204       const char *version = ::getXmlBlasterVersion();
00205       return FROM_MBS(version);
00206    }
00207 
00208    String ^XmlBlasterAccessM::getUsage() {
00209       check();
00210       char usage[XMLBLASTER_MAX_USAGE_LEN];
00211       ::xmlBlasterAccessUnparsedUsage(usage);
00212       return FROM_MBS(usage);
00213    }
00214 
00215 #endif // _MANAGED