package org.jboss.cache.aop;
import org.apache.log4j.Logger;
import org.jboss.cache.*;
import org.jgroups.View;
import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.util.*;
public class TreeCacheAopView
{
TreeCacheAopGui gui_ = null;
TreeCacheAop cache_ = null;
static Logger logger_ = Logger.getLogger(TreeCacheAopView.class.getName());
public TreeCacheAopView(TreeCacheAop cache) throws Exception
{
this.cache_ = cache;
}
public void start() throws Exception
{
if (gui_ == null) {
logger_.info("start(): creating the GUI");
gui_ = new TreeCacheAopGui(cache_);
}
}
public void stop()
{
if (gui_ != null) {
logger_.info("stop(): disposing the GUI");
gui_.dispose();
gui_ = null;
}
}
void populateTree(String dir) throws Exception
{
File file = new File(dir);
if (!file.exists()) return;
put(dir, null);
if (file.isDirectory()) {
String[] children = file.list();
if (children != null && children.length > 0) {
for (int i = 0; i < children.length; i++)
populateTree(dir + "/" + children[i]);
}
}
}
void put(String fqn, Map m)
{
try {
cache_.put(fqn, m);
} catch (Throwable t) {
System.err.println("TreeCacheAopView.put(): " + t);
}
}
public static void main(String args[])
{
TreeCacheAop tree = null;
TreeCacheAopView demo;
String start_directory = null;
String resource="META-INF/replSync-service.xml";
for(int i=0; i < args.length; i++) {
if(args[i].equals("-config")) {
resource=args[++i];
continue;
}
help();
return;
}
try {
tree = new TreeCacheAop();
PropertyConfigurator config = new PropertyConfigurator();
config.configure(tree, resource);
tree.addTreeCacheListener(new TreeCacheView.MyListener());
tree.createService();
tree.startService();
Runtime.getRuntime().addShutdownHook(new ShutdownThread(tree));
demo = new TreeCacheAopView(tree);
demo.start();
if (start_directory != null && start_directory.length() > 0) {
demo.populateTree(start_directory);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
static class ShutdownThread extends Thread
{
TreeCacheAop tree = null;
ShutdownThread(TreeCacheAop tree)
{
this.tree = tree;
}
public void run()
{
tree.stop();
}
}
static void help()
{
System.out.println("TreeCacheAopView [-help] [-config <configuration file (XML)]" +
"[-mbean_name <name of TreeCache MBean>] " +
"[-start_directory <dirname>] [-props <props>] " +
"[-use_queue <true/false>] [-queue_interval <ms>] " +
"[-queue_max_elements <num>]");
}
}
class TreeCacheAopGui extends JFrame implements WindowListener, TreeCacheListener,
TreeSelectionListener, TableModelListener
{
TreeCacheAop cache_;
DefaultTreeModel tree_model = null;
JTree jtree = null;
DefaultTableModel table_model = new DefaultTableModel();
JTable table = new JTable(table_model);
MyNode root = new MyNode(SEP, Fqn.fromString(SEP));
String props = null;
String selected_node = null;
JPanel tablePanel = null;
JMenu operationsMenu = null;
JPopupMenu operationsPopup = null;
JMenuBar menubar = null;
boolean use_system_exit = false;
static String SEP = TreeCache.SEPARATOR;
private static final int KEY_COL_WIDTH = 20;
private static final int VAL_COL_WIDTH = 300;
final String STRING = String.class.getName();
final String MAP = Map.class.getName();
final String OBJECT = Object.class.getName();
String currentNodeSelected = null;
public TreeCacheAopGui(TreeCacheAop cache) throws Exception
{
this.cache_ = cache;
cache_.addTreeCacheListener(this);
addNotify();
setTitle("TreeCacheAopGui: mbr=" + getLocalAddress());
tree_model = new DefaultTreeModel(root);
jtree = new JTree(tree_model);
jtree.setDoubleBuffered(true);
jtree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
JScrollPane scroll_pane = new JScrollPane(jtree);
panel.add(scroll_pane, BorderLayout.CENTER);
populateTree();
getContentPane().add(panel, BorderLayout.CENTER);
addWindowListener(this);
table_model.setColumnIdentifiers(new String[]{"Name", "Value"});
table_model.addTableModelListener(this);
setTableColumnWidths();
tablePanel = new JPanel();
tablePanel.setLayout(new BorderLayout());
tablePanel.add(table.getTableHeader(), BorderLayout.NORTH);
tablePanel.add(table, BorderLayout.CENTER);
getContentPane().add(tablePanel, BorderLayout.SOUTH);
jtree.addTreeSelectionListener(this);
MouseListener ml = new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
int selRow = jtree.getRowForLocation(e.getX(), e.getY());
TreePath selPath = jtree.getPathForLocation(e.getX(), e.getY());
if (selRow != -1) {
selected_node = makeFQN(selPath.getPath());
jtree.setSelectionPath(selPath);
if (e.getModifiers() == java.awt.event.InputEvent.BUTTON3_MASK) {
operationsPopup.show(e.getComponent(),
e.getX(), e.getY());
}
}
}
};
jtree.addMouseListener(ml);
createMenus();
setLocation(50, 50);
setSize(getInsets().left + getInsets().right + 485,
getInsets().top + getInsets().bottom + 367);
init();
setVisible(true);
}
void setSystemExit(boolean flag)
{
use_system_exit = flag;
}
public void windowClosed(WindowEvent event)
{
}
public void windowDeiconified(WindowEvent event)
{
}
public void windowIconified(WindowEvent event)
{
}
public void windowActivated(WindowEvent event)
{
}
public void windowDeactivated(WindowEvent event)
{
}
public void windowOpened(WindowEvent event)
{
}
public void windowClosing(WindowEvent event)
{
dispose();
}
public void tableChanged(TableModelEvent evt)
{
int row, col;
String key, val;
if (evt.getType() == TableModelEvent.UPDATE) {
row = evt.getFirstRow();
col = evt.getColumn();
if (col == 0) { key = (String) table_model.getValueAt(row, col);
val = (String) table_model.getValueAt(row, col + 1);
if (key != null && val != null) {
try {
cache_.put(selected_node, key, val);
} catch (Exception e) {
e.printStackTrace();
}
}
} else { key = (String) table_model.getValueAt(row, col - 1);
val = (String) table.getValueAt(row, col);
if (key != null && val != null) {
put(selected_node, key, val);
}
}
}
}
public void valueChanged(TreeSelectionEvent evt)
{
TreePath path = evt.getPath();
String fqn = SEP;
String component_name;
Map data = null;
for (int i = 0; i < path.getPathCount(); i++) {
component_name = ((MyNode) path.getPathComponent(i)).name;
if (component_name.equals(SEP))
continue;
if (fqn.equals(SEP))
fqn += component_name;
else
fqn = fqn + SEP + component_name;
}
data = getData(fqn);
System.out.println("valueChanged(): fqn: " + fqn + " data: " + data);
if (data != null) {
getContentPane().add(tablePanel, BorderLayout.SOUTH);
populateTable(data);
validate();
} else {
clearTable();
getContentPane().remove(tablePanel);
validate();
}
}
public void nodeCreated(Fqn fqn)
{
MyNode n, p;
n = root.add(fqn);
if (n != null) {
p = (MyNode) n.getParent();
tree_model.reload(p);
jtree.scrollPathToVisible(new TreePath(n.getPath()));
}
}
public void nodeRemoved(Fqn fqn)
{
MyNode n;
TreeNode par;
n = root.findNode(fqn.toString());
if (n != null) {
n.removeAllChildren();
par = n.getParent();
n.removeFromParent();
tree_model.reload(par);
}
}
public void nodeLoaded(Fqn fqn) {
nodeCreated(fqn);
}
public void nodeEvicted(Fqn fqn) {
nodeRemoved(fqn);
}
public void nodeModified(final Fqn fqn)
{
Map data;
if (currentNodeSelected != null && !currentNodeSelected.equals(fqn.toString())) return; data = getData(fqn.toString());
populateTable(data);
}
public void nodeVisited(Fqn fqn)
{
}
public void cacheStarted(TreeCache cache)
{
}
public void cacheStopped(TreeCache cache)
{
}
public void viewChange(final View new_view)
{
new Thread()
{
public void run()
{
Vector mbrship;
if (new_view != null && (mbrship = new_view.getMembers()) != null) {
_put(SEP, "members", mbrship);
_put(SEP, "coordinator", mbrship.firstElement());
}
}
}.start();
}
public void run()
{
}
void init()
{
Vector mbrship = null;
addGuiNode(SEP);
mbrship = getMembers() != null ? (Vector) getMembers().clone() : null;
if (mbrship != null && mbrship.size() > 0) {
_put(SEP, "members", mbrship);
_put(SEP, "coordinator", mbrship.firstElement());
}
}
private void populateTree()
{
addGuiNode(SEP);
}
void addGuiNode(String fqn)
{
Set children;
String child_name;
if (fqn == null) return;
root.add(Fqn.fromString(fqn));
children = getChildrenNames(fqn);
if (children != null) {
for (Iterator it = children.iterator(); it.hasNext();) {
child_name = (String) it.next();
addGuiNode(fqn + SEP + child_name);
}
}
}
String makeFQN(Object[] path)
{
StringBuffer sb = new StringBuffer("");
String tmp_name;
if (path == null) return null;
for (int i = 0; i < path.length; i++) {
tmp_name = ((MyNode) path[i]).name;
if (tmp_name.equals(SEP))
continue;
else
sb.append(SEP + tmp_name);
}
tmp_name = sb.toString();
if (tmp_name.length() == 0)
return SEP;
else
return tmp_name;
}
void clearTable()
{
int num_rows = table.getRowCount();
if (num_rows > 0) {
for (int i = 0; i < num_rows; i++)
table_model.removeRow(0);
table_model.fireTableRowsDeleted(0, num_rows - 1);
repaint();
}
}
void populateTable(Map data)
{
String key, strval = "<null>";
Object val;
int num_rows = 0;
Map.Entry entry;
if (data == null) return;
num_rows = data.size();
clearTable();
if (num_rows > 0) {
for (Iterator it = data.entrySet().iterator(); it.hasNext();) {
entry = (Map.Entry) it.next();
key = (String) entry.getKey();
val = entry.getValue();
if (val != null) strval = val.toString();
table_model.addRow(new Object[]{key, strval});
}
table_model.fireTableRowsInserted(0, num_rows - 1);
validate();
}
}
private void setTableColumnWidths()
{
table.sizeColumnsToFit(JTable.AUTO_RESIZE_NEXT_COLUMN);
TableColumn column = null;
column = table.getColumnModel().getColumn(0);
column.setMinWidth(KEY_COL_WIDTH);
column.setPreferredWidth(KEY_COL_WIDTH);
column = table.getColumnModel().getColumn(1);
column.setPreferredWidth(VAL_COL_WIDTH);
}
private void createMenus()
{
menubar = new JMenuBar();
operationsMenu = new JMenu("Operations");
AddNodeAction addNode = new AddNodeAction();
addNode.putValue(AbstractAction.NAME, "Add to this node");
RemoveNodeAction removeNode = new RemoveNodeAction();
removeNode.putValue(AbstractAction.NAME, "Remove this node");
AddModifyDataForNodeAction addModAction = new AddModifyDataForNodeAction();
addModAction.putValue(AbstractAction.NAME, "Add/Modify data");
PrintLockInfoAction print_locks = new PrintLockInfoAction();
print_locks.putValue(AbstractAction.NAME, "Print lock information (stdout)");
ReleaseAllLocksAction release_locks = new ReleaseAllLocksAction();
release_locks.putValue(AbstractAction.NAME, "Release all locks");
ExitAction exitAction = new ExitAction();
exitAction.putValue(AbstractAction.NAME, "Exit");
operationsMenu.add(addNode);
operationsMenu.add(removeNode);
operationsMenu.add(addModAction);
operationsMenu.add(print_locks);
operationsMenu.add(release_locks);
operationsMenu.add(exitAction);
menubar.add(operationsMenu);
setJMenuBar(menubar);
operationsPopup = new JPopupMenu();
operationsPopup.add(addNode);
operationsPopup.add(removeNode);
operationsPopup.add(addModAction);
}
Object getLocalAddress()
{
try {
return cache_.getLocalAddress();
} catch (Throwable t) {
System.err.println("TreeCacheAopGui.getLocalAddress(): " + t);
return null;
}
}
Map getData(String fqn)
{
Map data;
Set keys;
String key;
Object value;
if (fqn == null) return null;
currentNodeSelected = fqn;
MyNode node = root.findNode(fqn);
if (node == null) return null;
keys = getKeys(node.getFqn());
if (keys == null) return null;
data = new HashMap();
for (Iterator it = keys.iterator(); it.hasNext();) {
key = it.next().toString();
value = get(node.getFqn(), key);
if (value != null)
data.put(key, value);
}
return data;
}
void put(String fqn, Map m)
{
try {
cache_.put(fqn, m);
} catch (Throwable t) {
System.err.println("TreeCacheAopGui.put(): " + t);
}
}
private void put(String fqn, String key, Object value)
{
try {
cache_.put(fqn, key, value);
} catch (Throwable t) {
System.err.println("TreeCacheAopGui.put(): " + t);
}
}
void _put(String fqn, String key, Object value)
{
try {
cache_._put(null, fqn, key, value, false);
} catch (Throwable t) {
System.err.println("TreeCacheAopGui._put(): " + t);
}
}
Set getKeys(Fqn fqn)
{
try {
return cache_.getKeys(fqn);
} catch (Throwable t) {
t.printStackTrace();
System.err.println("TreeCacheAopGui.getKeys(): " + t);
return null;
}
}
Object get(Fqn fqn, String key)
{
try {
return cache_.get(fqn, key);
} catch (Throwable t) {
System.err.println("TreeCacheAopGui.get(): " + t);
return null;
}
}
Set getChildrenNames(String fqn)
{
try {
return cache_.getChildrenNames(fqn);
} catch (Throwable t) {
System.err.println("TreeCacheAopGui.getChildrenNames(): " + t);
return null;
}
}
Vector getMembers()
{
try {
return cache_.getMembers();
} catch (Throwable t) {
System.err.println("TreeCacheAopGui.getMembers(): " + t);
return null;
}
}
class ExitAction extends AbstractAction
{
public void actionPerformed(ActionEvent e)
{
dispose();
System.exit(0);
}
}
class AddNodeAction extends AbstractAction
{
public void actionPerformed(ActionEvent e)
{
JTextField fqnTextField = new JTextField();
if (selected_node != null)
fqnTextField.setText(selected_node);
Object[] information = {"Enter fully qualified name",
fqnTextField};
final String btnString1 = "OK";
final String btnString2 = "Cancel";
Object[] options = {btnString1, btnString2};
int userChoice = JOptionPane.showOptionDialog(null,
information,
"Add Node",
JOptionPane.YES_NO_OPTION,
JOptionPane.PLAIN_MESSAGE,
null,
options,
options[0]);
if (userChoice == 0) {
String userInput = fqnTextField.getText();
put(userInput, null);
}
}
}
class PrintLockInfoAction extends AbstractAction
{
public void actionPerformed(ActionEvent e)
{
System.out.println("\n*** lock information ****\n" + cache_.printLockInfo());
}
}
class ReleaseAllLocksAction extends AbstractAction
{
public void actionPerformed(ActionEvent e)
{
cache_.releaseAllLocks("/");
}
}
class RemoveNodeAction extends AbstractAction
{
public void actionPerformed(ActionEvent e)
{
try {
cache_.remove(selected_node);
} catch (Throwable t) {
System.err.println("RemoveNodeAction.actionPerformed(): " + t);
}
}
}
class AddModifyDataForNodeAction extends AbstractAction
{
public void actionPerformed(ActionEvent e)
{
Map data = getData(selected_node);
if (data != null) {
} else {
clearTable();
data = new HashMap();
data.put("Add Key", "Add Value");
}
populateTable(data);
getContentPane().add(tablePanel, BorderLayout.SOUTH);
validate();
}
}
class MyNode extends DefaultMutableTreeNode
{
String name = "<unnamed>"; Fqn fqn;
MyNode(String name, Fqn fqn)
{
this.fqn = fqn;
this.name = name;
}
public Fqn getFqn()
{
return fqn;
}
public MyNode add(Fqn fqn)
{
MyNode curr, n, ret = null;
StringTokenizer tok;
String child_name;
if (fqn == null) return null;
curr = this;
String fqnStr = fqn.toString();
tok = new StringTokenizer(fqnStr, TreeCacheAopGui.SEP);
int i = 0;
while (tok.hasMoreTokens()) {
child_name = tok.nextToken();
n = curr.findChild(child_name);
if (n == null) {
n = new MyNode(child_name, fqn.getFqnChild(i + 1));
if (ret == null) ret = n;
curr.add(n);
}
curr = n;
i++;
}
return ret;
}
public void remove(String fqn)
{
removeFromParent();
}
MyNode findNode(String fqn)
{
MyNode curr, n;
StringTokenizer tok;
String child_name;
if (fqn == null) return null;
curr = this;
tok = new StringTokenizer(fqn, TreeCacheAopGui.SEP);
while (tok.hasMoreTokens()) {
child_name = tok.nextToken();
n = curr.findChild(child_name);
if (n == null)
return null;
curr = n;
}
return curr;
}
MyNode findChild(String relative_name)
{
MyNode child;
if (relative_name == null || getChildCount() == 0)
return null;
for (int i = 0; i < getChildCount(); i++) {
child = (MyNode) getChildAt(i);
if (child.name == null) {
continue;
}
if (child.name.equals(relative_name))
return child;
}
return null;
}
String print(int indent)
{
StringBuffer sb = new StringBuffer();
for (int i = 0; i < indent; i++)
sb.append(" ");
if (!isRoot()) {
if (name == null)
sb.append("/<unnamed>");
else {
sb.append(TreeCacheAopGui.SEP + name);
}
}
sb.append("\n");
if (getChildCount() > 0) {
if (isRoot())
indent = 0;
else
indent += 4;
for (int i = 0; i < getChildCount(); i++)
sb.append(((MyNode) getChildAt(i)).print(indent));
}
return sb.toString();
}
public String toString()
{
return name;
}
}
}