http://git-wip-us.apache.org/repos/asf/zookeeper/blob/eab8c1eb/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorTreeViewer.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorTreeViewer.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorTreeViewer.java
new file mode 100644
index 0000000..e08f2d3
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorTreeViewer.java
@@ -0,0 +1,384 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.gui;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.swing.ImageIcon;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JComponent;
+import javax.swing.JTree;
+import javax.swing.SwingWorker;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreePath;
+
+import org.apache.zookeeper.inspector.gui.actions.AddNodeAction;
+import org.apache.zookeeper.inspector.gui.actions.DeleteNodeAction;
+import org.apache.zookeeper.inspector.manager.NodeListener;
+import org.apache.zookeeper.inspector.manager.ZooInspectorManager;
+
+import com.nitido.utils.toaster.Toaster;
+import static javax.swing.KeyStroke.getKeyStroke;
+
+/**
+ * A {@link JPanel} for showing the tree view of all the nodes in the zookeeper
+ * instance
+ */
+public class ZooInspectorTreeViewer extends JPanel implements NodeListener {
+ private final ZooInspectorManager zooInspectorManager;
+ private final JTree tree;
+ private final Toaster toasterManager;
+ private final ImageIcon toasterIcon;
+
+ /**
+ * @param zooInspectorManager
+ * - the {@link ZooInspectorManager} for the application
+ * @param listener
+ * - the {@link TreeSelectionListener} to listen for changes in
+ * the selected node on the node tree
+ */
+ public ZooInspectorTreeViewer(
+ final ZooInspectorManager zooInspectorManager,
+ TreeSelectionListener listener, IconResource iconResource) {
+
+ this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
+ .put(getKeyStroke(KeyEvent.VK_D, InputEvent.CTRL_MASK), "deleteNode");
+
+ this.getActionMap().put("deleteNode",
+ new DeleteNodeAction(this, this, zooInspectorManager));
+
+ this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
+ .put(getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK), "addNode");
+
+ this.getActionMap().put("addNode",
+ new AddNodeAction(this, this, zooInspectorManager));
+
+ this.zooInspectorManager = zooInspectorManager;
+ this.setLayout(new BorderLayout());
+ final JPopupMenu popupMenu = new JPopupMenu();
+
+ final JMenuItem addNode = new JMenuItem("Add Node");
+ addNode.addActionListener(new AddNodeAction(this, this, zooInspectorManager));
+
+ final JMenuItem deleteNode = new JMenuItem("Delete Node");
+ deleteNode.addActionListener(new DeleteNodeAction(this, this, zooInspectorManager));
+
+ final JMenuItem addNotify = new JMenuItem("Add Change Notification");
+ this.toasterManager = new Toaster();
+ this.toasterManager.setBorderColor(Color.BLACK);
+ this.toasterManager.setMessageColor(Color.BLACK);
+ this.toasterManager.setToasterColor(Color.WHITE);
+ toasterIcon = iconResource.get(IconResource.ICON_INFORMATION,"");
+ addNotify.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ List<String> selectedNodes = getSelectedNodes();
+ zooInspectorManager.addWatchers(selectedNodes,
+ ZooInspectorTreeViewer.this);
+ }
+ });
+ final JMenuItem removeNotify = new JMenuItem(
+ "Remove Change Notification");
+ removeNotify.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ List<String> selectedNodes = getSelectedNodes();
+ zooInspectorManager.removeWatchers(selectedNodes);
+ }
+ });
+ tree = new JTree(new DefaultMutableTreeNode());
+ tree.setCellRenderer(new ZooInspectorTreeCellRenderer(iconResource));
+ tree.setEditable(false);
+ tree.getSelectionModel().addTreeSelectionListener(listener);
+ tree.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (e.isPopupTrigger() || e.getButton() == MouseEvent.BUTTON3) {
+ // TODO only show add if a selected node isn't being
+ // watched, and only show remove if a selected node is being
+ // watched
+ popupMenu.removeAll();
+ popupMenu.add(addNode);
+ popupMenu.add(deleteNode);
+ popupMenu.add(addNotify);
+ popupMenu.add(removeNotify);
+ popupMenu.show(ZooInspectorTreeViewer.this, e.getX(), e
+ .getY());
+ }
+ }
+ });
+ this.add(tree, BorderLayout.CENTER);
+ }
+
+ /**
+ * Refresh the tree view
+ */
+ public void refreshView() {
+ final Set<TreePath> expandedNodes = new LinkedHashSet<TreePath>();
+ int rowCount = tree.getRowCount();
+ for (int i = 0; i < rowCount; i++) {
+ TreePath path = tree.getPathForRow(i);
+ if (tree.isExpanded(path)) {
+ expandedNodes.add(path);
+ }
+ }
+ final TreePath[] selectedNodes = tree.getSelectionPaths();
+ SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
+
+ @Override
+ protected Boolean doInBackground() throws Exception {
+ tree.setModel(new DefaultTreeModel(new ZooInspectorTreeNode(
+ "/", null)));
+ return true;
+ }
+
+ @Override
+ protected void done() {
+ for (TreePath path : expandedNodes) {
+ tree.expandPath(path);
+ }
+ tree.getSelectionModel().setSelectionPaths(selectedNodes);
+ }
+ };
+ worker.execute();
+ }
+
+ /**
+ * clear the tree view of all nodes
+ */
+ public void clearView() {
+ tree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode()));
+ }
+
+ private static class ZooInspectorTreeCellRenderer extends
+ DefaultTreeCellRenderer {
+ public ZooInspectorTreeCellRenderer(IconResource iconResource) {
+ setLeafIcon(iconResource.get(IconResource.ICON_TREE_LEAF,""));
+ setOpenIcon(iconResource.get(IconResource.ICON_TREE_OPEN,""));
+ setClosedIcon(iconResource.get(IconResource.ICON_TREE_CLOSE,""));
+ }
+ }
+
+ private class ZooInspectorTreeNode implements TreeNode {
+ private final String nodePath;
+ private final String nodeName;
+ private final ZooInspectorTreeNode parent;
+
+ public ZooInspectorTreeNode(String nodePath, ZooInspectorTreeNode parent) {
+ this.parent = parent;
+ this.nodePath = nodePath;
+ int index = nodePath.lastIndexOf("/");
+ if (index == -1) {
+ throw new IllegalArgumentException("Invalid node path"
+ + nodePath);
+ }
+ this.nodeName = nodePath.substring(index + 1);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see javax.swing.tree.TreeNode#children()
+ */
+ public Enumeration<TreeNode> children() {
+ List<String> children = zooInspectorManager
+ .getChildren(this.nodePath);
+ Collections.sort(children);
+ List<TreeNode> returnChildren = new ArrayList<TreeNode>();
+ for (String child : children) {
+ returnChildren.add(new ZooInspectorTreeNode((this.nodePath
+ .equals("/") ? "" : this.nodePath)
+ + "/" + child, this));
+ }
+ return Collections.enumeration(returnChildren);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see javax.swing.tree.TreeNode#getAllowsChildren()
+ */
+ public boolean getAllowsChildren() {
+ return zooInspectorManager.isAllowsChildren(this.nodePath);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see javax.swing.tree.TreeNode#getChildAt(int)
+ */
+ public TreeNode getChildAt(int childIndex) {
+ String child = zooInspectorManager.getNodeChild(this.nodePath,
+ childIndex);
+ if (child != null) {
+ return new ZooInspectorTreeNode((this.nodePath.equals("/") ? ""
+ : this.nodePath)
+ + "/" + child, this);
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see javax.swing.tree.TreeNode#getChildCount()
+ */
+ public int getChildCount() {
+ return zooInspectorManager.getNumChildren(this.nodePath);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see javax.swing.tree.TreeNode#getIndex(javax.swing.tree.TreeNode)
+ */
+ public int getIndex(TreeNode node) {
+ return zooInspectorManager.getNodeIndex(this.nodePath);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see javax.swing.tree.TreeNode#getParent()
+ */
+ public TreeNode getParent() {
+ return this.parent;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see javax.swing.tree.TreeNode#isLeaf()
+ */
+ public boolean isLeaf() {
+ return !zooInspectorManager.hasChildren(this.nodePath);
+ }
+
+ @Override
+ public String toString() {
+ return this.nodeName;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + getOuterType().hashCode();
+ result = prime * result
+ + ((nodePath == null) ? 0 : nodePath.hashCode());
+ result = prime * result
+ + ((parent == null) ? 0 : parent.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ZooInspectorTreeNode other = (ZooInspectorTreeNode) obj;
+ if (!getOuterType().equals(other.getOuterType()))
+ return false;
+ if (nodePath == null) {
+ if (other.nodePath != null)
+ return false;
+ } else if (!nodePath.equals(other.nodePath))
+ return false;
+ if (parent == null) {
+ if (other.parent != null)
+ return false;
+ } else if (!parent.equals(other.parent))
+ return false;
+ return true;
+ }
+
+ private ZooInspectorTreeViewer getOuterType() {
+ return ZooInspectorTreeViewer.this;
+ }
+
+ }
+
+ /**
+ * @return {@link List} of the currently selected nodes
+ */
+ public List<String> getSelectedNodes() {
+ TreePath[] paths = tree.getSelectionPaths();
+ List<String> selectedNodes = new ArrayList<String>();
+ if (paths != null) {
+ for (TreePath path : paths) {
+ StringBuilder sb = new StringBuilder();
+ Object[] pathArray = path.getPath();
+ for (Object o : pathArray) {
+ String nodeName = o.toString();
+ if (nodeName.length() > 0) {
+ sb.append("/");
+ sb.append(o.toString());
+ }
+ }
+ selectedNodes.add(sb.toString());
+ }
+ }
+ return selectedNodes;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.zookeeper.inspector.manager.NodeListener#processEvent(java
+ * .lang.String, java.lang.String, java.util.Map)
+ */
+ public void processEvent(String nodePath, String eventType,
+ Map<String, String> eventInfo) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Node: ");
+ sb.append(nodePath);
+ sb.append("\nEvent: ");
+ sb.append(eventType);
+ if (eventInfo != null) {
+ for (Map.Entry<String, String> entry : eventInfo.entrySet()) {
+ sb.append("\n");
+ sb.append(entry.getKey());
+ sb.append(": ");
+ sb.append(entry.getValue());
+ }
+ }
+ this.toasterManager.showToaster(toasterIcon, sb.toString());
+ }
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/eab8c1eb/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/about.html
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/about.html b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/about.html
new file mode 100644
index 0000000..17fb3dc
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/about.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>ZooInspector v0.1</title>
+</head>
+<body>
+<p>ZooInspector was developed by Colin Goodheart-Smithe and is
+available under the Apache Software Licence v2.0.</p>
+<p>The Icons used were sourced from the Eclipse project (<a
+ href="http://www.eclipse.org">http://www.eclipse.org</a>) and licensed
+under the Eclipse Public Licence v1.0. [<a
+ href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/org/documents/epl-v10.php</a>]
+</p>
+<p>ZooKeeper is available from <a
+ href="http://zookeeper.apache.org/">http://zookeeper.apache.org/</a>
+and is licensed under an Apache Software Licence v2.0</p>
+<p>The ApacheSoftware Licence v2.0 can be found at <a
+ href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a></p>
+</body>
+</html>
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/eab8c1eb/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/actions/AddNodeAction.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/actions/AddNodeAction.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/actions/AddNodeAction.java
new file mode 100644
index 0000000..3091611
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/actions/AddNodeAction.java
@@ -0,0 +1,74 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.gui.actions;
+
+import org.apache.zookeeper.inspector.gui.ZooInspectorPanel;
+import org.apache.zookeeper.inspector.gui.ZooInspectorTreeViewer;
+import org.apache.zookeeper.inspector.manager.ZooInspectorManager;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+import java.awt.event.KeyEvent;
+
+public class AddNodeAction extends AbstractAction {
+
+ private JPanel panel;
+ private ZooInspectorTreeViewer treeViewer;
+ private ZooInspectorManager zooInspectorManager;
+
+ public AddNodeAction(JPanel parentPanel,
+ ZooInspectorTreeViewer treeViewer,
+ ZooInspectorManager zooInspectorManager) {
+ this.panel = parentPanel;
+ this.treeViewer = treeViewer;
+ this.zooInspectorManager = zooInspectorManager;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ final List<String> selectedNodes = treeViewer
+ .getSelectedNodes();
+ if (selectedNodes.size() == 1) {
+ final String nodeName = JOptionPane.showInputDialog(
+ panel,
+ "Please Enter a name for the new node",
+ "Create Node", JOptionPane.INFORMATION_MESSAGE);
+ if (nodeName != null && nodeName.length() > 0) {
+ SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
+
+ @Override
+ protected Boolean doInBackground() throws Exception {
+ return zooInspectorManager
+ .createNode(selectedNodes.get(0),
+ nodeName);
+ }
+
+ @Override
+ protected void done() {
+ treeViewer.refreshView();
+ }
+ };
+ worker.execute();
+ }
+ } else {
+ JOptionPane.showMessageDialog(panel,
+ "Please select 1 parent node for the new node.");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/eab8c1eb/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/actions/DeleteNodeAction.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/actions/DeleteNodeAction.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/actions/DeleteNodeAction.java
new file mode 100644
index 0000000..9001670
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/actions/DeleteNodeAction.java
@@ -0,0 +1,79 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.gui.actions;
+
+import org.apache.zookeeper.inspector.gui.ZooInspectorTreeViewer;
+import org.apache.zookeeper.inspector.manager.ZooInspectorManager;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+import java.awt.event.KeyEvent;
+
+public class DeleteNodeAction extends AbstractAction {
+
+ private JPanel parentPanel;
+ private ZooInspectorTreeViewer treeViewer;
+ private ZooInspectorManager zooInspectorManager;
+
+ public DeleteNodeAction(JPanel parentPanel,
+ ZooInspectorTreeViewer treeViewer,
+ ZooInspectorManager zooInspectorManager) {
+ this.parentPanel = parentPanel;
+ this.treeViewer = treeViewer;
+ this.zooInspectorManager = zooInspectorManager;
+ }
+
+
+ public void actionPerformed(ActionEvent e) {
+ final List<String> selectedNodes = treeViewer
+ .getSelectedNodes();
+ if (selectedNodes.size() == 0) {
+ JOptionPane.showMessageDialog(parentPanel,
+ "Please select at least 1 node to be deleted");
+ } else {
+ int answer = JOptionPane.showConfirmDialog(
+ parentPanel,
+ "Are you sure you want to delete the selected nodes?"
+ + "(This action cannot be reverted)",
+ "Confirm Delete", JOptionPane.YES_NO_OPTION,
+ JOptionPane.WARNING_MESSAGE
+ );
+ if (answer == JOptionPane.YES_OPTION) {
+ SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
+
+ @Override
+ protected Boolean doInBackground() throws Exception {
+ for (String nodePath : selectedNodes) {
+ zooInspectorManager
+ .deleteNode(nodePath);
+ }
+ return true;
+ }
+
+ @Override
+ protected void done() {
+ treeViewer.refreshView();
+ }
+ };
+ worker.execute();
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/eab8c1eb/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/nodeviewer/NodeViewerACL.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/nodeviewer/NodeViewerACL.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/nodeviewer/NodeViewerACL.java
new file mode 100644
index 0000000..5ac203c
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/nodeviewer/NodeViewerACL.java
@@ -0,0 +1,187 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.gui.nodeviewer;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+
+import javax.swing.BorderFactory;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.SwingWorker;
+
+import org.apache.zookeeper.inspector.logger.LoggerFactory;
+import org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager;
+
+/**
+ * A node viewer for displaying the ACLs currently applied to the selected node
+ */
+public class NodeViewerACL extends ZooInspectorNodeViewer {
+ private ZooInspectorNodeManager zooInspectorManager;
+ private final JPanel aclDataPanel;
+ private String selectedNode;
+
+ /**
+ *
+ */
+ public NodeViewerACL() {
+ this.setLayout(new BorderLayout());
+ this.aclDataPanel = new JPanel();
+ this.aclDataPanel.setBackground(Color.WHITE);
+ JScrollPane scroller = new JScrollPane(this.aclDataPanel);
+ this.add(scroller, BorderLayout.CENTER);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
+ * getTitle()
+ */
+ @Override
+ public String getTitle() {
+ return "Node ACLs";
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
+ * nodeSelectionChanged(java.util.Set)
+ */
+ @Override
+ public void nodeSelectionChanged(List<String> selectedNodes) {
+ this.aclDataPanel.removeAll();
+ if (selectedNodes.size() > 0) {
+ this.selectedNode = selectedNodes.get(0);
+ SwingWorker<List<Map<String, String>>, Void> worker = new SwingWorker<List<Map<String, String>>, Void>() {
+
+ @Override
+ protected List<Map<String, String>> doInBackground()
+ throws Exception {
+ return NodeViewerACL.this.zooInspectorManager
+ .getACLs(NodeViewerACL.this.selectedNode);
+ }
+
+ @Override
+ protected void done() {
+ List<Map<String, String>> acls = null;
+ try {
+ acls = get();
+ } catch (InterruptedException e) {
+ acls = new ArrayList<Map<String, String>>();
+ LoggerFactory.getLogger().error(
+ "Error retrieving ACL Information for node: "
+ + NodeViewerACL.this.selectedNode, e);
+ } catch (ExecutionException e) {
+ acls = new ArrayList<Map<String, String>>();
+ LoggerFactory.getLogger().error(
+ "Error retrieving ACL Information for node: "
+ + NodeViewerACL.this.selectedNode, e);
+ }
+ aclDataPanel.setLayout(new GridBagLayout());
+ int j = 0;
+ for (Map<String, String> data : acls) {
+ int rowPos = 2 * j + 1;
+ JPanel aclPanel = new JPanel();
+ aclPanel.setBorder(BorderFactory
+ .createLineBorder(Color.BLACK));
+ aclPanel.setBackground(Color.WHITE);
+ aclPanel.setLayout(new GridBagLayout());
+ int i = 0;
+ for (Map.Entry<String, String> entry : data.entrySet()) {
+ int rowPosACL = 2 * i + 1;
+ JLabel label = new JLabel(entry.getKey());
+ JTextField text = new JTextField(entry.getValue());
+ text.setEditable(false);
+ GridBagConstraints c1 = new GridBagConstraints();
+ c1.gridx = 1;
+ c1.gridy = rowPosACL;
+ c1.gridwidth = 1;
+ c1.gridheight = 1;
+ c1.weightx = 0;
+ c1.weighty = 0;
+ c1.anchor = GridBagConstraints.NORTHWEST;
+ c1.fill = GridBagConstraints.BOTH;
+ c1.insets = new Insets(5, 5, 5, 5);
+ c1.ipadx = 0;
+ c1.ipady = 0;
+ aclPanel.add(label, c1);
+ GridBagConstraints c2 = new GridBagConstraints();
+ c2.gridx = 3;
+ c2.gridy = rowPosACL;
+ c2.gridwidth = 1;
+ c2.gridheight = 1;
+ c2.weightx = 0;
+ c2.weighty = 0;
+ c2.anchor = GridBagConstraints.NORTHWEST;
+ c2.fill = GridBagConstraints.BOTH;
+ c2.insets = new Insets(5, 5, 5, 5);
+ c2.ipadx = 0;
+ c2.ipady = 0;
+ aclPanel.add(text, c2);
+ i++;
+ }
+ GridBagConstraints c = new GridBagConstraints();
+ c.gridx = 1;
+ c.gridy = rowPos;
+ c.gridwidth = 1;
+ c.gridheight = 1;
+ c.weightx = 1;
+ c.weighty = 1;
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill = GridBagConstraints.NONE;
+ c.insets = new Insets(5, 5, 5, 5);
+ c.ipadx = 0;
+ c.ipady = 0;
+ aclDataPanel.add(aclPanel, c);
+ }
+ NodeViewerACL.this.aclDataPanel.revalidate();
+ NodeViewerACL.this.aclDataPanel.repaint();
+ }
+ };
+ worker.execute();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
+ * setZooInspectorManager
+ * (org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager)
+ */
+ @Override
+ public void setZooInspectorManager(
+ ZooInspectorNodeManager zooInspectorManager) {
+ this.zooInspectorManager = zooInspectorManager;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/eab8c1eb/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/nodeviewer/NodeViewerData.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/nodeviewer/NodeViewerData.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/nodeviewer/NodeViewerData.java
new file mode 100644
index 0000000..6061e17
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/nodeviewer/NodeViewerData.java
@@ -0,0 +1,143 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.gui.nodeviewer;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+import javax.swing.JButton;
+import javax.swing.JOptionPane;
+import javax.swing.JScrollPane;
+import javax.swing.JTextPane;
+import javax.swing.JToolBar;
+import javax.swing.SwingWorker;
+
+import org.apache.zookeeper.inspector.ZooInspector;
+import org.apache.zookeeper.inspector.gui.IconResource;
+import org.apache.zookeeper.inspector.logger.LoggerFactory;
+import org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager;
+
+/**
+ * A node viewer for displaying the data for the currently selected node
+ */
+public class NodeViewerData extends ZooInspectorNodeViewer {
+ private ZooInspectorNodeManager zooInspectorManager;
+ private final JTextPane dataArea;
+ private final JToolBar toolbar;
+ private String selectedNode;
+
+ public NodeViewerData() {
+ this.setLayout(new BorderLayout());
+ this.dataArea = new JTextPane();
+ this.toolbar = new JToolBar();
+ this.toolbar.setFloatable(false);
+ JScrollPane scroller = new JScrollPane(this.dataArea);
+ scroller
+ .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ this.add(scroller, BorderLayout.CENTER);
+ this.add(this.toolbar, BorderLayout.NORTH);
+ JButton saveButton = new JButton(ZooInspector.iconResource.get(IconResource.ICON_SAVE,""));
+ saveButton.addActionListener(new ActionListener() {
+
+ public void actionPerformed(ActionEvent e) {
+ if (selectedNode != null) {
+ if (JOptionPane.showConfirmDialog(NodeViewerData.this,
+ "Are you sure you want to save this node?"
+ + " (this action cannot be reverted)",
+ "Confirm Save", JOptionPane.YES_NO_OPTION,
+ JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) {
+ zooInspectorManager.setData(selectedNode, dataArea
+ .getText());
+ }
+ }
+ }
+ });
+ this.toolbar.add(saveButton);
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
+ * getTitle()
+ */
+ @Override
+ public String getTitle() {
+ return "Node Data";
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
+ * nodeSelectionChanged(java.util.Set)
+ */
+ @Override
+ public void nodeSelectionChanged(List<String> selectedNodes) {
+ if (selectedNodes.size() > 0) {
+ this.selectedNode = selectedNodes.get(0);
+ SwingWorker<String, Void> worker = new SwingWorker<String, Void>() {
+
+ @Override
+ protected String doInBackground() throws Exception {
+ return NodeViewerData.this.zooInspectorManager
+ .getData(NodeViewerData.this.selectedNode);
+ }
+
+ @Override
+ protected void done() {
+ String data = "";
+ try {
+ data = get();
+ } catch (InterruptedException e) {
+ LoggerFactory.getLogger().error(
+ "Error retrieving data for node: "
+ + NodeViewerData.this.selectedNode, e);
+ } catch (ExecutionException e) {
+ LoggerFactory.getLogger().error(
+ "Error retrieving data for node: "
+ + NodeViewerData.this.selectedNode, e);
+ }
+ NodeViewerData.this.dataArea.setText(data);
+ }
+ };
+ worker.execute();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
+ * setZooInspectorManager
+ * (org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager)
+ */
+ @Override
+ public void setZooInspectorManager(
+ ZooInspectorNodeManager zooInspectorManager) {
+ this.zooInspectorManager = zooInspectorManager;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/eab8c1eb/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/nodeviewer/NodeViewerMetaData.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/nodeviewer/NodeViewerMetaData.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/nodeviewer/NodeViewerMetaData.java
new file mode 100644
index 0000000..5c2df8d
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/nodeviewer/NodeViewerMetaData.java
@@ -0,0 +1,186 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.gui.nodeviewer;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.SwingWorker;
+
+import org.apache.zookeeper.data.Stat;
+import org.apache.zookeeper.inspector.logger.LoggerFactory;
+import org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager;
+
+/**
+ * A node viewer for displaying the meta data for the currently selected node.
+ * The meta data is essentially the information from the {@link Stat} for the
+ * node
+ */
+public class NodeViewerMetaData extends ZooInspectorNodeViewer {
+ private ZooInspectorNodeManager zooInspectorManager;
+ private final JPanel metaDataPanel;
+ private String selectedNode;
+
+ /**
+ *
+ */
+ public NodeViewerMetaData() {
+ this.setLayout(new BorderLayout());
+ this.metaDataPanel = new JPanel();
+ this.metaDataPanel.setBackground(Color.WHITE);
+ JScrollPane scroller = new JScrollPane(this.metaDataPanel);
+ this.add(scroller, BorderLayout.CENTER);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
+ * getTitle()
+ */
+ @Override
+ public String getTitle() {
+ return "Node Metadata";
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
+ * nodeSelectionChanged(java.util.Set)
+ */
+ @Override
+ public void nodeSelectionChanged(List<String> selectedNodes) {
+ this.metaDataPanel.removeAll();
+ if (selectedNodes.size() > 0) {
+ this.selectedNode = selectedNodes.get(0);
+ SwingWorker<Map<String, String>, Void> worker = new SwingWorker<Map<String, String>, Void>() {
+
+ @Override
+ protected Map<String, String> doInBackground() throws Exception {
+ return NodeViewerMetaData.this.zooInspectorManager
+ .getNodeMeta(NodeViewerMetaData.this.selectedNode);
+ }
+
+ @Override
+ protected void done() {
+ Map<String, String> data = null;
+ try {
+ data = get();
+ } catch (InterruptedException e) {
+ data = new HashMap<String, String>();
+ LoggerFactory.getLogger().error(
+ "Error retrieving meta data for node: "
+ + NodeViewerMetaData.this.selectedNode,
+ e);
+ } catch (ExecutionException e) {
+ data = new HashMap<String, String>();
+ LoggerFactory.getLogger().error(
+ "Error retrieving meta data for node: "
+ + NodeViewerMetaData.this.selectedNode,
+ e);
+ }
+ NodeViewerMetaData.this.metaDataPanel
+ .setLayout(new GridBagLayout());
+ JPanel infoPanel = new JPanel();
+ infoPanel.setBackground(Color.WHITE);
+ infoPanel.setLayout(new GridBagLayout());
+ int i = 0;
+ int rowPos = 0;
+ for (Map.Entry<String, String> entry : data.entrySet()) {
+ rowPos = 2 * i + 1;
+ JLabel label = new JLabel(entry.getKey());
+ JTextField text = new JTextField(entry.getValue());
+ text.setEditable(false);
+ GridBagConstraints c1 = new GridBagConstraints();
+ c1.gridx = 0;
+ c1.gridy = rowPos;
+ c1.gridwidth = 1;
+ c1.gridheight = 1;
+ c1.weightx = 0;
+ c1.weighty = 0;
+ c1.anchor = GridBagConstraints.WEST;
+ c1.fill = GridBagConstraints.HORIZONTAL;
+ c1.insets = new Insets(5, 5, 5, 5);
+ c1.ipadx = 0;
+ c1.ipady = 0;
+ infoPanel.add(label, c1);
+ GridBagConstraints c2 = new GridBagConstraints();
+ c2.gridx = 2;
+ c2.gridy = rowPos;
+ c2.gridwidth = 1;
+ c2.gridheight = 1;
+ c2.weightx = 0;
+ c2.weighty = 0;
+ c2.anchor = GridBagConstraints.WEST;
+ c2.fill = GridBagConstraints.HORIZONTAL;
+ c2.insets = new Insets(5, 5, 5, 5);
+ c2.ipadx = 0;
+ c2.ipady = 0;
+ infoPanel.add(text, c2);
+ i++;
+ }
+ GridBagConstraints c = new GridBagConstraints();
+ c.gridx = 1;
+ c.gridy = rowPos;
+ c.gridwidth = 1;
+ c.gridheight = 1;
+ c.weightx = 1;
+ c.weighty = 1;
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill = GridBagConstraints.NONE;
+ c.insets = new Insets(5, 5, 5, 5);
+ c.ipadx = 0;
+ c.ipady = 0;
+ NodeViewerMetaData.this.metaDataPanel.add(infoPanel, c);
+ NodeViewerMetaData.this.metaDataPanel.revalidate();
+ NodeViewerMetaData.this.metaDataPanel.repaint();
+ }
+ };
+ worker.execute();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
+ * setZooInspectorManager
+ * (org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager)
+ */
+ @Override
+ public void setZooInspectorManager(
+ ZooInspectorNodeManager zooInspectorManager) {
+ this.zooInspectorManager = zooInspectorManager;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/eab8c1eb/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/nodeviewer/ZooInspectorNodeViewer.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/nodeviewer/ZooInspectorNodeViewer.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/nodeviewer/ZooInspectorNodeViewer.java
new file mode 100644
index 0000000..32119a8
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/nodeviewer/ZooInspectorNodeViewer.java
@@ -0,0 +1,138 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.gui.nodeviewer;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+import java.util.List;
+
+import javax.swing.JPanel;
+
+import org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager;
+
+/**
+ * A {@link JPanel} for displaying information about the currently selected
+ * node(s)
+ */
+public abstract class ZooInspectorNodeViewer extends JPanel implements
+ Transferable {
+ /**
+ * The {@link DataFlavor} used for DnD in the node viewer configuration
+ * dialog
+ */
+ public static final DataFlavor nodeViewerDataFlavor = new DataFlavor(
+ ZooInspectorNodeViewer.class, "nodeviewer");
+
+ /**
+ * @param zooInspectorManager
+ */
+ public abstract void setZooInspectorManager(
+ ZooInspectorNodeManager zooInspectorManager);
+
+ /**
+ * Called whenever the selected nodes in the tree view changes.
+ *
+ * @param selectedNodes
+ * - the nodes currently selected in the tree view
+ *
+ */
+ public abstract void nodeSelectionChanged(List<String> selectedNodes);
+
+ /**
+ * @return the title of the node viewer. this will be shown on the tab for
+ * this node viewer.
+ */
+ public abstract String getTitle();
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * java.awt.datatransfer.Transferable#getTransferData(java.awt.datatransfer
+ * .DataFlavor)
+ */
+ public Object getTransferData(DataFlavor flavor)
+ throws UnsupportedFlavorException, IOException {
+ if (flavor.equals(nodeViewerDataFlavor)) {
+ return this.getClass().getCanonicalName();
+ } else {
+ return null;
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.awt.datatransfer.Transferable#getTransferDataFlavors()
+ */
+ public DataFlavor[] getTransferDataFlavors() {
+ return new DataFlavor[] { nodeViewerDataFlavor };
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seejava.awt.datatransfer.Transferable#isDataFlavorSupported(java.awt.
+ * datatransfer.DataFlavor)
+ */
+ public boolean isDataFlavorSupported(DataFlavor flavor) {
+ return flavor.equals(nodeViewerDataFlavor);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + ((getTitle() == null) ? 0 : getTitle().hashCode());
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ZooInspectorNodeViewer other = (ZooInspectorNodeViewer) obj;
+ if (getClass().getCanonicalName() != other.getClass()
+ .getCanonicalName()) {
+ return false;
+ }
+ if (getTitle() == null) {
+ if (other.getTitle() != null)
+ return false;
+ } else if (!getTitle().equals(other.getTitle()))
+ return false;
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/eab8c1eb/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/logger/LoggerFactory.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/logger/LoggerFactory.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/logger/LoggerFactory.java
new file mode 100644
index 0000000..e4fae41
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/logger/LoggerFactory.java
@@ -0,0 +1,36 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.logger;
+
+/**
+ * Provides a {@link Logger} for use across the entire application
+ *
+ */
+public class LoggerFactory
+{
+ private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger("org.apache.zookeeper.inspector"); //$NON-NLS-1$
+
+ /**
+ * @return {@link Logger} for ZooInspector
+ */
+ public static org.slf4j.Logger getLogger()
+ {
+ return logger;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/eab8c1eb/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/NodeListener.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/NodeListener.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/NodeListener.java
new file mode 100644
index 0000000..fe55a45
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/NodeListener.java
@@ -0,0 +1,37 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.manager;
+
+import java.util.Map;
+
+/**
+ * A Listener for Events on zookeeper nodes
+ */
+public interface NodeListener {
+ /**
+ * @param nodePath
+ * - the path of the node
+ * @param eventType
+ * - the event type
+ * @param eventInfo
+ * - a {@link Map} containing any other information about this
+ * event
+ */
+ public void processEvent(String nodePath, String eventType,
+ Map<String, String> eventInfo);
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/eab8c1eb/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/NodesCache.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/NodesCache.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/NodesCache.java
new file mode 100644
index 0000000..45c5a27
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/NodesCache.java
@@ -0,0 +1,86 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.manager;
+
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.data.Stat;
+import org.apache.zookeeper.inspector.logger.LoggerFactory;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+public class NodesCache {
+
+ public static final int CACHE_SIZE = 40000;
+
+ public static final int EXPIRATION_TIME = 100;
+
+ private final LoadingCache<String, List<String>> nodes;
+
+ private ZooKeeper zooKeeper;
+
+ public NodesCache(ZooKeeper zooKeeper) {
+ this.zooKeeper = zooKeeper;
+ this.nodes = CacheBuilder.newBuilder()
+ .maximumSize(CACHE_SIZE)
+ .expireAfterWrite(EXPIRATION_TIME, TimeUnit.MILLISECONDS)
+ .build(
+ new CacheLoader<String, List<String>>() {
+ @Override
+ public List<String> load(String nodePath) throws Exception {
+ return getChildren(nodePath);
+ }
+ }
+ );
+ }
+
+ public List<String> getChildren(String nodePath) {
+ try {
+ Stat s = zooKeeper.exists(nodePath, false);
+ if (s != null) {
+ List<String> children = this.zooKeeper.getChildren(nodePath, false);
+ Collections.sort(children);
+ return children;
+ }
+ } catch (Exception e) {
+ LoggerFactory.getLogger().error(
+ "Error occurred retrieving child of node: " + nodePath, e
+ );
+ }
+ return null;
+ }
+
+ public String getNodeChild(String nodePath, int index) {
+ List<String> childNodes = null;
+ try {
+ childNodes = nodes.get(nodePath);
+ return childNodes.get(index);
+ } catch (ExecutionException e) {
+ LoggerFactory.getLogger().error(
+ "Error occurred retrieving child " + index + "of node: " + nodePath, e
+ );
+ }
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/eab8c1eb/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/Pair.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/Pair.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/Pair.java
new file mode 100644
index 0000000..b72950c
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/Pair.java
@@ -0,0 +1,120 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.manager;
+
+/**
+ * A utility class for storing a pair of objects
+ *
+ * @param <K>
+ * @param <V>
+ */
+public class Pair<K, V> {
+ private K key;
+ private V value;
+
+ /**
+ * @param key
+ * @param value
+ */
+ public Pair(K key, V value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ /**
+ *
+ */
+ public Pair() {
+ // Do Nothing
+ }
+
+ /**
+ * @return key
+ */
+ public K getKey() {
+ return key;
+ }
+
+ /**
+ * @param key
+ */
+ public void setKey(K key) {
+ this.key = key;
+ }
+
+ /**
+ * @return value
+ */
+ public V getValue() {
+ return value;
+ }
+
+ /**
+ * @param value
+ */
+ public void setValue(V value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return "Pair [" + key + ", " + value + "]";
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((key == null) ? 0 : key.hashCode());
+ result = prime * result + ((value == null) ? 0 : value.hashCode());
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Pair<?, ?> other = (Pair<?, ?>) obj;
+ if (key == null) {
+ if (other.key != null)
+ return false;
+ } else if (!key.equals(other.key))
+ return false;
+ if (value == null) {
+ if (other.value != null)
+ return false;
+ } else if (!value.equals(other.value))
+ return false;
+ return true;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/eab8c1eb/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/ZooInspectorManager.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/ZooInspectorManager.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/ZooInspectorManager.java
new file mode 100644
index 0000000..74c3cb2
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/ZooInspectorManager.java
@@ -0,0 +1,139 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.manager;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.swing.JComboBox;
+import javax.swing.JTextField;
+
+/**
+ * A Manager for all interactions between the application and the Zookeeper
+ * instance
+ */
+public interface ZooInspectorManager extends ZooInspectorNodeManager,
+ ZooInspectorNodeTreeManager {
+
+ /**
+ * @param connectionProps
+ * @return true if successfully connected
+ */
+ public boolean connect(Properties connectionProps);
+
+ /**
+ * @return true if successfully disconnected
+ */
+ public boolean disconnect();
+
+ /**
+ * @return a {@link Pair} containing the following:
+ * <ul>
+ * <li>a {@link Map} of property keys to list of possible values. If
+ * the list size is 1 the value is taken to be the default value for
+ * a {@link JTextField}. If the list size is greater than 1, the
+ * values are taken to be the possible options to show in a
+ * {@link JComboBox} with the first selected as default.</li>
+ * <li>a {@link Map} of property keys to the label to show on the UI
+ * </li>
+ * <ul>
+ *
+ */
+ public Pair<Map<String, List<String>>, Map<String, String>> getConnectionPropertiesTemplate();
+
+ /**
+ * @param selectedNodes
+ * - the nodes to add the watcher to
+ * @param nodeListener
+ * - the node listener for this watcher
+ */
+ public void addWatchers(Collection<String> selectedNodes,
+ NodeListener nodeListener);
+
+ /**
+ * @param selectedNodes
+ * - the nodes to remove the watchers from
+ */
+ public void removeWatchers(Collection<String> selectedNodes);
+
+ /**
+ * @param selectedFile
+ * - the file to load which contains the node viewers
+ * configuration
+ * @return nodeViewers - the class names of the node viewers from the
+ * configuration
+ * @throws IOException
+ * - if the configuration file cannot be loaded
+ */
+ public List<String> loadNodeViewersFile(File selectedFile)
+ throws IOException;
+
+ /**
+ * @param selectedFile
+ * - the file to save the configuration to
+ * @param nodeViewersClassNames
+ * - the class names of the node viewers
+ * @throws IOException
+ * - if the configuration file cannot be saved
+ */
+ public void saveNodeViewersFile(File selectedFile,
+ List<String> nodeViewersClassNames) throws IOException;
+
+ /**
+ * @param nodeViewersClassNames
+ * - the class names of the node viewers
+ * @throws IOException
+ * - if the default configuration file cannot be loaded
+ */
+ public void setDefaultNodeViewerConfiguration(
+ List<String> nodeViewersClassNames) throws IOException;
+
+ /**
+ * @return nodeViewers - the class names of the node viewers from the
+ * configuration
+ * @throws IOException
+ * - if the default configuration file cannot be loaded
+ */
+ List<String> getDefaultNodeViewerConfiguration() throws IOException;
+
+ /**
+ * @param connectionProps
+ * - the connection properties last used to connect to the
+ * zookeeeper instance
+ */
+ public void setLastConnectionProps(Properties connectionProps);
+
+ /**
+ * @return last connection Properties - the connection properties last used
+ * to connect to the zookeeeper instance
+ */
+ public Properties getLastConnectionProps();
+
+ /**
+ * @param props
+ * - the properties to use as the default connection settings
+ * @throws IOException
+ * - if the default configuration file cannot be saved
+ */
+ public void saveDefaultConnectionFile(Properties props) throws IOException;
+
+}
|