Repository: zookeeper
Updated Branches:
refs/heads/branch-3.4 c6a9fcd15 -> 63aaf0a18
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/ZooInspectorManagerImpl.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/ZooInspectorManagerImpl.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/ZooInspectorManagerImpl.java
new file mode 100644
index 0000000..c1e826f
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/ZooInspectorManagerImpl.java
@@ -0,0 +1,884 @@
+/**
+ * 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.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.Watcher.Event.EventType;
+import org.apache.zookeeper.Watcher.Event.KeeperState;
+import org.apache.zookeeper.ZooDefs.Ids;
+import org.apache.zookeeper.ZooDefs.Perms;
+import org.apache.zookeeper.data.ACL;
+import org.apache.zookeeper.data.Stat;
+import org.apache.zookeeper.inspector.encryption.BasicDataEncryptionManager;
+import org.apache.zookeeper.inspector.encryption.DataEncryptionManager;
+import org.apache.zookeeper.inspector.logger.LoggerFactory;
+import org.apache.zookeeper.retry.ZooKeeperRetry;
+
+/**
+ * A default implementation of {@link ZooInspectorManager} for connecting to
+ * zookeeper instances
+ */
+public class ZooInspectorManagerImpl implements ZooInspectorManager {
+ private static final String A_VERSION = "ACL Version";
+ private static final String C_TIME = "Creation Time";
+ private static final String C_VERSION = "Children Version";
+ private static final String CZXID = "Creation ID";
+ private static final String DATA_LENGTH = "Data Length";
+ private static final String EPHEMERAL_OWNER = "Ephemeral Owner";
+ private static final String M_TIME = "Last Modified Time";
+ private static final String MZXID = "Modified ID";
+ private static final String NUM_CHILDREN = "Number of Children";
+ private static final String PZXID = "Node ID";
+ private static final String VERSION = "Data Version";
+ private static final String ACL_PERMS = "Permissions";
+ private static final String ACL_SCHEME = "Scheme";
+ private static final String ACL_ID = "Id";
+ private static final String SESSION_STATE = "Session State";
+ private static final String SESSION_ID = "Session ID";
+ /**
+ * The key used for the connect string in the connection properties file
+ */
+ public static final String CONNECT_STRING = "hosts";
+ /**
+ * The key used for the session timeout in the connection properties file
+ */
+ public static final String SESSION_TIMEOUT = "timeout";
+ /**
+ * The key used for the data encryption manager in the connection properties
+ * file
+ */
+ public static final String DATA_ENCRYPTION_MANAGER = "encryptionManager";
+ /**
+ * The key used for the authentication scheme in the connection properties file
+ */
+ public static final String AUTH_SCHEME_KEY = "authScheme";
+ /**
+ * The key used for the authentication data in the connection properties file
+ */
+ public static final String AUTH_DATA_KEY = "authData";
+
+ private static final File defaultNodeViewersFile = new File(
+ "./src/main/resources/defaultNodeViewers.cfg");
+ private static final File defaultConnectionFile = new File(
+ "./src/main/resources/defaultConnectionSettings.cfg");
+
+ private DataEncryptionManager encryptionManager;
+ private String connectString;
+ private int sessionTimeout;
+ private ZooKeeper zooKeeper;
+ private final Map<String, NodeWatcher> watchers = new HashMap<String, NodeWatcher>();
+ protected boolean connected = true;
+ private Properties lastConnectionProps;
+ private String defaultEncryptionManager;
+ private String defaultTimeout;
+ private String defaultHosts;
+ private String defaultAuthScheme;
+ private String defaultAuthValue;
+
+ /**
+ * @throws IOException
+ * - thrown if the default connection settings cannot be loaded
+ *
+ */
+ public ZooInspectorManagerImpl() throws IOException {
+ loadDefaultConnectionFile();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.zookeeper.inspector.manager.ZooInspectorManager#connect(java
+ * .util.Properties)
+ */
+ public boolean connect(Properties connectionProps) {
+ try {
+ if (this.zooKeeper == null) {
+ String connectString = connectionProps
+ .getProperty(CONNECT_STRING);
+ String sessionTimeout = connectionProps
+ .getProperty(SESSION_TIMEOUT);
+ String encryptionManager = connectionProps
+ .getProperty(DATA_ENCRYPTION_MANAGER);
+ String authScheme = connectionProps
+ .getProperty(AUTH_SCHEME_KEY);
+ String authData = connectionProps
+ .getProperty(AUTH_DATA_KEY);
+
+ if (connectString == null || sessionTimeout == null) {
+ throw new IllegalArgumentException(
+ "Both connect string and session timeout are required.");
+ }
+ if (encryptionManager == null) {
+ this.encryptionManager = new BasicDataEncryptionManager();
+ } else {
+ Class<?> clazz = Class.forName(encryptionManager);
+
+ if (Arrays.asList(clazz.getInterfaces()).contains(
+ DataEncryptionManager.class)) {
+ this.encryptionManager = (DataEncryptionManager) Class
+ .forName(encryptionManager).newInstance();
+ } else {
+ throw new IllegalArgumentException(
+ "Data encryption manager must implement DataEncryptionManager interface");
+ }
+ }
+ this.connectString = connectString;
+ this.sessionTimeout = Integer.valueOf(sessionTimeout);
+ this.zooKeeper = new ZooKeeperRetry(connectString, Integer
+ .valueOf(sessionTimeout), new Watcher() {
+
+ public void process(WatchedEvent event) {
+ if (event.getState() == KeeperState.Expired) {
+ connected = false;
+ }
+ }
+ });
+ if (authData != null && authData.length() > 0){
+ this.zooKeeper.addAuthInfo(authScheme, authData.getBytes());
+ }
+ ((ZooKeeperRetry) this.zooKeeper).setRetryLimit(10);
+ connected = ((ZooKeeperRetry) this.zooKeeper).testConnection();
+ }
+ } catch (Exception e) {
+ connected = false;
+ e.printStackTrace();
+ }
+ if (!connected){
+ disconnect();
+ }
+ return connected;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.zookeeper.inspector.manager.ZooInspectorManager#disconnect()
+ */
+ public boolean disconnect() {
+ try {
+ if (this.zooKeeper != null) {
+ this.zooKeeper.close();
+ this.zooKeeper = null;
+ connected = false;
+ removeWatchers(this.watchers.keySet());
+ return true;
+ }
+ } catch (Exception e) {
+ LoggerFactory.getLogger().error(
+ "Error occurred while disconnecting from ZooKeeper server",
+ e);
+ }
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorReadOnlyManager#
+ * getChildren(java.lang.String)
+ */
+ public List<String> getChildren(String nodePath) {
+ if (connected) {
+ try {
+
+ return zooKeeper.getChildren(nodePath, false);
+ } catch (Exception e) {
+ LoggerFactory.getLogger().error(
+ "Error occurred retrieving children of node: "
+ + nodePath, e);
+ }
+ }
+ return null;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.zookeeper.inspector.manager.ZooInspectorReadOnlyManager#getData
+ * (java.lang.String)
+ */
+ public String getData(String nodePath) {
+ if (connected) {
+ try {
+ if (nodePath.length() == 0) {
+ nodePath = "/";
+ }
+ Stat s = zooKeeper.exists(nodePath, false);
+ if (s != null) {
+ return this.encryptionManager.decryptData(zooKeeper
+ .getData(nodePath, false, s));
+ }
+ } catch (Exception e) {
+ LoggerFactory.getLogger().error(
+ "Error occurred getting data for node: " + nodePath, e);
+ }
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorReadOnlyManager#
+ * getNodeChild(java.lang.String, int)
+ */
+ public String getNodeChild(String nodePath, int childIndex) {
+ if (connected) {
+ try {
+ Stat s = zooKeeper.exists(nodePath, false);
+ if (s != null) {
+ return this.zooKeeper.getChildren(nodePath, false).get(
+ childIndex);
+ }
+ } catch (Exception e) {
+ LoggerFactory.getLogger().error(
+ "Error occurred retrieving child " + childIndex
+ + " of node: " + nodePath, e);
+ }
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorReadOnlyManager#
+ * getNodeIndex(java.lang.String)
+ */
+ public int getNodeIndex(String nodePath) {
+ if (connected) {
+ int index = nodePath.lastIndexOf("/");
+ if (index == -1
+ || (!nodePath.equals("/") && nodePath.charAt(nodePath
+ .length() - 1) == '/')) {
+ throw new IllegalArgumentException("Invalid node path: "
+ + nodePath);
+ }
+ String parentPath = nodePath.substring(0, index);
+ String child = nodePath.substring(index + 1);
+ if (parentPath != null && parentPath.length() > 0) {
+ List<String> children = this.getChildren(parentPath);
+ if (children != null) {
+ return children.indexOf(child);
+ }
+ }
+ }
+ return -1;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.zookeeper.inspector.manager.ZooInspectorReadOnlyManager#getACLs
+ * (java.lang.String)
+ */
+ public List<Map<String, String>> getACLs(String nodePath) {
+ List<Map<String, String>> returnACLs = new ArrayList<Map<String, String>>();
+ if (connected) {
+ try {
+ if (nodePath.length() == 0) {
+ nodePath = "/";
+ }
+ Stat s = zooKeeper.exists(nodePath, false);
+ if (s != null) {
+ List<ACL> acls = zooKeeper.getACL(nodePath, s);
+ for (ACL acl : acls) {
+ Map<String, String> aclMap = new LinkedHashMap<String, String>();
+ aclMap.put(ACL_SCHEME, acl.getId().getScheme());
+ aclMap.put(ACL_ID, acl.getId().getId());
+ StringBuilder sb = new StringBuilder();
+ int perms = acl.getPerms();
+ boolean addedPerm = false;
+ if ((perms & Perms.READ) == Perms.READ) {
+ sb.append("Read");
+ addedPerm = true;
+ }
+ if (addedPerm) {
+ sb.append(", ");
+ }
+ if ((perms & Perms.WRITE) == Perms.WRITE) {
+ sb.append("Write");
+ addedPerm = true;
+ }
+ if (addedPerm) {
+ sb.append(", ");
+ }
+ if ((perms & Perms.CREATE) == Perms.CREATE) {
+ sb.append("Create");
+ addedPerm = true;
+ }
+ if (addedPerm) {
+ sb.append(", ");
+ }
+ if ((perms & Perms.DELETE) == Perms.DELETE) {
+ sb.append("Delete");
+ addedPerm = true;
+ }
+ if (addedPerm) {
+ sb.append(", ");
+ }
+ if ((perms & Perms.ADMIN) == Perms.ADMIN) {
+ sb.append("Admin");
+ addedPerm = true;
+ }
+ aclMap.put(ACL_PERMS, sb.toString());
+ returnACLs.add(aclMap);
+ }
+ }
+ } catch (InterruptedException e) {
+ LoggerFactory.getLogger().error(
+ "Error occurred retrieving ACLs of node: " + nodePath,
+ e);
+ } catch (KeeperException e) {
+ LoggerFactory.getLogger().error(
+ "Error occurred retrieving ACLs of node: " + nodePath,
+ e);
+ }
+ }
+ return returnACLs;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorReadOnlyManager#
+ * getNodeMeta(java.lang.String)
+ */
+ public Map<String, String> getNodeMeta(String nodePath) {
+ Map<String, String> nodeMeta = new LinkedHashMap<String, String>();
+ if (connected) {
+ try {
+ if (nodePath.length() == 0) {
+ nodePath = "/";
+ }
+ Stat s = zooKeeper.exists(nodePath, false);
+ if (s != null) {
+ nodeMeta.put(A_VERSION, String.valueOf(s.getAversion()));
+ nodeMeta.put(C_TIME, String.valueOf(s.getCtime()));
+ nodeMeta.put(C_VERSION, String.valueOf(s.getCversion()));
+ nodeMeta.put(CZXID, String.valueOf(s.getCzxid()));
+ nodeMeta
+ .put(DATA_LENGTH, String.valueOf(s.getDataLength()));
+ nodeMeta.put(EPHEMERAL_OWNER, String.valueOf(s
+ .getEphemeralOwner()));
+ nodeMeta.put(M_TIME, String.valueOf(s.getMtime()));
+ nodeMeta.put(MZXID, String.valueOf(s.getMzxid()));
+ nodeMeta.put(NUM_CHILDREN, String.valueOf(s
+ .getNumChildren()));
+ nodeMeta.put(PZXID, String.valueOf(s.getPzxid()));
+ nodeMeta.put(VERSION, String.valueOf(s.getVersion()));
+ }
+ } catch (Exception e) {
+ LoggerFactory.getLogger().error(
+ "Error occurred retrieving meta data for node: "
+ + nodePath, e);
+ }
+ }
+ return nodeMeta;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorReadOnlyManager#
+ * getNumChildren(java.lang.String)
+ */
+ public int getNumChildren(String nodePath) {
+ if (connected) {
+ try {
+ Stat s = zooKeeper.exists(nodePath, false);
+ if (s != null) {
+ return s.getNumChildren();
+ }
+ } catch (Exception e) {
+ LoggerFactory.getLogger().error(
+ "Error occurred getting the number of children of node: "
+ + nodePath, e);
+ }
+ }
+ return -1;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorReadOnlyManager#
+ * hasChildren(java.lang.String)
+ */
+ public boolean hasChildren(String nodePath) {
+ return getNumChildren(nodePath) > 0;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorReadOnlyManager#
+ * isAllowsChildren(java.lang.String)
+ */
+ public boolean isAllowsChildren(String nodePath) {
+ if (connected) {
+ try {
+ Stat s = zooKeeper.exists(nodePath, false);
+ if (s != null) {
+ return s.getEphemeralOwner() == 0;
+ }
+ } catch (Exception e) {
+ LoggerFactory.getLogger().error(
+ "Error occurred determining whether node is allowed children: "
+ + nodePath, e);
+ }
+ }
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorReadOnlyManager#
+ * getSessionMeta()
+ */
+ public Map<String, String> getSessionMeta() {
+ Map<String, String> sessionMeta = new LinkedHashMap<String, String>();
+ try {
+ if (zooKeeper != null) {
+
+ sessionMeta.put(SESSION_ID, String.valueOf(zooKeeper
+ .getSessionId()));
+ sessionMeta.put(SESSION_STATE, String.valueOf(zooKeeper
+ .getState().toString()));
+ sessionMeta.put(CONNECT_STRING, this.connectString);
+ sessionMeta.put(SESSION_TIMEOUT, String
+ .valueOf(this.sessionTimeout));
+ }
+ } catch (Exception e) {
+ LoggerFactory.getLogger().error(
+ "Error occurred retrieving session meta data.", e);
+ }
+ return sessionMeta;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.zookeeper.inspector.manager.ZooInspectorNodeTreeManager#createNode
+ * (java.lang.String, java.lang.String)
+ */
+ public boolean createNode(String parent, String nodeName) {
+ if (connected) {
+ try {
+ String[] nodeElements = nodeName.split("/");
+ for (String nodeElement : nodeElements) {
+ String node = parent + "/" + nodeElement;
+ Stat s = zooKeeper.exists(node, false);
+ if (s == null) {
+ zooKeeper.create(node, this.encryptionManager
+ .encryptData(null), Ids.OPEN_ACL_UNSAFE,
+ CreateMode.PERSISTENT);
+ parent = node;
+ }
+ }
+ return true;
+ } catch (Exception e) {
+ LoggerFactory.getLogger().error(
+ "Error occurred creating node: " + parent + "/"
+ + nodeName, e);
+ }
+ }
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.zookeeper.inspector.manager.ZooInspectorNodeTreeManager#deleteNode
+ * (java.lang.String)
+ */
+ public boolean deleteNode(String nodePath) {
+ if (connected) {
+ try {
+ Stat s = zooKeeper.exists(nodePath, false);
+ if (s != null) {
+ List<String> children = zooKeeper.getChildren(nodePath,
+ false);
+ for (String child : children) {
+ String node = nodePath + "/" + child;
+ deleteNode(node);
+ }
+ zooKeeper.delete(nodePath, -1);
+ }
+ return true;
+ } catch (Exception e) {
+ LoggerFactory.getLogger().error(
+ "Error occurred deleting node: " + nodePath, e);
+ }
+ }
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager#setData
+ * (java.lang.String, java.lang.String)
+ */
+ public boolean setData(String nodePath, String data) {
+ if (connected) {
+ try {
+ zooKeeper.setData(nodePath, this.encryptionManager
+ .encryptData(data), -1);
+ return true;
+ } catch (Exception e) {
+ LoggerFactory.getLogger().error(
+ "Error occurred setting data for node: " + nodePath, e);
+ }
+ }
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorManager#
+ * getConnectionPropertiesTemplate()
+ */
+ public Pair<Map<String, List<String>>, Map<String, String>> getConnectionPropertiesTemplate() {
+ Map<String, List<String>> template = new LinkedHashMap<String, List<String>>();
+ template.put(CONNECT_STRING, Arrays
+ .asList(new String[] { defaultHosts }));
+ template.put(SESSION_TIMEOUT, Arrays
+ .asList(new String[] { defaultTimeout }));
+ template.put(DATA_ENCRYPTION_MANAGER, Arrays
+ .asList(new String[] { defaultEncryptionManager }));
+ template.put(AUTH_SCHEME_KEY, Arrays
+ .asList(new String[] { defaultAuthScheme }));
+ template.put(AUTH_DATA_KEY, Arrays
+ .asList(new String[] { defaultAuthValue }));
+ Map<String, String> labels = new LinkedHashMap<String, String>();
+ labels.put(CONNECT_STRING, "Connect String");
+ labels.put(SESSION_TIMEOUT, "Session Timeout");
+ labels.put(DATA_ENCRYPTION_MANAGER, "Data Encryption Manager");
+ labels.put(AUTH_SCHEME_KEY, "Authentication Scheme");
+ labels.put(AUTH_DATA_KEY, "Authentication Data");
+ return new Pair<Map<String, List<String>>, Map<String, String>>(
+ template, labels);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.zookeeper.inspector.manager.ZooInspectorManager#addWatchers
+ * (java.util.Collection,
+ * org.apache.zookeeper.inspector.manager.NodeListener)
+ */
+ public void addWatchers(Collection<String> selectedNodes,
+ NodeListener nodeListener) {
+ // add watcher for each node and add node to collection of
+ // watched nodes
+ if (connected) {
+ for (String node : selectedNodes) {
+ if (!watchers.containsKey(node)) {
+ try {
+ watchers.put(node, new NodeWatcher(node, nodeListener,
+ zooKeeper));
+ } catch (Exception e) {
+ LoggerFactory.getLogger().error(
+ "Error occurred adding node watcher for node: "
+ + node, e);
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.zookeeper.inspector.manager.ZooInspectorManager#removeWatchers
+ * (java.util.Collection)
+ */
+ public void removeWatchers(Collection<String> selectedNodes) {
+ // remove watcher for each node and remove node from
+ // collection of watched nodes
+ if (connected) {
+ for (String node : selectedNodes) {
+ if (watchers.containsKey(node)) {
+ NodeWatcher watcher = watchers.remove(node);
+ if (watcher != null) {
+ watcher.stop();
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * A Watcher which will re-add itself every time an event is fired
+ *
+ */
+ public class NodeWatcher implements Watcher {
+
+ private final String nodePath;
+ private final NodeListener nodeListener;
+ private final ZooKeeper zookeeper;
+ private boolean closed = false;
+
+ /**
+ * @param nodePath
+ * - the path to the node to watch
+ * @param nodeListener
+ * the {@link NodeListener} for this node
+ * @param zookeeper
+ * - a {@link ZooKeeper} to use to access zookeeper
+ * @throws InterruptedException
+ * @throws KeeperException
+ */
+ public NodeWatcher(String nodePath, NodeListener nodeListener,
+ ZooKeeper zookeeper) throws KeeperException,
+ InterruptedException {
+ this.nodePath = nodePath;
+ this.nodeListener = nodeListener;
+ this.zookeeper = zookeeper;
+ Stat s = zooKeeper.exists(nodePath, this);
+ if (s != null) {
+ zookeeper.getChildren(nodePath, this);
+ }
+ }
+
+ public void process(WatchedEvent event) {
+ if (!closed) {
+ try {
+ if (event.getType() != EventType.NodeDeleted) {
+
+ Stat s = zooKeeper.exists(nodePath, this);
+ if (s != null) {
+ zookeeper.getChildren(nodePath, this);
+ }
+ }
+ } catch (Exception e) {
+ LoggerFactory.getLogger().error(
+ "Error occurred re-adding node watcherfor node "
+ + nodePath, e);
+ }
+ nodeListener.processEvent(event.getPath(), event.getType()
+ .name(), null);
+ }
+ }
+
+ /**
+ *
+ */
+ public void stop() {
+ this.closed = true;
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorManager#
+ * loadNodeViewersFile(java.io.File)
+ */
+ public List<String> loadNodeViewersFile(File selectedFile)
+ throws IOException {
+ List<String> result = new ArrayList<String>();
+ if (defaultNodeViewersFile.exists()) {
+ FileReader reader = new FileReader(selectedFile);
+ try {
+ BufferedReader buff = new BufferedReader(reader);
+ try {
+ while (buff.ready()) {
+ String line = buff.readLine();
+ if (line != null && line.length() > 0 && !line.startsWith("#")) {
+ result.add(line);
+ }
+ }
+ } finally {
+ buff.close();
+ }
+ } finally {
+ reader.close();
+ }
+ }
+ return result;
+ }
+
+ private void loadDefaultConnectionFile() throws IOException {
+ if (defaultConnectionFile.exists()) {
+ Properties props = new Properties();
+
+ FileReader reader = new FileReader(defaultConnectionFile);
+ try {
+ props.load(reader);
+ } finally {
+ reader.close();
+ }
+ defaultEncryptionManager = props
+ .getProperty(DATA_ENCRYPTION_MANAGER) == null ? "org.apache.zookeeper.inspector.encryption.BasicDataEncryptionManager"
+ : props.getProperty(DATA_ENCRYPTION_MANAGER);
+ defaultTimeout = props.getProperty(SESSION_TIMEOUT) == null ? "5000"
+ : props.getProperty(SESSION_TIMEOUT);
+ defaultHosts = props.getProperty(CONNECT_STRING) == null ? "localhost:2181"
+ : props.getProperty(CONNECT_STRING);
+ defaultAuthScheme = props.getProperty(AUTH_SCHEME_KEY) == null ? ""
+ : props.getProperty(AUTH_SCHEME_KEY);
+ defaultAuthValue = props.getProperty(AUTH_DATA_KEY) == null ? ""
+ : props.getProperty(AUTH_DATA_KEY);
+ } else {
+ defaultEncryptionManager = "org.apache.zookeeper.inspector.encryption.BasicDataEncryptionManager";
+ defaultTimeout = "5000";
+ defaultHosts = "localhost:2181";
+ defaultAuthScheme = "";
+ defaultAuthValue = "";
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorManager#
+ * saveDefaultConnectionFile(java.util.Properties)
+ */
+ public void saveDefaultConnectionFile(Properties props) throws IOException {
+ File defaultDir = defaultConnectionFile.getParentFile();
+ if (!defaultDir.exists()) {
+ if (!defaultDir.mkdirs()) {
+ throw new IOException(
+ "Failed to create configuration directory: "
+ + defaultDir.getAbsolutePath());
+ }
+ }
+ if (!defaultConnectionFile.exists()) {
+ if (!defaultConnectionFile.createNewFile()) {
+ throw new IOException(
+ "Failed to create default connection file: "
+ + defaultConnectionFile.getAbsolutePath());
+ }
+ }
+ FileWriter writer = new FileWriter(defaultConnectionFile);
+ try {
+ props.store(writer, "Default connection for ZooInspector");
+ } finally {
+ writer.close();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorManager#
+ * saveNodeViewersFile(java.io.File, java.util.List)
+ */
+ public void saveNodeViewersFile(File selectedFile,
+ List<String> nodeViewersClassNames) throws IOException {
+ if (!selectedFile.exists()) {
+ if (!selectedFile.createNewFile()) {
+ throw new IOException(
+ "Failed to create node viewers configuration file: "
+ + selectedFile.getAbsolutePath());
+ }
+ }
+ FileWriter writer = new FileWriter(selectedFile);
+ try {
+ BufferedWriter buff = new BufferedWriter(writer);
+ try {
+ for (String nodeViewersClassName : nodeViewersClassNames) {
+ buff.append(nodeViewersClassName);
+ buff.append("\n");
+ }
+ } finally {
+ buff.flush();
+ buff.close();
+ }
+ } finally {
+ writer.close();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorManager#
+ * setDefaultNodeViewerConfiguration(java.io.File, java.util.List)
+ */
+ public void setDefaultNodeViewerConfiguration(
+ List<String> nodeViewersClassNames) throws IOException {
+ File defaultDir = defaultNodeViewersFile.getParentFile();
+ if (!defaultDir.exists()) {
+ if (!defaultDir.mkdirs()) {
+ throw new IOException(
+ "Failed to create configuration directory: "
+ + defaultDir.getAbsolutePath());
+ }
+ }
+ saveNodeViewersFile(defaultNodeViewersFile, nodeViewersClassNames);
+ }
+
+ public List<String> getDefaultNodeViewerConfiguration() throws IOException {
+ return loadNodeViewersFile(defaultNodeViewersFile);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorManager#
+ * getLastConnectionProps()
+ */
+ public Properties getLastConnectionProps() {
+ return this.lastConnectionProps;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorManager#
+ * setLastConnectionProps(java.util.Properties)
+ */
+ public void setLastConnectionProps(Properties connectionProps) {
+ this.lastConnectionProps = connectionProps;
+ }
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/ZooInspectorNodeManager.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/ZooInspectorNodeManager.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/ZooInspectorNodeManager.java
new file mode 100644
index 0000000..0c62547
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/ZooInspectorNodeManager.java
@@ -0,0 +1,33 @@
+/**
+ * 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 Manager for all interactions between the application and the nodes in a
+ * Zookeeper instance
+ * */
+public interface ZooInspectorNodeManager extends ZooInspectorReadOnlyManager {
+ /**
+ * @param nodePath
+ * - the path to the node on which to set the data
+ * @param data
+ * - the data to set on the this node
+ * @return true if the data for the node was successfully updated
+ */
+ public boolean setData(String nodePath, String data);
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/ZooInspectorNodeTreeManager.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/ZooInspectorNodeTreeManager.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/ZooInspectorNodeTreeManager.java
new file mode 100644
index 0000000..9718c1d
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/ZooInspectorNodeTreeManager.java
@@ -0,0 +1,43 @@
+/**
+ * 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 Manager for all interactions between the application and the node tree in a
+ * Zookeeper instance
+ */
+public interface ZooInspectorNodeTreeManager extends
+ ZooInspectorReadOnlyManager {
+
+ /**
+ * @param parent
+ * - the parent node path for the node to add
+ * @param nodeName
+ * - the name of the new node
+ * @return true if the node was successfully created
+ */
+ public abstract boolean createNode(String parent, String nodeName);
+
+ /**
+ * @param nodePath
+ * - the path to the node to delete
+ * @return true if the node was successfully deleted
+ */
+ public abstract boolean deleteNode(String nodePath);
+
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/ZooInspectorReadOnlyManager.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/ZooInspectorReadOnlyManager.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/ZooInspectorReadOnlyManager.java
new file mode 100644
index 0000000..d9fdf5c
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/manager/ZooInspectorReadOnlyManager.java
@@ -0,0 +1,99 @@
+/**
+ * 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.List;
+import java.util.Map;
+
+/**
+ * A Manager for all read only interactions between the application and a node
+ * in a Zookeeper instance
+ */
+public interface ZooInspectorReadOnlyManager {
+
+ /**
+ * @param nodePath
+ * - the path to the node to delete
+ * @return the data for the node
+ */
+ public abstract String getData(String nodePath);
+
+ /**
+ * @param nodePath
+ * - the path to the node to delete
+ * @return the metaData for the node
+ */
+ public abstract Map<String, String> getNodeMeta(String nodePath);
+
+ /**
+ * @param nodePath
+ * - the path to the node to delete
+ * @return the ACLs set on the node
+ */
+ public abstract List<Map<String, String>> getACLs(String nodePath);
+
+ /**
+ * @return the metaData for the current session
+ */
+ public abstract Map<String, String> getSessionMeta();
+
+ /**
+ * @param nodePath
+ * - the path to the node to delete
+ * @return true if the node has children
+ */
+ public abstract boolean hasChildren(String nodePath);
+
+ /**
+ * @param nodePath
+ * - the path to the node to delete
+ * @return the index of the node within its siblings
+ */
+ public abstract int getNodeIndex(String nodePath);
+
+ /**
+ * @param nodePath
+ * - the path to the node to delete
+ * @return the number of children of the node
+ */
+ public abstract int getNumChildren(String nodePath);
+
+ /**
+ * @param nodePath
+ * - the path to the node to delete
+ * @param childIndex
+ * - the index to the node in the list of node children
+ * @return the path to the node for the child of the nodePath at childIndex
+ */
+ public abstract String getNodeChild(String nodePath, int childIndex);
+
+ /**
+ * @param nodePath
+ * - the path to the node to delete
+ * @return true if the node allows children nodes
+ */
+ public abstract boolean isAllowsChildren(String nodePath);
+
+ /**
+ * @param nodePath
+ * - the path to the node to delete
+ * @return a {@link List} of the children of the node
+ */
+ public abstract List<String> getChildren(String nodePath);
+
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/retry/ZooKeeperRetry.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/retry/ZooKeeperRetry.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/retry/ZooKeeperRetry.java
new file mode 100644
index 0000000..ce959a1
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/retry/ZooKeeperRetry.java
@@ -0,0 +1,288 @@
+/**
+ * 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.retry;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.data.ACL;
+import org.apache.zookeeper.data.Stat;
+import org.apache.zookeeper.inspector.logger.LoggerFactory;
+
+/**
+ * A Class which extends {@link ZooKeeper} and will automatically retry calls to
+ * zookeeper if a {@link KeeperException.ConnectionLossException} occurs
+ */
+public class ZooKeeperRetry extends ZooKeeper {
+
+ private boolean closed = false;
+ private final Watcher watcher;
+ private int limit = -1;
+
+ /**
+ * @param connectString
+ * @param sessionTimeout
+ * @param watcher
+ * @throws IOException
+ */
+ public ZooKeeperRetry(String connectString, int sessionTimeout,
+ Watcher watcher) throws IOException {
+ super(connectString, sessionTimeout, watcher);
+ this.watcher = watcher;
+ }
+
+ /**
+ * @param connectString
+ * @param sessionTimeout
+ * @param watcher
+ * @param sessionId
+ * @param sessionPasswd
+ * @throws IOException
+ */
+ public ZooKeeperRetry(String connectString, int sessionTimeout,
+ Watcher watcher, long sessionId, byte[] sessionPasswd)
+ throws IOException {
+ super(connectString, sessionTimeout, watcher, sessionId, sessionPasswd);
+ this.watcher = watcher;
+ }
+
+ @Override
+ public synchronized void close() throws InterruptedException {
+ this.closed = true;
+ super.close();
+ }
+
+ @Override
+ public String create(String path, byte[] data, List<ACL> acl,
+ CreateMode createMode) throws KeeperException, InterruptedException {
+ int count = 0;
+ do {
+ try {
+ return super.create(path, data, acl, createMode);
+ } catch (KeeperException.ConnectionLossException e) {
+ LoggerFactory.getLogger().warn(
+ "ZooKeeper connection lost. Trying to reconnect.");
+ if (exists(path, false) != null) {
+ return path;
+ }
+ } catch (KeeperException.NodeExistsException e) {
+ return path;
+ }
+ } while (!closed && (limit == -1 || count++ < limit));
+ return null;
+ }
+
+ @Override
+ public void delete(String path, int version) throws InterruptedException,
+ KeeperException {
+ int count = 0;
+ do {
+ try {
+ super.delete(path, version);
+ } catch (KeeperException.ConnectionLossException e) {
+ LoggerFactory.getLogger().warn(
+ "ZooKeeper connection lost. Trying to reconnect.");
+ if (exists(path, false) == null) {
+ return;
+ }
+ } catch (KeeperException.NoNodeException e) {
+ break;
+ }
+ } while (!closed && (limit == -1 || count++ < limit));
+ }
+
+ @Override
+ public Stat exists(String path, boolean watch) throws KeeperException,
+ InterruptedException {
+ int count = 0;
+ do {
+ try {
+ return super.exists(path, watch ? watcher : null);
+ } catch (KeeperException.ConnectionLossException e) {
+ LoggerFactory.getLogger().warn(
+ "ZooKeeper connection lost. Trying to reconnect.");
+ }
+ } while (!closed && (limit == -1 || count++ < limit));
+ return null;
+ }
+
+ @Override
+ public Stat exists(String path, Watcher watcher) throws KeeperException,
+ InterruptedException {
+ int count = 0;
+ do {
+ try {
+ return super.exists(path, watcher);
+ } catch (KeeperException.ConnectionLossException e) {
+ LoggerFactory.getLogger().warn(
+ "ZooKeeper connection lost. Trying to reconnect.");
+ }
+ } while (!closed && (limit == -1 || count++ < limit));
+ return null;
+ }
+
+ @Override
+ public List<ACL> getACL(String path, Stat stat) throws KeeperException,
+ InterruptedException {
+ int count = 0;
+ do {
+ try {
+ return super.getACL(path, stat);
+ } catch (KeeperException.ConnectionLossException e) {
+ LoggerFactory.getLogger().warn(
+ "ZooKeeper connection lost. Trying to reconnect.");
+ }
+ } while (!closed && (limit == -1 || count++ < limit));
+ return null;
+ }
+
+ @Override
+ public List<String> getChildren(String path, boolean watch)
+ throws KeeperException, InterruptedException {
+ int count = 0;
+ do {
+ try {
+ return super.getChildren(path, watch ? watcher : null);
+ } catch (KeeperException.ConnectionLossException e) {
+ LoggerFactory.getLogger().warn(
+ "ZooKeeper connection lost. Trying to reconnect.");
+ }
+ } while (!closed && (limit == -1 || count++ < limit));
+ return new ArrayList<String>();
+ }
+
+ @Override
+ public List<String> getChildren(String path, Watcher watcher)
+ throws KeeperException, InterruptedException {
+ int count = 0;
+ do {
+ try {
+ return super.getChildren(path, watcher);
+ } catch (KeeperException.ConnectionLossException e) {
+ LoggerFactory.getLogger().warn(
+ "ZooKeeper connection lost. Trying to reconnect.");
+ }
+ } while (!closed && (limit == -1 || count++ < limit));
+ return new ArrayList<String>();
+ }
+
+ @Override
+ public byte[] getData(String path, boolean watch, Stat stat)
+ throws KeeperException, InterruptedException {
+ int count = 0;
+ do {
+ try {
+ return super.getData(path, watch ? watcher : null, stat);
+ } catch (KeeperException.ConnectionLossException e) {
+ LoggerFactory.getLogger().warn(
+ "ZooKeeper connection lost. Trying to reconnect.");
+ }
+ } while (!closed && (limit == -1 || count++ < limit));
+ return null;
+ }
+
+ @Override
+ public byte[] getData(String path, Watcher watcher, Stat stat)
+ throws KeeperException, InterruptedException {
+ int count = 0;
+ do {
+ try {
+ return super.getData(path, watcher, stat);
+ } catch (KeeperException.ConnectionLossException e) {
+ LoggerFactory.getLogger().warn(
+ "ZooKeeper connection lost. Trying to reconnect.");
+ }
+ } while (!closed && (limit == -1 || count++ < limit));
+ return null;
+ }
+
+ @Override
+ public Stat setACL(String path, List<ACL> acl, int aclVersion)
+ throws KeeperException, InterruptedException {
+ int count = 0;
+ do {
+ try {
+ return super.setACL(path, acl, aclVersion);
+ } catch (KeeperException.ConnectionLossException e) {
+ LoggerFactory.getLogger().warn(
+ "ZooKeeper connection lost. Trying to reconnect.");
+ Stat s = exists(path, false);
+ if (s != null) {
+ if (getACL(path, s).equals(acl)) {
+ return s;
+ }
+ } else {
+ return null;
+ }
+ }
+ } while (!closed && (limit == -1 || count++ < limit));
+ return null;
+ }
+
+ @Override
+ public Stat setData(String path, byte[] data, int version)
+ throws KeeperException, InterruptedException {
+ int count = 0;
+ do {
+ try {
+ return super.setData(path, data, version);
+ } catch (KeeperException.ConnectionLossException e) {
+ LoggerFactory.getLogger().warn(
+ "ZooKeeper connection lost. Trying to reconnect.");
+ Stat s = exists(path, false);
+ if (s != null) {
+ if (getData(path, false, s) == data) {
+ return s;
+ }
+ } else {
+ return null;
+ }
+ }
+ } while (!closed && (limit == -1 || count++ < limit));
+ return null;
+ }
+
+ /**
+ * @param limit
+ */
+ public void setRetryLimit(int limit) {
+ this.limit = limit;
+ }
+
+ /**
+ * @return true if successfully connected to zookeeper
+ */
+ public boolean testConnection() {
+ int count = 0;
+ do {
+ try {
+ return super.exists("/", null) != null;
+ } catch (Exception e) {
+ LoggerFactory.getLogger().warn(
+ "ZooKeeper connection lost. Trying to reconnect.");
+ }
+ } while (count++ < 5);
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/defaultConnectionSettings.cfg
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/defaultConnectionSettings.cfg b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/defaultConnectionSettings.cfg
new file mode 100644
index 0000000..36a34ff
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/defaultConnectionSettings.cfg
@@ -0,0 +1,21 @@
+# 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.
+#
+#Default connection for ZooInspector
+hosts=localhost\:2181
+encryptionManager=org.apache.zookeeper.inspector.encryption.BasicDataEncryptionManager
+timeout=5000
+authScheme=
+authData=
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/defaultNodeVeiwers.cfg
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/defaultNodeVeiwers.cfg b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/defaultNodeVeiwers.cfg
new file mode 100644
index 0000000..38fe9a8
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/defaultNodeVeiwers.cfg
@@ -0,0 +1,17 @@
+# 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.
+org.apache.zookeeper.inspector.gui.nodeviewer.NodeViewerData
+org.apache.zookeeper.inspector.gui.nodeviewer.NodeViewerMetaData
+org.apache.zookeeper.inspector.gui.nodeviewer.NodeViewerACL
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/edtsrclkup_co.gif
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/edtsrclkup_co.gif b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/edtsrclkup_co.gif
new file mode 100644
index 0000000..94eedf6
Binary files /dev/null and b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/edtsrclkup_co.gif differ
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/file_obj.gif
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/file_obj.gif b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/file_obj.gif
new file mode 100644
index 0000000..b226e41
Binary files /dev/null and b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/file_obj.gif differ
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/fldr_obj.gif
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/fldr_obj.gif b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/fldr_obj.gif
new file mode 100644
index 0000000..51e703b
Binary files /dev/null and b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/fldr_obj.gif differ
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/info_obj.gif
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/info_obj.gif b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/info_obj.gif
new file mode 100644
index 0000000..2da001e
Binary files /dev/null and b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/info_obj.gif differ
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/jspdecl.gif
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/jspdecl.gif b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/jspdecl.gif
new file mode 100644
index 0000000..35f48ef
Binary files /dev/null and b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/jspdecl.gif differ
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/launch_run.gif
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/launch_run.gif b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/launch_run.gif
new file mode 100644
index 0000000..57f4102
Binary files /dev/null and b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/launch_run.gif differ
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/launch_stop.gif
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/launch_stop.gif b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/launch_stop.gif
new file mode 100644
index 0000000..fbf1686
Binary files /dev/null and b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/launch_stop.gif differ
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/new_con.gif
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/new_con.gif b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/new_con.gif
new file mode 100644
index 0000000..9d05088
Binary files /dev/null and b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/new_con.gif differ
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/refresh.gif
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/refresh.gif b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/refresh.gif
new file mode 100644
index 0000000..3ca04d0
Binary files /dev/null and b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/refresh.gif differ
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/save_edit.gif
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/save_edit.gif b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/save_edit.gif
new file mode 100644
index 0000000..499dd0c
Binary files /dev/null and b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/save_edit.gif differ
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/search_next.gif
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/search_next.gif b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/search_next.gif
new file mode 100644
index 0000000..072b184
Binary files /dev/null and b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/search_next.gif differ
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/search_prev.gif
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/search_prev.gif b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/search_prev.gif
new file mode 100644
index 0000000..0716475
Binary files /dev/null and b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/search_prev.gif differ
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/trash.gif
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/trash.gif b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/trash.gif
new file mode 100644
index 0000000..5f47780
Binary files /dev/null and b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/icons/trash.gif differ
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/log4j.properties b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/log4j.properties
new file mode 100644
index 0000000..6f96d84
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/resources/log4j.properties
@@ -0,0 +1,9 @@
+# ***** Set root logger level to INFO and it appender to stdout.
+log4j.rootLogger=info, stdout
+
+# ***** stdout is set to be a ConsoleAppender.
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+# ***** stdout uses PatternLayout.
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+# ***** Pattern to output the caller's file name and line number.
+log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/zooInspector-dev.sh
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/zooInspector-dev.sh b/zookeeper-contrib/zookeeper-contrib-zooinspector/zooInspector-dev.sh
new file mode 100755
index 0000000..98a6c6e
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/zooInspector-dev.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# 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.
+
+java -cp ../../build/contrib/ZooInspector/zookeeper-dev-ZooInspector.jar:../../../build/lib/log4j-1.2.15.jar:lib/zookeeper-3.3.0.jar:lib/jtoaster-1.0.4.jar:lib org.apache.zookeeper.inspector.ZooInspector
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/zooInspector.cmd
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/zooInspector.cmd b/zookeeper-contrib/zookeeper-contrib-zooinspector/zooInspector.cmd
new file mode 100644
index 0000000..4fa3ab2
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/zooInspector.cmd
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# 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.
+
+java -cp zookeeper-dev-ZooInspector.jar;lib/log4j-1.2.15.jar;lib/zookeeper-3.3.0.jar;lib/jToaster-1.0.4.jar;lib org.apache.zookeeper.inspector.ZooInspector
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/zooInspector.sh
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/zooInspector.sh b/zookeeper-contrib/zookeeper-contrib-zooinspector/zooInspector.sh
new file mode 100755
index 0000000..b35b4ca
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/zooInspector.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# 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.
+
+java -cp lib/New.jar:zookeeper-dev-ZooInspector.jar:lib/log4j-1.2.15.jar:;lib/zookeeper-3.3.0.jar:lib/jToaster-1.0.4.jar:lib org.apache.zookeeper.inspector.ZooInspector
|