001: // $Id: DistributedTreeDemo.java,v 1.8 2005/05/30 16:14:40 belaban Exp $
002:
003: package org.jgroups.demos;
004:
005: import org.jgroups.blocks.DistributedTree;
006:
007: import javax.swing.*;
008: import javax.swing.event.TableModelEvent;
009: import javax.swing.event.TableModelListener;
010: import javax.swing.event.TreeSelectionEvent;
011: import javax.swing.event.TreeSelectionListener;
012: import javax.swing.table.DefaultTableModel;
013: import javax.swing.tree.DefaultMutableTreeNode;
014: import javax.swing.tree.DefaultTreeModel;
015: import javax.swing.tree.TreeNode;
016: import javax.swing.tree.TreePath;
017: import java.awt.*;
018: import java.awt.event.*;
019: import java.io.Serializable;
020: import java.util.Enumeration;
021: import java.util.Properties;
022: import java.util.StringTokenizer;
023: import java.util.Vector;
024:
025: class MyNode extends DefaultMutableTreeNode {
026: String name = "<unnamed>";
027:
028: MyNode(String name) {
029: this .name = name;
030: }
031:
032: MyNode(String name, Serializable user_obj) {
033: super (user_obj);
034: this .name = name;
035: }
036:
037: void add(String fqn) {
038: add(fqn, null);
039: }
040:
041: public void add(String fqn, Serializable user_obj) {
042: MyNode curr, n;
043: StringTokenizer tok;
044: String child_name;
045:
046: if (fqn == null)
047: return;
048: curr = this ;
049: tok = new StringTokenizer(fqn, "/");
050:
051: while (tok.hasMoreTokens()) {
052: child_name = tok.nextToken();
053: n = curr.findChild(child_name);
054: if (n == null) {
055: n = new MyNode(child_name, user_obj);
056: curr.add(n);
057: }
058: curr = n;
059: }
060: curr.userObject = user_obj;
061: }
062:
063: void modify(String fqn, Serializable new_element) {
064: if (fqn == null || new_element == null)
065: return;
066: MyNode n = findNode(fqn);
067: if (n != null)
068: n.userObject = new_element;
069: }
070:
071: void remove(String fqn) {
072: System.out.println("MyNode.remove(" + fqn + ')');
073: removeFromParent();
074: }
075:
076: public MyNode findNode(String fqn) {
077: MyNode curr, n;
078: StringTokenizer tok;
079: String child_name;
080:
081: if (fqn == null)
082: return null;
083: curr = this ;
084: tok = new StringTokenizer(fqn, "/");
085:
086: while (tok.hasMoreTokens()) {
087: child_name = tok.nextToken();
088: n = curr.findChild(child_name);
089: if (n == null)
090: return null;
091: curr = n;
092: }
093: return curr;
094: }
095:
096: MyNode findChild(String relative_name) {
097: MyNode child;
098:
099: if (relative_name == null || getChildCount() == 0)
100: return null;
101: for (int i = 0; i < getChildCount(); i++) {
102: child = (MyNode) getChildAt(i);
103: if (child.name == null) {
104: System.err.println("MyNode.findChild(" + relative_name
105: + "): child.name is null");
106: continue;
107: }
108:
109: if (child.name.equals(relative_name))
110: return child;
111: }
112: return null;
113: }
114:
115: String print(int indent) {
116: StringBuffer sb = new StringBuffer();
117:
118: for (int i = 0; i < indent; i++)
119: sb.append(' ');
120: if (!isRoot()) {
121: if (name == null)
122: sb.append("/<unnamed>");
123: else {
124: sb.append('/' + name);
125: if (userObject != null)
126: sb.append(" --> " + userObject);
127: }
128: }
129: sb.append('\n');
130: if (getChildCount() > 0) {
131: if (isRoot())
132: indent = 0;
133: else
134: indent += 4;
135: for (int i = 0; i < getChildCount(); i++)
136: sb.append(((MyNode) getChildAt(i)).print(indent));
137: }
138: return sb.toString();
139: }
140:
141: public String toString() {
142: return name;
143: }
144:
145: }
146:
147: /**
148: * Demo showing the DistributedTree class. It displays a panel with the tree structure in the upper half,
149: * and the properties of a chosen node on the bottom half. All updates are broadcast to all members.
150: */
151: public class DistributedTreeDemo extends Frame implements
152: WindowListener, DistributedTree.DistributedTreeListener,
153: TreeSelectionListener, TableModelListener {
154: DefaultTreeModel tree_model = null;
155: JTree jtree = null;
156: final DefaultTableModel table_model = new DefaultTableModel();
157: final JTable table = new JTable(table_model);
158: JScrollPane scroll_pane = null;
159: final MyNode root = new MyNode("/");
160: DistributedTree dt = null;
161: String props = null;
162: String selected_node = null;
163: boolean create = false;
164:
165: public DistributedTreeDemo(boolean create) throws Exception {
166: // we need state transfer here
167: // props="UDP:PING:FD:STABLE:NAKACK:UNICAST:FRAG:FLUSH:GMS:VIEW_ENFORCER:STATE_TRANSFER:QUEUE";
168:
169: // test for pbcast
170: props = "UDP(mcast_addr=228.1.2.3;mcast_port=45566;ip_ttl=0):"
171: + "PING(timeout=5000;num_initial_members=6):"
172: + "FD_SOCK:"
173: + "VERIFY_SUSPECT(timeout=1500):"
174: + "pbcast.NAKACK(gc_lag=5;retransmit_timeout=3000):"
175: + "UNICAST(timeout=5000):"
176: + "pbcast.STABLE(desired_avg_gossip=10000):"
177: + "FRAG(down_thread=false;up_thread=false):"
178: + "pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;"
179: + "shun=false;print_local_addr=true):"
180: + "pbcast.STATE_TRANSFER";
181:
182: this .create = create;
183: dt = new DistributedTree("DistributedTreeDemo", props);
184: dt.addDistributedTreeListener(this );
185: setLayout(new BorderLayout());
186: addNotify();
187: setSize(getInsets().left + getInsets().right + 485,
188: getInsets().top + getInsets().bottom + 367);
189: setTitle("DistributedTree");
190:
191: tree_model = new DefaultTreeModel(root);
192: jtree = new JTree(tree_model);
193: jtree.setDoubleBuffered(true);
194:
195: scroll_pane = new JScrollPane();
196: scroll_pane.getViewport().add(jtree);
197: scroll_pane.setDoubleBuffered(true);
198: add(scroll_pane, BorderLayout.CENTER);
199: addWindowListener(this );
200:
201: table_model
202: .setColumnIdentifiers(new String[] { "Name", "Value" });
203: table_model.addTableModelListener(this );
204: add(table, BorderLayout.SOUTH);
205:
206: dt.start();
207: System.out.println("Constructing initial GUI tree");
208: populateTree(dt, ""); // creates initial GUI from model
209: System.out.println("Constructing initial GUI tree -- done");
210:
211: Properties props1 = new Properties();
212: props1.setProperty("name", "EventService");
213: props1.setProperty("path", "/usr/local/Orbix2000/bin/es");
214: props1.setProperty("up", "true");
215: props1.setProperty("active", "false");
216:
217: Properties props2 = new Properties();
218: props2.setProperty("name", "NamingService");
219: props2.setProperty("path", "/usr/local/Orbix2000/bin/ns");
220: props2.setProperty("up", "true");
221: props2.setProperty("active", "true");
222:
223: Properties props3 = new Properties();
224: props3.setProperty("name", "ORBIX daemon");
225: props3.setProperty("path", "/usr/local/Orbix2000/bin/orbixd");
226: props3.setProperty("up", "true");
227: props3.setProperty("active", "true");
228: props3.setProperty("restart", "true");
229: props3.setProperty("restart_time", "3000");
230: props3.setProperty("restart_max", "10");
231:
232: Properties props4 = new Properties();
233: props4.setProperty("name", "Orbix2000 Version 1.1");
234: props4.setProperty("valid until", "11/12/2001");
235: props4.setProperty("up", "false");
236: props4.setProperty("active", "false");
237:
238: Properties props5 = new Properties();
239: props5.setProperty("name", "Orbix2000 Version 1.3b");
240: props5.setProperty("valid until", "12/31/2000");
241: props5.setProperty("up", "true");
242: props5.setProperty("active", "false");
243:
244: if (create) {
245: dt.add("/procs/NETSMART/es", props1);
246: dt.add("/procs/NETSMART/ns", props2);
247: dt.add("/procs/NETSMART/orbixd", props3);
248: dt.add("/procs/NETSMART/orbixd/Version_1.1", props4);
249: dt.add("/procs/NETSMART/orbixd/Version_1.2", props5);
250: Properties props6 = (Properties) props5.clone();
251: props6.setProperty("name", "osagent daemon");
252: props6.setProperty("path",
253: "/usr/local/Visigenics/bin/osagent");
254:
255: Properties props7 = new Properties();
256: props7.setProperty("name", "Visigenics latest product");
257: props7.setProperty("license",
258: "/vob/iem/Devp/etc/license.txt");
259:
260: dt.set("/procs/NETSMART/orbixd/Version_1.2", props6);
261: dt.add("/procs/NETSMART/orbixd/Version_2.0", props7);
262: }
263:
264: jtree.addTreeSelectionListener(this );
265:
266: MouseListener ml = new MouseAdapter() {
267: public void mouseClicked(MouseEvent e) {
268: int selRow = jtree
269: .getRowForLocation(e.getX(), e.getY());
270: TreePath selPath = jtree.getPathForLocation(e.getX(), e
271: .getY());
272: if (selRow != -1)
273: selected_node = makeFQN(selPath.getPath());
274: }
275: };
276: jtree.addMouseListener(ml);
277:
278: }
279:
280: String makeFQN(Object[] path) {
281: StringBuffer sb = new StringBuffer("");
282: String tmp_name;
283:
284: if (path == null)
285: return null;
286: for (int i = 0; i < path.length; i++) {
287: tmp_name = ((MyNode) path[i]).name;
288: if ("/".equals(tmp_name))
289: continue;
290: else
291: sb.append('/' + tmp_name);
292: }
293: tmp_name = sb.toString();
294: if (tmp_name.length() == 0)
295: return "/";
296: else
297: return tmp_name;
298: }
299:
300: void clearTable() {
301: int num_rows = table.getRowCount();
302:
303: if (num_rows > 0) {
304: for (int i = 0; i < num_rows; i++)
305: table_model.removeRow(0);
306: table_model.fireTableRowsDeleted(0, num_rows - 1);
307: repaint();
308: }
309: }
310:
311: void populateTable(Properties props) {
312: String key, val;
313: int num_rows = 0;
314:
315: if (props == null)
316: return;
317: num_rows = props.size();
318: clearTable();
319:
320: if (num_rows > 0) {
321: for (Enumeration e = props.keys(); e.hasMoreElements();) {
322: key = (String) e.nextElement();
323: val = (String) props.get(key);
324: if (val == null)
325: val = "<n/a>";
326: table_model.addRow(new Object[] { key, val });
327: }
328:
329: table_model.fireTableRowsInserted(0, num_rows - 1);
330: validate();
331: }
332:
333: }
334:
335: void populateTree(DistributedTree tree, String tmp_fqn) {
336: if (tree == null)
337: return;
338: Vector children = tree.getChildrenNames(tmp_fqn);
339: String child_name, tmp_name;
340: Serializable element;
341:
342: for (int i = 0; i < children.size(); i++) {
343: child_name = (String) children.elementAt(i);
344: tmp_name = tmp_fqn + '/' + child_name;
345: root.add(tmp_name, tree.get(tmp_name));
346: populateTree(tree, tmp_name);
347: }
348: }
349:
350: public synchronized void setVisible(boolean show) {
351: setLocation(50, 50);
352: super .setVisible(show);
353: }
354:
355: public void windowClosed(WindowEvent event) {
356: }
357:
358: public void windowDeiconified(WindowEvent event) {
359: }
360:
361: public void windowIconified(WindowEvent event) {
362: }
363:
364: public void windowActivated(WindowEvent event) {
365: }
366:
367: public void windowDeactivated(WindowEvent event) {
368: }
369:
370: public void windowOpened(WindowEvent event) {
371: }
372:
373: public void windowClosing(WindowEvent event) {
374: dt.stop();
375: System.exit(0);
376: }
377:
378: public void tableChanged(TableModelEvent evt) {
379: int row, col;
380: String key, val;
381:
382: if (evt.getType() == TableModelEvent.UPDATE) {
383: row = evt.getFirstRow();
384: col = evt.getColumn();
385:
386: Properties props = (Properties) dt.get(selected_node);
387: if (col == 0) { // set()
388: key = (String) table_model.getValueAt(row, col);
389: val = (String) table_model.getValueAt(row, col + 1);
390: if (props != null && key != null && val != null) {
391: props.setProperty(key, val);
392: dt.set(selected_node, props);
393: }
394: } else { // add()
395: key = (String) table_model.getValueAt(row, col - 1);
396: val = (String) table.getValueAt(row, col);
397: if (props != null && key != null && val != null) {
398: props.setProperty(key, val);
399: dt.add(selected_node, props);
400: }
401: }
402: System.out.println("key=" + key + ", val=" + val);
403:
404: }
405: }
406:
407: public void valueChanged(TreeSelectionEvent evt) {
408: TreePath path = evt.getPath();
409: String fqn = "/";
410: String component_name;
411: Properties props = null;
412:
413: for (int i = 0; i < path.getPathCount(); i++) {
414: component_name = ((MyNode) path.getPathComponent(i)).name;
415: if ("/".equals(component_name))
416: continue;
417: if ("/".equals(fqn))
418: fqn += component_name;
419: else
420: fqn = fqn + '/' + component_name;
421: }
422: props = (Properties) dt.get(fqn);
423: if (props != null)
424: populateTable(props);
425: else
426: clearTable();
427: }
428:
429: /* ------------------ DistributedTree.DistributedTreeListener interface ------------ */
430:
431: public void nodeAdded(String fqn, Serializable element) {
432: MyNode n;
433: System.out.println("** nodeCreated(" + fqn + ')');
434:
435: root.add(fqn, element);
436: n = root.findNode(fqn);
437: if (n != null)
438: tree_model.reload(n.getParent());
439: }
440:
441: public void nodeRemoved(String fqn) {
442: MyNode n;
443: TreeNode par;
444: System.out.println("** nodeRemoved(" + fqn + ')');
445: n = root.findNode(fqn);
446: if (n != null) {
447: n.removeAllChildren();
448: par = n.getParent();
449: n.removeFromParent();
450: tree_model.reload(par);
451: }
452: }
453:
454: public void nodeModified(String fqn, Serializable old_element,
455: Serializable new_element) {
456: System.out.println("** nodeModified(" + fqn + ')');
457: root.modify(fqn, new_element);
458: populateTable((Properties) new_element);
459: }
460:
461: /* ---------------- End of DistributedTree.DistributedTreeListener interface -------- */
462:
463: public static void main(String args[]) {
464: DistributedTreeDemo demo;
465: boolean create = false;
466:
467: for (int i = 0; i < args.length; i++) {
468: if ("-help".equals(args[i])) {
469: System.out
470: .println("DistributedTreeDemo [-create] [-help]");
471: return;
472: }
473: if ("-create".equals(args[i])) {
474: create = true;
475: continue;
476: }
477: }
478:
479: try {
480: demo = new DistributedTreeDemo(create);
481: demo.setVisible(true);
482: } catch (Exception ex) {
483: System.err.println(ex);
484: }
485: }
486: }
|