1 /*----------------------------------------------------------------------------
  2 Name:      XmlBlasterManaged.cpp
  3 Project:   xmlBlaster.org
  4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
  5 Author:    "Marcel Ruff" <xmlBlaster@marcelruff.info>
  6 Note:      Managed C++ wrapper around unmanaged C xmlBlaster client library DLL
  7 Todo:      Currently only works for one connection as i don't know how to pass
  8            'XmlBlasterAccessM^ xmlBlasterAccess' to myUpdate() function
  9 -----------------------------------------------------------------------------*/
 10 #ifdef _MANAGED // If /clr flag is set

 11 
 12 #include <iostream>

 13 #include "XmlBlasterManaged.h"

 14 #include "XmlBlasterAccessUnparsed.h"

 15 
 16 using namespace System;
 17 using namespace System::Text;
 18 using namespace System::Collections;
 19 
 20 using namespace org::xmlBlaster::client;
 21 
 22 /* Which multibyte string conversion to use, "toAnsi()" or "toUtf8()" */
 23 #define TO_MBS toAnsi

 24 #define FROM_MBS fromUtf8

 25 
 26 
 27 static void MarshalString(System::String^ s, std::string& os, const char *prefix=0) {
 28    if (prefix != 0) os = prefix;
 29    using namespace System::Runtime::InteropServices;
 30    const char* chars = 
 31       (const char*)(Marshal::StringToHGlobalAnsi(s)).ToPointer();
 32    os += chars;
 33    Marshal::FreeHGlobal(IntPtr((void*)chars));
 34 }
 35 
 36 /**
 37  * @return is malloced, you need to free it
 38  */
 39 static char *toAnsi(System::String^ s, const char *prefix=0) {
 40    std::string os;
 41    MarshalString(s, os, prefix);
 42    return strcpyAlloc(os.c_str());
 43 }
 44 
 45 static System::String^ fromUtf8(const char *encodedBytes) {
 46    std::string s(encodedBytes);
 47    String ^str= gcnew String(s.c_str());
 48 
 49    //System::String^ str;

 50    //str = encodedBytes;

 51    return str;
 52    /*
 53    //System::String^ str(p);
 54    UTF8Encoding^ utf8 = gcnew UTF8Encoding;
 55    const int len = (int)strlen(encodedBytes);
 56    array<Byte>^ arr;
 57    for (int i=0; (encodedBytes+i) != 0; i++)
 58    arr[i] = (Byte)encodedBytes[i];
 59    System::String^ decodedString = utf8->GetString(arr);
 60    return decodedString;
 61    */
 62 }
 63 
 64 
 65 /**
 66  * @return is malloced, you need to free it
 67  */
 68 static char *toUtf8(String^ unicodeString, const char *prefix=0) {
 69    UTF8Encoding^ utf8 = gcnew UTF8Encoding;
 70    Console::WriteLine("original=" + unicodeString );
 71    array<Byte>^encodedBytes = utf8->GetBytes( unicodeString );
 72    //Console::WriteLine();

 73    Console::WriteLine( "Encoded bytes:" );
 74 
 75    int prefixLen = (prefix == 0) ? 0 : (int)strlen(prefix);
 76    int len = prefixLen + encodedBytes->Length + 1;
 77 
 78    char *mbs = (char *)malloc(len);
 79    *(mbs+len-1) = 0;
 80    if (prefixLen > 0)
 81       strncpy0(mbs, prefix, prefixLen+1);
 82 
 83    int i=prefixLen;
 84    IEnumerator^ myEnum = encodedBytes->GetEnumerator();
 85    while ( myEnum->MoveNext() )
 86    {
 87       Byte b = safe_cast<Byte>(myEnum->Current);
 88       mbs[i] = b;
 89       Console::Write( "[{0}]", b );
 90    }
 91    return mbs;
 92 }
 93 
 94 
 95 /**
 96 * Here we receive the callback messages from xmlBlaster
 97 * @param msgUnitArr The received messages
 98 * @param userData Is the corresponding XmlBlasterAccessUnparsed * pointer
 99 * @param exception An OUT parameter to transport back an exception
100 * @see UpdateFp in XmlBlasterAccessUnparsed.h
101 * @see UpdateFp in CallbackServerUnparsed.h
102 */
103 static bool myUpdate(::MsgUnitArr *msgUnitArr, void *userData,
104                      ::XmlBlasterException *exception)
105 {
106    size_t i;
107    bool testException = false;
108    ::XmlBlasterAccessUnparsed *connection_ = (::XmlBlasterAccessUnparsed *)userData;
109    //Cannot convert an unmanaged type to a managed type

110    //XmlBlasterAccessM^ xmlBlasterAccess = static_cast<XmlBlasterAccessM^>(connection_->userObject);

111 
112    for (i=0; i<msgUnitArr->len; i++) {
113       char *xml = ::messageUnitToXml(&msgUnitArr->msgUnitArr[i]);
114       printf("[client] CALLBACK update(): Asynchronous message update arrived:%s\n",
115          xml);
116       ::xmlBlasterFree(xml);
117       msgUnitArr->msgUnitArr[i].responseQos = 
118          strcpyAlloc("<qos><state id='OK'/></qos>");
119       /* Return QoS: Everything is OK */
120    }
121    return true;
122 }
123 
124    XmlBlasterAccessM::XmlBlasterAccessM(Hashtable ^props) {
125       System::Console::WriteLine("Hello from xmlBlasterClientC CLR");
126 
127       int argc = (2*props->Count)+1;
128       const char ** ptr = (const char **)malloc(argc*sizeof(char *));
129       ptr[0] = strcpyAlloc("someClientName"); // TODO

130       IDictionaryEnumerator^ myEnumerator = props->GetEnumerator();
131       int i=1;
132       while (myEnumerator->MoveNext()) {
133          //System::Console::WriteLine("\t{0}:\t{1}", myEnumerator->Key, myEnumerator->Value);

134          ptr[i] = TO_MBS((System::String ^)myEnumerator->Key, "-");
135          printf("key='%s'\n", ptr[i]);
136          i++;
137          ptr[i] = TO_MBS((System::String ^)myEnumerator->Value);
138          printf("value='%s'\n", ptr[i]);
139          //std::cout << "UTF8 result is " << ptr[i] << std::endl;

140          i++;
141       }
142 
143       this->connection_ = getXmlBlasterAccessUnparsed(argc, (const char* const*)ptr);
144       // Cannot convert a managed type to an unmanaged type

145       //this->connection_->userObject = (void *)this; // Transports us to the myUpdate() method

146       // this->connection_->log = myLogger;    // Register our own logging function

147       // this->connection_->logUserP = this;   // Pass ourself to myLogger()

148    }
149 
150    XmlBlasterAccessM::~XmlBlasterAccessM() {
151       shutdown();
152    }
153 
154    String ^XmlBlasterAccessM::connect(String ^connectQos) {
155       ::XmlBlasterException xmlBlasterException;
156       check();
157       if (connection_->initialize(connection_, (UpdateFp)myUpdate, &xmlBlasterException) == false) {
158          printf("[client] Connection to xmlBlaster failed,"
159             " please start the server or check your configuration\n");
160          shutdown();
161          throw gcnew XmlBlasterExceptionM(FROM_MBS(xmlBlasterException.errorCode), FROM_MBS(xmlBlasterException.message));
162       }
163 
164       char *retQos = connection_->connect(connection_, TO_MBS(connectQos),
165          (UpdateFp)myUpdate, &xmlBlasterException);
166       if (*xmlBlasterException.errorCode != 0) {
167          printf("[client] Caught exception during connect errorCode=%s, message=%s\n",
168             xmlBlasterException.errorCode, xmlBlasterException.message);
169          shutdown();
170          throw gcnew XmlBlasterExceptionM(FROM_MBS(xmlBlasterException.errorCode), FROM_MBS(xmlBlasterException.message));
171       }
172       String^ ret = FROM_MBS(retQos);
173       xmlBlasterFree(retQos);
174       printf("[client] Connected to xmlBlaster ...\n");
175       return ret;
176    }
177 
178    System::Boolean XmlBlasterAccessM::disconnect(String ^qos) {
179       
180       ::XmlBlasterException xmlBlasterException;
181       check();
182       if (this->connection_->disconnect(this->connection_, TO_MBS(qos), &xmlBlasterException) == false) {
183          printf("[client] Caught exception in disconnect, errorCode=%s, message=%s\n",
184                xmlBlasterException.errorCode, xmlBlasterException.message);
185          shutdown();
186          return false;
187       }
188       return true;
189    }
190 
191    void XmlBlasterAccessM::check() {
192       if (this->connection_ == 0) {
193          throw gcnew XmlBlasterExceptionM(L"user.illegalArgument", L"The connection is shutdown, please create another XmlBlasterAccessM instance");
194       }
195    }
196 
197    void XmlBlasterAccessM::shutdown() {
198       freeXmlBlasterAccessUnparsed(this->connection_);
199       this->connection_ = 0;
200    }
201 
202    String ^XmlBlasterAccessM::getVersion() {
203       check();
204       const char *version = ::getXmlBlasterVersion();
205       return FROM_MBS(version);
206    }
207 
208    String ^XmlBlasterAccessM::getUsage() {
209       check();
210       char usage[XMLBLASTER_MAX_USAGE_LEN];
211       ::xmlBlasterAccessUnparsedUsage(usage);
212       return FROM_MBS(usage);
213    }
214 
215 #endif // _MANAGED



syntax highlighted by Code2HTML, v. 0.9.1