1 // xmlBlaster/demo/javaclients/HelloWorldSubscribe.java
2 package javaclients;
3
4 import java.util.logging.Logger;
5 import java.util.logging.Level;
6
7 import org.xmlBlaster.util.FileLocator;
8 import org.xmlBlaster.util.Global;
9 import org.xmlBlaster.util.XmlBlasterException;
10 import org.xmlBlaster.util.def.Constants;
11 import org.xmlBlaster.util.def.ErrorCode;
12 import org.xmlBlaster.util.property.Args;
13 import org.xmlBlaster.util.qos.HistoryQos;
14 import org.xmlBlaster.util.qos.ClientProperty;
15 import org.xmlBlaster.client.qos.ConnectQos;
16 import org.xmlBlaster.client.qos.ConnectReturnQos;
17 import org.xmlBlaster.client.qos.DisconnectQos;
18 import org.xmlBlaster.client.I_Callback;
19 import org.xmlBlaster.client.key.UpdateKey;
20 import org.xmlBlaster.client.key.SubscribeKey;
21 import org.xmlBlaster.client.key.UnSubscribeKey;
22 import org.xmlBlaster.client.qos.UpdateQos;
23 import org.xmlBlaster.client.qos.SubscribeQos;
24 import org.xmlBlaster.client.qos.SubscribeReturnQos;
25 import org.xmlBlaster.client.qos.UnSubscribeQos;
26 import org.xmlBlaster.client.qos.UnSubscribeReturnQos;
27 import org.xmlBlaster.util.qos.AccessFilterQos;
28 import org.xmlBlaster.client.I_XmlBlasterAccess;
29 import org.xmlBlaster.client.I_ConnectionStateListener;
30 import org.xmlBlaster.util.dispatch.ConnectionStateEnum;
31 import java.util.Map;
32 import java.util.Iterator;
33 import java.io.File;
34 import java.text.DateFormat;
35 import java.text.SimpleDateFormat;
36 import java.util.TimeZone;
37 import java.util.Date;
38
39
40 /**
41 * This client connects to xmlBlaster and subscribes to messages.
42 * <p>
43 * This is a nice client to experiment and play with xmlBlaster as there are many
44 * command line options to specify the type and amount of messages published.
45 * </p>
46 * <p>
47 * Try using 'java javaclients.HelloWorldPublish' in another window to publish some
48 * messages.
49 * Further you can type 'd' in the window running xmlBlaster to get a server dump.
50 * </p>
51 *
52 * Invoke (after starting the xmlBlaster server):
53 * <pre>
54 * java javaclients.HelloWorldSubscribe -xpath //key -initialUpdate true -unSubscribe true
55 *
56 * java javaclients.HelloWorldSubscribe -interactive false -oid Hello -initialUpdate true -unSubscribe true
57 *
58 * java javaclients.HelloWorldSubscribe -session.name joeSubscriber/5 -passwd secret -initialUpdate true -dump[HelloWorldSubscribe] true
59 *
60 * java javaclients.HelloWorldSubscribe -xpath //key -filter.type GnuRegexFilter -filter.query "^__sys__jdbc.*"
61 *
62 * java javaclients.HelloWorldSubscribe -xpath //key -filter.type XPathFilter -filter.query "//tomato"
63 *
64 * java javaclients.HelloWorldSubscribe -xpath //key -filter.type ContentLenFilter -filter.query "10"
65 * </pre>
66 * <p>
67 * If unSubscribe=false the message is not unsubscribed at the end, if disconnect=false we don't logout at the end.
68 * </p>
69 * @see java javaclients.HelloWorldPublish
70 * @see java javaclients.HelloWorldGet
71 * @see <a href="http://www.xmlBlaster.org/xmlBlaster/doc/requirements/interface.html" target="others">xmlBlaster interface</a>
72 */
73 public class HelloWorldSubscribe implements I_Callback
74 {
75
76 public class HelloThread extends Thread {
77
78 private Global global;
79
80 HelloThread(Global global) {
81 super();
82 this.global = global;
83 }
84
85 public void run() {
86 process(this.global);
87 }
88 }
89
90 private final String ME = "HelloWorldSubscribe";
91 private Global glob;
92 private static Logger log = Logger.getLogger(HelloWorldSubscribe.class.getName());
93 private I_XmlBlasterAccess con;
94 private SubscribeReturnQos srq;
95 private String subscribeServerId;
96 private int updateCounter;
97 private boolean connectPersistent;
98 private boolean firstConnect=true;
99 private boolean interactive;
100 private boolean autoSubscribe;
101 private boolean interactiveUpdate;
102 private long updateSleep;
103 private String updateExceptionErrorCode;
104 private String updateExceptionMessage;
105 private String updateExceptionRuntime;
106 private boolean shutdownCbServer;
107 private String oid;
108 private String domain;
109 private String xpath;
110 private boolean multiSubscribe;
111 private boolean persistentSubscribe;
112 private boolean notifyOnErase;
113 private boolean local;
114 private boolean initialUpdate;
115 private boolean updateOneway;
116 private boolean wantContent;
117 private boolean dumpToFile;
118 // only IF dumpToFile==true:
119 private String fileExtension;
120 private String filePrefix;
121 private String fileDateFormat;
122 private volatile DateFormat formatter;
123 private String fileLock;
124 private String fileHeader;
125 private int historyNumUpdates;
126 private boolean historyNewestFirst;
127 private String filterType;
128 private String filterVersion;
129 private String filterQuery;
130 private boolean unSubscribe;
131 private int maxContentLength;
132 private boolean connectRefreshSession;
133 private boolean runAsDaemon;
134 private boolean dumpToConsole;
135 private Map clientPropertyMap;
136 private Map connectQosClientPropertyMap;
137
138 public HelloWorldSubscribe() {
139
140 }
141
142 public HelloWorldSubscribe(Global global_) {
143 process(global_);
144 }
145
146 private void readEnv() {
147 this.connectPersistent = glob.getProperty().get("connect/qos/persistent", false);
148 this.interactive = glob.getProperty().get("interactive", true);
149 this.autoSubscribe = glob.getProperty().get("autoSubscribe", false);
150 this.interactiveUpdate = glob.getProperty().get("interactiveUpdate", false);
151 this.updateSleep = glob.getProperty().get("updateSleep", 0L);
152 this.updateExceptionErrorCode = glob.getProperty().get("updateException.errorCode", (String)null);
153 this.updateExceptionMessage = glob.getProperty().get("updateException.message", (String)null);
154 this.updateExceptionRuntime = glob.getProperty().get("updateException.runtime", (String)null);
155 this.shutdownCbServer = glob.getProperty().get("shutdownCbServer", false);
156 this.oid = glob.getProperty().get("oid", "");
157 this.domain = glob.getProperty().get("domain", "");
158 this.xpath = glob.getProperty().get("xpath", "");
159 this.multiSubscribe = glob.getProperty().get("multiSubscribe", true);
160 this.persistentSubscribe = glob.getProperty().get("persistentSubscribe", false);
161 this.notifyOnErase = glob.getProperty().get("notifyOnErase", true);
162 this.local = glob.getProperty().get("local", true);
163 this.initialUpdate = glob.getProperty().get("initialUpdate", true);
164 this.updateOneway = glob.getProperty().get("updateOneway", false);
165 this.wantContent = glob.getProperty().get("wantContent", true);
166 this.dumpToFile = glob.getProperty().get("dumpToFile", false);
167 // only IF dumpToFile==true:
168 this.fileExtension = glob.getProperty().get("fileExtension", ""); // for example ".jpg"
169 this.filePrefix = glob.getProperty().get("filePrefix", ""); // Fixed file name instead of topic as file name
170 this.fileDateFormat = glob.getProperty().get("fileDateFormat", "yyyy-MM-dd'T'HHmmss.S"); // How to format the date of the file name (ISO 8601)
171 this.fileLock = glob.getProperty().get("fileLock", ""); // add extension for lock file during Fixed file name instead of topic as file name, ".lck"
172 this.fileHeader = glob.getProperty().get("fileHeader", ""); // add a header text to the file, e.g. "<?xml version='1.0' encoding='UTF-8' ?>\n"
173 this.historyNumUpdates = glob.getProperty().get("historyNumUpdates", 1);
174 this.historyNewestFirst = glob.getProperty().get("historyNewestFirst", true);
175 this.filterType = glob.getProperty().get("filter.type", "GnuRegexFilter");// XPathFilter | ContentLenFilter
176 this.filterVersion = glob.getProperty().get("filter.version", "1.0");
177 this.filterQuery = glob.getProperty().get("filter.query", "");
178 this.unSubscribe = glob.getProperty().get("unSubscribe", true);
179 this.maxContentLength = glob.getProperty().get("maxContentLength", 250);
180 this.connectRefreshSession = glob.getProperty().get("connect/qos/sessionRefresh", false);
181 this.runAsDaemon = glob.getProperty().get("runAsDaemon", false);
182 this.dumpToConsole = glob.getProperty().get("dumpToConsole", true);
183 this.clientPropertyMap = glob.getProperty().get("clientProperty", (Map)null);
184 this.connectQosClientPropertyMap = glob.getProperty().get("connect/qos/clientProperty", (Map)null);
185 int numClients = glob.getProperty().get("numClients", 1);
186 }
187
188 public void processAsync(Global glob_) {
189 log.info("Starting one thread");
190 HelloThread th = new HelloThread(glob_);
191 th.start();
192 }
193
194 public void process(Global glob_) {
195 this.glob = glob_;
196
197 boolean disconnect = glob.getProperty().get("disconnect", true);
198 try {
199 readEnv();
200
201 if (oid.length() < 1 && xpath.length() < 1) {
202 log.warning("No -oid or -xpath given, we subscribe to oid='Hello'.");
203 oid = "Hello";
204 }
205
206 if (this.updateSleep > 0L && interactiveUpdate == true) {
207 log.warning("You can't set 'updateSleep' and 'interactiveUpdate' simultaneous, we reset interactiveUpdate to false");
208 this.interactiveUpdate = false;
209 }
210
211 if (this.updateExceptionErrorCode != null && this.updateExceptionRuntime != null) {
212 log.warning("You can't throw a runtime and an XmlBlasterException simultaneous, please check your settings " +
213 " -updateException.errorCode and -updateException.runtime");
214 this.updateExceptionRuntime = null;
215 }
216
217 log.info("Used settings are:");
218 log.info(" -connect/qos/persistent " + connectPersistent);
219 log.info(" -connect/qos/sessionRefresh " + connectRefreshSession);
220 if (connectQosClientPropertyMap != null) {
221 Iterator it = connectQosClientPropertyMap.keySet().iterator();
222 while (it.hasNext()) {
223 String key = (String)it.next();
224 log.info(" -connect/qos/clientProperty["+key+"] " + connectQosClientPropertyMap.get(key).toString());
225 }
226 }
227 else {
228 log.info(" -connect/qos/clientProperty[] ");
229 }
230 log.info(" -interactive " + interactive);
231 log.info(" -autoSubscribe " + autoSubscribe);
232 log.info(" -interactiveUpdate " + this.interactiveUpdate);
233 log.info(" -updateSleep " + this.updateSleep);
234 log.info(" -updateException.errorCode " + this.updateExceptionErrorCode);
235 log.info(" -updateException.message " + this.updateExceptionMessage);
236 log.info(" -updateException.runtime " + this.updateExceptionRuntime);
237 log.info(" -shutdownCbServer " + shutdownCbServer);
238 log.info(" -oid " + oid);
239 log.info(" -domain " + domain);
240 log.info(" -xpath " + xpath);
241 log.info(" -multiSubscribe " + multiSubscribe);
242 log.info(" -persistentSubscribe " + persistentSubscribe);
243 log.info(" -notifyOnErase " + notifyOnErase);
244 log.info(" -local " + local);
245 log.info(" -initialUpdate " + initialUpdate);
246 log.info(" -updateOneway " + updateOneway);
247 log.info(" -historyNumUpdates " + historyNumUpdates);
248 log.info(" -historyNewestFirst " + historyNewestFirst);
249 log.info(" -wantContent " + wantContent);
250 log.info(" -dumpToFile " + dumpToFile);
251 log.info(" -fileExtension " + fileExtension);
252 log.info(" -unSubscribe " + unSubscribe);
253 log.info(" -disconnect " + disconnect); // false: leaveServer
254 log.info(" -filter.type " + filterType);
255 log.info(" -filter.version " + filterVersion);
256 log.info(" -filter.query " + filterQuery);
257 if (this.clientPropertyMap != null) {
258 Iterator it = this.clientPropertyMap.keySet().iterator();
259 while (it.hasNext()) {
260 String key = (String)it.next();
261 log.info(" -clientProperty["+key+"] " + this.clientPropertyMap.get(key).toString());
262 }
263 }
264 else {
265 log.info(" -clientProperty[] ");
266 }
267
268 log.info("For more info please read:");
269 log.info(" http://www.xmlBlaster.org/xmlBlaster/doc/requirements/interface.subscribe.html");
270
271 con = glob.getXmlBlasterAccess();
272
273 // Do fail safe handling:
274 con.registerConnectionListener(new I_ConnectionStateListener() {
275 public void reachedAlive(ConnectionStateEnum oldState, I_XmlBlasterAccess connection) {
276 if (connection.getConnectReturnQos().isReconnected())
277 log.info("I_ConnectionStateListener.reachedAlive(): Same server instance found");
278 else
279 log.info("I_ConnectionStateListener.reachedAlive(): New server instance found, connected to " +
280 connection.getConnectReturnQos().getSessionName());
281
282 if (connection.getQueue().getNumOfEntries() > 0) {
283 log.info("I_ConnectionStateListener.reachedAlive(): Queue contains " +
284 connection.getQueue().getNumOfEntries() + " messages: " +
285 connection.getQueue().toXml(""));
286 // connection.getQueue().clear(); -> Would destroy ConnectQos if new connected
287 }
288
289 String id = connection.getConnectReturnQos().getSecretSessionId() + connection.getConnectReturnQos().getServerInstanceId();
290
291 if (!firstConnect && (subscribeServerId == null ||
292 !subscribeServerId.equals(id) && !persistentSubscribe)) {
293 subscribe(); // We lost the old subscription, initialize subscription again
294 }
295 }
296 public void reachedPolling(ConnectionStateEnum oldState, I_XmlBlasterAccess connection) {
297 log.warning("I_ConnectionStateListener.reachedPolling(): No connection to " + glob.getId() + ", we are polling ...");
298 }
299 public void reachedDead(ConnectionStateEnum oldState, I_XmlBlasterAccess connection) {
300 log.severe("I_ConnectionStateListener.reachedDead(): Connection to " + glob.getId() + " is dead, good bye");
301 System.exit(1);
302 }
303 public void reachedAliveSync(ConnectionStateEnum oldState, I_XmlBlasterAccess connection) {
304 }
305
306 });
307
308 // ConnectQos checks -session.name and -passwd from command line
309 ConnectQos qos = new ConnectQos(glob);
310 qos.setPersistent(connectPersistent);
311 qos.setRefreshSession(connectRefreshSession);
312 if (connectQosClientPropertyMap != null) {
313 Iterator it = connectQosClientPropertyMap.keySet().iterator();
314 while (it.hasNext()) {
315 String key = (String)it.next();
316 qos.addClientProperty(key, connectQosClientPropertyMap.get(key).toString());
317 }
318 }
319 log.info("ConnectQos is " + qos.toXml());
320 ConnectReturnQos crq = con.connect(qos, this); // Login to xmlBlaster, register for updates
321 // crq can be null if '-dispatch/connection/doSendConnect false' is set
322 log.info("Connect success as " + ((crq==null)?" faked connect":crq.toXml()));
323
324 subscribe(); // first time
325
326 if (shutdownCbServer) {
327 Global.waitOnKeyboardHit("Hit a key to shutdown callback server");
328 con.getCbServer().shutdown();
329 log.info("Callback server halted, no update should arrive ...");
330 /*
331 for (int ii=0; ii<4; ii++) {
332 Global.waitOnKeyboardHit("Hit a key to publish " + ii + "/4 ...");
333 org.xmlBlaster.util.MsgUnit msgUnit = new org.xmlBlaster.util.MsgUnit("<key oid='FromSubscriber'/>", (new String("BLA")).getBytes(), "<qos/>");
334 con.publish(msgUnit);
335 log.info("Published message");
336 }
337 */
338 }
339 else {
340 log.info("Waiting on update ...");
341 }
342
343 if (interactiveUpdate) {
344 try { Thread.sleep(1000000000); } catch( InterruptedException i) {}
345 }
346
347 char ret = 0;
348 if (unSubscribe && srq!=null) {
349 if (interactive) {
350 while (ret != 'q' && ret != 'u')
351 ret = (char)Global.waitOnKeyboardHit("Hit 'u' to unSubscribe, 'q' to quit");
352 }
353
354 if (ret == 0 || ret == 'u') {
355 UnSubscribeKey uk = new UnSubscribeKey(glob, srq.getSubscriptionId());
356 if (domain.length() > 0) // cluster routing information
357 uk.setDomain(domain);
358 UnSubscribeQos uq = new UnSubscribeQos(glob);
359 log.info("UnSubscribeKey=\n" + uk.toXml());
360 log.info("UnSubscribeQos=\n" + uq.toXml());
361 UnSubscribeReturnQos[] urqArr = con.unSubscribe(uk, uq);
362 log.info("UnSubscribe on " + urqArr.length + " subscriptions done");
363 }
364 }
365
366 if (runAsDaemon) {
367 while (true) {
368 try {
369 Thread.sleep(1000000000L);
370 }
371 catch (Exception e) {}
372 }
373 }
374 else {
375 if (ret != 'q')
376 Global.waitOnKeyboardHit("Hit a key to exit");
377 }
378 }
379 catch (XmlBlasterException e) {
380 log.severe(e.getMessage());
381 }
382 catch (Exception e) {
383 e.printStackTrace();
384 log.severe(e.toString());
385 }
386 finally {
387 if (con != null) {
388 if (disconnect) {
389 DisconnectQos dq = new DisconnectQos(glob);
390 con.disconnect(dq);
391 log.info("Disconnected, the server session is destroyed, bye");
392 }
393 else {
394 con.leaveServer(null);
395 log.info("Left server, our server side session remains, bye");
396 }
397 }
398 }
399 }
400
401 /**
402 * Does the xmlBlaster subscribe.
403 */
404 private void subscribe() {
405 try {
406 SubscribeKey sk = null;
407 String qStr = null;
408 if (oid.length() > 0) {
409 sk = new SubscribeKey(glob, oid);
410 qStr = oid;
411 }
412 else if (xpath.length() > 0) {
413 sk = new SubscribeKey(glob, xpath, Constants.XPATH);
414 qStr = xpath;
415 }
416 if (domain.length() > 0) { // cluster routing information
417 if (sk == null) sk = new SubscribeKey(glob, "", Constants.DOMAIN); // usually never
418 sk.setDomain(domain);
419 qStr = domain;
420 }
421 SubscribeQos sq = new SubscribeQos(glob);
422 sq.setWantInitialUpdate(initialUpdate);
423 sq.setWantUpdateOneway(updateOneway);
424 sq.setMultiSubscribe(multiSubscribe);
425 sq.setPersistent(persistentSubscribe);
426 sq.setWantNotify(notifyOnErase);
427 sq.setWantLocal(local);
428 sq.setWantContent(wantContent);
429
430 HistoryQos historyQos = new HistoryQos(glob);
431 historyQos.setNumEntries(historyNumUpdates);
432 historyQos.setNewestFirst(historyNewestFirst);
433 sq.setHistoryQos(historyQos);
434
435 if (filterQuery.length() > 0) {
436 AccessFilterQos filter = new AccessFilterQos(glob, filterType, filterVersion, filterQuery);
437 sq.addAccessFilter(filter);
438 }
439 if (clientPropertyMap != null) {
440 Iterator it = clientPropertyMap.keySet().iterator();
441 while (it.hasNext()) {
442 String key = (String)it.next();
443 sq.addClientProperty(key, clientPropertyMap.get(key).toString());
444 }
445 }
446
447 log.info("SubscribeKey=\n" + sk.toXml());
448 log.info("SubscribeQos=\n" + sq.toXml());
449
450 if (firstConnect && (interactive && !autoSubscribe)) {
451 Global.waitOnKeyboardHit("Hit a key to subscribe '" + qStr + "'");
452 }
453 firstConnect = false;
454
455 this.srq = con.subscribe(sk, sq);
456
457 subscribeServerId = con.getConnectReturnQos().getSecretSessionId() + con.getConnectReturnQos().getServerInstanceId();
458
459 log.info("Subscribed on topic '" + ((oid.length() > 0) ? oid : xpath) +
460 "', got subscription id='" + this.srq.getSubscriptionId() + "'\n" + this.srq.toXml());
461 if (log.isLoggable(Level.FINEST)) log.finest("Subscribed: " + sk.toXml() + sq.toXml() + srq.toXml());
462 }
463 catch (XmlBlasterException e) {
464 log.severe(e.getMessage());
465 }
466 }
467
468 /**
469 * Here the messages from xmlBlaster arrive.
470 */
471 public String update(String cbSessionId, UpdateKey updateKey, byte[] content,
472 UpdateQos updateQos) throws XmlBlasterException {
473 if (updateQos.isErased() && oid.length() > 0) { // Erased topic with EXACT subscription?
474 if (dumpToConsole) {
475 System.out.println("============= Topic '" + updateKey.getOid() + "' is ERASED =======================");
476 System.out.println(updateKey.toXml());
477 }
478 subscribe(); // topic is erased -> re-subsribe
479 return Constants.RET_OK; // "<qos><state id='OK'/></qos>";
480 }
481 ++updateCounter;
482 if (dumpToConsole) {
483 System.out.println("");
484 System.out.println("============= START #" + updateCounter + " '" + updateKey.getOid() + "' =======================");
485 log.info("Receiving update #" + updateCounter + " of a message ...");
486 System.out.println("<xmlBlaster>");
487 System.out.println(updateKey.toXml());
488 System.out.println("");
489 System.out.println("<content size='"+content.length+"'>");
490 if (maxContentLength < 0 || content.length < maxContentLength) {
491 System.out.println(new String(content));
492 }
493 else {
494 String str = new String(content, 0,maxContentLength-5);
495 System.out.println(str + " ...");
496 }
497 System.out.println("</content>");
498 System.out.println(updateQos.toXml());
499 System.out.println("</xmlBlaster>");
500 }
501
502 if (dumpToFile) {
503 String pre = (this.filePrefix.length() > 0) ? this.filePrefix : (updateKey.getOid() + "-");
504 String time = formatDate(updateQos.getRcvTimestamp().getMillis()); // 2005-06-15T052536
505 String fileName = pre + time;
506 if (fileExtension != null && fileExtension.length() > 0) {
507 fileName += fileExtension;
508 }
509 String lckFile = "";
510 if (this.fileLock.length() > 0) {
511 lckFile = fileName + this.fileLock;
512 }
513 try {
514 if (lckFile.length() > 0) {
515 FileLocator.writeFile(lckFile, "Writing " + fileName + " ...");
516 }
517 //byte[] tmp = "<?xml version='1.0' encoding='UTF-8' ?>\n".getBytes() + content;
518 byte[] tmp = content;
519 if (this.fileHeader.length() > 0) {
520 byte[] fh = this.fileHeader.getBytes();
521 tmp = new byte[fh.length+content.length];
522 System.arraycopy(fh, 0, tmp, 0, fh.length);
523 System.arraycopy(content, 0, tmp, fh.length, content.length);
524 }
525
526 FileLocator.writeFile(fileName, tmp);
527 log.info("Dumped content #" + updateCounter + " of topic '" + updateKey.getOid() + "' to file '" + fileName + "'");
528 }
529 catch (XmlBlasterException e) {
530 log.severe("Can't dump content to file '" + fileName + "': " + e.toString());
531 }
532 finally {
533 try {
534 if (lckFile.length() > 0) {
535 File f = new File(lckFile);
536 if (f.exists())
537 f.delete();
538 }
539 }
540 catch (Exception e) {
541 log.severe("Can't remove lock file '" + lckFile + "': " + e.toString());
542 }
543 }
544 }
545
546 // If clientProperty is base64 encoded we print the real value as well:
547 Map map = updateQos.getClientProperties();
548 Iterator it = map.values().iterator();
549 while (it.hasNext()) {
550 ClientProperty clientProperty = (ClientProperty)it.next();
551 if (clientProperty.isBase64()) {
552 if (dumpToConsole) {
553 System.out.println("\nClientProperty decoded: " + clientProperty.getName() + "='" + clientProperty.getStringValue() + "'");
554 }
555 }
556 }
557
558 if (dumpToConsole) {
559 System.out.println("============= END #" + updateCounter + " '" + updateKey.getOid() + "' =========================");
560 System.out.println("");
561 }
562
563 if (this.updateSleep > 0L) {
564 log.info("Sleeping for " + this.updateSleep + " millis ...");
565 try { Thread.sleep(this.updateSleep); } catch( InterruptedException i) {}
566 log.info("Waking up.");
567 } else if (this.interactiveUpdate) {
568 Global.waitOnKeyboardHit("Hit a key to return from update() (we are blocking the server callback) ...");
569 log.info("Returning update() - control goes back to server");
570 }
571
572 if (this.updateExceptionErrorCode != null) {
573 log.info("Throwing XmlBlasterException with errorCode='" + this.updateExceptionErrorCode + "' back to server ...");
574 ErrorCode errorCode;
575 try {
576 errorCode = ErrorCode.toErrorCode(this.updateExceptionErrorCode);
577 }
578 catch (IllegalArgumentException e) {
579 log.severe("Please supply a valid exception errorCode (see ErrorCode.java) for instead of -updateException.errorCode " + this.updateExceptionErrorCode + "");
580 return Constants.RET_OK; // "<qos><state id='OK'/></qos>";
581 }
582 throw new XmlBlasterException(updateKey.getGlobal(), errorCode, ME, this.updateExceptionMessage);
583 }
584
585 if (this.updateExceptionRuntime != null) {
586 log.info("Throwing RuntimeException '" + this.updateExceptionRuntime + "'");
587 throw new RuntimeException(this.updateExceptionRuntime);
588 }
589
590 return Constants.RET_OK; // "<qos><state id='OK'/></qos>";
591 }
592
593 /**
594 * Convert the long milli second time to a readable format as given with fileDateFormat.
595 * "yyyy-MM-dd'T'HHmmss" or with milli seconds "yyyy-MM-dd'T'HHmmss.S"
596 * @return Defaults to "2005-06-19T152029.344" (ISO 8601)
597 */
598 private String formatDate(long timestamp) {
599 if (this.fileDateFormat == null || this.fileDateFormat.length() == 0) {
600 return "";
601 }
602 if (this.fileDateFormat.equals("long")) {
603 return ""+timestamp;
604 }
605 if (this.formatter == null) { // cache
606 synchronized (this) {
607 if (this.formatter == null) {
608 this.formatter = new SimpleDateFormat(this.fileDateFormat); //, Locale.US);
609 this.formatter.setTimeZone(TimeZone.getDefault()); // from "user.timezone"
610 }
611 }
612 }
613 return this.formatter.format(new Date(timestamp));
614 }
615
616 /**
617 * Try
618 * <pre>
619 * java javaclients.HelloWorldSubscribe -help
620 * </pre>
621 * for usage help
622 */
623 public static void main(String args[]) {
624 Global glob = new Global();
625
626 if (glob.init(args) != 0) { // Get help with -help
627 System.out.println(glob.usage());
628 System.err.println("\nExample:");
629 System.err.println(" java javaclients.HelloWorldSubscribe -oid Hello -initialUpdate true\n");
630 System.exit(1);
631 }
632 try {
633 // check if the numClients parameter is set:
634
635 int numClients = Args.getArg(args, "-numClients", 1);
636 log.info("Number of clients to instantiate " + numClients);
637 if (numClients > 1) {
638 for (int i=0; i < numClients; i++) {
639 glob = new Global();
640 glob.init(args);
641 HelloWorldSubscribe demo = new HelloWorldSubscribe();
642 demo.processAsync(glob);
643 }
644 }
645 else {
646 HelloWorldSubscribe demo = new HelloWorldSubscribe();
647 demo.process(glob);
648 }
649 }
650 catch (XmlBlasterException ex) {
651 ex.printStackTrace();
652 }
653 }
654 }
syntax highlighted by Code2HTML, v. 0.9.1