1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 package org.apache.zookeeper.inspector.manager; 19 20 import java.io.BufferedReader; 21 import java.io.BufferedWriter; 22 import java.io.File; 23 import java.io.FileNotFoundException; 24 import java.io.FileReader; 25 import java.io.FileWriter; 26 import java.io.IOException; 27 import java.io.InputStream; 28 import java.io.InputStreamReader; 29 import java.util.ArrayList; 30 import java.util.Arrays; 31 import java.util.Collection; 32 import java.util.HashMap; 33 import java.util.LinkedHashMap; 34 import java.util.List; 35 import java.util.Map; 36 import java.util.Properties; 37 38 import org.apache.zookeeper.CreateMode; 39 import org.apache.zookeeper.KeeperException; 40 import org.apache.zookeeper.WatchedEvent; 41 import org.apache.zookeeper.Watcher; 42 import org.apache.zookeeper.ZooKeeper; 43 import org.apache.zookeeper.Watcher.Event.EventType; 44 import org.apache.zookeeper.Watcher.Event.KeeperState; 45 import org.apache.zookeeper.ZooDefs.Ids; 46 import org.apache.zookeeper.ZooDefs.Perms; 47 import org.apache.zookeeper.data.ACL; 48 import org.apache.zookeeper.data.Stat; 49 import org.apache.zookeeper.inspector.encryption.BasicDataEncryptionManager; 50 import org.apache.zookeeper.inspector.encryption.DataEncryptionManager; 51 import org.apache.zookeeper.inspector.logger.LoggerFactory; 52 import org.apache.zookeeper.retry.ZooKeeperRetry; 53 54 /** 55 * A default implementation of {@link ZooInspectorManager} for connecting to 56 * zookeeper instances 57 */ 58 public class ZooInspectorManagerImpl implements ZooInspectorManager { 59 private static final String A_VERSION = "ACL Version"; 60 private static final String C_TIME = "Creation Time"; 61 private static final String C_VERSION = "Children Version"; 62 private static final String CZXID = "Creation ID"; 63 private static final String DATA_LENGTH = "Data Length"; 64 private static final String EPHEMERAL_OWNER = "Ephemeral Owner"; 65 private static final String M_TIME = "Last Modified Time"; 66 private static final String MZXID = "Modified ID"; 67 private static final String NUM_CHILDREN = "Number of Children"; 68 private static final String PZXID = "Node ID"; 69 private static final String VERSION = "Data Version"; 70 private static final String ACL_PERMS = "Permissions"; 71 private static final String ACL_SCHEME = "Scheme"; 72 private static final String ACL_ID = "Id"; 73 private static final String SESSION_STATE = "Session State"; 74 private static final String SESSION_ID = "Session ID"; 75 /** 76 * The key used for the connect string in the connection properties file 77 */ 78 public static final String CONNECT_STRING = "hosts"; 79 /** 80 * The key used for the session timeout in the connection properties file 81 */ 82 public static final String SESSION_TIMEOUT = "timeout"; 83 /** 84 * The key used for the data encryption manager in the connection properties 85 * file 86 */ 87 public static final String DATA_ENCRYPTION_MANAGER = "encryptionManager"; 88 /** 89 * The key used for the authentication scheme in the connection properties file 90 */ 91 public static final String AUTH_SCHEME_KEY = "authScheme"; 92 /** 93 * The key used for the authentication data in the connection properties file 94 */ 95 public static final String AUTH_DATA_KEY = "authData"; 96 97 private static final String DEFAULT_ENCRYPTION_MANAGER = 98 BasicDataEncryptionManager.class.getName(); 99 private static final int DEFAULT_TIMEOUT = 5000; 100 private static final String DEFAULT_HOSTS = "localhost:2181"; 101 private static final String DEFAULT_AUTH_SCHEME = ""; 102 private static final String DEFAULT_AUTH_VALUE = ""; 103 104 private static final File defaultNodeViewersFile = new File( 105 "./src/main/resources/defaultNodeViewers.cfg"); 106 private static final File defaultConnectionFile = new File( 107 "./src/main/resources/defaultConnectionSettings.cfg"); 108 109 private DataEncryptionManager encryptionManager; 110 private String connectString; 111 private int sessionTimeout; 112 private ZooKeeper zooKeeper; 113 private final Map<String, NodeWatcher> watchers = new HashMap<String, NodeWatcher>(); 114 protected boolean connected = true; 115 private Properties lastConnectionProps; 116 private String defaultEncryptionManager; 117 private String defaultTimeout; 118 private String defaultHosts; 119 private String defaultAuthScheme; 120 private String defaultAuthValue; 121 private NodesCache nodesCache; 122 123 /** 124 * @throws IOException 125 * - thrown if the default connection settings cannot be loaded 126 * 127 */ ZooInspectorManagerImpl()128 public ZooInspectorManagerImpl() throws IOException { 129 loadDefaultConnectionFile(); 130 } 131 132 /* 133 * (non-Javadoc) 134 * 135 * @see 136 * org.apache.zookeeper.inspector.manager.ZooInspectorManager#connect(java 137 * .util.Properties) 138 */ connect(Properties connectionProps)139 public boolean connect(Properties connectionProps) { 140 try { 141 if (this.zooKeeper == null) { 142 String connectString = connectionProps 143 .getProperty(CONNECT_STRING); 144 String sessionTimeout = connectionProps 145 .getProperty(SESSION_TIMEOUT); 146 String encryptionManager = connectionProps 147 .getProperty(DATA_ENCRYPTION_MANAGER); 148 String authScheme = connectionProps 149 .getProperty(AUTH_SCHEME_KEY); 150 String authData = connectionProps 151 .getProperty(AUTH_DATA_KEY); 152 153 if (connectString == null || sessionTimeout == null) { 154 throw new IllegalArgumentException( 155 "Both connect string and session timeout are required."); 156 } 157 if (encryptionManager == null) { 158 this.encryptionManager = new BasicDataEncryptionManager(); 159 } else { 160 Class<?> clazz = Class.forName(encryptionManager); 161 162 if (Arrays.asList(clazz.getInterfaces()).contains( 163 DataEncryptionManager.class)) { 164 this.encryptionManager = (DataEncryptionManager) Class 165 .forName(encryptionManager).newInstance(); 166 } else { 167 throw new IllegalArgumentException( 168 "Data encryption manager must implement DataEncryptionManager interface"); 169 } 170 } 171 this.connectString = connectString; 172 this.sessionTimeout = Integer.valueOf(sessionTimeout); 173 this.zooKeeper = new ZooKeeperRetry(connectString, Integer 174 .valueOf(sessionTimeout), new Watcher() { 175 176 public void process(WatchedEvent event) { 177 if (event.getState() == KeeperState.Expired) { 178 connected = false; 179 } 180 } 181 }); 182 if (authData != null && authData.length() > 0){ 183 this.zooKeeper.addAuthInfo(authScheme, authData.getBytes()); 184 } 185 ((ZooKeeperRetry) this.zooKeeper).setRetryLimit(10); 186 connected = ((ZooKeeperRetry) this.zooKeeper).testConnection(); 187 } 188 } catch (Exception e) { 189 connected = false; 190 e.printStackTrace(); 191 } 192 if (!connected){ 193 disconnect(); 194 } else { 195 this.nodesCache = new NodesCache(zooKeeper); 196 } 197 return connected; 198 } 199 200 /* 201 * (non-Javadoc) 202 * 203 * @see 204 * org.apache.zookeeper.inspector.manager.ZooInspectorManager#disconnect() 205 */ disconnect()206 public boolean disconnect() { 207 try { 208 if (this.zooKeeper != null) { 209 this.zooKeeper.close(); 210 this.zooKeeper = null; 211 connected = false; 212 removeWatchers(this.watchers.keySet()); 213 return true; 214 } 215 } catch (Exception e) { 216 LoggerFactory.getLogger().error( 217 "Error occurred while disconnecting from ZooKeeper server", 218 e); 219 } 220 return false; 221 } 222 223 /* 224 * (non-Javadoc) 225 * 226 * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorReadOnlyManager# 227 * getChildren(java.lang.String) 228 */ getChildren(String nodePath)229 public List<String> getChildren(String nodePath) { 230 if (connected) { 231 return nodesCache.getChildren(nodePath); 232 } 233 return null; 234 235 } 236 237 /* 238 * (non-Javadoc) 239 * 240 * @see 241 * org.apache.zookeeper.inspector.manager.ZooInspectorReadOnlyManager#getData 242 * (java.lang.String) 243 */ getData(String nodePath)244 public String getData(String nodePath) { 245 if (connected) { 246 try { 247 if (nodePath.length() == 0) { 248 nodePath = "/"; 249 } 250 Stat s = zooKeeper.exists(nodePath, false); 251 if (s != null) { 252 return this.encryptionManager.decryptData(zooKeeper 253 .getData(nodePath, false, s)); 254 } 255 } catch (Exception e) { 256 LoggerFactory.getLogger().error( 257 "Error occurred getting data for node: " + nodePath, e); 258 } 259 } 260 return null; 261 } 262 263 /* 264 * (non-Javadoc) 265 * 266 * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorReadOnlyManager# 267 * getNodeChild(java.lang.String, int) 268 */ getNodeChild(String nodePath, int childIndex)269 public String getNodeChild(String nodePath, int childIndex) { 270 if (connected) { 271 return this.nodesCache.getNodeChild(nodePath, childIndex); 272 } 273 return null; 274 } 275 276 /* 277 * (non-Javadoc) 278 * 279 * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorReadOnlyManager# 280 * getNodeIndex(java.lang.String) 281 */ getNodeIndex(String nodePath)282 public int getNodeIndex(String nodePath) { 283 if (connected) { 284 int index = nodePath.lastIndexOf("/"); 285 if (index == -1 286 || (!nodePath.equals("/") && nodePath.charAt(nodePath 287 .length() - 1) == '/')) { 288 throw new IllegalArgumentException("Invalid node path: " 289 + nodePath); 290 } 291 String parentPath = nodePath.substring(0, index); 292 String child = nodePath.substring(index + 1); 293 if (parentPath != null && parentPath.length() > 0) { 294 List<String> children = this.nodesCache.getChildren(parentPath); 295 if (children != null) { 296 return children.indexOf(child); 297 } 298 } 299 } 300 return -1; 301 } 302 303 /* 304 * (non-Javadoc) 305 * 306 * @see 307 * org.apache.zookeeper.inspector.manager.ZooInspectorReadOnlyManager#getACLs 308 * (java.lang.String) 309 */ getACLs(String nodePath)310 public List<Map<String, String>> getACLs(String nodePath) { 311 List<Map<String, String>> returnACLs = new ArrayList<Map<String, String>>(); 312 if (connected) { 313 try { 314 if (nodePath.length() == 0) { 315 nodePath = "/"; 316 } 317 Stat s = zooKeeper.exists(nodePath, false); 318 if (s != null) { 319 List<ACL> acls = zooKeeper.getACL(nodePath, s); 320 for (ACL acl : acls) { 321 Map<String, String> aclMap = new LinkedHashMap<String, String>(); 322 aclMap.put(ACL_SCHEME, acl.getId().getScheme()); 323 aclMap.put(ACL_ID, acl.getId().getId()); 324 StringBuilder sb = new StringBuilder(); 325 int perms = acl.getPerms(); 326 boolean addedPerm = false; 327 if ((perms & Perms.READ) == Perms.READ) { 328 sb.append("Read"); 329 addedPerm = true; 330 } 331 if (addedPerm) { 332 sb.append(", "); 333 } 334 if ((perms & Perms.WRITE) == Perms.WRITE) { 335 sb.append("Write"); 336 addedPerm = true; 337 } 338 if (addedPerm) { 339 sb.append(", "); 340 } 341 if ((perms & Perms.CREATE) == Perms.CREATE) { 342 sb.append("Create"); 343 addedPerm = true; 344 } 345 if (addedPerm) { 346 sb.append(", "); 347 } 348 if ((perms & Perms.DELETE) == Perms.DELETE) { 349 sb.append("Delete"); 350 addedPerm = true; 351 } 352 if (addedPerm) { 353 sb.append(", "); 354 } 355 if ((perms & Perms.ADMIN) == Perms.ADMIN) { 356 sb.append("Admin"); 357 addedPerm = true; 358 } 359 aclMap.put(ACL_PERMS, sb.toString()); 360 returnACLs.add(aclMap); 361 } 362 } 363 } catch (InterruptedException e) { 364 LoggerFactory.getLogger().error( 365 "Error occurred retrieving ACLs of node: " + nodePath, 366 e); 367 } catch (KeeperException e) { 368 LoggerFactory.getLogger().error( 369 "Error occurred retrieving ACLs of node: " + nodePath, 370 e); 371 } 372 } 373 return returnACLs; 374 } 375 376 /* 377 * (non-Javadoc) 378 * 379 * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorReadOnlyManager# 380 * getNodeMeta(java.lang.String) 381 */ getNodeMeta(String nodePath)382 public Map<String, String> getNodeMeta(String nodePath) { 383 Map<String, String> nodeMeta = new LinkedHashMap<String, String>(); 384 if (connected) { 385 try { 386 if (nodePath.length() == 0) { 387 nodePath = "/"; 388 } 389 Stat s = zooKeeper.exists(nodePath, false); 390 if (s != null) { 391 nodeMeta.put(A_VERSION, String.valueOf(s.getAversion())); 392 nodeMeta.put(C_TIME, String.valueOf(s.getCtime())); 393 nodeMeta.put(C_VERSION, String.valueOf(s.getCversion())); 394 nodeMeta.put(CZXID, String.valueOf(s.getCzxid())); 395 nodeMeta 396 .put(DATA_LENGTH, String.valueOf(s.getDataLength())); 397 nodeMeta.put(EPHEMERAL_OWNER, String.valueOf(s 398 .getEphemeralOwner())); 399 nodeMeta.put(M_TIME, String.valueOf(s.getMtime())); 400 nodeMeta.put(MZXID, String.valueOf(s.getMzxid())); 401 nodeMeta.put(NUM_CHILDREN, String.valueOf(s 402 .getNumChildren())); 403 nodeMeta.put(PZXID, String.valueOf(s.getPzxid())); 404 nodeMeta.put(VERSION, String.valueOf(s.getVersion())); 405 } 406 } catch (Exception e) { 407 LoggerFactory.getLogger().error( 408 "Error occurred retrieving meta data for node: " 409 + nodePath, e); 410 } 411 } 412 return nodeMeta; 413 } 414 415 /* 416 * (non-Javadoc) 417 * 418 * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorReadOnlyManager# 419 * getNumChildren(java.lang.String) 420 */ getNumChildren(String nodePath)421 public int getNumChildren(String nodePath) { 422 if (connected) { 423 try { 424 Stat s = zooKeeper.exists(nodePath, false); 425 if (s != null) { 426 return s.getNumChildren(); 427 } 428 } catch (Exception e) { 429 LoggerFactory.getLogger().error( 430 "Error occurred getting the number of children of node: " 431 + nodePath, e); 432 } 433 } 434 return -1; 435 } 436 437 /* 438 * (non-Javadoc) 439 * 440 * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorReadOnlyManager# 441 * hasChildren(java.lang.String) 442 */ hasChildren(String nodePath)443 public boolean hasChildren(String nodePath) { 444 return getNumChildren(nodePath) > 0; 445 } 446 447 /* 448 * (non-Javadoc) 449 * 450 * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorReadOnlyManager# 451 * isAllowsChildren(java.lang.String) 452 */ isAllowsChildren(String nodePath)453 public boolean isAllowsChildren(String nodePath) { 454 if (connected) { 455 try { 456 Stat s = zooKeeper.exists(nodePath, false); 457 if (s != null) { 458 return s.getEphemeralOwner() == 0; 459 } 460 } catch (Exception e) { 461 LoggerFactory.getLogger().error( 462 "Error occurred determining whether node is allowed children: " 463 + nodePath, e); 464 } 465 } 466 return false; 467 } 468 469 /* 470 * (non-Javadoc) 471 * 472 * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorReadOnlyManager# 473 * getSessionMeta() 474 */ getSessionMeta()475 public Map<String, String> getSessionMeta() { 476 Map<String, String> sessionMeta = new LinkedHashMap<String, String>(); 477 try { 478 if (zooKeeper != null) { 479 480 sessionMeta.put(SESSION_ID, String.valueOf(zooKeeper 481 .getSessionId())); 482 sessionMeta.put(SESSION_STATE, String.valueOf(zooKeeper 483 .getState().toString())); 484 sessionMeta.put(CONNECT_STRING, this.connectString); 485 sessionMeta.put(SESSION_TIMEOUT, String 486 .valueOf(this.sessionTimeout)); 487 } 488 } catch (Exception e) { 489 LoggerFactory.getLogger().error( 490 "Error occurred retrieving session meta data.", e); 491 } 492 return sessionMeta; 493 } 494 495 /* 496 * (non-Javadoc) 497 * 498 * @see 499 * org.apache.zookeeper.inspector.manager.ZooInspectorNodeTreeManager#createNode 500 * (java.lang.String, java.lang.String) 501 */ createNode(String parent, String nodeName)502 public boolean createNode(String parent, String nodeName) { 503 if (connected) { 504 try { 505 String[] nodeElements = nodeName.split("/"); 506 for (String nodeElement : nodeElements) { 507 String node = parent + "/" + nodeElement; 508 Stat s = zooKeeper.exists(node, false); 509 if (s == null) { 510 zooKeeper.create(node, this.encryptionManager 511 .encryptData(null), Ids.OPEN_ACL_UNSAFE, 512 CreateMode.PERSISTENT); 513 parent = node; 514 } 515 } 516 return true; 517 } catch (Exception e) { 518 LoggerFactory.getLogger().error( 519 "Error occurred creating node: " + parent + "/" 520 + nodeName, e); 521 } 522 } 523 return false; 524 } 525 526 /* 527 * (non-Javadoc) 528 * 529 * @see 530 * org.apache.zookeeper.inspector.manager.ZooInspectorNodeTreeManager#deleteNode 531 * (java.lang.String) 532 */ deleteNode(String nodePath)533 public boolean deleteNode(String nodePath) { 534 if (connected) { 535 try { 536 Stat s = zooKeeper.exists(nodePath, false); 537 if (s != null) { 538 List<String> children = zooKeeper.getChildren(nodePath, 539 false); 540 for (String child : children) { 541 String node = nodePath + "/" + child; 542 deleteNode(node); 543 } 544 zooKeeper.delete(nodePath, -1); 545 } 546 return true; 547 } catch (Exception e) { 548 LoggerFactory.getLogger().error( 549 "Error occurred deleting node: " + nodePath, e); 550 } 551 } 552 return false; 553 } 554 555 /* 556 * (non-Javadoc) 557 * 558 * @see 559 * org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager#setData 560 * (java.lang.String, java.lang.String) 561 */ setData(String nodePath, String data)562 public boolean setData(String nodePath, String data) { 563 if (connected) { 564 try { 565 zooKeeper.setData(nodePath, this.encryptionManager 566 .encryptData(data), -1); 567 return true; 568 } catch (Exception e) { 569 LoggerFactory.getLogger().error( 570 "Error occurred setting data for node: " + nodePath, e); 571 } 572 } 573 return false; 574 } 575 576 /* 577 * (non-Javadoc) 578 * 579 * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorManager# 580 * getConnectionPropertiesTemplate() 581 */ getConnectionPropertiesTemplate()582 public Pair<Map<String, List<String>>, Map<String, String>> getConnectionPropertiesTemplate() { 583 Map<String, List<String>> template = new LinkedHashMap<String, List<String>>(); 584 template.put(CONNECT_STRING, Arrays 585 .asList(new String[] { defaultHosts })); 586 template.put(SESSION_TIMEOUT, Arrays 587 .asList(new String[] { defaultTimeout })); 588 template.put(DATA_ENCRYPTION_MANAGER, Arrays 589 .asList(new String[] { defaultEncryptionManager })); 590 template.put(AUTH_SCHEME_KEY, Arrays 591 .asList(new String[] { defaultAuthScheme })); 592 template.put(AUTH_DATA_KEY, Arrays 593 .asList(new String[] { defaultAuthValue })); 594 Map<String, String> labels = new LinkedHashMap<String, String>(); 595 labels.put(CONNECT_STRING, "Connect String"); 596 labels.put(SESSION_TIMEOUT, "Session Timeout"); 597 labels.put(DATA_ENCRYPTION_MANAGER, "Data Encryption Manager"); 598 labels.put(AUTH_SCHEME_KEY, "Authentication Scheme"); 599 labels.put(AUTH_DATA_KEY, "Authentication Data"); 600 return new Pair<Map<String, List<String>>, Map<String, String>>( 601 template, labels); 602 } 603 604 /* 605 * (non-Javadoc) 606 * 607 * @see 608 * org.apache.zookeeper.inspector.manager.ZooInspectorManager#addWatchers 609 * (java.util.Collection, 610 * org.apache.zookeeper.inspector.manager.NodeListener) 611 */ addWatchers(Collection<String> selectedNodes, NodeListener nodeListener)612 public void addWatchers(Collection<String> selectedNodes, 613 NodeListener nodeListener) { 614 // add watcher for each node and add node to collection of 615 // watched nodes 616 if (connected) { 617 for (String node : selectedNodes) { 618 if (!watchers.containsKey(node)) { 619 try { 620 watchers.put(node, new NodeWatcher(node, nodeListener, 621 zooKeeper)); 622 } catch (Exception e) { 623 LoggerFactory.getLogger().error( 624 "Error occurred adding node watcher for node: " 625 + node, e); 626 } 627 } 628 } 629 } 630 } 631 632 /* 633 * (non-Javadoc) 634 * 635 * @see 636 * org.apache.zookeeper.inspector.manager.ZooInspectorManager#removeWatchers 637 * (java.util.Collection) 638 */ removeWatchers(Collection<String> selectedNodes)639 public void removeWatchers(Collection<String> selectedNodes) { 640 // remove watcher for each node and remove node from 641 // collection of watched nodes 642 if (connected) { 643 for (String node : selectedNodes) { 644 if (watchers.containsKey(node)) { 645 NodeWatcher watcher = watchers.remove(node); 646 if (watcher != null) { 647 watcher.stop(); 648 } 649 } 650 } 651 } 652 } 653 654 /** 655 * A Watcher which will re-add itself every time an event is fired 656 * 657 */ 658 public class NodeWatcher implements Watcher { 659 660 private final String nodePath; 661 private final NodeListener nodeListener; 662 private final ZooKeeper zookeeper; 663 private boolean closed = false; 664 665 /** 666 * @param nodePath 667 * - the path to the node to watch 668 * @param nodeListener 669 * the {@link NodeListener} for this node 670 * @param zookeeper 671 * - a {@link ZooKeeper} to use to access zookeeper 672 * @throws InterruptedException 673 * @throws KeeperException 674 */ NodeWatcher(String nodePath, NodeListener nodeListener, ZooKeeper zookeeper)675 public NodeWatcher(String nodePath, NodeListener nodeListener, 676 ZooKeeper zookeeper) throws KeeperException, 677 InterruptedException { 678 this.nodePath = nodePath; 679 this.nodeListener = nodeListener; 680 this.zookeeper = zookeeper; 681 Stat s = zooKeeper.exists(nodePath, this); 682 if (s != null) { 683 zookeeper.getChildren(nodePath, this); 684 } 685 } 686 process(WatchedEvent event)687 public void process(WatchedEvent event) { 688 if (!closed) { 689 try { 690 if (event.getType() != EventType.NodeDeleted) { 691 692 Stat s = zooKeeper.exists(nodePath, this); 693 if (s != null) { 694 zookeeper.getChildren(nodePath, this); 695 } 696 } 697 } catch (Exception e) { 698 LoggerFactory.getLogger().error( 699 "Error occurred re-adding node watcherfor node " 700 + nodePath, e); 701 } 702 nodeListener.processEvent(event.getPath(), event.getType() 703 .name(), null); 704 } 705 } 706 707 /** 708 * 709 */ stop()710 public void stop() { 711 this.closed = true; 712 } 713 714 } 715 716 /* 717 * (non-Javadoc) 718 * 719 * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorManager# 720 * loadNodeViewersFile(java.io.File) 721 */ loadNodeViewersFile(File selectedFile)722 public List<String> loadNodeViewersFile(File selectedFile) 723 throws IOException { 724 List<String> result = new ArrayList<String>(); 725 726 try(BufferedReader reader = getReaderForFile(selectedFile)) { 727 if(reader == null) { 728 return result; 729 } 730 731 String line = ""; 732 while (line != null) { 733 line = reader.readLine(); 734 if(line != null) { 735 line = line.trim(); 736 if (!line.isEmpty() && !line.startsWith("#")) { 737 result.add(line); 738 } 739 } 740 } 741 } 742 743 return result; 744 } 745 loadDefaultConnectionFile()746 private void loadDefaultConnectionFile() throws IOException { 747 Properties props = new Properties(); 748 749 try(BufferedReader reader = getReaderForFile(defaultConnectionFile)) { 750 //If reader is null, it's OK. Default values will get set below. 751 if(reader != null) { 752 props.load(reader); 753 } 754 } 755 756 defaultEncryptionManager = props.getProperty(DATA_ENCRYPTION_MANAGER) == null ? 757 DEFAULT_ENCRYPTION_MANAGER : props.getProperty(DATA_ENCRYPTION_MANAGER); 758 defaultTimeout = props.getProperty(SESSION_TIMEOUT) == null ? 759 Integer.toString(DEFAULT_TIMEOUT) : props.getProperty(SESSION_TIMEOUT); 760 defaultHosts = props.getProperty(CONNECT_STRING) == null ? 761 DEFAULT_HOSTS : props.getProperty(CONNECT_STRING); 762 defaultAuthScheme = props.getProperty(AUTH_SCHEME_KEY) == null ? 763 DEFAULT_AUTH_SCHEME : props.getProperty(AUTH_SCHEME_KEY); 764 defaultAuthValue = props.getProperty(AUTH_DATA_KEY) == null ? 765 DEFAULT_AUTH_VALUE : props.getProperty(AUTH_DATA_KEY); 766 } 767 768 /* 769 * (non-Javadoc) 770 * 771 * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorManager# 772 * saveDefaultConnectionFile(java.util.Properties) 773 */ saveDefaultConnectionFile(Properties props)774 public void saveDefaultConnectionFile(Properties props) throws IOException { 775 File defaultDir = defaultConnectionFile.getParentFile(); 776 if (!defaultDir.exists()) { 777 if (!defaultDir.mkdirs()) { 778 throw new IOException( 779 "Failed to create configuration directory: " 780 + defaultDir.getAbsolutePath()); 781 } 782 } 783 if (!defaultConnectionFile.exists()) { 784 if (!defaultConnectionFile.createNewFile()) { 785 throw new IOException( 786 "Failed to create default connection file: " 787 + defaultConnectionFile.getAbsolutePath()); 788 } 789 } 790 FileWriter writer = new FileWriter(defaultConnectionFile); 791 try { 792 props.store(writer, "Default connection for ZooInspector"); 793 } finally { 794 writer.close(); 795 } 796 } 797 798 /* 799 * (non-Javadoc) 800 * 801 * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorManager# 802 * saveNodeViewersFile(java.io.File, java.util.List) 803 */ saveNodeViewersFile(File selectedFile, List<String> nodeViewersClassNames)804 public void saveNodeViewersFile(File selectedFile, 805 List<String> nodeViewersClassNames) throws IOException { 806 if (!selectedFile.exists()) { 807 if (!selectedFile.createNewFile()) { 808 throw new IOException( 809 "Failed to create node viewers configuration file: " 810 + selectedFile.getAbsolutePath()); 811 } 812 } 813 FileWriter writer = new FileWriter(selectedFile); 814 try { 815 BufferedWriter buff = new BufferedWriter(writer); 816 try { 817 for (String nodeViewersClassName : nodeViewersClassNames) { 818 buff.append(nodeViewersClassName); 819 buff.append("\n"); 820 } 821 } finally { 822 buff.flush(); 823 buff.close(); 824 } 825 } finally { 826 writer.close(); 827 } 828 } 829 830 /* 831 * (non-Javadoc) 832 * 833 * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorManager# 834 * setDefaultNodeViewerConfiguration(java.io.File, java.util.List) 835 */ setDefaultNodeViewerConfiguration( List<String> nodeViewersClassNames)836 public void setDefaultNodeViewerConfiguration( 837 List<String> nodeViewersClassNames) throws IOException { 838 File defaultDir = defaultNodeViewersFile.getParentFile(); 839 if (!defaultDir.exists()) { 840 if (!defaultDir.mkdirs()) { 841 throw new IOException( 842 "Failed to create configuration directory: " 843 + defaultDir.getAbsolutePath()); 844 } 845 } 846 saveNodeViewersFile(defaultNodeViewersFile, nodeViewersClassNames); 847 } 848 getDefaultNodeViewerConfiguration()849 public List<String> getDefaultNodeViewerConfiguration() throws IOException { 850 List<String> defaultNodeViewers = loadNodeViewersFile(defaultNodeViewersFile); 851 if (defaultNodeViewers.isEmpty()) { 852 LoggerFactory.getLogger().warn("List of default node viewers is empty"); 853 } 854 return defaultNodeViewers; 855 } 856 857 /* 858 * (non-Javadoc) 859 * 860 * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorManager# 861 * getLastConnectionProps() 862 */ getLastConnectionProps()863 public Properties getLastConnectionProps() { 864 return this.lastConnectionProps; 865 } 866 867 /* 868 * (non-Javadoc) 869 * 870 * @seeorg.apache.zookeeper.inspector.manager.ZooInspectorManager# 871 * setLastConnectionProps(java.util.Properties) 872 */ setLastConnectionProps(Properties connectionProps)873 public void setLastConnectionProps(Properties connectionProps) { 874 this.lastConnectionProps = connectionProps; 875 } 876 getReaderForFile(File file)877 private static BufferedReader getReaderForFile(File file) { 878 //check the filesystem first 879 if (file.exists()) { 880 try { 881 return new BufferedReader(new FileReader(file)); 882 } catch (FileNotFoundException e) { 883 return null; 884 } 885 } 886 887 //fall back to checking the CLASSPATH with only the filename 888 //(for cases where the file exists in src/main/resources) 889 InputStream classpathStream = ZooInspectorManagerImpl.class.getClassLoader() 890 .getResourceAsStream(file.getName()); 891 if (classpathStream != null) { 892 return new BufferedReader(new InputStreamReader(classpathStream)); 893 } 894 895 //couldn't find the file anywhere 896 return null; 897 } 898 } 899