1 /*------------------------------------------------------------------------------
2 Name: XmlBlasterAccess.h
3 Project: xmlBlaster.org
4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
5 ------------------------------------------------------------------------------*/
6 #ifndef _CLIENT_XMLBLASTERACCESS_H
7 #define _CLIENT_XMLBLASTERACCESS_H
8
9 #include <util/xmlBlasterDef.h>
10 #include <util/Global.h>
11 #include <util/qos/ConnectQos.h>
12 #include <client/I_ConnectionProblems.h>
13 #include <client/I_Callback.h>
14 #include <util/thread/ThreadImpl.h>
15 #include <util/dispatch/I_PostSendListener.h>
16 #include <util/ReferenceCounterBase.h>
17 #include <util/ReferenceHolder.h>
18 #include <util/XmlBlasterException.h>
19 #include <util/queue/MsgQueueEntry.h>
20 #include <util/queue/I_Queue.h>
21 #include <string>
22 #include <vector>
23 #include <map>
24
25 /* The following comment is used by doxygen for the main html page: */
26 /*! \mainpage Hints about the C++ client library usage.
27 *
28 * \section intro_sec The C++ client library
29 *
30 * The xmlBlaster C++ client library supports access to xmlBlaster with asynchronous callbacks,
31 * client side queuing and fail safe reconnect using the CORBA or SOCKET protocol plugin.
32 * Details about compilation and its usage can be found in the
33 * http://www.xmlblaster.org/xmlBlaster/doc/requirements/client.cpp.html requirement.
34 *
35 * As a C++ developer your entry point to use is the class org::xmlBlaster::client::XmlBlasterAccess and
36 * a complete overview demo code is HelloWorld2.cpp
37 *
38 * \section c_sec The C client library
39 * The C client library offers some basic functionality like the SOCKET protocol with
40 * the struct #XmlBlasterAccessUnparsed or persistent queues with struct #I_Queue.
41 * These features are heavily used by the C++ library.
42 * If you need a tiny xmlBlaster access you can choose to use the C client library directly
43 * without any C++ code.
44 *
45 * For details read the
46 * http://www.xmlblaster.org/xmlBlaster/doc/requirements/client.c.socket.html requirement and the
47 * http://www.xmlblaster.org/xmlBlaster/doc/requirements/client.c.queue.html requirement.
48 * and look at the API documentation at http://www.xmlblaster.org/xmlBlaster/doc/doxygen/c/html/index.html
49 */
50
51 // Note: I_ConnectionProblems.h includes I_ConnectionsHandler.h includes I_XmlBlasterConnection.h
52 // which includes all EraseQos, SubscribeKey etc.
53 // -> We could try to avoid this by forward declaration, but all cpp files must
54 // then include them thereselves.
55
56 // Declare classes without the need to include them in this header file
57 namespace org { namespace xmlBlaster { namespace util {
58 class MessageUnit;
59 }}}
60 namespace org { namespace xmlBlaster { namespace util { namespace dispatch {
61 class DispatchManager;
62 class ConnectionsHandler;
63 }}}}
64 namespace org { namespace xmlBlaster { namespace client { namespace protocol {
65 class I_CallbackServer;
66 }}}}
67
68 namespace org { namespace xmlBlaster { namespace client {
69
70 /*
71 * The interface org::xmlBlaster::client::I_CallbackRaw/I_Callback/I_CallbackExtended are enforced by AbstractCallbackExtended
72 * is for the protocol drivers.
73 */
74 typedef std::map<std::string, I_Callback*> CallbackMapType;
75 typedef std::map<std::string, std::string> StringMap;
76
77 /**
78 * This is the main entry point for programmers to the C++ client library.
79 *
80 * Exactly one Global instance and one instance of this are a pair which can't be
81 * mixed with other instances.
82 */
83 class Dll_Export XmlBlasterAccess : public org::xmlBlaster::client::I_Callback,
84 public org::xmlBlaster::util::ReferenceCounterBase,
85 public org::xmlBlaster::util::dispatch::I_PostSendListener
86 {
87 private:
88 std::string ME;
89
90 org::xmlBlaster::util::Global& global_;
91 org::xmlBlaster::util::GlobalRef globalRef_;
92 org::xmlBlaster::util::I_Log& log_;
93 std::string instanceName_;
94
95 /** The cluster node id (name) to which we want to connect, needed for nicer logging, can be null */
96 std::string serverNodeId_;
97 org::xmlBlaster::util::qos::ConnectQosRef connectQos_;
98 /** The return from connect() */
99 org::xmlBlaster::util::qos::ConnectReturnQosRef connectReturnQos_;
100 /** The dispatcher framework **/
101 org::xmlBlaster::util::dispatch::DispatchManager* dispatchManager_;
102 /** The callback server */
103 org::xmlBlaster::client::protocol::I_CallbackServer* cbServer_;
104 /** The connection server for this address */
105 org::xmlBlaster::util::dispatch::ConnectionsHandler* connection_;
106
107 /** Used to callback the clients default update() method (as given on connect()) */
108 org::xmlBlaster::client::I_Callback* updateClient_;
109
110 /**
111 * Used to temporary store the fail safe notification address (if any). Once initFailsafe is called, this
112 * pointer is set to NULL again. This way connection_.initFailsafe will be invoked even if the user has
113 * called XmlBlasterAccess::initFailsafe before the connection_ member has been created.
114 */
115 org::xmlBlaster::client::I_ConnectionProblems* connectionProblems_;
116 CallbackMapType subscriptionCallbackMap_;
117 org::xmlBlaster::util::thread::Mutex updateMutex_;
118 /** this makes sure only one invocation is done at a time on this connection. The update method is not blocked by this mutex. The shutdown is blocked */
119 org::xmlBlaster::util::thread::Mutex invocationMutex_;
120
121 org::xmlBlaster::util::dispatch::I_PostSendListener* postSendListener_;
122
123 /**
124 * Private copy constructor, clones are not supported
125 */
126 XmlBlasterAccess(const XmlBlasterAccess &global);
127
128 /**
129 * Private assignment operator, clones are not supported
130 */
131 XmlBlasterAccess& operator =(const XmlBlasterAccess &);
132
133 void cleanup(bool doLock);
134
135 public:
136 /**
137 * Create an xmlBlaster accessor.
138 * @param glob Your environment handle or null to use the default org::xmlBlaster::util::Global.instance()
139 */
140 XmlBlasterAccess(org::xmlBlaster::util::Global& global);
141
142 /**
143 * Create an xmlBlaster accessor.
144 * @param glob Your environment handle or null to use the default org::xmlBlaster::util::Global.instance()
145 */
146 XmlBlasterAccess(org::xmlBlaster::util::GlobalRef global);
147
148 virtual ~XmlBlasterAccess();
149
150 /**
151 * Access the global handle of this connection.
152 * The returned Global lifetime is limited by XmlBlasterAccess lifetime.
153 * @return The global handle containing the connection specific settings.
154 */
155 org::xmlBlaster::util::Global& getGlobal();
156
157 /**
158 * Access the client side queue
159 * @return null if not configured
160 */
161 org::xmlBlaster::util::queue::I_Queue* getQueue();
162
163 /**
164 * Login to xmlBlaster.
165 * Calling multiple times for changed connections should be possible but is not deeply tested.
166 * @param qos Your configuration desire
167 * @param client If not null callback messages will be routed to client.update()
168 * @return The returned QOS for this connection
169 */
170 org::xmlBlaster::util::qos::ConnectReturnQos connect(const org::xmlBlaster::util::qos::ConnectQos& qos, org::xmlBlaster::client::I_Callback *clientCb);
171
172 /**
173 * Access the current ConnectQos instance.
174 * @return A reference on ConnectQos, you don' need to take care on new/delete, just use it.
175 * Changes made on the instance are seen in the library as well.
176 */
177 org::xmlBlaster::util::qos::ConnectQosRef getConnectQos();
178 org::xmlBlaster::util::qos::ConnectReturnQosRef getConnectReturnQos();
179
180 /**
181 * Access the previously with connect() registered callback pointer.
182 * @return Can be NULL
183 */
184 org::xmlBlaster::client::I_Callback* getCallback();
185
186 /**
187 * Extracts address data from org::xmlBlaster::util::qos::ConnectQos (or adds default if missing)
188 * and instantiate a callback server as specified in org::xmlBlaster::util::qos::ConnectQos
189 */
190 void createDefaultCbServer();
191
192 /**
193 * Create a new instance of the desired protocol driver like CORBA or RMI driver using the plugin loader.
194 * @param type E.g. "IOR" or "SOCKET", if null we use the same protocol as our client access.
195 * @param version The version of the driver, e.g. "1.0"
196 */
197 org::xmlBlaster::client::protocol::I_CallbackServer* initCbServer(const std::string& loginName, const std::string& type, const std::string& version);
198
199 /**
200 * Register a listener for to receive information about the progress of incoming data.
201 * Only one listener is supported, the last call overwrites older calls.
202 * @param listener Your listener, pass 0 to unregister.
203 * @return The previously registered listener or 0
204 */
205 org::xmlBlaster::util::dispatch::I_PostSendListener* registerPostSendListener(org::xmlBlaster::util::dispatch::I_PostSendListener *listener);
206
207 /**
208 * Register a listener for to receive the return Qos of send messages
209 * from the client queue.
210 * Only one listener is supported, the last call overwrites older calls.
211 * <p/>
212 * Note: The synchronously send returned QoS are not delivered here as they
213 * are returned by the method invocation already:
214 * <pre>
215 * PublishReturnQos pubRetQos = con.publish(msgUnit);
216 * </pre>
217 * @param listener Your listener, pass 0 to unregister.
218 * @return The previously registered listener or 0
219 */
220 org::xmlBlaster::client::protocol::I_ProgressListener* registerProgressListener(org::xmlBlaster::client::protocol::I_ProgressListener *listener);
221
222 /**
223 * Initializes the little client helper framework for authentication.
224 * <p />
225 * The first goal is a proper loginQoS xml std::string for authentication.
226 * <p />
227 * The second goal is to intercept the messages for encryption (or whatever the
228 * plugin supports).
229 * <p />
230 * See xmlBlaster.properties, for example:
231 * <pre>
232 * Security.Client.DefaultPlugin=gui,1.0
233 * Security.Client.Plugin[gui][1.0]=org.xmlBlaster.authentication.plugins.gui.ClientSecurityHelper
234 * </pre>
235 */
236 void initSecuritySettings(const std::string& secMechanism, const std::string& secVersion);
237
238 /**
239 * Logout from the server.
240 * <p>
241 * Depending on your arguments, the callback server is removed as well, releasing all CORBA/RMI/XmlRpc threads.
242 * Note that this kills the server ping thread as well (if in failsafe mode)
243 * </p>
244 * @param qos The disconnect quality of service
245 * @param flush Flushed pending publishOneway() messages if any
246 * @param shutdown shutdown lowlevel connection as well (e.g. CORBA connection)
247 * @param shutdownCb shutdown callback server as well (if any was established)
248 * @return <code>true</code> successfully logged out<br />
249 * <code>false</code> failure on logout
250 * @see <a href="http://www.xmlBlaster.org/xmlBlaster/doc/requirements/interface.disconnect.html">interface.disconnect requirement</a>
251 */
252 bool disconnect(const org::xmlBlaster::util::qos::DisconnectQos& qos, bool flush=true, bool shutdown=true, bool shutdownCb=true);
253
254 /**
255 * Enforced by I_PostSendListener
256 * @see org::xmlBlaster::util::dispatch::I_PostSendListener
257 */
258 void postSend(const std::vector<org::xmlBlaster::util::queue::EntryType> &entries);
259
260 /**
261 * Enforced by I_PostSendListener
262 * @see org::xmlBlaster::util::dispatch::I_PostSendListener
263 */
264 bool sendingFailed(const std::vector<org::xmlBlaster::util::queue::EntryType> &entries, const org::xmlBlaster::util::XmlBlasterException &exception);
265
266 /**
267 * Create a descriptive ME, for logging only
268 * @return e.g. "/node/heron/client/joe/3"
269 */
270 std::string getId();
271
272 /**
273 * The public session ID of this login session.
274 */
275 std::string getSessionName();
276
277 /**
278 * Your changes outside change the internal sessionName.
279 * @return A reference counted SessionName.
280 */
281 org::xmlBlaster::util::SessionNameRef getSessionNameRef();
282
283 /**
284 * Access the login name.
285 * @return your login name or null if you are not logged in
286 */
287 std::string getLoginName();
288
289 /**
290 * Allows to set the node name for nicer logging.
291 */
292 void setServerNodeId(const std::string& nodeId);
293
294 /**
295 * The cluster node id (name) to which we want to connect.
296 * <p />
297 * Needed only for nicer logging when running in a cluster.<br />
298 * Is configurable with "-server.node.id golan"
299 * @return e.g. "golan", defaults to "xmlBlaster"
300 */
301 std::string getServerNodeId() const;
302
303 /**
304 * Put the given message entry into the queue
305 */
306 // org::xmlBlaster::util::queue::MsgQueueEntry queueMessage(const org::xmlBlaster::util::queue::MsgQueueEntry& entry);
307
308 /**
309 * Put the given message entry into the queue
310 */
311 // std::vector<MsgQueueEntry*> queueMessage(const std::vector<MsgQueueEntry*>& entries);
312
313 // org::xmlBlaster::client::qos::SubscribeReturnQos
314 // std::string subscribe(const std::string& xmlKey, const std::string& qos);
315 org::xmlBlaster::client::qos::SubscribeReturnQos subscribe(const org::xmlBlaster::client::key::SubscribeKey& key, const org::xmlBlaster::client::qos::SubscribeQos& qos, I_Callback *callback=0);
316
317 // std::vector<org::xmlBlaster::util::MessageUnit> get(const std::string& xmlKey, const std::string& qos);
318 std::vector<org::xmlBlaster::util::MessageUnit> get(const org::xmlBlaster::client::key::GetKey& key, const org::xmlBlaster::client::qos::GetQos& qos);
319
320 /**
321 * This method synchronously accesses maxEntries messages from any xmlBlaster server side queue.
322 * <p>
323 * This is a convenience method which uses get() with a specific Qos.
324 * <p>Important note:<br />
325 * Currently you shouldn't use unlimited timeout==-1 as this could
326 * lead to a server side thread leak on client disconnect.
327 * As a workaround please use a loop and a timeout of for example 60000
328 * and just ignore returned arrays of length 0.
329 * </p>
330 * @param oid The identifier like
331 * "topic/hello" to access a history queue,
332 * "client/joe" to access a subject queue or
333 * "client/joe/session/1"
334 * to access a callback queue.
335 * The string must follow the formatting rule of ContextNode.java
336 * @param maxEntries The maximum number of entries to retrieve
337 * @param timeout The time to wait until return.
338 * If you choose a negative value it will block until the maxEntries
339 * has been reached.
340 * If the value is '0' (i.e. zero) it will not wait and will correspond to a non-blocking get.
341 * If the value is positive it will block until the specified amount in milliseconds
342 * has elapsed or when the maxEntries has been reached (whichever comes first).
343 * @param consumable Expressed with 'true' or 'false'.
344 * If true the entries returned are deleted from the queue
345 * @return An array of messages, is never null but may be an array of length=0 if no message is delivered
346 * @see org.xmlBlaster.util.context.ContextNode
347 * @see <a href="http://www.xmlblaster.org/xmlBlaster/doc/requirements/engine.qos.queryspec.QueueQuery.html">engine.qos.queryspec.QueueQuery requirement</a>
348 * @see javax.jms.MessageConsumer#receive
349 */
350 std::vector<org::xmlBlaster::util::MessageUnit> receive(std::string oid, int maxEntries, long timeout, bool consumable);
351
352 std::vector<org::xmlBlaster::util::MessageUnit> request(org::xmlBlaster::util::MessageUnit &msgUnit, long timeout, int maxEntries);
353
354 /**
355 * @return oid
356 */
357 std::string createTemporaryTopic(long destroyDelay, int historyMaxMsg);
358
359 // org::xmlBlaster::client::qos::UnSubscribeReturnQos[]
360 // std::vector<std::string> unSubscribe(const std::string& xmlKey, const std::string& qos);
361 std::vector<org::xmlBlaster::client::qos::UnSubscribeReturnQos> unSubscribe(const org::xmlBlaster::client::key::UnSubscribeKey& key, const org::xmlBlaster::client::qos::UnSubscribeQos& qos);
362
363 // org::xmlBlaster::client::qos::PublishReturnQos
364 // std::string publish(const org::xmlBlaster::util::MessageUnit& msgUnit);
365 org::xmlBlaster::client::qos::PublishReturnQos publish(const org::xmlBlaster::util::MessageUnit& msgUnit);
366
367 void publishOneway(const std::vector<org::xmlBlaster::util::MessageUnit>& msgUnitArr);
368
369 // std::vector<std::string> publishArr(const std::vector<org::xmlBlaster::util::MessageUnit>& msgUnitArr);
370 std::vector<org::xmlBlaster::client::qos::PublishReturnQos> publishArr(const std::vector<org::xmlBlaster::util::MessageUnit> &msgUnitArr);
371
372 // org::xmlBlaster::client::qos::EraseReturnQos[]
373 // std::vector<std::string> erase(const std::string& xmlKey, const std::string& qos);
374 std::vector<org::xmlBlaster::client::qos::EraseReturnQos> erase(const org::xmlBlaster::client::key::EraseKey& key, const org::xmlBlaster::client::qos::EraseQos& qos);
375
376 /**
377 * Switch callback dispatcher on/off.
378 * This is a convenience function (see ConnectQos). It will update the client side
379 * ConnectQos as well so we don't loose the setting on reconnects after server maintenance.
380 * @param isActive true: XmlBlaster server delivers callback messages
381 * false: XmlBlaster server keeps messages for this client in the callback queue
382 */
383 void setCallbackDispatcherActive(bool isActive);
384
385 /**
386 * Convenience method to send an administrative command to xmlBlaster.
387 * If the command contains a '=' it is interpreted as a set() call, else it is used as
388 * a get() call.
389 * @param command for example "client/joe/?dispatcherActive" (a getter) or "client/joe/?dispatcherActive=false" (a setter).
390 * The "__cmd:" is added by us
391 * To enforce a getter or setter you can write "get client/joe/?dispatcherActive" or
392 * "set client/joe/?dispatcherActive=false"
393 * @param publishQosP optional Qos, e.g. to set persistance for set command
394 * @return When setting a value you get the returned state, else the retrieved data
395 * @throws XmlBlasterException on problems
396 */
397 std::string sendAdministrativeCommand(const std::string &command, org::xmlBlaster::client::qos::PublishQos *publishQosP = (org::xmlBlaster::client::qos::PublishQos *)0);
398
399 /**
400 * This is the callback method invoked from xmlBlaster
401 * delivering us a new asynchronous message.
402 * @see org.xmlBlaster.client.I_Callback#update(String, org::xmlBlaster::client::key::UpdateKey, byte[], org::xmlBlaster::client::qos::UpdateQos)
403 */
404 std::string update(const std::string &sessionId, org::xmlBlaster::client::key::UpdateKey &updateKey, const unsigned char *content, long contentSize, org::xmlBlaster::client::qos::UpdateQos &updateQos);
405
406 /**
407 * Command line usage.
408 */
409 static std::string usage();
410
411 /**
412 * used to initialize the failsafe behaviour of the client.
413 * If connectionProblems is not NULL, then the passed object will be notified for connection lost
414 * and reconnected events.
415 */
416 void initFailsafe(I_ConnectionProblems* connectionProblems=NULL);
417
418 std::string ping();
419
420 /**
421 * Flushes all entries in the queue, i.e. the entries of the queue are sent to xmlBlaster.
422 * If the queue is empty or NULL, then 0 is returned. If the state is in POLLING or DEAD, then -1 is
423 * returned.. This method blocks until all entries in the queue have been sent.
424 */
425 long flushQueue();
426
427 /**
428 * Same as isAlive() || isPolling()
429 * @return true if connect() call was successful, even if we are polling
430 */
431 bool isConnected() const;
432
433 /**
434 * Check if we are 'online'.
435 * @return true if connected with server and ready
436 */
437 bool isAlive() const;
438
439 /**
440 * Check if we are polling for the server.
441 * @return true if polling for the server
442 */
443 bool isPolling() const;
444
445 /**
446 * Check if this handle is still useful
447 * @return true if we have given up
448 */
449 bool isDead() const;
450
451 /**
452 * Get connection status string for logging.
453 * @return "ALIVE" | "POLLING" | "DEAD"
454 */
455 std::string getStatusString() const;
456
457 /**
458 * Disconnect and cleanup client side resources but keep our login session on server side.
459 * <p>
460 * As the login session on server side stays alive, all subscriptions stay valid
461 * and callback messages are queued by the server.
462 * If you connect at a later time the server sends us all queued messages.
463 * </p>
464 * <p>
465 * Once you have called this method the XmlBlasterAccess instance
466 * becomes invalid and any further invocation results in
467 * an XmlBlasterException to be thrown.
468 * </p>
469 * @param map The properties to pass while leaving server.
470 * Currently this argument has no effect.
471 */
472 void leaveServer(const StringMap &map);
473 };
474
475 typedef org::xmlBlaster::util::ReferenceHolder<org::xmlBlaster::client::XmlBlasterAccess> XmlBlasterAccessRef;
476
477 }}} // namespaces
478
479 #endif
syntax highlighted by Code2HTML, v. 0.9.1