|
@@ -0,0 +1,852 @@
|
|
|
+/**
|
|
|
+ * 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";
|
|
|
+
|
|
|
+ private static final File defaultNodeViewersFile = new File(
|
|
|
+ "./config/defaultNodeVeiwers.cfg");
|
|
|
+ private static final File defaultConnectionFile = new File(
|
|
|
+ "./config/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;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @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);
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ ((ZooKeeperRetry) this.zooKeeper).setRetryLimit(10);
|
|
|
+ connected = ((ZooKeeperRetry) this.zooKeeper).testConnection();
|
|
|
+ return connected;
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ connected = false;
|
|
|
+ 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 }));
|
|
|
+ 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");
|
|
|
+ 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 occured 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 occured 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) {
|
|
|
+ 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);
|
|
|
+ } else {
|
|
|
+ defaultEncryptionManager = "org.apache.zookeeper.inspector.encryption.BasicDataEncryptionManager";
|
|
|
+ defaultTimeout = "5000";
|
|
|
+ defaultHosts = "localhost:2181";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * (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;
|
|
|
+ }
|
|
|
+}
|