1 /*------------------------------------------------------------------------------
2 Name: MainGUI.java
3 Project: xmlBlaster.org
4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
5 Comment: Main class to invoke the xmlBlaster server
6 Version: $Id: MainGUI.java 14922 2006-03-12 23:12:20Z ruff $
7 ------------------------------------------------------------------------------*/
8 package org.xmlBlaster;
9
10 import java.util.logging.LogRecord;
11 import java.util.logging.Logger;
12 import java.util.logging.Level;
13 import org.xmlBlaster.util.StopWatch;
14
15 import org.xmlBlaster.util.XmlBlasterException;
16 import org.xmlBlaster.util.MsgUnitRaw;
17 import org.xmlBlaster.util.def.Constants;
18 import org.xmlBlaster.util.log.XbNotifyHandler;
19 import org.xmlBlaster.engine.ServerScope;
20 import org.xmlBlaster.engine.qos.AddressServer;
21 import org.xmlBlaster.protocol.I_Authenticate;
22 import org.xmlBlaster.protocol.I_XmlBlaster;
23 import org.xmlBlaster.client.qos.ConnectQos;
24 import org.xmlBlaster.client.qos.ConnectReturnQos;
25 import org.xmlBlaster.client.key.GetKey;
26
27 import java.awt.BorderLayout;
28 import java.awt.Button;
29 import java.awt.Checkbox;
30 import java.awt.Color;
31 import java.awt.Font;
32 import java.awt.Frame;
33 import java.awt.GridBagConstraints;
34 import java.awt.GridBagLayout;
35 import java.awt.GridLayout;
36 import java.awt.Image;
37 import java.awt.Insets;
38 import java.awt.Label;
39 import java.awt.Panel;
40 import java.awt.TextArea;
41 import java.awt.TextField;
42 import java.awt.Toolkit;
43 import java.awt.event.*;
44 import java.util.Vector;
45
46 import org.jacorb.poa.gui.beans.FillLevelBar;
47
48
49 /**
50 * Start xmlBlaster with a GUI based control panel.
51 * <p />
52 * A control panel pops up, where you can<br />
53 * <ul>
54 * <li>Stop xmlBlaster</li>
55 * <li>View the performance monitor</li>
56 * <li>See and adjust logging output</li>
57 * <li>Invoke XPath queries on messages in xmlBlaster</li>
58 * </ul>
59 * The available start parameters are similar to Main
60 * <p>
61 * The login name "__sys__GuiQuery" is reserved!<br />
62 * </p>
63 * @see org.xmlBlaster.Main
64 */
65 public class MainGUI extends Frame implements Runnable, org.xmlBlaster.util.log.I_LogListener
66 {
67 private static final long serialVersionUID = 1L;
68 private ServerScope glob;
69 private static Logger log = Logger.getLogger(MainGUI.class.getName());
70
71 private Toolkit toolkit = Toolkit.getDefaultToolkit();
72 /** The xmlBlaster server, is set from Main() constructor */
73 org.xmlBlaster.Main xmlBlasterMain = null;
74
75 private Button exitButton;
76 private Button hideButton;
77 private Button clearLogButton;
78 private Button dumpButton;
79
80 /** TextArea with scroll bars for logging output. */
81 private TextArea logOutput = null;
82 /** To save memory consumption, limit number of logging lines to this value. */
83 private final long MAX_LOG_LINES = 3000;
84 /** The actual number of logged lines in the TextArea. */
85 private long numLogLines = 0;
86
87 /** Approximate elapsed time since startup of this server. */
88 private long elapsedTime = 0L;
89 /** Time when xmlBlaster was started */
90 private long startupTime = 0L;
91 /** Last time the performance was evaluated */
92 private long lastPollingTime = 0L;
93
94 /** Performance monitor for number of published messages. */
95 private FillLevelBar publishedMessagesBar = new FillLevelBar();
96 private Label publishedLabel = new Label(); // display total count
97 private int peakPublishedMessages = 0;
98 private long publishedMessages = 0L;
99 private long lastPublishedMessages = 0L;
100
101 /** Performance monitor for number of update messages (callbacks to clients). */
102 private FillLevelBar sentMessagesBar = new FillLevelBar();
103 private Label sentLabel = new Label();
104 private int peakSentMessages = 0;
105 private long sentMessages = 0L;
106 private long lastSentMessages = 0L;
107
108 /** Performance monitor for number of synchronous accessed messages. */
109 private FillLevelBar getMessagesBar = new FillLevelBar();
110 private Label getLabel = new Label();
111 private int peakGetMessages = 0;
112 private long getMessages = 0L;
113 private long lastGetMessages = 0L;
114
115 /** XPath query input field. */
116 private TextField inputTextField = new TextField();
117 /** Display XPath query results. */
118 private TextArea queryOutput = null;
119 /** A client accessing xmlBlaster to do some XPath query. */
120 private GuiQuery clientQuery = null;
121 /** Remember previous query strings. */
122 private QueryHistory queryHistory;
123
124
125 /**
126 * Construct the xmlBlaster GUI.
127 */
128 public MainGUI(ServerScope glob, org.xmlBlaster.Main main)
129 {
130 this.xmlBlasterMain = main;
131 this.glob = glob;
132
133
134 // set the application icon
135 java.net.URL oUrl;
136 oUrl = this.getClass().getResource("AppIcon.gif");
137 Image img = null;
138 if (oUrl != null)
139 img = java.awt.Toolkit.getDefaultToolkit().getImage(oUrl);
140 if(img != null)
141 {
142 this.setIconImage(img);
143 System.out.println(img.toString());
144 }
145 else
146 {
147 System.out.println("AppIcon.gif not found");
148 }
149
150
151 setTitle("XmlBlaster Control Panel");
152 init();
153
154 // Poll xmlBlaster internal states
155 PollingThread poller = new PollingThread(this);
156 poller.start();
157
158 }
159
160
161 /**
162 * Start the GUI thread.
163 */
164 public void run()
165 {
166 show();
167 if (this.xmlBlasterMain == null)
168 this.xmlBlasterMain = new org.xmlBlaster.Main(glob, this);
169 }
170
171 /**
172 * Event fired by Logger.java through interface I_LogListener.
173 * <p />
174 * log.addLogDevice(this);
175 * <p />
176 * Log output into TextArea<br />
177 * If the number of lines displayed is too big, cut half of them
178 */
179 public void log(LogRecord record)
180 {
181 String str = record.getLevel().toString() + " [" + record.getLoggerName() + "] " + record.getMessage();
182 if (logOutput == null) {
183 System.err.println(str + "\n");
184 return;
185 }
186 if (numLogLines > MAX_LOG_LINES) {
187 String text = logOutput.getText();
188 text = text.substring(text.length()/2, text.length());
189 logOutput.setText(text);
190 }
191 numLogLines++;
192 logOutput.append(str + "\n");
193 }
194
195 /**
196 * Event fired every 1 seconds by the PollingThread.
197 * <p />
198 * Update the statistic bars.
199 * @param sleepTime Milliseconds how long the PollingThread was sleeping (no zero division check!)
200 */
201 void pollEvent(long sleepTime)
202 {
203 long current = System.currentTimeMillis();
204 if (lastPollingTime > 0L) {
205 sleepTime = current - lastPollingTime; // correct sleepTime with the real sleeping time
206 }
207 lastPollingTime = current;
208 elapsedTime += current - startupTime;
209
210 double sleepSeconds = sleepTime / 1000.0;
211 //double elapsedSeconds = elapsedTime / 1000.0;
212
213 {
214 publishedMessages = this.glob.getRequestBroker().getNumPublish();
215 int currentPublishedAvg = (int)((publishedMessages - lastPublishedMessages)/sleepSeconds);
216 if ((publishedMessages - lastPublishedMessages) == 1) currentPublishedAvg = 1;
217 //int totalPublishedAvg = (int)(numPublish/elapsedSeconds);
218 publishedMessagesBar.setCurrentValue(currentPublishedAvg);
219 if (currentPublishedAvg > peakPublishedMessages) {
220 peakPublishedMessages = currentPublishedAvg;
221 publishedMessagesBar.setAvgValue(peakPublishedMessages);
222 }
223 //publishedMessagesBar.setAvgValue(totalPublishedAvg);
224 publishedLabel.setText("Total: " + publishedMessages);
225 lastPublishedMessages = publishedMessages;
226 }
227
228 {
229 sentMessages = 0;// TODO SessionInfo.sentMessages;
230 int currentSentAvg = (int)((sentMessages - lastSentMessages)/sleepSeconds);
231 if ((sentMessages - lastSentMessages) == 1) currentSentAvg = 1;
232 //int totalSentAvg = (int)(sentMessages/elapsedSeconds);
233 sentMessagesBar.setCurrentValue(currentSentAvg);
234 if (currentSentAvg > peakSentMessages) {
235 peakSentMessages = currentSentAvg;
236 sentMessagesBar.setAvgValue(peakSentMessages);
237 }
238 // sentMessagesBar.setAvgValue(totalSentAvg);
239 sentLabel.setText("Total: " + sentMessages);
240 lastSentMessages = sentMessages;
241 }
242
243 {
244 getMessages = this.glob.getRequestBroker().getNumGet();
245 int currentGetAvg = (int)((getMessages - lastGetMessages)/sleepSeconds);
246 if ((getMessages - lastGetMessages) == 1) currentGetAvg = 1;
247 //int totalGetAvg = (int)(numGet/elapsedSeconds);
248 // System.out.println("totally numGet=" + numGet + " current avg=" + currentGetAvg + " total avg=" + totalGetAvg);
249 getMessagesBar.setCurrentValue(currentGetAvg);
250 if (currentGetAvg > peakGetMessages) {
251 peakGetMessages = currentGetAvg;
252 getMessagesBar.setAvgValue(peakGetMessages);
253 }
254 // getMessagesBar.setAvgValue(totalGetAvg);
255 getLabel.setText("Total: " + getMessages);
256 lastGetMessages = getMessages;
257 }
258 }
259
260 private void registerLogEvents() {
261 XbNotifyHandler.instance().register(Level.ALL.intValue(), this);
262 }
263
264 private void unregisterLogEvents() {
265 XbNotifyHandler.instance().unregister(Level.ALL.intValue(), this);
266 }
267
268 /**
269 * Build the GUI layout.
270 */
271 private void init()
272 {
273 registerLogEvents();
274 setLayout(new GridBagLayout());
275 GridBagConstraints gbc = new GridBagConstraints();
276 gbc.fill = GridBagConstraints.BOTH;
277 gbc.insets = new Insets(5,5,5,5);
278
279 // Exit Button
280 exitButton = new Button("Exit");
281 class BeepListener implements ActionListener {
282 public void actionPerformed(ActionEvent e) {
283 toolkit.beep();
284 if (clientQuery != null)
285 clientQuery.logout();
286 //unregisterLogEvents();
287 log.info("Good bye!");
288 System.exit(0);
289 }
290 }
291 exitButton.addActionListener(new BeepListener());
292 gbc.gridx=0; gbc.gridy=0; gbc.gridwidth=1; gbc.gridheight=1;
293 gbc.weightx = gbc.weighty = 0.0;
294 add(exitButton, gbc);
295
296 // Hide Button
297 hideButton = new Button("Hide Window");
298 class HideListener implements ActionListener {
299 public void actionPerformed(ActionEvent e) {
300 hideWindow();
301 }
302 }
303 hideButton.addActionListener(new HideListener());
304 gbc.gridx=1; gbc.gridy=0; gbc.gridwidth=1; gbc.gridheight=1;
305 gbc.weightx = gbc.weighty = 0.0;
306 add(hideButton, gbc);
307
308 // Statistic display with fill level bars
309 int offset = 0;
310 gbc.gridx=offset; gbc.gridy=1; gbc.gridwidth=1; gbc.gridheight=1;
311 gbc.weightx = gbc.weighty = 0.0;
312 createBarPanel(publishedMessagesBar, publishedLabel, "Published", gbc, offset++);
313 createBarPanel(sentMessagesBar, sentLabel, "Update", gbc, offset++);
314 createBarPanel(getMessagesBar, getLabel, "Get", gbc, offset++);
315
316
317 { // XPath query GUI
318 Panel panel = new Panel();
319 panel.setName("QueryPanel");
320 panel.setLayout(new BorderLayout());
321 panel.setBackground(java.awt.SystemColor.control);
322
323 { // Field to enter XPath text
324 Panel inputPanel = new Panel();
325 inputPanel.setLayout(new BorderLayout());
326
327 Label inputLabel = new Label("XPath query: ");
328 inputPanel.add("West", inputLabel);
329
330 inputTextField.setText("//key");
331 inputPanel.add("Center", inputTextField);
332 inputTextField.addKeyListener(new XPathKeyListener());
333
334 panel.add("North", inputPanel);
335 }
336
337 { // TextArea to show query results
338 queryOutput = new TextArea();
339 queryOutput.setEditable(false);
340
341 panel.add("South", queryOutput);
342 }
343
344 gbc.gridx=offset; gbc.gridy=1; gbc.gridwidth=3; gbc.gridheight=1;
345 add(panel, gbc);
346 }
347
348
349 // Checkboxes for log levels
350 gbc.gridx=0; gbc.gridy=2; gbc.gridwidth=1; gbc.gridheight=1;
351 add(new Label("Choose Logging Level: "), gbc);
352 gbc.gridx=1; gbc.gridwidth=3; gbc.gridheight=1;
353 add(createLogLevelBoxes(), gbc);
354
355
356 // Clear logging output - Button
357 clearLogButton = new Button("Clear Log Window");
358 class ClearListener implements ActionListener {
359 public void actionPerformed(ActionEvent e) {
360 logOutput.setText("");
361 }
362 }
363 clearLogButton.addActionListener(new ClearListener());
364 gbc.gridx=4; gbc.gridy=2; gbc.gridwidth=1; gbc.gridheight=1;
365 gbc.weightx = gbc.weighty = 0.0;
366 add(clearLogButton, gbc);
367
368
369 // Dump internal state - Button
370 dumpButton = new Button("Dump State");
371 class DumpListener implements ActionListener {
372 public void actionPerformed(ActionEvent e) {
373 // logOutput.setText(""); // clear log window
374 try {
375 log.info("Dump start");
376 I_Authenticate auth = xmlBlasterMain.getAuthenticate();
377 StringBuffer buf = new StringBuffer(auth.toXml());
378 buf.append(xmlBlasterMain.getXmlBlaster().toXml());
379 LogRecord record = new LogRecord(Level.INFO, buf.toString());
380 log(record);
381 log.info("Dump end");
382 }
383 catch(XmlBlasterException ee) {
384 log.severe("Sorry, dump failed: " + ee.getMessage());
385 }
386 }
387 }
388 dumpButton.addActionListener(new DumpListener());
389 gbc.gridx=5; gbc.gridy=2; gbc.gridwidth=1; gbc.gridheight=1;
390 gbc.weightx = gbc.weighty = 0.0;
391 add(dumpButton, gbc);
392
393
394 // TextArea for log outputs
395 gbc.gridx=0; gbc.gridy=3; gbc.gridwidth=6; gbc.gridheight=6;
396 gbc.weightx = gbc.weighty = 1.0;
397 logOutput = new TextArea("", 30, 100); // set rows here (width 100 is ignored)
398 logOutput.setEditable(false);
399 add(logOutput, gbc);
400
401 pack();
402
403 startupTime = System.currentTimeMillis();
404 }
405
406
407 /**
408 * Hide the window.
409 * Note that all the resources are still busy, only logging is directed to console
410 */
411 private void hideWindow()
412 {
413 unregisterLogEvents();
414 if (isShowing()) {
415 log.info("Press <g> and <Enter> to popup the GUI again (press ? for other options).");
416 setVisible(false); // dispose(); would clean up all resources
417 }
418 }
419
420
421 /**
422 * Hide the window.
423 * Note that all the resources are still busy, only logging is directed to console
424 */
425 void showWindow()
426 {
427 if (!isShowing()) {
428 registerLogEvents();
429 if (log.isLoggable(Level.FINE)) log.fine("Show window again ...");
430 show();
431 }
432 }
433
434
435 /**
436 * Get the events when a Checkbox is selected with the mouse.
437 */
438 class LogLevelListener implements ItemListener
439 {
440 public void itemStateChanged(ItemEvent e)
441 {
442 /*
443 String name = (String)e.getItem();
444 try {
445 Level level = Level.parse(value);
446 glob.changeLogLevel(name, level);
447 }
448 catch (XmlBlasterException ex) {
449 log.warning("Cannot set log level attribute '"+ name +"':" + ex.getMessage());
450 }
451 */
452 log.warning("is not implemented");
453 }
454 }
455
456
457 /**
458 * Create a Panel with a FillLevelBar and some labels.
459 * @param messageBar The instance of FillLevelBar to use
460 * @param totalCountLabel The instance of total count Label to use
461 * @param token Describing text e.g. "Published"
462 * @param gbc The layout manager
463 * @param offset The position of the panel (grid layout)
464 */
465 private void createBarPanel(FillLevelBar messageBar, Label totalCountLabel, String token, GridBagConstraints gbc, int offset)
466 {
467 final int LABEL_LOCATION_X = 2;
468 final int LABEL_LOCATION_Y = 10;
469 final int LABEL_WIDTH = 90;
470 final int LABEL_HEIGHT = 12;
471 final int BAR_X = 32;
472 final int BAR_Y = LABEL_LOCATION_Y + 2 * LABEL_HEIGHT;
473 final int BAR_WIDTH = 50;
474 final int BAR_HEIGHT = 130;
475 final int TOTAL_LABEL_Y = BAR_Y + BAR_HEIGHT;
476 final int PANEL_WIDTH = LABEL_LOCATION_X + LABEL_WIDTH + 2; // 94
477 final int PANEL_HEIGHT = TOTAL_LABEL_Y + LABEL_HEIGHT + 4; // 180
478 Font barFont = new java.awt.Font("dialog", 2, 10);
479
480 Panel panel = new Panel();
481 panel.setName(token + "MessagePanel");
482 panel.setLayout(null);
483 panel.setBackground(java.awt.SystemColor.control);
484 panel.setSize(PANEL_WIDTH, PANEL_HEIGHT);
485
486 Label label1 = new Label();
487 label1.setName("Label1");
488 label1.setLocation(LABEL_LOCATION_X, LABEL_LOCATION_Y);
489 label1.setText(token);
490 label1.setBackground(java.awt.SystemColor.control);
491 label1.setSize(LABEL_WIDTH, LABEL_HEIGHT);
492 label1.setForeground(java.awt.Color.black);
493 label1.setFont(barFont);
494 label1.setAlignment(1);
495 panel.add(label1, label1.getName());
496
497 Label label2 = new Label();
498 label2.setName("Label2");
499 label2.setLocation(LABEL_LOCATION_X, LABEL_LOCATION_Y + LABEL_HEIGHT);
500 label2.setText("[messages/sec]");
501 label2.setBackground(java.awt.SystemColor.control);
502 label2.setSize(LABEL_WIDTH, LABEL_HEIGHT);
503 label2.setForeground(java.awt.Color.black);
504 label2.setFont(barFont);
505 label2.setAlignment(1);
506 panel.add(label2, label2.getName());
507
508 messageBar.setName(token + "Messages");
509 messageBar.setLocation(BAR_X, BAR_Y);
510 messageBar.setBackground(java.awt.SystemColor.control);
511 messageBar.setSize(BAR_WIDTH, BAR_HEIGHT);
512 boolean useAvg = true;
513 boolean isVariable = true; // !!!
514 int MAX_SCALE = 10;
515 messageBar.init(0, 5, MAX_SCALE, Color.green, Color.green, useAvg, isVariable);
516 messageBar.setAvgValue(0);
517 // messageBar.init(0, 5, 100, Color.yellow, Color.green, true, true);
518 panel.add(messageBar, messageBar.getName());
519
520 totalCountLabel.setName(token + "Label");
521 totalCountLabel.setLocation(LABEL_LOCATION_X, TOTAL_LABEL_Y);
522 totalCountLabel.setText("Total: 0");
523 totalCountLabel.setBackground(java.awt.SystemColor.control);
524 totalCountLabel.setSize(LABEL_WIDTH, LABEL_HEIGHT);
525 totalCountLabel.setForeground(java.awt.Color.black);
526 totalCountLabel.setFont(barFont);
527 totalCountLabel.setAlignment(1);
528 panel.add(totalCountLabel, totalCountLabel.getName());
529
530 gbc.gridx=offset;
531 add(panel, gbc);
532 }
533
534
535 /**
536 * Create Checkboxes to adjust the logging levels
537 * @return container with checkboxes
538 */
539 private Panel createLogLevelBoxes()
540 {
541 Panel container = new Panel();
542 container.setLayout(new GridLayout(1, 7));
543
544 Checkbox error = new Checkbox("ERROR", null, true);
545 error.addItemListener(new LogLevelListener());
546 container.add(error);
547
548 Checkbox warning = new Checkbox("WARN", null, true);
549 warning.addItemListener(new LogLevelListener());
550 container.add(warning);
551
552 Checkbox info = new Checkbox("INFO", null, true);
553 info.addItemListener(new LogLevelListener());
554 container.add(info);
555
556 if (true/*log.CALL*/) { // log.CALL=true/false: check for dead code elimination
557 Checkbox calls = new Checkbox("CALL", null, false);
558 calls.addItemListener(new LogLevelListener());
559 container.add(calls);
560 }
561
562 if (true/*log.TIME*/) {
563 Checkbox time = new Checkbox("TIME", null, false);
564 time.addItemListener(new LogLevelListener());
565 container.add(time);
566 }
567
568 if (true/*log.TRACE*/) {
569 Checkbox trace = new Checkbox("TRACE", null, false);
570 trace.addItemListener(new LogLevelListener());
571 container.add(trace);
572 }
573
574 if (true/*log.DUMP*/) {
575 Checkbox dump = new Checkbox("DUMP", null, false);
576 dump.addItemListener(new LogLevelListener());
577 container.add(dump);
578 }
579 return container;
580 }
581
582
583 /**
584 * Access the query history.
585 */
586 private QueryHistory getQueryHistory()
587 {
588 if (queryHistory == null)
589 queryHistory = new QueryHistory();
590 return queryHistory;
591 }
592
593
594 /**
595 * Invoke: <pre>jaco org.xmlBlaster.MainGUI</pre><br />
596 * to start xmlBlaster with a control panel
597 */
598 static public void main(String[] args)
599 {
600 ServerScope glob = new ServerScope(args);
601 Main.controlPanel = new MainGUI(glob, null);
602 Main.controlPanel.run();
603 }
604
605
606
607
608 /**
609 * Polls the state of xmlBlaster.
610 */
611 private class PollingThread extends Thread
612 {
613 private final int POLLING_FREQUENCY = 1000; // sleep 1 sec
614 private final MainGUI mainGUI;
615
616
617 /**
618 **/
619 public PollingThread(MainGUI mainGUI)
620 {
621 this.mainGUI = mainGUI;
622 // !!! setPriority(Thread.MIN_PRIORITY);
623 }
624
625
626 /**
627 * Start the timeout thread.
628 **/
629 public void run()
630 {
631 Thread.currentThread().setName("XmlBlaster GUIPollingThread");
632 try {
633 if (log.isLoggable(Level.FINE)) log.fine("Starting poller");
634 while (true) {
635 sleep(POLLING_FREQUENCY);
636 mainGUI.pollEvent(POLLING_FREQUENCY); // Todo: calculate the exact sleeping period
637 }
638 }
639 catch (Exception e) {
640 log.fine("PollingThread problem: "+ e.toString());
641 //e.printStackTrace();
642 }
643 }
644 }
645
646
647
648 /**
649 * Handles return key when a XPath query is entered into the TextField.
650 */
651 private class XPathKeyListener implements KeyListener
652 {
653 /**
654 * Access XPath query string (event from KeyListener).
655 */
656 public final void keyPressed(KeyEvent ev)
657 {
658 switch (ev.getKeyCode())
659 {
660 case KeyEvent.VK_ENTER:
661 try {
662 if (clientQuery == null) {
663 clientQuery = new GuiQuery(xmlBlasterMain.getAuthenticate(), xmlBlasterMain.getXmlBlaster());
664 }
665 queryOutput.setText("");
666 getQueryHistory().changedHistory(inputTextField.getText());
667 MsgUnitRaw[] msgArr = clientQuery.get(inputTextField.getText());
668 for (int ii=0; ii<msgArr.length; ii++) {
669 /*
670 UpdateKey updateKey = new UpdateKey();
671 updateKey.init(msgArr[ii].getKey());
672 queryOutput.append("### UpdateKey:\n" + updateKey.printOn().toString());
673 */
674 queryOutput.append("### XmlKey:\n" + msgArr[ii].getKey());
675 queryOutput.append("\n");
676 queryOutput.append("### Content:\n" + new String(msgArr[ii].getContent()) + "\n");
677 queryOutput.append("======================================================\n");
678 }
679 if (msgArr.length == 0) {
680 if (publishedMessages == 0L) {
681 queryOutput.setText("\n");
682 queryOutput.append (" Sorry, no data in xmlBlaster.\n");
683 queryOutput.append (" Use a demo client to publish some.\n");
684 queryOutput.append ("\n");
685 }
686 else
687 queryOutput.setText("****** Sorry, no match ******");
688 }
689 } catch(XmlBlasterException e) {
690 log.severe("XmlBlasterException: " + e.getMessage());
691 }
692 break;
693 case KeyEvent.VK_DOWN:
694 displayHistory(getQueryHistory().getNext());
695 break;
696 case KeyEvent.VK_UP:
697 displayHistory(getQueryHistory().getPrev());
698 break;
699 }
700 }
701 public final void keyReleased(KeyEvent ev)
702 {
703 }
704 public final void keyTyped(KeyEvent ev)
705 {
706 }
707 }
708
709
710 /**
711 * Scrolling with key arrow up/down your last XPath queries.
712 * @param stmt The XPath stmt to display
713 */
714 private void displayHistory(String stmt)
715 {
716 if (stmt.length() < 1) return;
717 inputTextField.setText(stmt);
718 }
719
720
721 /**
722 * A client accessing xmlBlaster to do some XPath query.
723 */
724 private class GuiQuery
725 {
726 private String queryType = Constants.XPATH;
727 private StopWatch stop = new StopWatch();
728 /** Handle to login */
729 I_Authenticate authenticate;
730 /** The handle to access xmlBlaster */
731 private I_XmlBlaster xmlBlasterImpl;
732 /** The session id on successful authentication */
733 private String secretSessionId;
734 private AddressServer addressServer;
735
736 /**
737 * Login to xmlBlaster and get a sessionId.
738 */
739 public GuiQuery(I_Authenticate authenticate, I_XmlBlaster xmlBlasterImpl) throws XmlBlasterException
740 {
741 this.xmlBlasterImpl = xmlBlasterImpl;
742 this.authenticate = authenticate;
743 String loginName = glob.getProperty().get("__sys__GuiQuery.loginName", "__sys__GuiQuery");
744 String passwd = glob.getProperty().get("__sys__GuiQuery.password", "secret");
745 ConnectQos connectQos = new ConnectQos(authenticate.getGlobal());
746 connectQos.loadClientPlugin("htpasswd", "1.0", loginName, passwd);
747 connectQos.getSessionQos().setSessionTimeout(0L);
748 // TODO: Port to use "LOCAL" protocol to connect
749 this.addressServer = new AddressServer(authenticate.getGlobal(), "NATIVE", authenticate.getGlobal().getId(), (java.util.Properties)null);
750 String ret = authenticate.connect(addressServer, connectQos.toXml(), null); // synchronous access only, no callback.
751 ConnectReturnQos retQos = new ConnectReturnQos(authenticate.getGlobal(), ret);
752 this.secretSessionId = retQos.getSecretSessionId();
753 log.info("login for '" + loginName + "' successful.");
754 }
755
756 /**
757 * Query xmlBlaster.
758 */
759 MsgUnitRaw[] get(String queryString)
760 {
761 try {
762 GetKey getKey = new GetKey(this.authenticate.getGlobal(), queryString, queryType);
763 stop.restart();
764 MsgUnitRaw[] msgArr = this.xmlBlasterImpl.get(this.addressServer, this.secretSessionId, getKey.toXml(), "<qos/>");
765 log.info("Got " + msgArr.length + " messages for query '" + queryString + "'" + stop.nice());
766 return msgArr;
767 } catch(XmlBlasterException e) {
768 log.severe("XmlBlasterException: " + e.getMessage());
769 return new MsgUnitRaw[0];
770 }
771 }
772
773 /** Logout. */
774 void logout() {
775 try { this.authenticate.disconnect(this.addressServer, this.secretSessionId, null); } catch (XmlBlasterException e) { }
776 }
777 }
778
779
780 /**
781 * Implements a stack to hold the previous XPath queries.
782 */
783 private class QueryHistory
784 {
785 //private String ME = "QueryHistory";
786 private Vector stack = new Vector();
787 private int currentIndex = 0;
788
789
790 /**
791 * Constructs a history stack.
792 */
793 public QueryHistory()
794 {
795 }
796
797 /**
798 * Add new statement into history.
799 */
800 public void changedHistory(String stmt)
801 {
802 if (stack.size() > 1) {
803 String last = (String)stack.elementAt(stack.size()-1);
804 if (last.equals(stmt)) return;
805 }
806 currentIndex = stack.size();
807 stack.addElement(stmt);
808 }
809
810
811 /**
812 * Access previous XPath query.
813 */
814 String getPrev()
815 {
816 if (stack.size() < 1) return "";
817 if (currentIndex > 0) currentIndex--;
818 return (String)stack.elementAt(currentIndex);
819 }
820
821
822 /**
823 * Access next XPath query.
824 */
825 String getNext()
826 {
827 if (stack.size() < 1) return "";
828 if (currentIndex < stack.size()-1) currentIndex++;
829 return (String)stack.elementAt(currentIndex);
830 }
831
832
833 /**
834 * Access last (the newest), sets current to last.
835 */
836 String getLast()
837 {
838 if (stack.size() < 1) return "";
839 currentIndex = stack.size() - 1;
840 return (String)stack.elementAt(currentIndex);
841 }
842
843
844 /**
845 * Access first (the oldest), sets current to first.
846 */
847 String getFirst()
848 {
849 if (stack.size() < 1) return "";
850 currentIndex = 0;
851 return (String)stack.elementAt(currentIndex);
852 }
853
854 }
855 }
syntax highlighted by Code2HTML, v. 0.9.1