Forráskód Böngészése

Set svn:eol-style property to native.

git-svn-id: https://svn.apache.org/repos/asf/zookeeper/trunk@1584497 13f79535-47bb-0310-9956-ffa450edef68
Michi Mutsuzaki 11 éve
szülő
commit
b1befb0c4d
37 módosított fájl, 7217 hozzáadás és 7217 törlés
  1. 6 6
      bin/README.txt
  2. 24 24
      bin/zkCli.cmd
  3. 24 24
      bin/zkServer.cmd
  4. 1252 1252
      src/c/c-doc.Doxyfile
  5. 126 126
      src/contrib/loggraph/web/org/apache/zookeeper/graph/resources/date.format.js
  6. 93 93
      src/contrib/zooinspector/README.txt
  7. 139 139
      src/contrib/zooinspector/build.xml
  8. 47 47
      src/contrib/zooinspector/ivy.xml
  9. 8 8
      src/contrib/zooinspector/lib/log4j.properties
  10. 71 71
      src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/ZooInspector.java
  11. 50 50
      src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/encryption/BasicDataEncryptionManager.java
  12. 39 39
      src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/encryption/DataEncryptionManager.java
  13. 37 37
      src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/NodeViewersChangeListener.java
  14. 79 79
      src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/ZooInspectorAboutDialog.java
  15. 321 321
      src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/ZooInspectorConnectionPropertiesDialog.java
  16. 631 631
      src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/ZooInspectorNodeViewersDialog.java
  17. 140 140
      src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/ZooInspectorNodeViewersPanel.java
  18. 318 318
      src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/ZooInspectorPanel.java
  19. 356 356
      src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/ZooInspectorTreeViewer.java
  20. 21 21
      src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/about.html
  21. 187 187
      src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/nodeviewer/NodeViewerACL.java
  22. 143 143
      src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/nodeviewer/NodeViewerData.java
  23. 186 186
      src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/nodeviewer/NodeViewerMetaData.java
  24. 138 138
      src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/nodeviewer/ZooInspectorNodeViewer.java
  25. 36 36
      src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/logger/LoggerFactory.java
  26. 37 37
      src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/manager/NodeListener.java
  27. 120 120
      src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/manager/Pair.java
  28. 139 139
      src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/manager/ZooInspectorManager.java
  29. 885 885
      src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/manager/ZooInspectorManagerImpl.java
  30. 33 33
      src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/manager/ZooInspectorNodeManager.java
  31. 288 288
      src/contrib/zooinspector/src/java/org/apache/zookeeper/retry/ZooKeeperRetry.java
  32. 18 18
      src/contrib/zooinspector/zooInspector.cmd
  33. 128 128
      src/java/main/org/apache/zookeeper/server/SnapshotFormatter.java
  34. 149 149
      src/java/test/org/apache/zookeeper/server/PrepRequestProcessorTest.java
  35. 107 107
      src/java/test/org/apache/zookeeper/test/FLEPredicateTest.java
  36. 736 736
      src/java/test/org/apache/zookeeper/test/ReconfigTest.java
  37. 105 105
      src/java/test/org/apache/zookeeper/test/SessionInvalidationTest.java

+ 6 - 6
bin/README.txt

@@ -1,6 +1,6 @@
-This directory contain scripts that allow easy access (classpath in particular)
-to the ZooKeeper server and command line client.
-
-Files ending in .sh are unix and cygwin compatible
-
-Files ending in .cmd are msdos/windows compatible
+This directory contain scripts that allow easy access (classpath in particular)
+to the ZooKeeper server and command line client.
+
+Files ending in .sh are unix and cygwin compatible
+
+Files ending in .cmd are msdos/windows compatible

+ 24 - 24
bin/zkCli.cmd

@@ -1,24 +1,24 @@
-@echo off
-REM Licensed to the Apache Software Foundation (ASF) under one or more
-REM contributor license agreements.  See the NOTICE file distributed with
-REM this work for additional information regarding copyright ownership.
-REM The ASF licenses this file to You under the Apache License, Version 2.0
-REM (the "License"); you may not use this file except in compliance with
-REM the License.  You may obtain a copy of the License at
-REM
-REM     http://www.apache.org/licenses/LICENSE-2.0
-REM
-REM Unless required by applicable law or agreed to in writing, software
-REM distributed under the License is distributed on an "AS IS" BASIS,
-REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-REM See the License for the specific language governing permissions and
-REM limitations under the License.
-
-setlocal
-call "%~dp0zkEnv.cmd"
-
-set ZOOMAIN=org.apache.zookeeper.ZooKeeperMain
-call %JAVA% "-Dzookeeper.log.dir=%ZOO_LOG_DIR%" "-Dzookeeper.root.logger=%ZOO_LOG4J_PROP%" -cp "%CLASSPATH%" %ZOOMAIN% %*
-
-endlocal
-
+@echo off
+REM Licensed to the Apache Software Foundation (ASF) under one or more
+REM contributor license agreements.  See the NOTICE file distributed with
+REM this work for additional information regarding copyright ownership.
+REM The ASF licenses this file to You under the Apache License, Version 2.0
+REM (the "License"); you may not use this file except in compliance with
+REM the License.  You may obtain a copy of the License at
+REM
+REM     http://www.apache.org/licenses/LICENSE-2.0
+REM
+REM Unless required by applicable law or agreed to in writing, software
+REM distributed under the License is distributed on an "AS IS" BASIS,
+REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+REM See the License for the specific language governing permissions and
+REM limitations under the License.
+
+setlocal
+call "%~dp0zkEnv.cmd"
+
+set ZOOMAIN=org.apache.zookeeper.ZooKeeperMain
+call %JAVA% "-Dzookeeper.log.dir=%ZOO_LOG_DIR%" "-Dzookeeper.root.logger=%ZOO_LOG4J_PROP%" -cp "%CLASSPATH%" %ZOOMAIN% %*
+
+endlocal
+

+ 24 - 24
bin/zkServer.cmd

@@ -1,24 +1,24 @@
-@echo off
-REM Licensed to the Apache Software Foundation (ASF) under one or more
-REM contributor license agreements.  See the NOTICE file distributed with
-REM this work for additional information regarding copyright ownership.
-REM The ASF licenses this file to You under the Apache License, Version 2.0
-REM (the "License"); you may not use this file except in compliance with
-REM the License.  You may obtain a copy of the License at
-REM
-REM     http://www.apache.org/licenses/LICENSE-2.0
-REM
-REM Unless required by applicable law or agreed to in writing, software
-REM distributed under the License is distributed on an "AS IS" BASIS,
-REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-REM See the License for the specific language governing permissions and
-REM limitations under the License.
-
-setlocal
-call "%~dp0zkEnv.cmd"
-
-set ZOOMAIN=org.apache.zookeeper.server.quorum.QuorumPeerMain
-echo on
-call %JAVA% "-Dzookeeper.log.dir=%ZOO_LOG_DIR%" "-Dzookeeper.root.logger=%ZOO_LOG4J_PROP%" -cp "%CLASSPATH%" %ZOOMAIN% "%ZOOCFG%" %*
-
-endlocal
+@echo off
+REM Licensed to the Apache Software Foundation (ASF) under one or more
+REM contributor license agreements.  See the NOTICE file distributed with
+REM this work for additional information regarding copyright ownership.
+REM The ASF licenses this file to You under the Apache License, Version 2.0
+REM (the "License"); you may not use this file except in compliance with
+REM the License.  You may obtain a copy of the License at
+REM
+REM     http://www.apache.org/licenses/LICENSE-2.0
+REM
+REM Unless required by applicable law or agreed to in writing, software
+REM distributed under the License is distributed on an "AS IS" BASIS,
+REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+REM See the License for the specific language governing permissions and
+REM limitations under the License.
+
+setlocal
+call "%~dp0zkEnv.cmd"
+
+set ZOOMAIN=org.apache.zookeeper.server.quorum.QuorumPeerMain
+echo on
+call %JAVA% "-Dzookeeper.log.dir=%ZOO_LOG_DIR%" "-Dzookeeper.root.logger=%ZOO_LOG4J_PROP%" -cp "%CLASSPATH%" %ZOOMAIN% "%ZOOCFG%" %*
+
+endlocal

+ 1252 - 1252
src/c/c-doc.Doxyfile

@@ -1,1252 +1,1252 @@
-# Doxyfile 1.4.7
-
-# This file describes the settings to be used by the documentation system
-# doxygen (www.doxygen.org) for a project
-#
-# All text after a hash (#) is considered a comment and will be ignored
-# The format is:
-#       TAG = value [value, ...]
-# For lists items can also be appended using:
-#       TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (" ")
-
-#---------------------------------------------------------------------------
-# Project related configuration options
-#---------------------------------------------------------------------------
-
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
-# by quotes) that should identify the project.
-
-PROJECT_NAME = $(PROJECT)-$(VERSION)
-
-# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
-# This could be handy for archiving the generated documentation or 
-# if some version control system is used.
-
-PROJECT_NUMBER = 
-
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
-# base path where the generated documentation will be put. 
-# If a relative path is entered, it will be relative to the location 
-# where doxygen was started. If left blank the current directory will be used.
-
-OUTPUT_DIRECTORY = $(DOCDIR)
-
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
-# 4096 sub-directories (in 2 levels) under the output directory of each output 
-# format and will distribute the generated files over these directories. 
-# Enabling this option can be useful when feeding doxygen a huge amount of 
-# source files, where putting all generated files in the same directory would 
-# otherwise cause performance problems for the file system.
-
-CREATE_SUBDIRS = NO
-
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
-# documentation generated by doxygen is written. Doxygen will use this 
-# information to generate all constant output in the proper language. 
-# The default language is English, other supported languages are: 
-# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, 
-# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, 
-# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, 
-# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, 
-# Swedish, and Ukrainian.
-
-OUTPUT_LANGUAGE = English
-
-# This tag can be used to specify the encoding used in the generated output. 
-# The encoding is not always determined by the language that is chosen, 
-# but also whether or not the output is meant for Windows or non-Windows users. 
-# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES 
-# forces the Windows encoding (this is the default for the Windows binary), 
-# whereas setting the tag to NO uses a Unix-style encoding (the default for 
-# all platforms other than Windows).
-
-USE_WINDOWS_ENCODING = NO
-
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
-# include brief member descriptions after the members that are listed in 
-# the file and class documentation (similar to JavaDoc). 
-# Set to NO to disable this.
-
-BRIEF_MEMBER_DESC = YES
-
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
-# the brief description of a member or function before the detailed description. 
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
-# brief descriptions will be completely suppressed.
-
-REPEAT_BRIEF = YES
-
-# This tag implements a quasi-intelligent brief description abbreviator 
-# that is used to form the text in various listings. Each string 
-# in this list, if found as the leading text of the brief description, will be 
-# stripped from the text and the result after processing the whole list, is 
-# used as the annotated text. Otherwise, the brief description is used as-is. 
-# If left blank, the following values are used ("$name" is automatically 
-# replaced with the name of the entity): "The $name class" "The $name widget" 
-# "The $name file" "is" "provides" "specifies" "contains" 
-# "represents" "a" "an" "the"
-
-ABBREVIATE_BRIEF = 
-
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
-# Doxygen will generate a detailed section even if there is only a brief 
-# description.
-
-ALWAYS_DETAILED_SEC = NO
-
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
-# inherited members of a class in the documentation of that class as if those 
-# members were ordinary class members. Constructors, destructors and assignment 
-# operators of the base classes will not be shown.
-
-INLINE_INHERITED_MEMB = NO
-
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
-# path before files name in the file list and in the header files. If set 
-# to NO the shortest path that makes the file name unique will be used.
-
-FULL_PATH_NAMES = YES
-
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
-# can be used to strip a user-defined part of the path. Stripping is 
-# only done if one of the specified strings matches the left-hand part of 
-# the path. The tag can be used to show relative paths in the file list. 
-# If left blank the directory from which doxygen is run is used as the 
-# path to strip.
-
-STRIP_FROM_PATH = 
-
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
-# the path mentioned in the documentation of a class, which tells 
-# the reader which header file to include in order to use a class. 
-# If left blank only the name of the header file containing the class 
-# definition is used. Otherwise one should specify the include paths that 
-# are normally passed to the compiler using the -I flag.
-
-STRIP_FROM_INC_PATH = 
-
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
-# (but less readable) file names. This can be useful is your file systems 
-# doesn't support long names like on DOS, Mac, or CD-ROM.
-
-SHORT_NAMES = NO
-
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
-# will interpret the first line (until the first dot) of a JavaDoc-style 
-# comment as the brief description. If set to NO, the JavaDoc 
-# comments will behave just like the Qt-style comments (thus requiring an 
-# explicit @brief command for a brief description.
-
-JAVADOC_AUTOBRIEF = NO
-
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
-# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
-# comments) as a brief description. This used to be the default behaviour. 
-# The new default is to treat a multi-line C++ comment block as a detailed 
-# description. Set this tag to YES if you prefer the old behaviour instead.
-
-MULTILINE_CPP_IS_BRIEF = NO
-
-# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
-# will output the detailed description near the top, like JavaDoc.
-# If set to NO, the detailed description appears after the member 
-# documentation.
-
-DETAILS_AT_TOP = NO
-
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
-# member inherits the documentation from any documented member that it 
-# re-implements.
-
-INHERIT_DOCS = YES
-
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
-# a new page for each member. If set to NO, the documentation of a member will 
-# be part of the file/class/namespace that contains it.
-
-SEPARATE_MEMBER_PAGES = NO
-
-# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
-# Doxygen uses this value to replace tabs by spaces in code fragments.
-
-TAB_SIZE = 8
-
-# This tag can be used to specify a number of aliases that acts 
-# as commands in the documentation. An alias has the form "name=value". 
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
-# put the command \sideeffect (or @sideeffect) in the documentation, which 
-# will result in a user-defined paragraph with heading "Side Effects:". 
-# You can put \n's in the value part of an alias to insert newlines.
-
-ALIASES = 
-
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
-# sources only. Doxygen will then generate output that is more tailored for C. 
-# For instance, some of the names that are used will be different. The list 
-# of all members will be omitted, etc.
-
-OPTIMIZE_OUTPUT_FOR_C = YES
-
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
-# sources only. Doxygen will then generate output that is more tailored for Java. 
-# For instance, namespaces will be presented as packages, qualified scopes 
-# will look different, etc.
-
-OPTIMIZE_OUTPUT_JAVA = NO
-
-# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to 
-# include (a tag file for) the STL sources as input, then you should 
-# set this tag to YES in order to let doxygen match functions declarations and 
-# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 
-# func(std::string) {}). This also make the inheritance and collaboration 
-# diagrams that involve STL classes more complete and accurate.
-
-BUILTIN_STL_SUPPORT = NO
-
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
-# tag is set to YES, then doxygen will reuse the documentation of the first 
-# member in the group (if any) for the other members of the group. By default 
-# all members of a group must be documented explicitly.
-
-DISTRIBUTE_GROUP_DOC = NO
-
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
-# the same type (for instance a group of public functions) to be put as a 
-# subgroup of that type (e.g. under the Public Functions section). Set it to 
-# NO to prevent subgrouping. Alternatively, this can be done per class using 
-# the \nosubgrouping command.
-
-SUBGROUPING = YES
-
-#---------------------------------------------------------------------------
-# Build related configuration options
-#---------------------------------------------------------------------------
-
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
-# documentation are documented, even if no documentation was available. 
-# Private class members and static file members will be hidden unless 
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
-
-EXTRACT_ALL = NO
-
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
-# will be included in the documentation.
-
-EXTRACT_PRIVATE = NO
-
-# If the EXTRACT_STATIC tag is set to YES all static members of a file 
-# will be included in the documentation.
-
-EXTRACT_STATIC = YES
-
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
-# defined locally in source files will be included in the documentation. 
-# If set to NO only classes defined in header files are included.
-
-EXTRACT_LOCAL_CLASSES = YES
-
-# This flag is only useful for Objective-C code. When set to YES local 
-# methods, which are defined in the implementation section but not in 
-# the interface are included in the documentation. 
-# If set to NO (the default) only methods in the interface are included.
-
-EXTRACT_LOCAL_METHODS = NO
-
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
-# undocumented members of documented classes, files or namespaces. 
-# If set to NO (the default) these members will be included in the 
-# various overviews, but no documentation section is generated. 
-# This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_MEMBERS = NO
-
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
-# undocumented classes that are normally visible in the class hierarchy. 
-# If set to NO (the default) these classes will be included in the various 
-# overviews. This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_CLASSES = NO
-
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
-# friend (class|struct|union) declarations. 
-# If set to NO (the default) these declarations will be included in the 
-# documentation.
-
-HIDE_FRIEND_COMPOUNDS = NO
-
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
-# documentation blocks found inside the body of a function. 
-# If set to NO (the default) these blocks will be appended to the 
-# function's detailed documentation block.
-
-HIDE_IN_BODY_DOCS = NO
-
-# The INTERNAL_DOCS tag determines if documentation 
-# that is typed after a \internal command is included. If the tag is set 
-# to NO (the default) then the documentation will be excluded. 
-# Set it to YES to include the internal documentation.
-
-INTERNAL_DOCS = NO
-
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
-# file names in lower-case letters. If set to YES upper-case letters are also 
-# allowed. This is useful if you have classes or files whose names only differ 
-# in case and if your file system supports case sensitive file names. Windows 
-# and Mac users are advised to set this option to NO.
-
-CASE_SENSE_NAMES = YES
-
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
-# will show members with their full class and namespace scopes in the 
-# documentation. If set to YES the scope will be hidden.
-
-HIDE_SCOPE_NAMES = NO
-
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
-# will put a list of the files that are included by a file in the documentation 
-# of that file.
-
-SHOW_INCLUDE_FILES = NO
-
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
-# is inserted in the documentation for inline members.
-
-INLINE_INFO = YES
-
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
-# will sort the (detailed) documentation of file and class members 
-# alphabetically by member name. If set to NO the members will appear in 
-# declaration order.
-
-SORT_MEMBER_DOCS = YES
-
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
-# brief documentation of file, namespace and class members alphabetically 
-# by member name. If set to NO (the default) the members will appear in 
-# declaration order.
-
-SORT_BRIEF_DOCS = NO
-
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
-# sorted by fully-qualified names, including namespaces. If set to 
-# NO (the default), the class list will be sorted only by class name, 
-# not including the namespace part. 
-# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the 
-# alphabetical list.
-
-SORT_BY_SCOPE_NAME = NO
-
-# The GENERATE_TODOLIST tag can be used to enable (YES) or 
-# disable (NO) the todo list. This list is created by putting \todo 
-# commands in the documentation.
-
-GENERATE_TODOLIST = YES
-
-# The GENERATE_TESTLIST tag can be used to enable (YES) or 
-# disable (NO) the test list. This list is created by putting \test 
-# commands in the documentation.
-
-GENERATE_TESTLIST = YES
-
-# The GENERATE_BUGLIST tag can be used to enable (YES) or 
-# disable (NO) the bug list. This list is created by putting \bug 
-# commands in the documentation.
-
-GENERATE_BUGLIST = YES
-
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
-# disable (NO) the deprecated list. This list is created by putting 
-# \deprecated commands in the documentation.
-
-GENERATE_DEPRECATEDLIST = YES
-
-# The ENABLED_SECTIONS tag can be used to enable conditional 
-# documentation sections, marked by \if sectionname ... \endif.
-
-ENABLED_SECTIONS = 
-
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
-# the initial value of a variable or define consists of for it to appear in 
-# the documentation. If the initializer consists of more lines than specified 
-# here it will be hidden. Use a value of 0 to hide initializers completely. 
-# The appearance of the initializer of individual variables and defines in the 
-# documentation can be controlled using \showinitializer or \hideinitializer 
-# command in the documentation regardless of this setting.
-
-MAX_INITIALIZER_LINES = 30
-
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
-# at the bottom of the documentation of classes and structs. If set to YES the 
-# list will mention the files that were used to generate the documentation.
-
-SHOW_USED_FILES = YES
-
-# If the sources in your project are distributed over multiple directories 
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
-# in the documentation. The default is NO.
-
-SHOW_DIRECTORIES = NO
-
-# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
-# doxygen should invoke to get the current version for each file (typically from the 
-# version control system). Doxygen will invoke the program by executing (via 
-# popen()) the command <command> <input-file>, where <command> is the value of 
-# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
-# provided by doxygen. Whatever the program writes to standard output 
-# is used as the file version. See the manual for examples.
-
-FILE_VERSION_FILTER = 
-
-#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
-#---------------------------------------------------------------------------
-
-# The QUIET tag can be used to turn on/off the messages that are generated 
-# by doxygen. Possible values are YES and NO. If left blank NO is used.
-
-QUIET = NO
-
-# The WARNINGS tag can be used to turn on/off the warning messages that are 
-# generated by doxygen. Possible values are YES and NO. If left blank 
-# NO is used.
-
-WARNINGS = YES
-
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
-# automatically be disabled.
-
-WARN_IF_UNDOCUMENTED = YES
-
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
-# potential errors in the documentation, such as not documenting some 
-# parameters in a documented function, or documenting parameters that 
-# don't exist or using markup commands wrongly.
-
-WARN_IF_DOC_ERROR = YES
-
-# This WARN_NO_PARAMDOC option can be abled to get warnings for 
-# functions that are documented, but have no documentation for their parameters 
-# or return value. If set to NO (the default) doxygen will only warn about 
-# wrong or incomplete parameter documentation, but not about the absence of 
-# documentation.
-
-WARN_NO_PARAMDOC = NO
-
-# The WARN_FORMAT tag determines the format of the warning messages that 
-# doxygen can produce. The string should contain the $file, $line, and $text 
-# tags, which will be replaced by the file and line number from which the 
-# warning originated and the warning text. Optionally the format may contain 
-# $version, which will be replaced by the version of the file (if it could 
-# be obtained via FILE_VERSION_FILTER)
-
-WARN_FORMAT = "$file:$line: $text"
-
-# The WARN_LOGFILE tag can be used to specify a file to which warning 
-# and error messages should be written. If left blank the output is written 
-# to stderr.
-
-WARN_LOGFILE = 
-
-#---------------------------------------------------------------------------
-# configuration options related to the input files
-#---------------------------------------------------------------------------
-
-# The INPUT tag can be used to specify the files and/or directories that contain 
-# documented source files. You may enter file names like "myfile.cpp" or 
-# directories like "/usr/src/myproject". Separate the files or directories 
-# with spaces.
-
-INPUT = include/zookeeper.h
-
-# If the value of the INPUT tag contains directories, you can use the 
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
-# blank the following patterns are tested: 
-# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
-# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
-
-FILE_PATTERNS = 
-
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
-# should be searched for input files as well. Possible values are YES and NO. 
-# If left blank NO is used.
-
-RECURSIVE = NO
-
-# The EXCLUDE tag can be used to specify files and/or directories that should 
-# excluded from the INPUT source files. This way you can easily exclude a 
-# subdirectory from a directory tree whose root is specified with the INPUT tag.
-
-EXCLUDE = 
-
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
-# directories that are symbolic links (a Unix filesystem feature) are excluded 
-# from the input.
-
-EXCLUDE_SYMLINKS = NO
-
-# If the value of the INPUT tag contains directories, you can use the 
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
-# certain files from those directories. Note that the wildcards are matched 
-# against the file with absolute path, so to exclude all test directories 
-# for example use the pattern */test/*
-
-EXCLUDE_PATTERNS = 
-
-# The EXAMPLE_PATH tag can be used to specify one or more files or 
-# directories that contain example code fragments that are included (see 
-# the \include command).
-
-EXAMPLE_PATH = 
-
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
-# blank all files are included.
-
-EXAMPLE_PATTERNS = 
-
-# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
-# searched for input files to be used with the \include or \dontinclude 
-# commands irrespective of the value of the RECURSIVE tag. 
-# Possible values are YES and NO. If left blank NO is used.
-
-EXAMPLE_RECURSIVE = NO
-
-# The IMAGE_PATH tag can be used to specify one or more files or 
-# directories that contain image that are included in the documentation (see 
-# the \image command).
-
-IMAGE_PATH = 
-
-# The INPUT_FILTER tag can be used to specify a program that doxygen should 
-# invoke to filter for each input file. Doxygen will invoke the filter program 
-# by executing (via popen()) the command <filter> <input-file>, where <filter> 
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
-# input file. Doxygen will then use the output that the filter program writes 
-# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
-# ignored.
-
-INPUT_FILTER = 
-
-# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
-# basis.  Doxygen will compare the file name with each pattern and apply the 
-# filter if there is a match.  The filters are a list of the form: 
-# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
-# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
-# is applied to all files.
-
-FILTER_PATTERNS = 
-
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
-# INPUT_FILTER) will be used to filter the input files when producing source 
-# files to browse (i.e. when SOURCE_BROWSER is set to YES).
-
-FILTER_SOURCE_FILES = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to source browsing
-#---------------------------------------------------------------------------
-
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
-# be generated. Documented entities will be cross-referenced with these sources. 
-# Note: To get rid of all source code in the generated output, make sure also 
-# VERBATIM_HEADERS is set to NO.
-
-SOURCE_BROWSER = NO
-
-# Setting the INLINE_SOURCES tag to YES will include the body 
-# of functions and classes directly in the documentation.
-
-INLINE_SOURCES = NO
-
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
-# doxygen to hide any special comment blocks from generated source code 
-# fragments. Normal C and C++ comments will always remain visible.
-
-STRIP_CODE_COMMENTS = YES
-
-# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
-# then for each documented function all documented 
-# functions referencing it will be listed.
-
-REFERENCED_BY_RELATION = YES
-
-# If the REFERENCES_RELATION tag is set to YES (the default) 
-# then for each documented function all documented entities 
-# called/used by that function will be listed.
-
-REFERENCES_RELATION = YES
-
-# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
-# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
-# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
-# link to the source code.  Otherwise they will link to the documentstion.
-
-REFERENCES_LINK_SOURCE = YES
-
-# If the USE_HTAGS tag is set to YES then the references to source code 
-# will point to the HTML generated by the htags(1) tool instead of doxygen 
-# built-in source browser. The htags tool is part of GNU's global source 
-# tagging system (see http://www.gnu.org/software/global/global.html). You 
-# will need version 4.8.6 or higher.
-
-USE_HTAGS = NO
-
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
-# will generate a verbatim copy of the header file for each class for 
-# which an include is specified. Set to NO to disable this.
-
-VERBATIM_HEADERS = YES
-
-#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
-#---------------------------------------------------------------------------
-
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
-# of all compounds will be generated. Enable this if the project 
-# contains a lot of classes, structs, unions or interfaces.
-
-ALPHABETICAL_INDEX = NO
-
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
-# in which this list will be split (can be a number in the range [1..20])
-
-COLS_IN_ALPHA_INDEX = 5
-
-# In case all classes in a project start with a common prefix, all 
-# classes will be put under the same header in the alphabetical index. 
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
-# should be ignored while generating the index headers.
-
-IGNORE_PREFIX = 
-
-#---------------------------------------------------------------------------
-# configuration options related to the HTML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
-# generate HTML output.
-
-GENERATE_HTML = $(GENERATE_HTML)
-
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `html' will be used as the default path.
-
-HTML_OUTPUT = html
-
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
-# doxygen will generate files with .html extension.
-
-HTML_FILE_EXTENSION = .html
-
-# The HTML_HEADER tag can be used to specify a personal HTML header for 
-# each generated HTML page. If it is left blank doxygen will generate a 
-# standard header.
-
-HTML_HEADER = 
-
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
-# each generated HTML page. If it is left blank doxygen will generate a 
-# standard footer.
-
-HTML_FOOTER = 
-
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
-# style sheet that is used by each HTML page. It can be used to 
-# fine-tune the look of the HTML output. If the tag is left blank doxygen 
-# will generate a default style sheet. Note that doxygen will try to copy 
-# the style sheet file to the HTML output directory, so don't put your own 
-# stylesheet in the HTML output directory as well, or it will be erased!
-
-HTML_STYLESHEET = 
-
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
-# files or namespaces will be aligned in HTML using tables. If set to 
-# NO a bullet list will be used.
-
-HTML_ALIGN_MEMBERS = YES
-
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
-# will be generated that can be used as input for tools like the 
-# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
-# of the generated HTML documentation.
-
-GENERATE_HTMLHELP = $(GENERATE_HTMLHELP)
-
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
-# be used to specify the file name of the resulting .chm file. You 
-# can add a path in front of the file if the result should not be 
-# written to the html output directory.
-
-CHM_FILE = ../$(PROJECT).chm
-
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
-# be used to specify the location (absolute path including file name) of 
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
-# the HTML help compiler on the generated index.hhp.
-
-HHC_LOCATION = $(HHC_PATH)
-
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
-# controls if a separate .chi index file is generated (YES) or that 
-# it should be included in the master .chm file (NO).
-
-GENERATE_CHI = $(GENERATE_CHI)
-
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
-# controls whether a binary table of contents is generated (YES) or a 
-# normal table of contents (NO) in the .chm file.
-
-BINARY_TOC = NO
-
-# The TOC_EXPAND flag can be set to YES to add extra items for group members 
-# to the contents of the HTML help documentation and to the tree view.
-
-TOC_EXPAND = NO
-
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
-# top of each HTML page. The value NO (the default) enables the index and 
-# the value YES disables it.
-
-DISABLE_INDEX = NO
-
-# This tag can be used to set the number of enum values (range [1..20]) 
-# that doxygen will group on one line in the generated HTML documentation.
-
-ENUM_VALUES_PER_LINE = 4
-
-# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
-# generated containing a tree-like index structure (just like the one that 
-# is generated for HTML Help). For this to work a browser that supports 
-# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
-# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
-# probably better off using the HTML help feature.
-
-GENERATE_TREEVIEW = NO
-
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
-# used to set the initial width (in pixels) of the frame in which the tree 
-# is shown.
-
-TREEVIEW_WIDTH = 250
-
-#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
-# generate Latex output.
-
-GENERATE_LATEX = $(GENERATE_LATEX)
-
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `latex' will be used as the default path.
-
-LATEX_OUTPUT = latex
-
-# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
-# invoked. If left blank `latex' will be used as the default command name.
-
-LATEX_CMD_NAME = latex
-
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
-# generate index for LaTeX. If left blank `makeindex' will be used as the 
-# default command name.
-
-MAKEINDEX_CMD_NAME = makeindex
-
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
-# LaTeX documents. This may be useful for small projects and may help to 
-# save some trees in general.
-
-COMPACT_LATEX = NO
-
-# The PAPER_TYPE tag can be used to set the paper type that is used 
-# by the printer. Possible values are: a4, a4wide, letter, legal and 
-# executive. If left blank a4wide will be used.
-
-PAPER_TYPE = $(PAPER_SIZE)
-
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
-# packages that should be included in the LaTeX output.
-
-EXTRA_PACKAGES = 
-
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
-# the generated latex document. The header should contain everything until 
-# the first chapter. If it is left blank doxygen will generate a 
-# standard header. Notice: only use this tag if you know what you are doing!
-
-LATEX_HEADER = 
-
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
-# contain links (just like the HTML output) instead of page references 
-# This makes the output suitable for online browsing using a pdf viewer.
-
-PDF_HYPERLINKS = NO
-
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
-# plain latex in the generated Makefile. Set this option to YES to get a 
-# higher quality PDF documentation.
-
-USE_PDFLATEX = $(GENERATE_PDF)
-
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
-# command to the generated LaTeX files. This will instruct LaTeX to keep 
-# running if errors occur, instead of asking the user for help. 
-# This option is also used when generating formulas in HTML.
-
-LATEX_BATCHMODE = NO
-
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
-# include the index chapters (such as File Index, Compound Index, etc.) 
-# in the output.
-
-LATEX_HIDE_INDICES = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the RTF output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
-# The RTF output is optimized for Word 97 and may not look very pretty with 
-# other RTF readers or editors.
-
-GENERATE_RTF = $(GENERATE_RTF)
-
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `rtf' will be used as the default path.
-
-RTF_OUTPUT = rtf
-
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
-# RTF documents. This may be useful for small projects and may help to 
-# save some trees in general.
-
-COMPACT_RTF = NO
-
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
-# will contain hyperlink fields. The RTF file will 
-# contain links (just like the HTML output) instead of page references. 
-# This makes the output suitable for online browsing using WORD or other 
-# programs which support those fields. 
-# Note: wordpad (write) and others do not support links.
-
-RTF_HYPERLINKS = NO
-
-# Load stylesheet definitions from file. Syntax is similar to doxygen's 
-# config file, i.e. a series of assignments. You only have to provide 
-# replacements, missing definitions are set to their default value.
-
-RTF_STYLESHEET_FILE = 
-
-# Set optional variables used in the generation of an rtf document. 
-# Syntax is similar to doxygen's config file.
-
-RTF_EXTENSIONS_FILE = 
-
-#---------------------------------------------------------------------------
-# configuration options related to the man page output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
-# generate man pages
-
-GENERATE_MAN = $(GENERATE_MAN)
-
-# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `man' will be used as the default path.
-
-MAN_OUTPUT = man
-
-# The MAN_EXTENSION tag determines the extension that is added to 
-# the generated man pages (default is the subroutine's section .3)
-
-MAN_EXTENSION = .3
-
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
-# then it will generate one additional man file for each entity 
-# documented in the real man page(s). These additional files 
-# only source the real man page, but without them the man command 
-# would be unable to find the correct page. The default is NO.
-
-MAN_LINKS = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the XML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_XML tag is set to YES Doxygen will 
-# generate an XML file that captures the structure of 
-# the code including all documentation.
-
-GENERATE_XML = $(GENERATE_XML)
-
-# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `xml' will be used as the default path.
-
-XML_OUTPUT = xml
-
-# The XML_SCHEMA tag can be used to specify an XML schema, 
-# which can be used by a validating XML parser to check the 
-# syntax of the XML files.
-
-XML_SCHEMA = 
-
-# The XML_DTD tag can be used to specify an XML DTD, 
-# which can be used by a validating XML parser to check the 
-# syntax of the XML files.
-
-XML_DTD = 
-
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
-# dump the program listings (including syntax highlighting 
-# and cross-referencing information) to the XML output. Note that 
-# enabling this will significantly increase the size of the XML output.
-
-XML_PROGRAMLISTING = YES
-
-#---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
-# generate an AutoGen Definitions (see autogen.sf.net) file 
-# that captures the structure of the code including all 
-# documentation. Note that this feature is still experimental 
-# and incomplete at the moment.
-
-GENERATE_AUTOGEN_DEF = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the Perl module output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
-# generate a Perl module file that captures the structure of 
-# the code including all documentation. Note that this 
-# feature is still experimental and incomplete at the 
-# moment.
-
-GENERATE_PERLMOD = NO
-
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
-# to generate PDF and DVI output from the Perl module output.
-
-PERLMOD_LATEX = NO
-
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
-# nicely formatted so it can be parsed by a human reader.  This is useful 
-# if you want to understand what is going on.  On the other hand, if this 
-# tag is set to NO the size of the Perl module output will be much smaller 
-# and Perl will parse it just the same.
-
-PERLMOD_PRETTY = YES
-
-# The names of the make variables in the generated doxyrules.make file 
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
-# This is useful so different doxyrules.make files included by the same 
-# Makefile don't overwrite each other's variables.
-
-PERLMOD_MAKEVAR_PREFIX = 
-
-#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor   
-#---------------------------------------------------------------------------
-
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
-# evaluate all C-preprocessor directives found in the sources and include 
-# files.
-
-ENABLE_PREPROCESSING = YES
-
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
-# names in the source code. If set to NO (the default) only conditional 
-# compilation will be performed. Macro expansion can be done in a controlled 
-# way by setting EXPAND_ONLY_PREDEF to YES.
-
-MACRO_EXPANSION = NO
-
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
-# then the macro expansion is limited to the macros specified with the 
-# PREDEFINED and EXPAND_AS_DEFINED tags.
-
-EXPAND_ONLY_PREDEF = NO
-
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
-# in the INCLUDE_PATH (see below) will be search if a #include is found.
-
-SEARCH_INCLUDES = YES
-
-# The INCLUDE_PATH tag can be used to specify one or more directories that 
-# contain include files that are not input files but should be processed by 
-# the preprocessor.
-
-INCLUDE_PATH = 
-
-# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
-# patterns (like *.h and *.hpp) to filter out the header-files in the 
-# directories. If left blank, the patterns specified with FILE_PATTERNS will 
-# be used.
-
-INCLUDE_FILE_PATTERNS = 
-
-# The PREDEFINED tag can be used to specify one or more macro names that 
-# are defined before the preprocessor is started (similar to the -D option of 
-# gcc). The argument of the tag is a list of macros of the form: name 
-# or name=definition (no spaces). If the definition and the = are 
-# omitted =1 is assumed. To prevent a macro definition from being 
-# undefined via #undef or recursively expanded use the := operator 
-# instead of the = operator.
-
-PREDEFINED = 
-
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
-# this tag can be used to specify a list of macro names that should be expanded. 
-# The macro definition that is found in the sources will be used. 
-# Use the PREDEFINED tag if you want to use a different macro definition.
-
-EXPAND_AS_DEFINED = 
-
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
-# doxygen's preprocessor will remove all function-like macros that are alone 
-# on a line, have an all uppercase name, and do not end with a semicolon. Such 
-# function macros are typically used for boiler-plate code, and will confuse 
-# the parser if not removed.
-
-SKIP_FUNCTION_MACROS = YES
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to external references   
-#---------------------------------------------------------------------------
-
-# The TAGFILES option can be used to specify one or more tagfiles. 
-# Optionally an initial location of the external documentation 
-# can be added for each tagfile. The format of a tag file without 
-# this location is as follows: 
-#   TAGFILES = file1 file2 ... 
-# Adding location for the tag files is done as follows: 
-#   TAGFILES = file1=loc1 "file2 = loc2" ... 
-# where "loc1" and "loc2" can be relative or absolute paths or 
-# URLs. If a location is present for each tag, the installdox tool 
-# does not have to be run to correct the links.
-# Note that each tag file must have a unique name
-# (where the name does NOT include the path)
-# If a tag file is not located in the directory in which doxygen 
-# is run, you must also specify the path to the tagfile here.
-
-TAGFILES = 
-
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
-# a tag file that is based on the input files it reads.
-
-GENERATE_TAGFILE = $(DOCDIR)/$(PROJECT).tag
-
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
-# in the class index. If set to NO only the inherited external classes 
-# will be listed.
-
-ALLEXTERNALS = NO
-
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
-# in the modules index. If set to NO, only the current project's groups will 
-# be listed.
-
-EXTERNAL_GROUPS = YES
-
-# The PERL_PATH should be the absolute path and name of the perl script 
-# interpreter (i.e. the result of `which perl').
-
-PERL_PATH = /usr/bin/perl
-
-#---------------------------------------------------------------------------
-# Configuration options related to the dot tool   
-#---------------------------------------------------------------------------
-
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
-# or super classes. Setting the tag to NO turns the diagrams off. Note that 
-# this option is superseded by the HAVE_DOT option below. This is only a 
-# fallback. It is recommended to install and use dot, since it yields more 
-# powerful graphs.
-
-CLASS_DIAGRAMS = YES
-
-# If set to YES, the inheritance and collaboration graphs will hide 
-# inheritance and usage relations if the target is undocumented 
-# or is not a class.
-
-HIDE_UNDOC_RELATIONS = YES
-
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
-# available from the path. This tool is part of Graphviz, a graph visualization 
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
-# have no effect if this option is set to NO (the default)
-
-HAVE_DOT = $(HAVE_DOT)
-
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
-# will generate a graph for each documented class showing the direct and 
-# indirect inheritance relations. Setting this tag to YES will force the 
-# the CLASS_DIAGRAMS tag to NO.
-
-CLASS_GRAPH = YES
-
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
-# will generate a graph for each documented class showing the direct and 
-# indirect implementation dependencies (inheritance, containment, and 
-# class references variables) of the class with other documented classes.
-
-COLLABORATION_GRAPH = YES
-
-# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
-# will generate a graph for groups, showing the direct groups dependencies
-
-GROUP_GRAPHS = YES
-
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
-# collaboration diagrams in a style similar to the OMG's Unified Modeling 
-# Language.
-
-UML_LOOK = NO
-
-# If set to YES, the inheritance and collaboration graphs will show the 
-# relations between templates and their instances.
-
-TEMPLATE_RELATIONS = NO
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
-# tags are set to YES then doxygen will generate a graph for each documented 
-# file showing the direct and indirect include dependencies of the file with 
-# other documented files.
-
-INCLUDE_GRAPH = YES
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
-# documented header file showing the documented files that directly or 
-# indirectly include this file.
-
-INCLUDED_BY_GRAPH = YES
-
-# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
-# generate a call dependency graph for every global function or class method. 
-# Note that enabling this option will significantly increase the time of a run. 
-# So in most cases it will be better to enable call graphs for selected 
-# functions only using the \callgraph command.
-
-CALL_GRAPH = NO
-
-# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
-# generate a caller dependency graph for every global function or class method. 
-# Note that enabling this option will significantly increase the time of a run. 
-# So in most cases it will be better to enable caller graphs for selected 
-# functions only using the \callergraph command.
-
-CALLER_GRAPH = NO
-
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
-# will graphical hierarchy of all classes instead of a textual one.
-
-GRAPHICAL_HIERARCHY = YES
-
-# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
-# then doxygen will show the dependencies a directory has on other directories 
-# in a graphical way. The dependency relations are determined by the #include
-# relations between the files in the directories.
-
-DIRECTORY_GRAPH = YES
-
-# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
-# generated by dot. Possible values are png, jpg, or gif
-# If left blank png will be used.
-
-DOT_IMAGE_FORMAT = png
-
-# The tag DOT_PATH can be used to specify the path where the dot tool can be 
-# found. If left blank, it is assumed the dot tool can be found in the path.
-
-DOT_PATH = $(DOT_PATH)
-
-# The DOTFILE_DIRS tag can be used to specify one or more directories that 
-# contain dot files that are included in the documentation (see the 
-# \dotfile command).
-
-DOTFILE_DIRS = 
-
-# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
-# this value, doxygen will try to truncate the graph, so that it fits within 
-# the specified constraint. Beware that most browsers cannot cope with very 
-# large images.
-
-MAX_DOT_GRAPH_WIDTH = 1024
-
-# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
-# this value, doxygen will try to truncate the graph, so that it fits within 
-# the specified constraint. Beware that most browsers cannot cope with very 
-# large images.
-
-MAX_DOT_GRAPH_HEIGHT = 1024
-
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
-# graphs generated by dot. A depth value of 3 means that only nodes reachable 
-# from the root by following a path via at most 3 edges will be shown. Nodes 
-# that lay further from the root node will be omitted. Note that setting this 
-# option to 1 or 2 may greatly reduce the computation time needed for large 
-# code bases. Also note that a graph may be further truncated if the graph's 
-# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH 
-# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), 
-# the graph is not depth-constrained.
-
-MAX_DOT_GRAPH_DEPTH = 0
-
-# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
-# background. This is disabled by default, which results in a white background. 
-# Warning: Depending on the platform used, enabling this option may lead to 
-# badly anti-aliased labels on the edges of a graph (i.e. they become hard to 
-# read).
-
-DOT_TRANSPARENT = NO
-
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
-# files in one run (i.e. multiple -o and -T options on the command line). This 
-# makes dot run faster, but since only newer versions of dot (>1.8.10) 
-# support this, this feature is disabled by default.
-
-DOT_MULTI_TARGETS = NO
-
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
-# generate a legend page explaining the meaning of the various boxes and 
-# arrows in the dot generated graphs.
-
-GENERATE_LEGEND = YES
-
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
-# remove the intermediate dot files that are used to generate 
-# the various graphs.
-
-DOT_CLEANUP = YES
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to the search engine   
-#---------------------------------------------------------------------------
-
-# The SEARCHENGINE tag specifies whether or not a search engine should be 
-# used. If set to NO the values of all tags below this one will be ignored.
-
-SEARCHENGINE = NO
+# Doxyfile 1.4.7
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME = $(PROJECT)-$(VERSION)
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER = 
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = $(DOCDIR)
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, 
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, 
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, 
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, 
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# This tag can be used to specify the encoding used in the generated output. 
+# The encoding is not always determined by the language that is chosen, 
+# but also whether or not the output is meant for Windows or non-Windows users. 
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES 
+# forces the Windows encoding (this is the default for the Windows binary), 
+# whereas setting the tag to NO uses a Unix-style encoding (the default for 
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF = 
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
+
+STRIP_FROM_PATH = 
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like the Qt-style comments (thus requiring an 
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
+# sources only. Doxygen will then generate output that is more tailored for Java. 
+# For instance, namespaces will be presented as packages, qualified scopes 
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to 
+# include (a tag file for) the STL sources as input, then you should 
+# set this tag to YES in order to let doxygen match functions declarations and 
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 
+# func(std::string) {}). This also make the inheritance and collaboration 
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST = YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from the 
+# version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the program writes to standard output 
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT = include/zookeeper.h
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
+
+FILE_PATTERNS = 
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE = 
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
+# directories that are symbolic links (a Unix filesystem feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories. Note that the wildcards are matched 
+# against the file with absolute path, so to exclude all test directories 
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS = 
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# is applied to all files.
+
+FILTER_PATTERNS = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default) 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.  Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code 
+# will point to the HTML generated by the htags(1) tool instead of doxygen 
+# built-in source browser. The htags tool is part of GNU's global source 
+# tagging system (see http://www.gnu.org/software/global/global.html). You 
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML = $(GENERATE_HTML)
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = $(GENERATE_HTMLHELP)
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE = ../$(PROJECT).chm
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION = $(HHC_PATH)
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = $(GENERATE_CHI)
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX = $(GENERATE_LATEX)
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = $(PAPER_SIZE)
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX = $(GENERATE_PDF)
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF = $(GENERATE_RTF)
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN = $(GENERATE_MAN)
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML = $(GENERATE_XML)
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse 
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE = $(DOCDIR)/$(PROJECT).tag
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option is superseded by the HAVE_DOT option below. This is only a 
+# fallback. It is recommended to install and use dot, since it yields more 
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = $(HAVE_DOT)
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
+# generate a call dependency graph for every global function or class method. 
+# Note that enabling this option will significantly increase the time of a run. 
+# So in most cases it will be better to enable call graphs for selected 
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
+# generate a caller dependency graph for every global function or class method. 
+# Note that enabling this option will significantly increase the time of a run. 
+# So in most cases it will be better to enable caller graphs for selected 
+# functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH = $(DOT_PATH)
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS = 
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes 
+# that lay further from the root node will be omitted. Note that setting this 
+# option to 1 or 2 may greatly reduce the computation time needed for large 
+# code bases. Also note that a graph may be further truncated if the graph's 
+# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH 
+# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), 
+# the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is disabled by default, which results in a white background. 
+# Warning: Depending on the platform used, enabling this option may lead to 
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to 
+# read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO

+ 126 - 126
src/contrib/loggraph/web/org/apache/zookeeper/graph/resources/date.format.js

@@ -1,126 +1,126 @@
-/*
- * Date Format 1.2.3
- * (c) 2007-2009 Steven Levithan <stevenlevithan.com>
- * MIT license
- *
- * Includes enhancements by Scott Trenda <scott.trenda.net>
- * and Kris Kowal <cixar.com/~kris.kowal/>
- *
- * Accepts a date, a mask, or a date and a mask.
- * Returns a formatted version of the given date.
- * The date defaults to the current date/time.
- * The mask defaults to dateFormat.masks.default.
- */
-
-var dateFormat = function () {
-	var	token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
-		timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
-		timezoneClip = /[^-+\dA-Z]/g,
-		pad = function (val, len) {
-			val = String(val);
-			len = len || 2;
-			while (val.length < len) val = "0" + val;
-			return val;
-		};
-
-	// Regexes and supporting functions are cached through closure
-	return function (date, mask, utc) {
-		var dF = dateFormat;
-
-		// You can't provide utc if you skip other args (use the "UTC:" mask prefix)
-		if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
-			mask = date;
-			date = undefined;
-		}
-
-		// Passing date through Date applies Date.parse, if necessary
-		date = date ? new Date(date) : new Date;
-		if (isNaN(date)) throw SyntaxError("invalid date");
-
-		mask = String(dF.masks[mask] || mask || dF.masks["default"]);
-
-		// Allow setting the utc argument via the mask
-		if (mask.slice(0, 4) == "UTC:") {
-			mask = mask.slice(4);
-			utc = true;
-		}
-
-		var	_ = utc ? "getUTC" : "get",
-			d = date[_ + "Date"](),
-			D = date[_ + "Day"](),
-			m = date[_ + "Month"](),
-			y = date[_ + "FullYear"](),
-			H = date[_ + "Hours"](),
-			M = date[_ + "Minutes"](),
-			s = date[_ + "Seconds"](),
-			L = date[_ + "Milliseconds"](),
-			o = utc ? 0 : date.getTimezoneOffset(),
-			flags = {
-				d:    d,
-				dd:   pad(d),
-				ddd:  dF.i18n.dayNames[D],
-				dddd: dF.i18n.dayNames[D + 7],
-				m:    m + 1,
-				mm:   pad(m + 1),
-				mmm:  dF.i18n.monthNames[m],
-				mmmm: dF.i18n.monthNames[m + 12],
-				yy:   String(y).slice(2),
-				yyyy: y,
-				h:    H % 12 || 12,
-				hh:   pad(H % 12 || 12),
-				H:    H,
-				HH:   pad(H),
-				M:    M,
-				MM:   pad(M),
-				s:    s,
-				ss:   pad(s),
-				l:    pad(L, 3),
-				L:    pad(L > 99 ? Math.round(L / 10) : L),
-				t:    H < 12 ? "a"  : "p",
-				tt:   H < 12 ? "am" : "pm",
-				T:    H < 12 ? "A"  : "P",
-				TT:   H < 12 ? "AM" : "PM",
-				Z:    utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
-				o:    (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
-				S:    ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
-			};
-
-		return mask.replace(token, function ($0) {
-			return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
-		});
-	};
-}();
-
-// Some common format strings
-dateFormat.masks = {
-	"default":      "ddd mmm dd yyyy HH:MM:ss",
-	shortDate:      "m/d/yy",
-	mediumDate:     "mmm d, yyyy",
-	longDate:       "mmmm d, yyyy",
-	fullDate:       "dddd, mmmm d, yyyy",
-	shortTime:      "h:MM TT",
-	mediumTime:     "h:MM:ss TT",
-	longTime:       "h:MM:ss TT Z",
-	isoDate:        "yyyy-mm-dd",
-	isoTime:        "HH:MM:ss",
-	isoDateTime:    "yyyy-mm-dd'T'HH:MM:ss",
-	isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
-};
-
-// Internationalization strings
-dateFormat.i18n = {
-	dayNames: [
-		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
-		"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
-	],
-	monthNames: [
-		"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
-		"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
-	]
-};
-
-// For convenience...
-Date.prototype.format = function (mask, utc) {
-	return dateFormat(this, mask, utc);
-};
-
+/*
+ * Date Format 1.2.3
+ * (c) 2007-2009 Steven Levithan <stevenlevithan.com>
+ * MIT license
+ *
+ * Includes enhancements by Scott Trenda <scott.trenda.net>
+ * and Kris Kowal <cixar.com/~kris.kowal/>
+ *
+ * Accepts a date, a mask, or a date and a mask.
+ * Returns a formatted version of the given date.
+ * The date defaults to the current date/time.
+ * The mask defaults to dateFormat.masks.default.
+ */
+
+var dateFormat = function () {
+	var	token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
+		timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
+		timezoneClip = /[^-+\dA-Z]/g,
+		pad = function (val, len) {
+			val = String(val);
+			len = len || 2;
+			while (val.length < len) val = "0" + val;
+			return val;
+		};
+
+	// Regexes and supporting functions are cached through closure
+	return function (date, mask, utc) {
+		var dF = dateFormat;
+
+		// You can't provide utc if you skip other args (use the "UTC:" mask prefix)
+		if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
+			mask = date;
+			date = undefined;
+		}
+
+		// Passing date through Date applies Date.parse, if necessary
+		date = date ? new Date(date) : new Date;
+		if (isNaN(date)) throw SyntaxError("invalid date");
+
+		mask = String(dF.masks[mask] || mask || dF.masks["default"]);
+
+		// Allow setting the utc argument via the mask
+		if (mask.slice(0, 4) == "UTC:") {
+			mask = mask.slice(4);
+			utc = true;
+		}
+
+		var	_ = utc ? "getUTC" : "get",
+			d = date[_ + "Date"](),
+			D = date[_ + "Day"](),
+			m = date[_ + "Month"](),
+			y = date[_ + "FullYear"](),
+			H = date[_ + "Hours"](),
+			M = date[_ + "Minutes"](),
+			s = date[_ + "Seconds"](),
+			L = date[_ + "Milliseconds"](),
+			o = utc ? 0 : date.getTimezoneOffset(),
+			flags = {
+				d:    d,
+				dd:   pad(d),
+				ddd:  dF.i18n.dayNames[D],
+				dddd: dF.i18n.dayNames[D + 7],
+				m:    m + 1,
+				mm:   pad(m + 1),
+				mmm:  dF.i18n.monthNames[m],
+				mmmm: dF.i18n.monthNames[m + 12],
+				yy:   String(y).slice(2),
+				yyyy: y,
+				h:    H % 12 || 12,
+				hh:   pad(H % 12 || 12),
+				H:    H,
+				HH:   pad(H),
+				M:    M,
+				MM:   pad(M),
+				s:    s,
+				ss:   pad(s),
+				l:    pad(L, 3),
+				L:    pad(L > 99 ? Math.round(L / 10) : L),
+				t:    H < 12 ? "a"  : "p",
+				tt:   H < 12 ? "am" : "pm",
+				T:    H < 12 ? "A"  : "P",
+				TT:   H < 12 ? "AM" : "PM",
+				Z:    utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
+				o:    (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
+				S:    ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
+			};
+
+		return mask.replace(token, function ($0) {
+			return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
+		});
+	};
+}();
+
+// Some common format strings
+dateFormat.masks = {
+	"default":      "ddd mmm dd yyyy HH:MM:ss",
+	shortDate:      "m/d/yy",
+	mediumDate:     "mmm d, yyyy",
+	longDate:       "mmmm d, yyyy",
+	fullDate:       "dddd, mmmm d, yyyy",
+	shortTime:      "h:MM TT",
+	mediumTime:     "h:MM:ss TT",
+	longTime:       "h:MM:ss TT Z",
+	isoDate:        "yyyy-mm-dd",
+	isoTime:        "HH:MM:ss",
+	isoDateTime:    "yyyy-mm-dd'T'HH:MM:ss",
+	isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
+};
+
+// Internationalization strings
+dateFormat.i18n = {
+	dayNames: [
+		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+		"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
+	],
+	monthNames: [
+		"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+		"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
+	]
+};
+
+// For convenience...
+Date.prototype.format = function (mask, utc) {
+	return dateFormat(this, mask, utc);
+};
+

+ 93 - 93
src/contrib/zooinspector/README.txt

@@ -1,94 +1,94 @@
-==========================================
-ZooInspector - Browser and Editor for ZooKeeper Instances
-Author: Colin Goodheart-Smithe
-Date: February 2010
-==========================================
-
-ZooInspector is a Java Swing based application for browsing and editing ZooKeeper instances.
-
-Contents
---------
-	- Features
-	- Pre-requisites
-	- Build Instructions
-	- Using ZooInspector
-	- Creating and Using Plugins
-	
-Features
---------
-	Below is a list of features in the current release of ZooInspector.
-	- Load connection settings from a zookeeper properties file
-	- Plugable DataEncryptionManagers to specify how data should be encrypted and decrypted in the Zookeeper instance
-	- Browseable tree view of the ZooKeeper instance
-	- View the data in a node
-	- View the ACL's currently applied to a node
-	- View the metadata for a node (Version, Number of Children, Last modified Tiem, etc.)
-	- Plugable NodeViewers interface
-	- Ability to save/load and set default Node Viewers
-	
-Pre-requisites
---------------
-	- The main zookeeper build script must have been run before building this module
-	
-Build Instructions
-------------------
-	1. Open a command line.
-	2. cd into this directory
-	3. Run command: ant
-	4. ZooInspector will be built to ../../../build/contrib/ZooInspector
-	5. Copy zookeeper-3.x.x.jar into the lib sub-directory (if you are using zookeeper-3.3.0.jar it will have been
-       copied to this directory during the build
-	6. By default the zookeeper.cmd and zookeeper.sh files expect zookeeper-3.3.0.jar.  If you are using another version
-	   you will need to change these files to point to the zookeeper-3.x.x.jar you copied to the lib directory
-	7. To run ZooInspector run zooInspector.cmd (on Windows) or zooInspector.sh (on Linux).  If you are using 
-	   zookeeper-3.3.0.jar and do not require any classpath changes you can run the zookeeper-dev-ZooInspector.jar
-	   directly
-
-Using ZooInspector
-------------------
-	To start ZooInspector run zooInspector.cmd (on Windows) or zooInspector.sh (on Linux).  If you are using 
-	zookeeper-3.3.0.jar and do not require any classpath changes you can run the zookeeper-dev-ZooInspector.jar
-	directly.
-	
-	Click the play button on the toolbar to bring up the connection dialog.  From here you can enter connection 
-	information for your zookeeper instance.  You can also load the connection properties from a file.  This file can 
-	have the format as a normal zookeeper properties file (i.e. hosts and timeout key-value pairs) and van optional have
-	an encryptionManager key-value pair to specify the DataEncryptionManager to use for this connection 
-	(DataEncryptionManagers are explained in further detail in the 'Creating and Using Plugins' section below).  You can
-	also set the entered information as the defaults so that when you first start ZooInspector these settings are 
-	automatically loaded into this dialog.  Pressing the OK button with connect to your ZooKeeper instance and show the
-	current node tree on the left of the main panel.
-	
-	Clicking a node in the node tree will load the data for that node into the node viewers.  Three node viewers are 
-	currently distributed with ZooInspector:
-		1. Node Data - This enables you to see the data current stored on that node.  This data can be modified and 
-		   saved.  The data is decrypted and encrypted using the DataEncryptionManager specified on the connection 
-		   dialog.
-		2. Node Metadata - This enables you to see the metadata associiated with this node.  This is Essentially the data
-		   obtained from the Stat object for this node.
-		3. Node ACLs - This allows you to see the ACLs currently applied to this node.  Currently there is no ability
-		   to change the ACLs on a node, but it is a feature I would like to add.
-	Other custom Node Viewers can be added, this is explained in the 'Creating and Using Plugins' section below.
-	
-
-Creating and Using Plugins
---------------------------
-	There are two types of plugin which can be used with ZooInspector:
-		1. DataEncryptionManager - This specifies how data should be encrypted and decrypted when working with a 
-		   zookeeper instance.
-		2. ZooInspectorNodeViewer - This is a GUI panel which provides a view of visualisation on a node.
-	More information on these interfaces can be found in the javadocs for this module.
-	
-	To use a plugin in ZooInspector, build the plugin to a jar and copy the jar to the lib sub-directory.  Edit the 
-	zooInspector.cmd and/or zooInspector.sh files to include your new jar on the classpath and run ZooInspector.
-	
-	For DataEncryptionManagers, click the play button to open the connection dialog and enter the full class name of 
-	your DataEncryptionManager in the 'Data Encryption Manager' field.  You can make this Data Encryption Manager the 
-	default by clicking 'Set As Default'.  Click the 'OK' button to instantiate and use your plugin.
-	
-	For ZooInspectorNodeViewers, Click the 'Change Node Viewers' button on the toolbar (looks like a tree with a pencil)
-	and enter the full classname for your Node Viewer in the field left of the 'Add' button, then click the 'Add' 
-	button.  The Node Viewer will be instantiated and should appear in the list.  You can change the order of the Node 
-	viewers by clicking the up and dpwn buttons and delete a Node Viewer by clicking the delete button.  You can save 
-	to configuration to a file or set it as the default if necessary. Then click the 'OK' button and your Node Viewer 
+==========================================
+ZooInspector - Browser and Editor for ZooKeeper Instances
+Author: Colin Goodheart-Smithe
+Date: February 2010
+==========================================
+
+ZooInspector is a Java Swing based application for browsing and editing ZooKeeper instances.
+
+Contents
+--------
+	- Features
+	- Pre-requisites
+	- Build Instructions
+	- Using ZooInspector
+	- Creating and Using Plugins
+	
+Features
+--------
+	Below is a list of features in the current release of ZooInspector.
+	- Load connection settings from a zookeeper properties file
+	- Plugable DataEncryptionManagers to specify how data should be encrypted and decrypted in the Zookeeper instance
+	- Browseable tree view of the ZooKeeper instance
+	- View the data in a node
+	- View the ACL's currently applied to a node
+	- View the metadata for a node (Version, Number of Children, Last modified Tiem, etc.)
+	- Plugable NodeViewers interface
+	- Ability to save/load and set default Node Viewers
+	
+Pre-requisites
+--------------
+	- The main zookeeper build script must have been run before building this module
+	
+Build Instructions
+------------------
+	1. Open a command line.
+	2. cd into this directory
+	3. Run command: ant
+	4. ZooInspector will be built to ../../../build/contrib/ZooInspector
+	5. Copy zookeeper-3.x.x.jar into the lib sub-directory (if you are using zookeeper-3.3.0.jar it will have been
+       copied to this directory during the build
+	6. By default the zookeeper.cmd and zookeeper.sh files expect zookeeper-3.3.0.jar.  If you are using another version
+	   you will need to change these files to point to the zookeeper-3.x.x.jar you copied to the lib directory
+	7. To run ZooInspector run zooInspector.cmd (on Windows) or zooInspector.sh (on Linux).  If you are using 
+	   zookeeper-3.3.0.jar and do not require any classpath changes you can run the zookeeper-dev-ZooInspector.jar
+	   directly
+
+Using ZooInspector
+------------------
+	To start ZooInspector run zooInspector.cmd (on Windows) or zooInspector.sh (on Linux).  If you are using 
+	zookeeper-3.3.0.jar and do not require any classpath changes you can run the zookeeper-dev-ZooInspector.jar
+	directly.
+	
+	Click the play button on the toolbar to bring up the connection dialog.  From here you can enter connection 
+	information for your zookeeper instance.  You can also load the connection properties from a file.  This file can 
+	have the format as a normal zookeeper properties file (i.e. hosts and timeout key-value pairs) and van optional have
+	an encryptionManager key-value pair to specify the DataEncryptionManager to use for this connection 
+	(DataEncryptionManagers are explained in further detail in the 'Creating and Using Plugins' section below).  You can
+	also set the entered information as the defaults so that when you first start ZooInspector these settings are 
+	automatically loaded into this dialog.  Pressing the OK button with connect to your ZooKeeper instance and show the
+	current node tree on the left of the main panel.
+	
+	Clicking a node in the node tree will load the data for that node into the node viewers.  Three node viewers are 
+	currently distributed with ZooInspector:
+		1. Node Data - This enables you to see the data current stored on that node.  This data can be modified and 
+		   saved.  The data is decrypted and encrypted using the DataEncryptionManager specified on the connection 
+		   dialog.
+		2. Node Metadata - This enables you to see the metadata associiated with this node.  This is Essentially the data
+		   obtained from the Stat object for this node.
+		3. Node ACLs - This allows you to see the ACLs currently applied to this node.  Currently there is no ability
+		   to change the ACLs on a node, but it is a feature I would like to add.
+	Other custom Node Viewers can be added, this is explained in the 'Creating and Using Plugins' section below.
+	
+
+Creating and Using Plugins
+--------------------------
+	There are two types of plugin which can be used with ZooInspector:
+		1. DataEncryptionManager - This specifies how data should be encrypted and decrypted when working with a 
+		   zookeeper instance.
+		2. ZooInspectorNodeViewer - This is a GUI panel which provides a view of visualisation on a node.
+	More information on these interfaces can be found in the javadocs for this module.
+	
+	To use a plugin in ZooInspector, build the plugin to a jar and copy the jar to the lib sub-directory.  Edit the 
+	zooInspector.cmd and/or zooInspector.sh files to include your new jar on the classpath and run ZooInspector.
+	
+	For DataEncryptionManagers, click the play button to open the connection dialog and enter the full class name of 
+	your DataEncryptionManager in the 'Data Encryption Manager' field.  You can make this Data Encryption Manager the 
+	default by clicking 'Set As Default'.  Click the 'OK' button to instantiate and use your plugin.
+	
+	For ZooInspectorNodeViewers, Click the 'Change Node Viewers' button on the toolbar (looks like a tree with a pencil)
+	and enter the full classname for your Node Viewer in the field left of the 'Add' button, then click the 'Add' 
+	button.  The Node Viewer will be instantiated and should appear in the list.  You can change the order of the Node 
+	viewers by clicking the up and dpwn buttons and delete a Node Viewer by clicking the delete button.  You can save 
+	to configuration to a file or set it as the default if necessary. Then click the 'OK' button and your Node Viewer 
 	should appear in the tabs on the right of the main panel.

+ 139 - 139
src/contrib/zooinspector/build.xml

@@ -1,139 +1,139 @@
-<!--
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You under the Apache License, Version 2.0
-   (the "License"); you may not use this file except in compliance with
-   the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
--->
-
-<project name="ZooInspector" default="jar">
-	<import file="../build-contrib.xml" />
-
-
-	<target name="setjarname">
-		<property name="jarname" value="${build.dir}/zookeeper-${version}-${name}.jar" />
-	</target>
-
-	<target name="init" depends="checkMainCompiled, zookeeperbuildcontrib.init">
-		<mkdir dir="${build.dir}/licences" />
-		<copy todir="${build.dir}/licences">
-			<fileset dir="${basedir}/licences" />
-		</copy>
-		<mkdir dir="${build.dir}/icons" />
-		<copy todir="${build.dir}/icons">
-			<fileset dir="${basedir}/src/main/resources/icons" />
-		</copy>
-		<mkdir dir="${build.dir}/config" />
-		<copy todir="${build.dir}/config">
-			<fileset dir="${basedir}/config" />
-		</copy>
-		<copy todir="${build.dir}/lib">
-			<fileset file="${basedir}/lib/log4j.properties" />
-		</copy>
-		<copy todir="${build.dir}/lib">
-			<fileset file="../../../build/zookeeper-${version}.jar" />
-		</copy>
-		<copy todir="${build.dir}">
-			<fileset dir="${basedir}" includes="*.*" excludes="build.xml,ivy.xml" />
-		</copy>
-	</target>
-
-	<!-- Override jar target to specify main class -->
-	<target name="jar" depends="setjarname, compile">
-		<echo message="contrib: ${name}" />
-
-		<jar jarfile="${jarname}">
-			<manifest>
-				<attribute name="Main-Class" value="org.apache.zookeeper.inspector.ZooInspector" />
-				<attribute name="Built-By" value="${user.name}" />
-				<attribute name="Built-At" value="${build.time}" />
-				<attribute name="Built-On" value="${host.name}" />
-				<attribute name="Implementation-Title" value="org.apache.zookeeper" />
-				<attribute name="Implementation-Version" value="${revision}" />
-				<attribute name="Implementation-Vendor" value="The Apache Software Foundation" />
-			</manifest>
-			<fileset file="${zk.root}/LICENSE.txt" />
-			<fileset dir="${build.classes}" />
-			<fileset dir="${basedir}/src/main/resources" />
-			<fileset dir="${basedir}/src/java" excludes="**/*.jar, **/*.java"/>
-		</jar>
-	</target>
-
-	<target name="compile" depends="ivy-retrieve,zookeeperbuildcontrib.compile" />
-
-	<target name="test" depends="checkMainTestCompiled,compile-test,test-init,test-category,junit.run" />
-
-	<target name="compile-test" depends="ivy-retrieve-test,compile">
-		<property name="target.jdk" value="${ant.java.version}" />
-		<property name="src.test.local" location="${basedir}/test" />
-		<mkdir dir="${build.test}" />
-		<javac srcdir="${src.test.local}" destdir="${build.test}" target="${target.jdk}" debug="on">
-			<classpath refid="classpath" />
-			<classpath>
-				<pathelement location="${zk.root}/build/test/classes" />
-			</classpath>
-		</javac>
-	</target>
-
-	<target name="test-init" depends="jar,compile-test">
-		<delete dir="${test.log.dir}" />
-		<delete dir="${test.tmp.dir}" />
-		<delete dir="${test.data.dir}" />
-		<mkdir dir="${test.log.dir}" />
-		<mkdir dir="${test.tmp.dir}" />
-		<mkdir dir="${test.data.dir}" />
-	</target>
-
-	<target name="test-category">
-		<property name="test.category" value="" />
-	</target>
-
-	<target name="junit.run">
-		<echo message="${test.src.dir}" />
-		<junit showoutput="${test.output}" printsummary="${test.junit.printsummary}" haltonfailure="${test.junit.haltonfailure}" fork="yes" forkmode="${test.junit.fork.mode}" maxmemory="${test.junit.maxmem}" dir="${basedir}" timeout="${test.timeout}" errorProperty="tests.failed" failureProperty="tests.failed">
-			<sysproperty key="build.test.dir" value="${test.tmp.dir}" />
-			<sysproperty key="test.data.dir" value="${test.data.dir}" />
-			<sysproperty key="log4j.configuration" value="file:${basedir}/conf/log4j.properties" />
-			<classpath refid="classpath" />
-			<classpath>
-				<pathelement path="${build.test}" />
-				<pathelement location="${zk.root}/build/test/classes" />
-			</classpath>
-			<formatter type="${test.junit.output.format}" />
-			<batchtest todir="${test.log.dir}" unless="testcase">
-				<fileset dir="${test.src.dir}" includes="**/*${test.category}Test.java" />
-			</batchtest>
-			<batchtest todir="${test.log.dir}" if="testcase">
-				<fileset dir="${test.src.dir}" includes="**/${testcase}.java" />
-			</batchtest>
-		</junit>
-		<fail if="tests.failed">Tests failed!</fail>
-	</target>
-
-	<target name="package" depends="jar, zookeeperbuildcontrib.package" unless="skip.contrib">
-
-		<copy file="${basedir}/build.xml" todir="${dist.dir}/contrib/${name}" />
-
-		<mkdir dir="${dist.dir}/contrib/${name}/src" />
-		<copy todir="${dist.dir}/contrib/${name}/src">
-			<fileset dir="${basedir}/src" />
-		</copy>
-		<mkdir dir="${dist.dir}/contrib/${name}/licences" />
-		<copy todir="${dist.dir}/contrib/${name}/licences">
-			<fileset dir="${basedir}/licences" />
-		</copy>
-		<mkdir dir="${dist.dir}/contrib/${name}/config" />
-		<copy todir="${dist.dir}/contrib/${name}/config">
-			<fileset dir="${basedir}/config" />
-		</copy>
-	</target>
-</project>
+<!--
+   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.
+-->
+
+<project name="ZooInspector" default="jar">
+	<import file="../build-contrib.xml" />
+
+
+	<target name="setjarname">
+		<property name="jarname" value="${build.dir}/zookeeper-${version}-${name}.jar" />
+	</target>
+
+	<target name="init" depends="checkMainCompiled, zookeeperbuildcontrib.init">
+		<mkdir dir="${build.dir}/licences" />
+		<copy todir="${build.dir}/licences">
+			<fileset dir="${basedir}/licences" />
+		</copy>
+		<mkdir dir="${build.dir}/icons" />
+		<copy todir="${build.dir}/icons">
+			<fileset dir="${basedir}/src/main/resources/icons" />
+		</copy>
+		<mkdir dir="${build.dir}/config" />
+		<copy todir="${build.dir}/config">
+			<fileset dir="${basedir}/config" />
+		</copy>
+		<copy todir="${build.dir}/lib">
+			<fileset file="${basedir}/lib/log4j.properties" />
+		</copy>
+		<copy todir="${build.dir}/lib">
+			<fileset file="../../../build/zookeeper-${version}.jar" />
+		</copy>
+		<copy todir="${build.dir}">
+			<fileset dir="${basedir}" includes="*.*" excludes="build.xml,ivy.xml" />
+		</copy>
+	</target>
+
+	<!-- Override jar target to specify main class -->
+	<target name="jar" depends="setjarname, compile">
+		<echo message="contrib: ${name}" />
+
+		<jar jarfile="${jarname}">
+			<manifest>
+				<attribute name="Main-Class" value="org.apache.zookeeper.inspector.ZooInspector" />
+				<attribute name="Built-By" value="${user.name}" />
+				<attribute name="Built-At" value="${build.time}" />
+				<attribute name="Built-On" value="${host.name}" />
+				<attribute name="Implementation-Title" value="org.apache.zookeeper" />
+				<attribute name="Implementation-Version" value="${revision}" />
+				<attribute name="Implementation-Vendor" value="The Apache Software Foundation" />
+			</manifest>
+			<fileset file="${zk.root}/LICENSE.txt" />
+			<fileset dir="${build.classes}" />
+			<fileset dir="${basedir}/src/main/resources" />
+			<fileset dir="${basedir}/src/java" excludes="**/*.jar, **/*.java"/>
+		</jar>
+	</target>
+
+	<target name="compile" depends="ivy-retrieve,zookeeperbuildcontrib.compile" />
+
+	<target name="test" depends="checkMainTestCompiled,compile-test,test-init,test-category,junit.run" />
+
+	<target name="compile-test" depends="ivy-retrieve-test,compile">
+		<property name="target.jdk" value="${ant.java.version}" />
+		<property name="src.test.local" location="${basedir}/test" />
+		<mkdir dir="${build.test}" />
+		<javac srcdir="${src.test.local}" destdir="${build.test}" target="${target.jdk}" debug="on">
+			<classpath refid="classpath" />
+			<classpath>
+				<pathelement location="${zk.root}/build/test/classes" />
+			</classpath>
+		</javac>
+	</target>
+
+	<target name="test-init" depends="jar,compile-test">
+		<delete dir="${test.log.dir}" />
+		<delete dir="${test.tmp.dir}" />
+		<delete dir="${test.data.dir}" />
+		<mkdir dir="${test.log.dir}" />
+		<mkdir dir="${test.tmp.dir}" />
+		<mkdir dir="${test.data.dir}" />
+	</target>
+
+	<target name="test-category">
+		<property name="test.category" value="" />
+	</target>
+
+	<target name="junit.run">
+		<echo message="${test.src.dir}" />
+		<junit showoutput="${test.output}" printsummary="${test.junit.printsummary}" haltonfailure="${test.junit.haltonfailure}" fork="yes" forkmode="${test.junit.fork.mode}" maxmemory="${test.junit.maxmem}" dir="${basedir}" timeout="${test.timeout}" errorProperty="tests.failed" failureProperty="tests.failed">
+			<sysproperty key="build.test.dir" value="${test.tmp.dir}" />
+			<sysproperty key="test.data.dir" value="${test.data.dir}" />
+			<sysproperty key="log4j.configuration" value="file:${basedir}/conf/log4j.properties" />
+			<classpath refid="classpath" />
+			<classpath>
+				<pathelement path="${build.test}" />
+				<pathelement location="${zk.root}/build/test/classes" />
+			</classpath>
+			<formatter type="${test.junit.output.format}" />
+			<batchtest todir="${test.log.dir}" unless="testcase">
+				<fileset dir="${test.src.dir}" includes="**/*${test.category}Test.java" />
+			</batchtest>
+			<batchtest todir="${test.log.dir}" if="testcase">
+				<fileset dir="${test.src.dir}" includes="**/${testcase}.java" />
+			</batchtest>
+		</junit>
+		<fail if="tests.failed">Tests failed!</fail>
+	</target>
+
+	<target name="package" depends="jar, zookeeperbuildcontrib.package" unless="skip.contrib">
+
+		<copy file="${basedir}/build.xml" todir="${dist.dir}/contrib/${name}" />
+
+		<mkdir dir="${dist.dir}/contrib/${name}/src" />
+		<copy todir="${dist.dir}/contrib/${name}/src">
+			<fileset dir="${basedir}/src" />
+		</copy>
+		<mkdir dir="${dist.dir}/contrib/${name}/licences" />
+		<copy todir="${dist.dir}/contrib/${name}/licences">
+			<fileset dir="${basedir}/licences" />
+		</copy>
+		<mkdir dir="${dist.dir}/contrib/${name}/config" />
+		<copy todir="${dist.dir}/contrib/${name}/config">
+			<fileset dir="${basedir}/config" />
+		</copy>
+	</target>
+</project>

+ 47 - 47
src/contrib/zooinspector/ivy.xml

@@ -1,48 +1,48 @@
-<!--
-   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.
--->
-
-<ivy-module version="2.0"
-            xmlns:e="http://ant.apache.org/ivy/extra">
-
-  <info organisation="org.apache.zookeeper"
-        module="${name}" revision="${version}">
-    <license name="Apache 2.0"/>
-    <ivyauthor name="Apache Hadoop" url="http://hadoop.apache.org"/>
-    <description>ZooInspector</description>
-  </info>
-
-  <configurations defaultconfmapping="default">
-    <conf name="default"/>
-    <conf name="test"/>
-    <conf name="releaseaudit" visibility="private" description="Artifacts required for releaseaudit target"/>
-  </configurations>
-
-  <dependencies>
-    <dependency org="org.slf4j" name="slf4j-api" rev="1.6.1"/>
-    <dependency org="org.slf4j" name="slf4j-log4j12" rev="1.6.1" transitive="false"/>
-            
-    <dependency org="log4j" name="log4j" rev="1.2.15" transitive="false"/>
-    <dependency org="junit" name="junit" rev="4.7" conf="test->default"/>
-        <dependency org="org.apache.rat" name="apache-rat-tasks" 
-                rev="0.6" conf="releaseaudit->default"/>
-    <dependency org="commons-lang" name="commons-lang" 
-                rev="2.4" conf="releaseaudit->default"/>
-    <dependency org="commons-collections" name="commons-collections" 
-                rev="3.1" conf="releaseaudit->default"/>
-  </dependencies>
-
+<!--
+   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.
+-->
+
+<ivy-module version="2.0"
+            xmlns:e="http://ant.apache.org/ivy/extra">
+
+  <info organisation="org.apache.zookeeper"
+        module="${name}" revision="${version}">
+    <license name="Apache 2.0"/>
+    <ivyauthor name="Apache Hadoop" url="http://hadoop.apache.org"/>
+    <description>ZooInspector</description>
+  </info>
+
+  <configurations defaultconfmapping="default">
+    <conf name="default"/>
+    <conf name="test"/>
+    <conf name="releaseaudit" visibility="private" description="Artifacts required for releaseaudit target"/>
+  </configurations>
+
+  <dependencies>
+    <dependency org="org.slf4j" name="slf4j-api" rev="1.6.1"/>
+    <dependency org="org.slf4j" name="slf4j-log4j12" rev="1.6.1" transitive="false"/>
+            
+    <dependency org="log4j" name="log4j" rev="1.2.15" transitive="false"/>
+    <dependency org="junit" name="junit" rev="4.7" conf="test->default"/>
+        <dependency org="org.apache.rat" name="apache-rat-tasks" 
+                rev="0.6" conf="releaseaudit->default"/>
+    <dependency org="commons-lang" name="commons-lang" 
+                rev="2.4" conf="releaseaudit->default"/>
+    <dependency org="commons-collections" name="commons-collections" 
+                rev="3.1" conf="releaseaudit->default"/>
+  </dependencies>
+
 </ivy-module>

+ 8 - 8
src/contrib/zooinspector/lib/log4j.properties

@@ -1,9 +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.
+# ***** 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

+ 71 - 71
src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/ZooInspector.java

@@ -1,71 +1,71 @@
-/**
- * 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;
-
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
-
-import javax.swing.JFrame;
-import javax.swing.JOptionPane;
-import javax.swing.UIManager;
-
-import org.apache.zookeeper.inspector.gui.IconResource;
-import org.apache.zookeeper.inspector.gui.ZooInspectorPanel;
-import org.apache.zookeeper.inspector.logger.LoggerFactory;
-import org.apache.zookeeper.inspector.manager.ZooInspectorManagerImpl;
-
-/**
- * 
- */
-public class ZooInspector {
-	
-	public static IconResource iconResource;
-	
-    /**
-     * @param args
-     *            - not used. The value of these parameters will have no effect
-     *            on the application
-     */
-    public static void main(String[] args) {
-        try {
-            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
-            JFrame frame = new JFrame("ZooInspector");
-            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
-            iconResource = new IconResource();
-            final ZooInspectorPanel zooInspectorPanel = new ZooInspectorPanel(
-                    new ZooInspectorManagerImpl(), iconResource);
-            frame.addWindowListener(new WindowAdapter() {
-                @Override
-                public void windowClosed(WindowEvent e) {
-                    super.windowClosed(e);
-                    zooInspectorPanel.disconnect(true);
-                }
-            });
-
-            frame.setContentPane(zooInspectorPanel);
-            frame.setSize(1024, 768);
-            frame.setVisible(true);
-        } catch (Exception e) {
-            LoggerFactory.getLogger().error(
-                    "Error occurred loading ZooInspector", e);
-            JOptionPane.showMessageDialog(null,
-                    "ZooInspector failed to start: " + e.getMessage(), "Error",
-                    JOptionPane.ERROR_MESSAGE);
-        }
-    }
-}
+/**
+ * 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;
+
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.UIManager;
+
+import org.apache.zookeeper.inspector.gui.IconResource;
+import org.apache.zookeeper.inspector.gui.ZooInspectorPanel;
+import org.apache.zookeeper.inspector.logger.LoggerFactory;
+import org.apache.zookeeper.inspector.manager.ZooInspectorManagerImpl;
+
+/**
+ * 
+ */
+public class ZooInspector {
+	
+	public static IconResource iconResource;
+	
+    /**
+     * @param args
+     *            - not used. The value of these parameters will have no effect
+     *            on the application
+     */
+    public static void main(String[] args) {
+        try {
+            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+            JFrame frame = new JFrame("ZooInspector");
+            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+            iconResource = new IconResource();
+            final ZooInspectorPanel zooInspectorPanel = new ZooInspectorPanel(
+                    new ZooInspectorManagerImpl(), iconResource);
+            frame.addWindowListener(new WindowAdapter() {
+                @Override
+                public void windowClosed(WindowEvent e) {
+                    super.windowClosed(e);
+                    zooInspectorPanel.disconnect(true);
+                }
+            });
+
+            frame.setContentPane(zooInspectorPanel);
+            frame.setSize(1024, 768);
+            frame.setVisible(true);
+        } catch (Exception e) {
+            LoggerFactory.getLogger().error(
+                    "Error occurred loading ZooInspector", e);
+            JOptionPane.showMessageDialog(null,
+                    "ZooInspector failed to start: " + e.getMessage(), "Error",
+                    JOptionPane.ERROR_MESSAGE);
+        }
+    }
+}

+ 50 - 50
src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/encryption/BasicDataEncryptionManager.java

@@ -1,50 +1,50 @@
-/**
- * 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.encryption;
-
-/**
- *
- */
-public class BasicDataEncryptionManager implements DataEncryptionManager {
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see
-     * org.apache.zookeeper.inspector.encryption.DataEncryptionManager#decryptData
-     * (byte[])
-     */
-    public String decryptData(byte[] encrypted) throws Exception {
-        return new String(encrypted);
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see
-     * org.apache.zookeeper.inspector.encryption.DataEncryptionManager#encryptData
-     * (java.lang.String)
-     */
-    public byte[] encryptData(String data) throws Exception {
-        if (data == null) {
-            return new byte[0];
-        }
-        return data.getBytes();
-    }
-
-}
+/**
+ * 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.encryption;
+
+/**
+ *
+ */
+public class BasicDataEncryptionManager implements DataEncryptionManager {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.zookeeper.inspector.encryption.DataEncryptionManager#decryptData
+     * (byte[])
+     */
+    public String decryptData(byte[] encrypted) throws Exception {
+        return new String(encrypted);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.zookeeper.inspector.encryption.DataEncryptionManager#encryptData
+     * (java.lang.String)
+     */
+    public byte[] encryptData(String data) throws Exception {
+        if (data == null) {
+            return new byte[0];
+        }
+        return data.getBytes();
+    }
+
+}

+ 39 - 39
src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/encryption/DataEncryptionManager.java

@@ -1,39 +1,39 @@
-/**
- * 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.encryption;
-
-/**
- * A class which describes how data should be encrypted and decrypted
- */
-public interface DataEncryptionManager {
-    /**
-     * @param data
-     *            - the data to be encrypted
-     * @return the encrypted data
-     * @throws Exception
-     */
-    public byte[] encryptData(String data) throws Exception;
-
-    /**
-     * @param encrypted
-     *            - the data to be decrypted
-     * @return the decrypted data
-     * @throws Exception
-     */
-    public String decryptData(byte[] encrypted) throws Exception;
-}
+/**
+ * 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.encryption;
+
+/**
+ * A class which describes how data should be encrypted and decrypted
+ */
+public interface DataEncryptionManager {
+    /**
+     * @param data
+     *            - the data to be encrypted
+     * @return the encrypted data
+     * @throws Exception
+     */
+    public byte[] encryptData(String data) throws Exception;
+
+    /**
+     * @param encrypted
+     *            - the data to be decrypted
+     * @return the decrypted data
+     * @throws Exception
+     */
+    public String decryptData(byte[] encrypted) throws Exception;
+}

+ 37 - 37
src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/NodeViewersChangeListener.java

@@ -1,37 +1,37 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.zookeeper.inspector.gui;
-
-import java.util.List;
-
-import org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer;
-
-/**
- * A Listener for changes to the configuration of which node viewers are shown
- */
-public interface NodeViewersChangeListener {
-    /**
-     * Called when the node viewers configuration is changed (i.e node viewers
-     * are added, removed or the order of the node viewers is changed)
-     * 
-     * @param newViewers
-     *            - a {@link List} of {@link ZooInspectorNodeViewer}s which are
-     *            to be shown
-     */
-    public void nodeViewersChanged(List<ZooInspectorNodeViewer> newViewers);
-}
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.gui;
+
+import java.util.List;
+
+import org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer;
+
+/**
+ * A Listener for changes to the configuration of which node viewers are shown
+ */
+public interface NodeViewersChangeListener {
+    /**
+     * Called when the node viewers configuration is changed (i.e node viewers
+     * are added, removed or the order of the node viewers is changed)
+     * 
+     * @param newViewers
+     *            - a {@link List} of {@link ZooInspectorNodeViewer}s which are
+     *            to be shown
+     */
+    public void nodeViewersChanged(List<ZooInspectorNodeViewer> newViewers);
+}

+ 79 - 79
src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/ZooInspectorAboutDialog.java

@@ -1,79 +1,79 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.zookeeper.inspector.gui;
-
-import java.awt.BorderLayout;
-import java.awt.Dimension;
-import java.awt.FlowLayout;
-import java.awt.Frame;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.IOException;
-
-import javax.swing.JButton;
-import javax.swing.JDialog;
-import javax.swing.JEditorPane;
-import javax.swing.JPanel;
-
-import org.apache.zookeeper.inspector.logger.LoggerFactory;
-
-/**
- * The About Dialog for the application
- */
-public class ZooInspectorAboutDialog extends JDialog {
-    /**
-     * @param frame
-     *            - the Frame from which the dialog is displayed
-     */
-    public ZooInspectorAboutDialog(Frame frame, IconResource iconResource) {
-        super(frame);
-        this.setLayout(new BorderLayout());
-        this.setIconImage(iconResource.get(IconResource.ICON_INFORMATION, "About ZooInspector").getImage());
-        this.setTitle("About ZooInspector");
-        this.setModal(true);
-        this.setAlwaysOnTop(true);
-        this.setResizable(false);
-        JPanel panel = new JPanel();
-        panel.setLayout(new BorderLayout());
-        JEditorPane aboutPane = new JEditorPane();
-        aboutPane.setEditable(false);
-        aboutPane.setOpaque(false);
-        java.net.URL aboutURL = ZooInspectorAboutDialog.class
-                .getResource("about.html");
-        try {
-            aboutPane.setPage(aboutURL);
-        } catch (IOException e) {
-            LoggerFactory.getLogger().error(
-                    "Error loading about.html, file may be corrupt", e);
-        }
-        panel.add(aboutPane, BorderLayout.CENTER);
-        panel.setPreferredSize(new Dimension(600, 200));
-        JPanel buttonsPanel = new JPanel();
-        buttonsPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10));
-        JButton okButton = new JButton("OK");
-        okButton.addActionListener(new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                ZooInspectorAboutDialog.this.dispose();
-            }
-        });
-        buttonsPanel.add(okButton);
-        this.add(panel, BorderLayout.CENTER);
-        this.add(buttonsPanel, BorderLayout.SOUTH);
-        this.pack();
-    }
-}
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.gui;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Frame;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JEditorPane;
+import javax.swing.JPanel;
+
+import org.apache.zookeeper.inspector.logger.LoggerFactory;
+
+/**
+ * The About Dialog for the application
+ */
+public class ZooInspectorAboutDialog extends JDialog {
+    /**
+     * @param frame
+     *            - the Frame from which the dialog is displayed
+     */
+    public ZooInspectorAboutDialog(Frame frame, IconResource iconResource) {
+        super(frame);
+        this.setLayout(new BorderLayout());
+        this.setIconImage(iconResource.get(IconResource.ICON_INFORMATION, "About ZooInspector").getImage());
+        this.setTitle("About ZooInspector");
+        this.setModal(true);
+        this.setAlwaysOnTop(true);
+        this.setResizable(false);
+        JPanel panel = new JPanel();
+        panel.setLayout(new BorderLayout());
+        JEditorPane aboutPane = new JEditorPane();
+        aboutPane.setEditable(false);
+        aboutPane.setOpaque(false);
+        java.net.URL aboutURL = ZooInspectorAboutDialog.class
+                .getResource("about.html");
+        try {
+            aboutPane.setPage(aboutURL);
+        } catch (IOException e) {
+            LoggerFactory.getLogger().error(
+                    "Error loading about.html, file may be corrupt", e);
+        }
+        panel.add(aboutPane, BorderLayout.CENTER);
+        panel.setPreferredSize(new Dimension(600, 200));
+        JPanel buttonsPanel = new JPanel();
+        buttonsPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10));
+        JButton okButton = new JButton("OK");
+        okButton.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                ZooInspectorAboutDialog.this.dispose();
+            }
+        });
+        buttonsPanel.add(okButton);
+        this.add(panel, BorderLayout.CENTER);
+        this.add(buttonsPanel, BorderLayout.SOUTH);
+        this.pack();
+    }
+}

+ 321 - 321
src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/ZooInspectorConnectionPropertiesDialog.java

@@ -1,321 +1,321 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.zookeeper.inspector.gui;
-
-import java.awt.BorderLayout;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Insets;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Map.Entry;
-
-import javax.swing.JButton;
-import javax.swing.JComboBox;
-import javax.swing.JComponent;
-import javax.swing.JDialog;
-import javax.swing.JFileChooser;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JTextField;
-
-import org.apache.zookeeper.inspector.logger.LoggerFactory;
-import org.apache.zookeeper.inspector.manager.Pair;
-
-/**
- * The connection properties dialog. This is used to determine the settings for
- * connecting to a zookeeper instance
- */
-public class ZooInspectorConnectionPropertiesDialog extends JDialog {
-
-    private final HashMap<String, JComponent> components;
-
-    /**
-     * @param lastConnectionProps
-     *            - the last connection properties used. if this is the first
-     *            conneciton since starting the applications this will be the
-     *            default settings
-     * @param connectionPropertiesTemplateAndLabels
-     *            - the connection properties and labels to show in this dialog
-     * @param zooInspectorPanel
-     *            - the {@link ZooInspectorPanel} linked to this dialog
-     */
-    public ZooInspectorConnectionPropertiesDialog(
-            Properties lastConnectionProps,
-            Pair<Map<String, List<String>>, Map<String, String>> connectionPropertiesTemplateAndLabels,
-            final ZooInspectorPanel zooInspectorPanel) {
-        final Map<String, List<String>> connectionPropertiesTemplate = connectionPropertiesTemplateAndLabels
-                .getKey();
-        final Map<String, String> connectionPropertiesLabels = connectionPropertiesTemplateAndLabels
-                .getValue();
-        this.setLayout(new BorderLayout());
-        this.setTitle("Connection Settings");
-        this.setModal(true);
-        this.setAlwaysOnTop(true);
-        this.setResizable(false);
-        final JPanel options = new JPanel();
-        final JFileChooser fileChooser = new JFileChooser();
-        options.setLayout(new GridBagLayout());
-        int i = 0;
-        components = new HashMap<String, JComponent>();
-        for (Entry<String, List<String>> entry : connectionPropertiesTemplate
-                .entrySet()) {
-            int rowPos = 2 * i + 1;
-            JLabel label = new JLabel(connectionPropertiesLabels.get(entry
-                    .getKey()));
-            GridBagConstraints c1 = new GridBagConstraints();
-            c1.gridx = 0;
-            c1.gridy = rowPos;
-            c1.gridwidth = 1;
-            c1.gridheight = 1;
-            c1.weightx = 0;
-            c1.weighty = 0;
-            c1.anchor = GridBagConstraints.WEST;
-            c1.fill = GridBagConstraints.HORIZONTAL;
-            c1.insets = new Insets(5, 5, 5, 5);
-            c1.ipadx = 0;
-            c1.ipady = 0;
-            options.add(label, c1);
-            if (entry.getValue().size() == 0) {
-                JTextField text = new JTextField();
-                GridBagConstraints c2 = new GridBagConstraints();
-                c2.gridx = 2;
-                c2.gridy = rowPos;
-                c2.gridwidth = 1;
-                c2.gridheight = 1;
-                c2.weightx = 0;
-                c2.weighty = 0;
-                c2.anchor = GridBagConstraints.WEST;
-                c2.fill = GridBagConstraints.HORIZONTAL;
-                c2.insets = new Insets(5, 5, 5, 5);
-                c2.ipadx = 0;
-                c2.ipady = 0;
-                options.add(text, c2);
-                components.put(entry.getKey(), text);
-            } else if (entry.getValue().size() == 1) {
-                JTextField text = new JTextField(entry.getValue().get(0));
-                GridBagConstraints c2 = new GridBagConstraints();
-                c2.gridx = 2;
-                c2.gridy = rowPos;
-                c2.gridwidth = 1;
-                c2.gridheight = 1;
-                c2.weightx = 0;
-                c2.weighty = 0;
-                c2.anchor = GridBagConstraints.WEST;
-                c2.fill = GridBagConstraints.HORIZONTAL;
-                c2.insets = new Insets(5, 5, 5, 5);
-                c2.ipadx = 0;
-                c2.ipady = 0;
-                options.add(text, c2);
-                components.put(entry.getKey(), text);
-            } else {
-                List<String> list = entry.getValue();
-                JComboBox combo = new JComboBox(list.toArray(new String[list
-                        .size()]));
-                combo.setSelectedItem(list.get(0));
-                GridBagConstraints c2 = new GridBagConstraints();
-                c2.gridx = 2;
-                c2.gridy = rowPos;
-                c2.gridwidth = 1;
-                c2.gridheight = 1;
-                c2.weightx = 0;
-                c2.weighty = 0;
-                c2.anchor = GridBagConstraints.WEST;
-                c2.fill = GridBagConstraints.HORIZONTAL;
-                c2.insets = new Insets(5, 5, 5, 5);
-                c2.ipadx = 0;
-                c2.ipady = 0;
-                options.add(combo, c2);
-                components.put(entry.getKey(), combo);
-            }
-            i++;
-        }
-        loadConnectionProps(lastConnectionProps);
-        JPanel buttonsPanel = new JPanel();
-        buttonsPanel.setLayout(new GridBagLayout());
-        JButton loadPropsFileButton = new JButton("Load from file");
-        loadPropsFileButton.addActionListener(new ActionListener() {
-
-            public void actionPerformed(ActionEvent e) {
-                int result = fileChooser
-                        .showOpenDialog(ZooInspectorConnectionPropertiesDialog.this);
-                if (result == JFileChooser.APPROVE_OPTION) {
-                    File propsFilePath = fileChooser.getSelectedFile();
-                    Properties props = new Properties();
-                    try {
-                        FileReader reader = new FileReader(propsFilePath);
-                        try {
-                            props.load(reader);
-                            loadConnectionProps(props);
-                        } finally {
-                            reader.close();
-                        }
-                    } catch (IOException ex) {
-                        LoggerFactory
-                                .getLogger()
-                                .error(
-                                        "An Error occurred loading connection properties from file",
-                                        ex);
-                        JOptionPane
-                                .showMessageDialog(
-                                        ZooInspectorConnectionPropertiesDialog.this,
-                                        "An Error occurred loading connection properties from file",
-                                        "Error", JOptionPane.ERROR_MESSAGE);
-                    }
-                    options.revalidate();
-                    options.repaint();
-                }
-
-            }
-        });
-        GridBagConstraints c3 = new GridBagConstraints();
-        c3.gridx = 0;
-        c3.gridy = 0;
-        c3.gridwidth = 1;
-        c3.gridheight = 1;
-        c3.weightx = 0;
-        c3.weighty = 1;
-        c3.anchor = GridBagConstraints.SOUTHWEST;
-        c3.fill = GridBagConstraints.NONE;
-        c3.insets = new Insets(5, 5, 5, 5);
-        c3.ipadx = 0;
-        c3.ipady = 0;
-        buttonsPanel.add(loadPropsFileButton, c3);
-        JButton saveDefaultPropsFileButton = new JButton("Set As Default");
-        saveDefaultPropsFileButton.addActionListener(new ActionListener() {
-
-            public void actionPerformed(ActionEvent e) {
-
-                Properties connectionProps = getConnectionProps();
-                try {
-                    zooInspectorPanel
-                            .setdefaultConnectionProps(connectionProps);
-                } catch (IOException ex) {
-                    LoggerFactory
-                            .getLogger()
-                            .error(
-                                    "An Error occurred saving the default connection properties file",
-                                    ex);
-                    JOptionPane
-                            .showMessageDialog(
-                                    ZooInspectorConnectionPropertiesDialog.this,
-                                    "An Error occurred saving the default connection properties file",
-                                    "Error", JOptionPane.ERROR_MESSAGE);
-                }
-            }
-        });
-        GridBagConstraints c6 = new GridBagConstraints();
-        c6.gridx = 1;
-        c6.gridy = 0;
-        c6.gridwidth = 1;
-        c6.gridheight = 1;
-        c6.weightx = 1;
-        c6.weighty = 1;
-        c6.anchor = GridBagConstraints.SOUTHWEST;
-        c6.fill = GridBagConstraints.NONE;
-        c6.insets = new Insets(5, 5, 5, 5);
-        c6.ipadx = 0;
-        c6.ipady = 0;
-        buttonsPanel.add(saveDefaultPropsFileButton, c6);
-        JButton okButton = new JButton("OK");
-        okButton.addActionListener(new ActionListener() {
-
-            public void actionPerformed(ActionEvent e) {
-                ZooInspectorConnectionPropertiesDialog.this.dispose();
-                Properties connectionProps = getConnectionProps();
-                zooInspectorPanel.connect(connectionProps);
-            }
-        });
-        GridBagConstraints c4 = new GridBagConstraints();
-        c4.gridx = 2;
-        c4.gridy = 0;
-        c4.gridwidth = 1;
-        c4.gridheight = 1;
-        c4.weightx = 0;
-        c4.weighty = 1;
-        c4.anchor = GridBagConstraints.SOUTH;
-        c4.fill = GridBagConstraints.HORIZONTAL;
-        c4.insets = new Insets(5, 5, 5, 5);
-        c4.ipadx = 0;
-        c4.ipady = 0;
-        buttonsPanel.add(okButton, c4);
-        JButton cancelButton = new JButton("Cancel");
-        cancelButton.addActionListener(new ActionListener() {
-
-            public void actionPerformed(ActionEvent e) {
-                ZooInspectorConnectionPropertiesDialog.this.dispose();
-            }
-        });
-        GridBagConstraints c5 = new GridBagConstraints();
-        c5.gridx = 3;
-        c5.gridy = 0;
-        c5.gridwidth = 1;
-        c5.gridheight = 1;
-        c5.weightx = 0;
-        c5.weighty = 1;
-        c5.anchor = GridBagConstraints.SOUTH;
-        c5.fill = GridBagConstraints.HORIZONTAL;
-        c5.insets = new Insets(5, 5, 5, 5);
-        c5.ipadx = 0;
-        c5.ipady = 0;
-        buttonsPanel.add(cancelButton, c5);
-        this.add(options, BorderLayout.CENTER);
-        this.add(buttonsPanel, BorderLayout.SOUTH);
-        this.pack();
-    }
-
-    private void loadConnectionProps(Properties props) {
-        if (props != null) {
-            for (Object key : props.keySet()) {
-                String propsKey = (String) key;
-                if (components.containsKey(propsKey)) {
-                    JComponent component = components.get(propsKey);
-                    String value = props.getProperty(propsKey);
-                    if (component instanceof JTextField) {
-                        ((JTextField) component).setText(value);
-                    } else if (component instanceof JComboBox) {
-                        ((JComboBox) component).setSelectedItem(value);
-                    }
-                }
-            }
-        }
-    }
-
-    private Properties getConnectionProps() {
-        Properties connectionProps = new Properties();
-        for (Entry<String, JComponent> entry : components.entrySet()) {
-            String value = null;
-            JComponent component = entry.getValue();
-            if (component instanceof JTextField) {
-                value = ((JTextField) component).getText();
-            } else if (component instanceof JComboBox) {
-                value = ((JComboBox) component).getSelectedItem().toString();
-            }
-            connectionProps.put(entry.getKey(), value);
-        }
-        return connectionProps;
-    }
-}
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.gui;
+
+import java.awt.BorderLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Map.Entry;
+
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+import org.apache.zookeeper.inspector.logger.LoggerFactory;
+import org.apache.zookeeper.inspector.manager.Pair;
+
+/**
+ * The connection properties dialog. This is used to determine the settings for
+ * connecting to a zookeeper instance
+ */
+public class ZooInspectorConnectionPropertiesDialog extends JDialog {
+
+    private final HashMap<String, JComponent> components;
+
+    /**
+     * @param lastConnectionProps
+     *            - the last connection properties used. if this is the first
+     *            conneciton since starting the applications this will be the
+     *            default settings
+     * @param connectionPropertiesTemplateAndLabels
+     *            - the connection properties and labels to show in this dialog
+     * @param zooInspectorPanel
+     *            - the {@link ZooInspectorPanel} linked to this dialog
+     */
+    public ZooInspectorConnectionPropertiesDialog(
+            Properties lastConnectionProps,
+            Pair<Map<String, List<String>>, Map<String, String>> connectionPropertiesTemplateAndLabels,
+            final ZooInspectorPanel zooInspectorPanel) {
+        final Map<String, List<String>> connectionPropertiesTemplate = connectionPropertiesTemplateAndLabels
+                .getKey();
+        final Map<String, String> connectionPropertiesLabels = connectionPropertiesTemplateAndLabels
+                .getValue();
+        this.setLayout(new BorderLayout());
+        this.setTitle("Connection Settings");
+        this.setModal(true);
+        this.setAlwaysOnTop(true);
+        this.setResizable(false);
+        final JPanel options = new JPanel();
+        final JFileChooser fileChooser = new JFileChooser();
+        options.setLayout(new GridBagLayout());
+        int i = 0;
+        components = new HashMap<String, JComponent>();
+        for (Entry<String, List<String>> entry : connectionPropertiesTemplate
+                .entrySet()) {
+            int rowPos = 2 * i + 1;
+            JLabel label = new JLabel(connectionPropertiesLabels.get(entry
+                    .getKey()));
+            GridBagConstraints c1 = new GridBagConstraints();
+            c1.gridx = 0;
+            c1.gridy = rowPos;
+            c1.gridwidth = 1;
+            c1.gridheight = 1;
+            c1.weightx = 0;
+            c1.weighty = 0;
+            c1.anchor = GridBagConstraints.WEST;
+            c1.fill = GridBagConstraints.HORIZONTAL;
+            c1.insets = new Insets(5, 5, 5, 5);
+            c1.ipadx = 0;
+            c1.ipady = 0;
+            options.add(label, c1);
+            if (entry.getValue().size() == 0) {
+                JTextField text = new JTextField();
+                GridBagConstraints c2 = new GridBagConstraints();
+                c2.gridx = 2;
+                c2.gridy = rowPos;
+                c2.gridwidth = 1;
+                c2.gridheight = 1;
+                c2.weightx = 0;
+                c2.weighty = 0;
+                c2.anchor = GridBagConstraints.WEST;
+                c2.fill = GridBagConstraints.HORIZONTAL;
+                c2.insets = new Insets(5, 5, 5, 5);
+                c2.ipadx = 0;
+                c2.ipady = 0;
+                options.add(text, c2);
+                components.put(entry.getKey(), text);
+            } else if (entry.getValue().size() == 1) {
+                JTextField text = new JTextField(entry.getValue().get(0));
+                GridBagConstraints c2 = new GridBagConstraints();
+                c2.gridx = 2;
+                c2.gridy = rowPos;
+                c2.gridwidth = 1;
+                c2.gridheight = 1;
+                c2.weightx = 0;
+                c2.weighty = 0;
+                c2.anchor = GridBagConstraints.WEST;
+                c2.fill = GridBagConstraints.HORIZONTAL;
+                c2.insets = new Insets(5, 5, 5, 5);
+                c2.ipadx = 0;
+                c2.ipady = 0;
+                options.add(text, c2);
+                components.put(entry.getKey(), text);
+            } else {
+                List<String> list = entry.getValue();
+                JComboBox combo = new JComboBox(list.toArray(new String[list
+                        .size()]));
+                combo.setSelectedItem(list.get(0));
+                GridBagConstraints c2 = new GridBagConstraints();
+                c2.gridx = 2;
+                c2.gridy = rowPos;
+                c2.gridwidth = 1;
+                c2.gridheight = 1;
+                c2.weightx = 0;
+                c2.weighty = 0;
+                c2.anchor = GridBagConstraints.WEST;
+                c2.fill = GridBagConstraints.HORIZONTAL;
+                c2.insets = new Insets(5, 5, 5, 5);
+                c2.ipadx = 0;
+                c2.ipady = 0;
+                options.add(combo, c2);
+                components.put(entry.getKey(), combo);
+            }
+            i++;
+        }
+        loadConnectionProps(lastConnectionProps);
+        JPanel buttonsPanel = new JPanel();
+        buttonsPanel.setLayout(new GridBagLayout());
+        JButton loadPropsFileButton = new JButton("Load from file");
+        loadPropsFileButton.addActionListener(new ActionListener() {
+
+            public void actionPerformed(ActionEvent e) {
+                int result = fileChooser
+                        .showOpenDialog(ZooInspectorConnectionPropertiesDialog.this);
+                if (result == JFileChooser.APPROVE_OPTION) {
+                    File propsFilePath = fileChooser.getSelectedFile();
+                    Properties props = new Properties();
+                    try {
+                        FileReader reader = new FileReader(propsFilePath);
+                        try {
+                            props.load(reader);
+                            loadConnectionProps(props);
+                        } finally {
+                            reader.close();
+                        }
+                    } catch (IOException ex) {
+                        LoggerFactory
+                                .getLogger()
+                                .error(
+                                        "An Error occurred loading connection properties from file",
+                                        ex);
+                        JOptionPane
+                                .showMessageDialog(
+                                        ZooInspectorConnectionPropertiesDialog.this,
+                                        "An Error occurred loading connection properties from file",
+                                        "Error", JOptionPane.ERROR_MESSAGE);
+                    }
+                    options.revalidate();
+                    options.repaint();
+                }
+
+            }
+        });
+        GridBagConstraints c3 = new GridBagConstraints();
+        c3.gridx = 0;
+        c3.gridy = 0;
+        c3.gridwidth = 1;
+        c3.gridheight = 1;
+        c3.weightx = 0;
+        c3.weighty = 1;
+        c3.anchor = GridBagConstraints.SOUTHWEST;
+        c3.fill = GridBagConstraints.NONE;
+        c3.insets = new Insets(5, 5, 5, 5);
+        c3.ipadx = 0;
+        c3.ipady = 0;
+        buttonsPanel.add(loadPropsFileButton, c3);
+        JButton saveDefaultPropsFileButton = new JButton("Set As Default");
+        saveDefaultPropsFileButton.addActionListener(new ActionListener() {
+
+            public void actionPerformed(ActionEvent e) {
+
+                Properties connectionProps = getConnectionProps();
+                try {
+                    zooInspectorPanel
+                            .setdefaultConnectionProps(connectionProps);
+                } catch (IOException ex) {
+                    LoggerFactory
+                            .getLogger()
+                            .error(
+                                    "An Error occurred saving the default connection properties file",
+                                    ex);
+                    JOptionPane
+                            .showMessageDialog(
+                                    ZooInspectorConnectionPropertiesDialog.this,
+                                    "An Error occurred saving the default connection properties file",
+                                    "Error", JOptionPane.ERROR_MESSAGE);
+                }
+            }
+        });
+        GridBagConstraints c6 = new GridBagConstraints();
+        c6.gridx = 1;
+        c6.gridy = 0;
+        c6.gridwidth = 1;
+        c6.gridheight = 1;
+        c6.weightx = 1;
+        c6.weighty = 1;
+        c6.anchor = GridBagConstraints.SOUTHWEST;
+        c6.fill = GridBagConstraints.NONE;
+        c6.insets = new Insets(5, 5, 5, 5);
+        c6.ipadx = 0;
+        c6.ipady = 0;
+        buttonsPanel.add(saveDefaultPropsFileButton, c6);
+        JButton okButton = new JButton("OK");
+        okButton.addActionListener(new ActionListener() {
+
+            public void actionPerformed(ActionEvent e) {
+                ZooInspectorConnectionPropertiesDialog.this.dispose();
+                Properties connectionProps = getConnectionProps();
+                zooInspectorPanel.connect(connectionProps);
+            }
+        });
+        GridBagConstraints c4 = new GridBagConstraints();
+        c4.gridx = 2;
+        c4.gridy = 0;
+        c4.gridwidth = 1;
+        c4.gridheight = 1;
+        c4.weightx = 0;
+        c4.weighty = 1;
+        c4.anchor = GridBagConstraints.SOUTH;
+        c4.fill = GridBagConstraints.HORIZONTAL;
+        c4.insets = new Insets(5, 5, 5, 5);
+        c4.ipadx = 0;
+        c4.ipady = 0;
+        buttonsPanel.add(okButton, c4);
+        JButton cancelButton = new JButton("Cancel");
+        cancelButton.addActionListener(new ActionListener() {
+
+            public void actionPerformed(ActionEvent e) {
+                ZooInspectorConnectionPropertiesDialog.this.dispose();
+            }
+        });
+        GridBagConstraints c5 = new GridBagConstraints();
+        c5.gridx = 3;
+        c5.gridy = 0;
+        c5.gridwidth = 1;
+        c5.gridheight = 1;
+        c5.weightx = 0;
+        c5.weighty = 1;
+        c5.anchor = GridBagConstraints.SOUTH;
+        c5.fill = GridBagConstraints.HORIZONTAL;
+        c5.insets = new Insets(5, 5, 5, 5);
+        c5.ipadx = 0;
+        c5.ipady = 0;
+        buttonsPanel.add(cancelButton, c5);
+        this.add(options, BorderLayout.CENTER);
+        this.add(buttonsPanel, BorderLayout.SOUTH);
+        this.pack();
+    }
+
+    private void loadConnectionProps(Properties props) {
+        if (props != null) {
+            for (Object key : props.keySet()) {
+                String propsKey = (String) key;
+                if (components.containsKey(propsKey)) {
+                    JComponent component = components.get(propsKey);
+                    String value = props.getProperty(propsKey);
+                    if (component instanceof JTextField) {
+                        ((JTextField) component).setText(value);
+                    } else if (component instanceof JComboBox) {
+                        ((JComboBox) component).setSelectedItem(value);
+                    }
+                }
+            }
+        }
+    }
+
+    private Properties getConnectionProps() {
+        Properties connectionProps = new Properties();
+        for (Entry<String, JComponent> entry : components.entrySet()) {
+            String value = null;
+            JComponent component = entry.getValue();
+            if (component instanceof JTextField) {
+                value = ((JTextField) component).getText();
+            } else if (component instanceof JComboBox) {
+                value = ((JComboBox) component).getSelectedItem().toString();
+            }
+            connectionProps.put(entry.getKey(), value);
+        }
+        return connectionProps;
+    }
+}

+ 631 - 631
src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/ZooInspectorNodeViewersDialog.java

@@ -1,631 +1,631 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.zookeeper.inspector.gui;
-
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.FlowLayout;
-import java.awt.Frame;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Insets;
-import java.awt.datatransfer.Transferable;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.swing.DefaultListCellRenderer;
-import javax.swing.DefaultListModel;
-import javax.swing.DropMode;
-import javax.swing.ImageIcon;
-import javax.swing.JButton;
-import javax.swing.JComponent;
-import javax.swing.JDialog;
-import javax.swing.JFileChooser;
-import javax.swing.JLabel;
-import javax.swing.JList;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTextField;
-import javax.swing.ListSelectionModel;
-import javax.swing.TransferHandler;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
-
-import org.apache.zookeeper.inspector.gui.Toolbar.Button;
-import org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer;
-import org.apache.zookeeper.inspector.logger.LoggerFactory;
-import org.apache.zookeeper.inspector.manager.ZooInspectorManager;
-
-/**
- * A {@link JDialog} for configuring which {@link ZooInspectorNodeViewer}s to
- * show in the application
- */
-public class ZooInspectorNodeViewersDialog extends JDialog implements
-        ListSelectionListener {
-
-    private final JList viewersList;
-    private final JFileChooser fileChooser = new JFileChooser(new File("."));
-    private final Map<Button, JButton> buttons = new HashMap<Button, JButton>();
-    /**
-     * @param frame
-     *            - the Frame from which the dialog is displayed
-     * @param currentViewers
-     *            - the {@link ZooInspectorNodeViewer}s to show
-     * @param listeners
-     *            - the {@link NodeViewersChangeListener}s which need to be
-     *            notified of changes to the node viewers configuration
-     * @param manager
-     *            - the {@link ZooInspectorManager} for the application
-     * 
-     */
-    public ZooInspectorNodeViewersDialog(Frame frame,
-            final List<ZooInspectorNodeViewer> currentViewers,
-            final Collection<NodeViewersChangeListener> listeners,
-            final ZooInspectorManager manager,
-            final IconResource iconResource) {
-        super(frame);
-        final List<ZooInspectorNodeViewer> newViewers = new ArrayList<ZooInspectorNodeViewer>(
-                currentViewers);
-        this.setLayout(new BorderLayout());
-        this.setIconImage(iconResource.get(IconResource.ICON_ChangeNodeViewers,"")
-                .getImage());
-        this.setTitle("About ZooInspector");
-        this.setModal(true);
-        this.setAlwaysOnTop(true);
-        this.setResizable(true);
-        final JPanel panel = new JPanel();
-        panel.setLayout(new GridBagLayout());
-        viewersList = new JList();
-        DefaultListModel model = new DefaultListModel();
-        for (ZooInspectorNodeViewer viewer : newViewers) {
-            model.addElement(viewer);
-        }
-        viewersList.setModel(model);
-        viewersList.setCellRenderer(new DefaultListCellRenderer() {
-            @Override
-            public Component getListCellRendererComponent(JList list,
-                    Object value, int index, boolean isSelected,
-                    boolean cellHasFocus) {
-                ZooInspectorNodeViewer viewer = (ZooInspectorNodeViewer) value;
-                JLabel label = (JLabel) super.getListCellRendererComponent(
-                        list, value, index, isSelected, cellHasFocus);
-                label.setText(viewer.getTitle());
-                return label;
-            }
-        });
-        viewersList.setDropMode(DropMode.INSERT);
-        viewersList.enableInputMethods(true);
-        viewersList.setDragEnabled(true);
-        viewersList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-        viewersList.getSelectionModel().addListSelectionListener(this);
-        viewersList.setTransferHandler(new TransferHandler() {
-
-            @Override
-            public boolean canImport(TransferHandler.TransferSupport info) {
-                // we only import NodeViewers
-                if (!info
-                        .isDataFlavorSupported(ZooInspectorNodeViewer.nodeViewerDataFlavor)) {
-                    return false;
-                }
-
-                JList.DropLocation dl = (JList.DropLocation) info
-                        .getDropLocation();
-                if (dl.getIndex() == -1) {
-                    return false;
-                }
-                return true;
-            }
-
-            @Override
-            public boolean importData(TransferHandler.TransferSupport info) {
-                JList.DropLocation dl = (JList.DropLocation) info
-                        .getDropLocation();
-                DefaultListModel listModel = (DefaultListModel) viewersList
-                        .getModel();
-                int index = dl.getIndex();
-                boolean insert = dl.isInsert();
-                // Get the string that is being dropped.
-                Transferable t = info.getTransferable();
-                String data;
-                try {
-                    data = (String) t
-                            .getTransferData(ZooInspectorNodeViewer.nodeViewerDataFlavor);
-                } catch (Exception e) {
-                    return false;
-                }
-                try {
-                    ZooInspectorNodeViewer viewer = (ZooInspectorNodeViewer) Class
-                            .forName(data).newInstance();
-                    if (listModel.contains(viewer)) {
-                        listModel.removeElement(viewer);
-                    }
-                    if (insert) {
-                        listModel.add(index, viewer);
-                    } else {
-                        listModel.set(index, viewer);
-                    }
-                    return true;
-                } catch (Exception e) {
-                    LoggerFactory.getLogger().error(
-                            "Error instantiating class: " + data, e);
-                    return false;
-                }
-
-            }
-
-            @Override
-            public int getSourceActions(JComponent c) {
-                return MOVE;
-            }
-
-            @Override
-            protected Transferable createTransferable(JComponent c) {
-                JList list = (JList) c;
-                ZooInspectorNodeViewer value = (ZooInspectorNodeViewer) list
-                        .getSelectedValue();
-                return value;
-            }
-        });
-        JScrollPane scroller = new JScrollPane(viewersList);
-        GridBagConstraints c1 = new GridBagConstraints();
-        c1.gridx = 0;
-        c1.gridy = 0;
-        c1.gridwidth = 3;
-        c1.gridheight = 3;
-        c1.weightx = 0;
-        c1.weighty = 1;
-        c1.anchor = GridBagConstraints.CENTER;
-        c1.fill = GridBagConstraints.BOTH;
-        c1.insets = new Insets(5, 5, 5, 5);
-        c1.ipadx = 0;
-        c1.ipady = 0;
-        panel.add(scroller, c1);
-
-        final JTextField newViewerTextField = new JTextField();
-
-        for(Button button : Button.values()) {
-            JButton jbutton = button.createJButton(iconResource);
-            buttons.put(button, jbutton);
-        }
-        GridBagConstraints c2 = new GridBagConstraints();
-        c2.gridx = 3;
-        c2.gridy = 0;
-        c2.gridwidth = 1;
-        c2.gridheight = 1;
-        c2.weightx = 0;
-        c2.weighty = 0;
-        c2.anchor = GridBagConstraints.NORTH;
-        c2.fill = GridBagConstraints.HORIZONTAL;
-        c2.insets = new Insets(5, 5, 5, 5);
-        c2.ipadx = 0;
-        c2.ipady = 0;
-        panel.add(buttons.get(Button.up), c2);
-        GridBagConstraints c3 = new GridBagConstraints();
-        c3.gridx = 3;
-        c3.gridy = 2;
-        c3.gridwidth = 1;
-        c3.gridheight = 1;
-        c3.weightx = 0;
-        c3.weighty = 0;
-        c3.anchor = GridBagConstraints.NORTH;
-        c3.fill = GridBagConstraints.HORIZONTAL;
-        c3.insets = new Insets(5, 5, 5, 5);
-        c3.ipadx = 0;
-        c3.ipady = 0;
-        panel.add(buttons.get(Button.down), c3);
-        GridBagConstraints c4 = new GridBagConstraints();
-        c4.gridx = 3;
-        c4.gridy = 1;
-        c4.gridwidth = 1;
-        c4.gridheight = 1;
-        c4.weightx = 0;
-        c4.weighty = 0;
-        c4.anchor = GridBagConstraints.NORTH;
-        c4.fill = GridBagConstraints.HORIZONTAL;
-        c4.insets = new Insets(5, 5, 5, 5);
-        c4.ipadx = 0;
-        c4.ipady = 0;
-        panel.add(buttons.get(Button.remove), c4);
-        GridBagConstraints c5 = new GridBagConstraints();
-        c5.gridx = 0;
-        c5.gridy = 3;
-        c5.gridwidth = 3;
-        c5.gridheight = 1;
-        c5.weightx = 0;
-        c5.weighty = 0;
-        c5.anchor = GridBagConstraints.CENTER;
-        c5.fill = GridBagConstraints.BOTH;
-        c5.insets = new Insets(5, 5, 5, 5);
-        c5.ipadx = 0;
-        c5.ipady = 0;
-        panel.add(newViewerTextField, c5);
-        GridBagConstraints c6 = new GridBagConstraints();
-        c6.gridx = 3;
-        c6.gridy = 3;
-        c6.gridwidth = 1;
-        c6.gridheight = 1;
-        c6.weightx = 0;
-        c6.weighty = 0;
-        c6.anchor = GridBagConstraints.CENTER;
-        c6.fill = GridBagConstraints.BOTH;
-        c6.insets = new Insets(5, 5, 5, 5);
-        c6.ipadx = 0;
-        c6.ipady = 0;
-        panel.add(buttons.get(Button.add), c6);
-        buttons.get(Button.up).addActionListener(new ActionListener() {
-
-            public void actionPerformed(ActionEvent e) {
-                DefaultListModel listModel = (DefaultListModel) viewersList
-                        .getModel();
-                ZooInspectorNodeViewer viewer = (ZooInspectorNodeViewer) viewersList
-                        .getSelectedValue();
-                int index = viewersList.getSelectedIndex();
-                if (listModel.contains(viewer)) {
-                    listModel.removeElementAt(index);
-                    listModel.insertElementAt(viewer, index - 1);
-                    viewersList.setSelectedValue(viewer, true);
-                }
-            }
-        });
-        buttons.get(Button.down).addActionListener(new ActionListener() {
-
-            public void actionPerformed(ActionEvent e) {
-                DefaultListModel listModel = (DefaultListModel) viewersList
-                        .getModel();
-                ZooInspectorNodeViewer viewer = (ZooInspectorNodeViewer) viewersList
-                        .getSelectedValue();
-                int index = viewersList.getSelectedIndex();
-                if (listModel.contains(viewer)) {
-                    listModel.removeElementAt(index);
-                    listModel.insertElementAt(viewer, index + 1);
-                    viewersList.setSelectedValue(viewer, true);
-                }
-            }
-        });
-        buttons.get(Button.remove).addActionListener(new ActionListener() {
-
-            public void actionPerformed(ActionEvent e) {
-                DefaultListModel listModel = (DefaultListModel) viewersList
-                        .getModel();
-                ZooInspectorNodeViewer viewer = (ZooInspectorNodeViewer) viewersList
-                        .getSelectedValue();
-                int index = viewersList.getSelectedIndex();
-                if (listModel.contains(viewer)) {
-                    listModel.removeElement(viewer);
-                    viewersList
-                            .setSelectedIndex(index == listModel.size() ? index - 1
-                                    : index);
-                }
-            }
-        });
-        buttons.get(Button.add).addActionListener(new ActionListener() {
-
-            public void actionPerformed(ActionEvent e) {
-                String className = newViewerTextField.getText();
-                if (className == null || className.length() == 0) {
-                    JOptionPane
-                            .showMessageDialog(
-                                    ZooInspectorNodeViewersDialog.this,
-                                    "Please enter the full class name for a Node Viewer and click the add button",
-                                    "Input Error", JOptionPane.ERROR_MESSAGE);
-                } else {
-                    try {
-                        DefaultListModel listModel = (DefaultListModel) viewersList
-                                .getModel();
-                        ZooInspectorNodeViewer viewer = (ZooInspectorNodeViewer) Class
-                                .forName(className).newInstance();
-                        if (listModel.contains(viewer)) {
-                            JOptionPane
-                                    .showMessageDialog(
-                                            ZooInspectorNodeViewersDialog.this,
-                                            "Node viewer already exists.  Each node viewer can only be added once.",
-                                            "Input Error",
-                                            JOptionPane.ERROR_MESSAGE);
-                        } else {
-                            listModel.addElement(viewer);
-                        }
-                    } catch (Exception ex) {
-                        LoggerFactory
-                                .getLogger()
-                                .error(
-                                        "An error occurred while instaniating the node viewer. ",
-                                        ex);
-                        JOptionPane.showMessageDialog(
-                                ZooInspectorNodeViewersDialog.this,
-                                "An error occurred while instaniating the node viewer: "
-                                        + ex.getMessage(), "Error",
-                                JOptionPane.ERROR_MESSAGE);
-                    }
-                }
-            }
-        });
-
-        GridBagConstraints c7 = new GridBagConstraints();
-        c7.gridx = 0;
-        c7.gridy = 4;
-        c7.gridwidth = 1;
-        c7.gridheight = 1;
-        c7.weightx = 1;
-        c7.weighty = 0;
-        c7.anchor = GridBagConstraints.WEST;
-        c7.fill = GridBagConstraints.VERTICAL;
-        c7.insets = new Insets(5, 5, 5, 5);
-        c7.ipadx = 0;
-        c7.ipady = 0;
-        panel.add(buttons.get(Button.save), c7);
-        GridBagConstraints c8 = new GridBagConstraints();
-        c8.gridx = 1;
-        c8.gridy = 4;
-        c8.gridwidth = 1;
-        c8.gridheight = 1;
-        c8.weightx = 0;
-        c8.weighty = 0;
-        c8.anchor = GridBagConstraints.WEST;
-        c8.fill = GridBagConstraints.VERTICAL;
-        c8.insets = new Insets(5, 5, 5, 5);
-        c8.ipadx = 0;
-        c8.ipady = 0;
-        panel.add(buttons.get(Button.load), c8);
-        GridBagConstraints c9 = new GridBagConstraints();
-        c9.gridx = 2;
-        c9.gridy = 4;
-        c9.gridwidth = 1;
-        c9.gridheight = 1;
-        c9.weightx = 0;
-        c9.weighty = 0;
-        c9.anchor = GridBagConstraints.WEST;
-        c9.fill = GridBagConstraints.VERTICAL;
-        c9.insets = new Insets(5, 5, 5, 5);
-        c9.ipadx = 0;
-        c9.ipady = 0;
-        panel.add(buttons.get(Button.setDefaults), c9);
-        buttons.get(Button.save).addActionListener(new ActionListener() {
-
-            public void actionPerformed(ActionEvent e) {
-                int result = fileChooser
-                        .showSaveDialog(ZooInspectorNodeViewersDialog.this);
-                if (result == JFileChooser.APPROVE_OPTION) {
-                    File selectedFile = fileChooser.getSelectedFile();
-                    int answer = JOptionPane.YES_OPTION;
-                    if (selectedFile.exists()) {
-                        answer = JOptionPane
-                                .showConfirmDialog(
-                                        ZooInspectorNodeViewersDialog.this,
-                                        "The specified file already exists.  do you want to overwrite it?",
-                                        "Confirm Overwrite",
-                                        JOptionPane.YES_NO_OPTION,
-                                        JOptionPane.WARNING_MESSAGE);
-                    }
-                    if (answer == JOptionPane.YES_OPTION) {
-                        DefaultListModel listModel = (DefaultListModel) viewersList
-                                .getModel();
-                        List<String> nodeViewersClassNames = new ArrayList<String>();
-                        Object[] modelContents = listModel.toArray();
-                        for (Object o : modelContents) {
-                            nodeViewersClassNames
-                                    .add(((ZooInspectorNodeViewer) o)
-                                            .getClass().getCanonicalName());
-                        }
-                        try {
-                            manager.saveNodeViewersFile(selectedFile,
-                                    nodeViewersClassNames);
-                        } catch (IOException ex) {
-                            LoggerFactory
-                                    .getLogger()
-                                    .error(
-                                            "Error saving node viewer configuration from file.",
-                                            ex);
-                            JOptionPane.showMessageDialog(
-                                    ZooInspectorNodeViewersDialog.this,
-                                    "Error saving node viewer configuration from file: "
-                                            + ex.getMessage(), "Error",
-                                    JOptionPane.ERROR_MESSAGE);
-                        }
-                    }
-                }
-            }
-        });
-        buttons.get(Button.load).addActionListener(new ActionListener() {
-
-            public void actionPerformed(ActionEvent e) {
-                int result = fileChooser
-                        .showOpenDialog(ZooInspectorNodeViewersDialog.this);
-                if (result == JFileChooser.APPROVE_OPTION) {
-                    try {
-                        List<String> nodeViewersClassNames = manager
-                                .loadNodeViewersFile(fileChooser
-                                        .getSelectedFile());
-                        List<ZooInspectorNodeViewer> nodeViewers = new ArrayList<ZooInspectorNodeViewer>();
-                        for (String nodeViewersClassName : nodeViewersClassNames) {
-                            ZooInspectorNodeViewer viewer = (ZooInspectorNodeViewer) Class
-                                    .forName(nodeViewersClassName)
-                                    .newInstance();
-                            nodeViewers.add(viewer);
-                        }
-                        DefaultListModel model = new DefaultListModel();
-                        for (ZooInspectorNodeViewer viewer : nodeViewers) {
-                            model.addElement(viewer);
-                        }
-                        viewersList.setModel(model);
-                        panel.revalidate();
-                        panel.repaint();
-                    } catch (Exception ex) {
-                        LoggerFactory
-                                .getLogger()
-                                .error(
-                                        "Error loading node viewer configuration from file.",
-                                        ex);
-                        JOptionPane.showMessageDialog(
-                                ZooInspectorNodeViewersDialog.this,
-                                "Error loading node viewer configuration from file: "
-                                        + ex.getMessage(), "Error",
-                                JOptionPane.ERROR_MESSAGE);
-                    }
-                }
-            }
-        });
-        buttons.get(Button.setDefaults).addActionListener(new ActionListener() {
-
-            public void actionPerformed(ActionEvent e) {
-                int answer = JOptionPane
-                        .showConfirmDialog(
-                                ZooInspectorNodeViewersDialog.this,
-                                "Are you sure you want to save this configuration as the default?",
-                                "Confirm Set Defaults",
-                                JOptionPane.YES_NO_OPTION,
-                                JOptionPane.WARNING_MESSAGE);
-                if (answer == JOptionPane.YES_OPTION) {
-                    DefaultListModel listModel = (DefaultListModel) viewersList
-                            .getModel();
-                    List<String> nodeViewersClassNames = new ArrayList<String>();
-                    Object[] modelContents = listModel.toArray();
-                    for (Object o : modelContents) {
-                        nodeViewersClassNames.add(((ZooInspectorNodeViewer) o)
-                                .getClass().getCanonicalName());
-                    }
-                    try {
-                        manager
-                                .setDefaultNodeViewerConfiguration(nodeViewersClassNames);
-                    } catch (IOException ex) {
-                        LoggerFactory
-                                .getLogger()
-                                .error(
-                                        "Error setting default node viewer configuration.",
-                                        ex);
-                        JOptionPane.showMessageDialog(
-                                ZooInspectorNodeViewersDialog.this,
-                                "Error setting default node viewer configuration: "
-                                        + ex.getMessage(), "Error",
-                                JOptionPane.ERROR_MESSAGE);
-                    }
-                }
-            }
-        });
-
-        JPanel buttonsPanel = new JPanel();
-        buttonsPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10));
-        JButton okButton = new JButton("OK");
-        okButton.addActionListener(new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                ZooInspectorNodeViewersDialog.this.dispose();
-                DefaultListModel listModel = (DefaultListModel) viewersList
-                        .getModel();
-                newViewers.clear();
-                Object[] modelContents = listModel.toArray();
-                for (Object o : modelContents) {
-                    newViewers.add((ZooInspectorNodeViewer) o);
-                }
-                currentViewers.clear();
-                currentViewers.addAll(newViewers);
-                for (NodeViewersChangeListener listener : listeners) {
-                    listener.nodeViewersChanged(currentViewers);
-                }
-            }
-        });
-        buttonsPanel.add(okButton);
-        JButton cancelButton = new JButton("Cancel");
-        cancelButton.addActionListener(new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                ZooInspectorNodeViewersDialog.this.dispose();
-            }
-        });
-        buttonsPanel.add(cancelButton);
-        this.add(panel, BorderLayout.CENTER);
-        this.add(buttonsPanel, BorderLayout.SOUTH);
-        this.pack();
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see
-     * javax.swing.event.ListSelectionListener#valueChanged(javax.swing.event
-     * .ListSelectionEvent)
-     */
-    public void valueChanged(ListSelectionEvent e) {
-        JButton removeButton = buttons.get(Button.remove);
-        JButton upButton = buttons.get(Button.up);
-        JButton downButton = buttons.get(Button.down);
-        int index = viewersList.getSelectedIndex();
-
-        if (index == -1) {
-            removeButton.setEnabled(false);
-            upButton.setEnabled(false);
-            downButton.setEnabled(false);
-        } else {
-            removeButton.setEnabled(true);
-            if (index == 0) {
-                upButton.setEnabled(false);
-            } else {
-                upButton.setEnabled(true);
-            }
-            if (index == ((DefaultListModel) viewersList.getModel()).getSize()) {
-                downButton.setEnabled(false);
-            } else {
-                downButton.setEnabled(true);
-            }
-        }
-    }
-
-    public static enum Button {
-        up("Move currently selected node viewer up",IconResource.ICON_UP,false),
-        down("Move currently selected node viewer down",IconResource.ICON_DOWN,false),
-        add("Add node viewer",IconResource.ICON_ADD,true),
-        remove("Remove currently selected node viewer",IconResource.ICON_REMOVE,false),
-        save("Save current node viewer configuration to file","Save"),
-        load("Load node viewer configuration from file","Load"),
-        setDefaults("Set current configuration asd defaults","Set as defaults");
-
-        private String toolTip;
-        private String icon;
-        private boolean enabled;
-
-        Button(String toolTip, String icon, boolean enabled) {
-            this.toolTip = toolTip;
-            this.icon = icon;
-            this.enabled = enabled;
-        }
-
-        Button(String toolTip, String icon) {
-            this(toolTip, icon, true);
-        }
-
-        public JButton createJButton(IconResource iconResource) {
-            ImageIcon imageIcon = iconResource.get(icon, toolTip);
-            JButton jbutton;
-
-            if(imageIcon == null) {
-                jbutton = new JButton(icon);
-            } else {
-                jbutton = new JButton(imageIcon);
-            }
-
-            jbutton.setEnabled(enabled);
-            jbutton.setToolTipText(toolTip);
-            return jbutton;
-        }
-    }
-}
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.gui;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.FlowLayout;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.datatransfer.Transferable;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.DefaultListModel;
+import javax.swing.DropMode;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.ListSelectionModel;
+import javax.swing.TransferHandler;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import org.apache.zookeeper.inspector.gui.Toolbar.Button;
+import org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer;
+import org.apache.zookeeper.inspector.logger.LoggerFactory;
+import org.apache.zookeeper.inspector.manager.ZooInspectorManager;
+
+/**
+ * A {@link JDialog} for configuring which {@link ZooInspectorNodeViewer}s to
+ * show in the application
+ */
+public class ZooInspectorNodeViewersDialog extends JDialog implements
+        ListSelectionListener {
+
+    private final JList viewersList;
+    private final JFileChooser fileChooser = new JFileChooser(new File("."));
+    private final Map<Button, JButton> buttons = new HashMap<Button, JButton>();
+    /**
+     * @param frame
+     *            - the Frame from which the dialog is displayed
+     * @param currentViewers
+     *            - the {@link ZooInspectorNodeViewer}s to show
+     * @param listeners
+     *            - the {@link NodeViewersChangeListener}s which need to be
+     *            notified of changes to the node viewers configuration
+     * @param manager
+     *            - the {@link ZooInspectorManager} for the application
+     * 
+     */
+    public ZooInspectorNodeViewersDialog(Frame frame,
+            final List<ZooInspectorNodeViewer> currentViewers,
+            final Collection<NodeViewersChangeListener> listeners,
+            final ZooInspectorManager manager,
+            final IconResource iconResource) {
+        super(frame);
+        final List<ZooInspectorNodeViewer> newViewers = new ArrayList<ZooInspectorNodeViewer>(
+                currentViewers);
+        this.setLayout(new BorderLayout());
+        this.setIconImage(iconResource.get(IconResource.ICON_ChangeNodeViewers,"")
+                .getImage());
+        this.setTitle("About ZooInspector");
+        this.setModal(true);
+        this.setAlwaysOnTop(true);
+        this.setResizable(true);
+        final JPanel panel = new JPanel();
+        panel.setLayout(new GridBagLayout());
+        viewersList = new JList();
+        DefaultListModel model = new DefaultListModel();
+        for (ZooInspectorNodeViewer viewer : newViewers) {
+            model.addElement(viewer);
+        }
+        viewersList.setModel(model);
+        viewersList.setCellRenderer(new DefaultListCellRenderer() {
+            @Override
+            public Component getListCellRendererComponent(JList list,
+                    Object value, int index, boolean isSelected,
+                    boolean cellHasFocus) {
+                ZooInspectorNodeViewer viewer = (ZooInspectorNodeViewer) value;
+                JLabel label = (JLabel) super.getListCellRendererComponent(
+                        list, value, index, isSelected, cellHasFocus);
+                label.setText(viewer.getTitle());
+                return label;
+            }
+        });
+        viewersList.setDropMode(DropMode.INSERT);
+        viewersList.enableInputMethods(true);
+        viewersList.setDragEnabled(true);
+        viewersList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+        viewersList.getSelectionModel().addListSelectionListener(this);
+        viewersList.setTransferHandler(new TransferHandler() {
+
+            @Override
+            public boolean canImport(TransferHandler.TransferSupport info) {
+                // we only import NodeViewers
+                if (!info
+                        .isDataFlavorSupported(ZooInspectorNodeViewer.nodeViewerDataFlavor)) {
+                    return false;
+                }
+
+                JList.DropLocation dl = (JList.DropLocation) info
+                        .getDropLocation();
+                if (dl.getIndex() == -1) {
+                    return false;
+                }
+                return true;
+            }
+
+            @Override
+            public boolean importData(TransferHandler.TransferSupport info) {
+                JList.DropLocation dl = (JList.DropLocation) info
+                        .getDropLocation();
+                DefaultListModel listModel = (DefaultListModel) viewersList
+                        .getModel();
+                int index = dl.getIndex();
+                boolean insert = dl.isInsert();
+                // Get the string that is being dropped.
+                Transferable t = info.getTransferable();
+                String data;
+                try {
+                    data = (String) t
+                            .getTransferData(ZooInspectorNodeViewer.nodeViewerDataFlavor);
+                } catch (Exception e) {
+                    return false;
+                }
+                try {
+                    ZooInspectorNodeViewer viewer = (ZooInspectorNodeViewer) Class
+                            .forName(data).newInstance();
+                    if (listModel.contains(viewer)) {
+                        listModel.removeElement(viewer);
+                    }
+                    if (insert) {
+                        listModel.add(index, viewer);
+                    } else {
+                        listModel.set(index, viewer);
+                    }
+                    return true;
+                } catch (Exception e) {
+                    LoggerFactory.getLogger().error(
+                            "Error instantiating class: " + data, e);
+                    return false;
+                }
+
+            }
+
+            @Override
+            public int getSourceActions(JComponent c) {
+                return MOVE;
+            }
+
+            @Override
+            protected Transferable createTransferable(JComponent c) {
+                JList list = (JList) c;
+                ZooInspectorNodeViewer value = (ZooInspectorNodeViewer) list
+                        .getSelectedValue();
+                return value;
+            }
+        });
+        JScrollPane scroller = new JScrollPane(viewersList);
+        GridBagConstraints c1 = new GridBagConstraints();
+        c1.gridx = 0;
+        c1.gridy = 0;
+        c1.gridwidth = 3;
+        c1.gridheight = 3;
+        c1.weightx = 0;
+        c1.weighty = 1;
+        c1.anchor = GridBagConstraints.CENTER;
+        c1.fill = GridBagConstraints.BOTH;
+        c1.insets = new Insets(5, 5, 5, 5);
+        c1.ipadx = 0;
+        c1.ipady = 0;
+        panel.add(scroller, c1);
+
+        final JTextField newViewerTextField = new JTextField();
+
+        for(Button button : Button.values()) {
+            JButton jbutton = button.createJButton(iconResource);
+            buttons.put(button, jbutton);
+        }
+        GridBagConstraints c2 = new GridBagConstraints();
+        c2.gridx = 3;
+        c2.gridy = 0;
+        c2.gridwidth = 1;
+        c2.gridheight = 1;
+        c2.weightx = 0;
+        c2.weighty = 0;
+        c2.anchor = GridBagConstraints.NORTH;
+        c2.fill = GridBagConstraints.HORIZONTAL;
+        c2.insets = new Insets(5, 5, 5, 5);
+        c2.ipadx = 0;
+        c2.ipady = 0;
+        panel.add(buttons.get(Button.up), c2);
+        GridBagConstraints c3 = new GridBagConstraints();
+        c3.gridx = 3;
+        c3.gridy = 2;
+        c3.gridwidth = 1;
+        c3.gridheight = 1;
+        c3.weightx = 0;
+        c3.weighty = 0;
+        c3.anchor = GridBagConstraints.NORTH;
+        c3.fill = GridBagConstraints.HORIZONTAL;
+        c3.insets = new Insets(5, 5, 5, 5);
+        c3.ipadx = 0;
+        c3.ipady = 0;
+        panel.add(buttons.get(Button.down), c3);
+        GridBagConstraints c4 = new GridBagConstraints();
+        c4.gridx = 3;
+        c4.gridy = 1;
+        c4.gridwidth = 1;
+        c4.gridheight = 1;
+        c4.weightx = 0;
+        c4.weighty = 0;
+        c4.anchor = GridBagConstraints.NORTH;
+        c4.fill = GridBagConstraints.HORIZONTAL;
+        c4.insets = new Insets(5, 5, 5, 5);
+        c4.ipadx = 0;
+        c4.ipady = 0;
+        panel.add(buttons.get(Button.remove), c4);
+        GridBagConstraints c5 = new GridBagConstraints();
+        c5.gridx = 0;
+        c5.gridy = 3;
+        c5.gridwidth = 3;
+        c5.gridheight = 1;
+        c5.weightx = 0;
+        c5.weighty = 0;
+        c5.anchor = GridBagConstraints.CENTER;
+        c5.fill = GridBagConstraints.BOTH;
+        c5.insets = new Insets(5, 5, 5, 5);
+        c5.ipadx = 0;
+        c5.ipady = 0;
+        panel.add(newViewerTextField, c5);
+        GridBagConstraints c6 = new GridBagConstraints();
+        c6.gridx = 3;
+        c6.gridy = 3;
+        c6.gridwidth = 1;
+        c6.gridheight = 1;
+        c6.weightx = 0;
+        c6.weighty = 0;
+        c6.anchor = GridBagConstraints.CENTER;
+        c6.fill = GridBagConstraints.BOTH;
+        c6.insets = new Insets(5, 5, 5, 5);
+        c6.ipadx = 0;
+        c6.ipady = 0;
+        panel.add(buttons.get(Button.add), c6);
+        buttons.get(Button.up).addActionListener(new ActionListener() {
+
+            public void actionPerformed(ActionEvent e) {
+                DefaultListModel listModel = (DefaultListModel) viewersList
+                        .getModel();
+                ZooInspectorNodeViewer viewer = (ZooInspectorNodeViewer) viewersList
+                        .getSelectedValue();
+                int index = viewersList.getSelectedIndex();
+                if (listModel.contains(viewer)) {
+                    listModel.removeElementAt(index);
+                    listModel.insertElementAt(viewer, index - 1);
+                    viewersList.setSelectedValue(viewer, true);
+                }
+            }
+        });
+        buttons.get(Button.down).addActionListener(new ActionListener() {
+
+            public void actionPerformed(ActionEvent e) {
+                DefaultListModel listModel = (DefaultListModel) viewersList
+                        .getModel();
+                ZooInspectorNodeViewer viewer = (ZooInspectorNodeViewer) viewersList
+                        .getSelectedValue();
+                int index = viewersList.getSelectedIndex();
+                if (listModel.contains(viewer)) {
+                    listModel.removeElementAt(index);
+                    listModel.insertElementAt(viewer, index + 1);
+                    viewersList.setSelectedValue(viewer, true);
+                }
+            }
+        });
+        buttons.get(Button.remove).addActionListener(new ActionListener() {
+
+            public void actionPerformed(ActionEvent e) {
+                DefaultListModel listModel = (DefaultListModel) viewersList
+                        .getModel();
+                ZooInspectorNodeViewer viewer = (ZooInspectorNodeViewer) viewersList
+                        .getSelectedValue();
+                int index = viewersList.getSelectedIndex();
+                if (listModel.contains(viewer)) {
+                    listModel.removeElement(viewer);
+                    viewersList
+                            .setSelectedIndex(index == listModel.size() ? index - 1
+                                    : index);
+                }
+            }
+        });
+        buttons.get(Button.add).addActionListener(new ActionListener() {
+
+            public void actionPerformed(ActionEvent e) {
+                String className = newViewerTextField.getText();
+                if (className == null || className.length() == 0) {
+                    JOptionPane
+                            .showMessageDialog(
+                                    ZooInspectorNodeViewersDialog.this,
+                                    "Please enter the full class name for a Node Viewer and click the add button",
+                                    "Input Error", JOptionPane.ERROR_MESSAGE);
+                } else {
+                    try {
+                        DefaultListModel listModel = (DefaultListModel) viewersList
+                                .getModel();
+                        ZooInspectorNodeViewer viewer = (ZooInspectorNodeViewer) Class
+                                .forName(className).newInstance();
+                        if (listModel.contains(viewer)) {
+                            JOptionPane
+                                    .showMessageDialog(
+                                            ZooInspectorNodeViewersDialog.this,
+                                            "Node viewer already exists.  Each node viewer can only be added once.",
+                                            "Input Error",
+                                            JOptionPane.ERROR_MESSAGE);
+                        } else {
+                            listModel.addElement(viewer);
+                        }
+                    } catch (Exception ex) {
+                        LoggerFactory
+                                .getLogger()
+                                .error(
+                                        "An error occurred while instaniating the node viewer. ",
+                                        ex);
+                        JOptionPane.showMessageDialog(
+                                ZooInspectorNodeViewersDialog.this,
+                                "An error occurred while instaniating the node viewer: "
+                                        + ex.getMessage(), "Error",
+                                JOptionPane.ERROR_MESSAGE);
+                    }
+                }
+            }
+        });
+
+        GridBagConstraints c7 = new GridBagConstraints();
+        c7.gridx = 0;
+        c7.gridy = 4;
+        c7.gridwidth = 1;
+        c7.gridheight = 1;
+        c7.weightx = 1;
+        c7.weighty = 0;
+        c7.anchor = GridBagConstraints.WEST;
+        c7.fill = GridBagConstraints.VERTICAL;
+        c7.insets = new Insets(5, 5, 5, 5);
+        c7.ipadx = 0;
+        c7.ipady = 0;
+        panel.add(buttons.get(Button.save), c7);
+        GridBagConstraints c8 = new GridBagConstraints();
+        c8.gridx = 1;
+        c8.gridy = 4;
+        c8.gridwidth = 1;
+        c8.gridheight = 1;
+        c8.weightx = 0;
+        c8.weighty = 0;
+        c8.anchor = GridBagConstraints.WEST;
+        c8.fill = GridBagConstraints.VERTICAL;
+        c8.insets = new Insets(5, 5, 5, 5);
+        c8.ipadx = 0;
+        c8.ipady = 0;
+        panel.add(buttons.get(Button.load), c8);
+        GridBagConstraints c9 = new GridBagConstraints();
+        c9.gridx = 2;
+        c9.gridy = 4;
+        c9.gridwidth = 1;
+        c9.gridheight = 1;
+        c9.weightx = 0;
+        c9.weighty = 0;
+        c9.anchor = GridBagConstraints.WEST;
+        c9.fill = GridBagConstraints.VERTICAL;
+        c9.insets = new Insets(5, 5, 5, 5);
+        c9.ipadx = 0;
+        c9.ipady = 0;
+        panel.add(buttons.get(Button.setDefaults), c9);
+        buttons.get(Button.save).addActionListener(new ActionListener() {
+
+            public void actionPerformed(ActionEvent e) {
+                int result = fileChooser
+                        .showSaveDialog(ZooInspectorNodeViewersDialog.this);
+                if (result == JFileChooser.APPROVE_OPTION) {
+                    File selectedFile = fileChooser.getSelectedFile();
+                    int answer = JOptionPane.YES_OPTION;
+                    if (selectedFile.exists()) {
+                        answer = JOptionPane
+                                .showConfirmDialog(
+                                        ZooInspectorNodeViewersDialog.this,
+                                        "The specified file already exists.  do you want to overwrite it?",
+                                        "Confirm Overwrite",
+                                        JOptionPane.YES_NO_OPTION,
+                                        JOptionPane.WARNING_MESSAGE);
+                    }
+                    if (answer == JOptionPane.YES_OPTION) {
+                        DefaultListModel listModel = (DefaultListModel) viewersList
+                                .getModel();
+                        List<String> nodeViewersClassNames = new ArrayList<String>();
+                        Object[] modelContents = listModel.toArray();
+                        for (Object o : modelContents) {
+                            nodeViewersClassNames
+                                    .add(((ZooInspectorNodeViewer) o)
+                                            .getClass().getCanonicalName());
+                        }
+                        try {
+                            manager.saveNodeViewersFile(selectedFile,
+                                    nodeViewersClassNames);
+                        } catch (IOException ex) {
+                            LoggerFactory
+                                    .getLogger()
+                                    .error(
+                                            "Error saving node viewer configuration from file.",
+                                            ex);
+                            JOptionPane.showMessageDialog(
+                                    ZooInspectorNodeViewersDialog.this,
+                                    "Error saving node viewer configuration from file: "
+                                            + ex.getMessage(), "Error",
+                                    JOptionPane.ERROR_MESSAGE);
+                        }
+                    }
+                }
+            }
+        });
+        buttons.get(Button.load).addActionListener(new ActionListener() {
+
+            public void actionPerformed(ActionEvent e) {
+                int result = fileChooser
+                        .showOpenDialog(ZooInspectorNodeViewersDialog.this);
+                if (result == JFileChooser.APPROVE_OPTION) {
+                    try {
+                        List<String> nodeViewersClassNames = manager
+                                .loadNodeViewersFile(fileChooser
+                                        .getSelectedFile());
+                        List<ZooInspectorNodeViewer> nodeViewers = new ArrayList<ZooInspectorNodeViewer>();
+                        for (String nodeViewersClassName : nodeViewersClassNames) {
+                            ZooInspectorNodeViewer viewer = (ZooInspectorNodeViewer) Class
+                                    .forName(nodeViewersClassName)
+                                    .newInstance();
+                            nodeViewers.add(viewer);
+                        }
+                        DefaultListModel model = new DefaultListModel();
+                        for (ZooInspectorNodeViewer viewer : nodeViewers) {
+                            model.addElement(viewer);
+                        }
+                        viewersList.setModel(model);
+                        panel.revalidate();
+                        panel.repaint();
+                    } catch (Exception ex) {
+                        LoggerFactory
+                                .getLogger()
+                                .error(
+                                        "Error loading node viewer configuration from file.",
+                                        ex);
+                        JOptionPane.showMessageDialog(
+                                ZooInspectorNodeViewersDialog.this,
+                                "Error loading node viewer configuration from file: "
+                                        + ex.getMessage(), "Error",
+                                JOptionPane.ERROR_MESSAGE);
+                    }
+                }
+            }
+        });
+        buttons.get(Button.setDefaults).addActionListener(new ActionListener() {
+
+            public void actionPerformed(ActionEvent e) {
+                int answer = JOptionPane
+                        .showConfirmDialog(
+                                ZooInspectorNodeViewersDialog.this,
+                                "Are you sure you want to save this configuration as the default?",
+                                "Confirm Set Defaults",
+                                JOptionPane.YES_NO_OPTION,
+                                JOptionPane.WARNING_MESSAGE);
+                if (answer == JOptionPane.YES_OPTION) {
+                    DefaultListModel listModel = (DefaultListModel) viewersList
+                            .getModel();
+                    List<String> nodeViewersClassNames = new ArrayList<String>();
+                    Object[] modelContents = listModel.toArray();
+                    for (Object o : modelContents) {
+                        nodeViewersClassNames.add(((ZooInspectorNodeViewer) o)
+                                .getClass().getCanonicalName());
+                    }
+                    try {
+                        manager
+                                .setDefaultNodeViewerConfiguration(nodeViewersClassNames);
+                    } catch (IOException ex) {
+                        LoggerFactory
+                                .getLogger()
+                                .error(
+                                        "Error setting default node viewer configuration.",
+                                        ex);
+                        JOptionPane.showMessageDialog(
+                                ZooInspectorNodeViewersDialog.this,
+                                "Error setting default node viewer configuration: "
+                                        + ex.getMessage(), "Error",
+                                JOptionPane.ERROR_MESSAGE);
+                    }
+                }
+            }
+        });
+
+        JPanel buttonsPanel = new JPanel();
+        buttonsPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10));
+        JButton okButton = new JButton("OK");
+        okButton.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                ZooInspectorNodeViewersDialog.this.dispose();
+                DefaultListModel listModel = (DefaultListModel) viewersList
+                        .getModel();
+                newViewers.clear();
+                Object[] modelContents = listModel.toArray();
+                for (Object o : modelContents) {
+                    newViewers.add((ZooInspectorNodeViewer) o);
+                }
+                currentViewers.clear();
+                currentViewers.addAll(newViewers);
+                for (NodeViewersChangeListener listener : listeners) {
+                    listener.nodeViewersChanged(currentViewers);
+                }
+            }
+        });
+        buttonsPanel.add(okButton);
+        JButton cancelButton = new JButton("Cancel");
+        cancelButton.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                ZooInspectorNodeViewersDialog.this.dispose();
+            }
+        });
+        buttonsPanel.add(cancelButton);
+        this.add(panel, BorderLayout.CENTER);
+        this.add(buttonsPanel, BorderLayout.SOUTH);
+        this.pack();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * javax.swing.event.ListSelectionListener#valueChanged(javax.swing.event
+     * .ListSelectionEvent)
+     */
+    public void valueChanged(ListSelectionEvent e) {
+        JButton removeButton = buttons.get(Button.remove);
+        JButton upButton = buttons.get(Button.up);
+        JButton downButton = buttons.get(Button.down);
+        int index = viewersList.getSelectedIndex();
+
+        if (index == -1) {
+            removeButton.setEnabled(false);
+            upButton.setEnabled(false);
+            downButton.setEnabled(false);
+        } else {
+            removeButton.setEnabled(true);
+            if (index == 0) {
+                upButton.setEnabled(false);
+            } else {
+                upButton.setEnabled(true);
+            }
+            if (index == ((DefaultListModel) viewersList.getModel()).getSize()) {
+                downButton.setEnabled(false);
+            } else {
+                downButton.setEnabled(true);
+            }
+        }
+    }
+
+    public static enum Button {
+        up("Move currently selected node viewer up",IconResource.ICON_UP,false),
+        down("Move currently selected node viewer down",IconResource.ICON_DOWN,false),
+        add("Add node viewer",IconResource.ICON_ADD,true),
+        remove("Remove currently selected node viewer",IconResource.ICON_REMOVE,false),
+        save("Save current node viewer configuration to file","Save"),
+        load("Load node viewer configuration from file","Load"),
+        setDefaults("Set current configuration asd defaults","Set as defaults");
+
+        private String toolTip;
+        private String icon;
+        private boolean enabled;
+
+        Button(String toolTip, String icon, boolean enabled) {
+            this.toolTip = toolTip;
+            this.icon = icon;
+            this.enabled = enabled;
+        }
+
+        Button(String toolTip, String icon) {
+            this(toolTip, icon, true);
+        }
+
+        public JButton createJButton(IconResource iconResource) {
+            ImageIcon imageIcon = iconResource.get(icon, toolTip);
+            JButton jbutton;
+
+            if(imageIcon == null) {
+                jbutton = new JButton(icon);
+            } else {
+                jbutton = new JButton(imageIcon);
+            }
+
+            jbutton.setEnabled(enabled);
+            jbutton.setToolTipText(toolTip);
+            return jbutton;
+        }
+    }
+}

+ 140 - 140
src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/ZooInspectorNodeViewersPanel.java

@@ -1,140 +1,140 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.zookeeper.inspector.gui;
-
-import java.awt.BorderLayout;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.swing.JPanel;
-import javax.swing.JTabbedPane;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import javax.swing.event.TreeSelectionEvent;
-import javax.swing.event.TreeSelectionListener;
-import javax.swing.tree.TreePath;
-
-import org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer;
-import org.apache.zookeeper.inspector.manager.ZooInspectorManager;
-import org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager;
-
-/**
- * This is the {@link JPanel} which contains the {@link ZooInspectorNodeViewer}s
- */
-public class ZooInspectorNodeViewersPanel extends JPanel implements
-        TreeSelectionListener, ChangeListener {
-
-    private final List<ZooInspectorNodeViewer> nodeVeiwers = new ArrayList<ZooInspectorNodeViewer>();
-    private final List<Boolean> needsReload = new ArrayList<Boolean>();
-    private final JTabbedPane tabbedPane;
-    private final List<String> selectedNodes = new ArrayList<String>();
-    private final ZooInspectorNodeManager zooInspectorManager;
-
-    /**
-     * @param zooInspectorManager
-     *            - the {@link ZooInspectorManager} for the application
-     * @param nodeVeiwers
-     *            - the {@link ZooInspectorNodeViewer}s to show
-     */
-    public ZooInspectorNodeViewersPanel(
-            ZooInspectorNodeManager zooInspectorManager,
-            List<ZooInspectorNodeViewer> nodeVeiwers) {
-        this.zooInspectorManager = zooInspectorManager;
-        this.setLayout(new BorderLayout());
-        tabbedPane = new JTabbedPane(JTabbedPane.TOP,
-                JTabbedPane.WRAP_TAB_LAYOUT);
-        setNodeViewers(nodeVeiwers);
-        tabbedPane.addChangeListener(this);
-        this.add(tabbedPane, BorderLayout.CENTER);
-        reloadSelectedViewer();
-    }
-
-    /**
-     * @param nodeViewers
-     *            - the {@link ZooInspectorNodeViewer}s to show
-     */
-    public void setNodeViewers(List<ZooInspectorNodeViewer> nodeViewers) {
-        this.nodeVeiwers.clear();
-        this.nodeVeiwers.addAll(nodeViewers);
-        needsReload.clear();
-        tabbedPane.removeAll();
-        for (ZooInspectorNodeViewer nodeViewer : nodeVeiwers) {
-            nodeViewer.setZooInspectorManager(zooInspectorManager);
-            needsReload.add(true);
-            tabbedPane.add(nodeViewer.getTitle(), nodeViewer);
-        }
-        this.revalidate();
-        this.repaint();
-    }
-
-    private void reloadSelectedViewer() {
-        int index = this.tabbedPane.getSelectedIndex();
-        if (index != -1 && this.needsReload.get(index)) {
-            ZooInspectorNodeViewer viewer = this.nodeVeiwers.get(index);
-            viewer.nodeSelectionChanged(selectedNodes);
-            this.needsReload.set(index, false);
-        }
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see
-     * javax.swing.event.TreeSelectionListener#valueChanged(javax.swing.event
-     * .TreeSelectionEvent)
-     */
-    public void valueChanged(TreeSelectionEvent e) {
-        TreePath[] paths = e.getPaths();
-        selectedNodes.clear();
-        for (TreePath path : paths) {
-            boolean appended = false;
-            StringBuilder sb = new StringBuilder();
-            Object[] pathArray = path.getPath();
-            for (Object o : pathArray) {
-                if (o != null) {
-                    String nodeName = o.toString();
-                    if (nodeName != null) {
-                        if (nodeName.length() > 0) {
-                            appended = true;
-                            sb.append("/"); //$NON-NLS-1$
-                            sb.append(o.toString());
-                        }
-                    }
-                }
-            }
-            if (appended) {
-                selectedNodes.add(sb.toString());
-            }
-        }
-        for (int i = 0; i < needsReload.size(); i++) {
-            this.needsReload.set(i, true);
-        }
-        reloadSelectedViewer();
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see
-     * javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent
-     * )
-     */
-    public void stateChanged(ChangeEvent e) {
-        reloadSelectedViewer();
-    }
-}
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.gui;
+
+import java.awt.BorderLayout;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.TreePath;
+
+import org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer;
+import org.apache.zookeeper.inspector.manager.ZooInspectorManager;
+import org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager;
+
+/**
+ * This is the {@link JPanel} which contains the {@link ZooInspectorNodeViewer}s
+ */
+public class ZooInspectorNodeViewersPanel extends JPanel implements
+        TreeSelectionListener, ChangeListener {
+
+    private final List<ZooInspectorNodeViewer> nodeVeiwers = new ArrayList<ZooInspectorNodeViewer>();
+    private final List<Boolean> needsReload = new ArrayList<Boolean>();
+    private final JTabbedPane tabbedPane;
+    private final List<String> selectedNodes = new ArrayList<String>();
+    private final ZooInspectorNodeManager zooInspectorManager;
+
+    /**
+     * @param zooInspectorManager
+     *            - the {@link ZooInspectorManager} for the application
+     * @param nodeVeiwers
+     *            - the {@link ZooInspectorNodeViewer}s to show
+     */
+    public ZooInspectorNodeViewersPanel(
+            ZooInspectorNodeManager zooInspectorManager,
+            List<ZooInspectorNodeViewer> nodeVeiwers) {
+        this.zooInspectorManager = zooInspectorManager;
+        this.setLayout(new BorderLayout());
+        tabbedPane = new JTabbedPane(JTabbedPane.TOP,
+                JTabbedPane.WRAP_TAB_LAYOUT);
+        setNodeViewers(nodeVeiwers);
+        tabbedPane.addChangeListener(this);
+        this.add(tabbedPane, BorderLayout.CENTER);
+        reloadSelectedViewer();
+    }
+
+    /**
+     * @param nodeViewers
+     *            - the {@link ZooInspectorNodeViewer}s to show
+     */
+    public void setNodeViewers(List<ZooInspectorNodeViewer> nodeViewers) {
+        this.nodeVeiwers.clear();
+        this.nodeVeiwers.addAll(nodeViewers);
+        needsReload.clear();
+        tabbedPane.removeAll();
+        for (ZooInspectorNodeViewer nodeViewer : nodeVeiwers) {
+            nodeViewer.setZooInspectorManager(zooInspectorManager);
+            needsReload.add(true);
+            tabbedPane.add(nodeViewer.getTitle(), nodeViewer);
+        }
+        this.revalidate();
+        this.repaint();
+    }
+
+    private void reloadSelectedViewer() {
+        int index = this.tabbedPane.getSelectedIndex();
+        if (index != -1 && this.needsReload.get(index)) {
+            ZooInspectorNodeViewer viewer = this.nodeVeiwers.get(index);
+            viewer.nodeSelectionChanged(selectedNodes);
+            this.needsReload.set(index, false);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * javax.swing.event.TreeSelectionListener#valueChanged(javax.swing.event
+     * .TreeSelectionEvent)
+     */
+    public void valueChanged(TreeSelectionEvent e) {
+        TreePath[] paths = e.getPaths();
+        selectedNodes.clear();
+        for (TreePath path : paths) {
+            boolean appended = false;
+            StringBuilder sb = new StringBuilder();
+            Object[] pathArray = path.getPath();
+            for (Object o : pathArray) {
+                if (o != null) {
+                    String nodeName = o.toString();
+                    if (nodeName != null) {
+                        if (nodeName.length() > 0) {
+                            appended = true;
+                            sb.append("/"); //$NON-NLS-1$
+                            sb.append(o.toString());
+                        }
+                    }
+                }
+            }
+            if (appended) {
+                selectedNodes.add(sb.toString());
+            }
+        }
+        for (int i = 0; i < needsReload.size(); i++) {
+            this.needsReload.set(i, true);
+        }
+        reloadSelectedViewer();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent
+     * )
+     */
+    public void stateChanged(ChangeEvent e) {
+        reloadSelectedViewer();
+    }
+}

+ 318 - 318
src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/ZooInspectorPanel.java

@@ -1,318 +1,318 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.zookeeper.inspector.gui;
-
-import java.awt.BorderLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Properties;
-import java.util.concurrent.ExecutionException;
-
-import javax.swing.JButton;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JSplitPane;
-import javax.swing.JToolBar;
-import javax.swing.SwingWorker;
-
-import org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer;
-import org.apache.zookeeper.inspector.logger.LoggerFactory;
-import org.apache.zookeeper.inspector.manager.ZooInspectorManager;
-
-/**
- * The parent {@link JPanel} for the whole application
- */
-public class ZooInspectorPanel extends JPanel implements
-        NodeViewersChangeListener {
-    private final IconResource iconResource;
-    private final Toolbar toolbar;
-    private final ZooInspectorNodeViewersPanel nodeViewersPanel;
-    private final ZooInspectorTreeViewer treeViewer;
-    private final ZooInspectorManager zooInspectorManager;
-
-    private final List<NodeViewersChangeListener> listeners = new ArrayList<NodeViewersChangeListener>();
-    {
-        listeners.add(this);
-    }
-
-    /**
-     * @param zooInspectorManager
-     *            - the {@link ZooInspectorManager} for the application
-     */
-    public ZooInspectorPanel(final ZooInspectorManager zooInspectorManager, final IconResource iconResource) {
-        this.zooInspectorManager = zooInspectorManager;
-        this.iconResource = iconResource;
-        toolbar = new Toolbar(iconResource);
-        final ArrayList<ZooInspectorNodeViewer> nodeViewers = new ArrayList<ZooInspectorNodeViewer>();
-        try {
-            List<String> defaultNodeViewersClassNames = this.zooInspectorManager
-                    .getDefaultNodeViewerConfiguration();
-            for (String className : defaultNodeViewersClassNames) {
-                nodeViewers.add((ZooInspectorNodeViewer) Class.forName(
-                        className).newInstance());
-            }
-        } catch (Exception ex) {
-            LoggerFactory.getLogger().error(
-                    "Error loading default node viewers.", ex);
-            JOptionPane.showMessageDialog(ZooInspectorPanel.this,
-                    "Error loading default node viewers: " + ex.getMessage(),
-                    "Error", JOptionPane.ERROR_MESSAGE);
-        }
-        nodeViewersPanel = new ZooInspectorNodeViewersPanel(
-                zooInspectorManager, nodeViewers);
-        treeViewer = new ZooInspectorTreeViewer(zooInspectorManager,
-                nodeViewersPanel, iconResource);
-        this.setLayout(new BorderLayout());
-        
-        toolbar.addActionListener(Toolbar.Button.connect, new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                ZooInspectorConnectionPropertiesDialog zicpd = new ZooInspectorConnectionPropertiesDialog(
-                        zooInspectorManager.getLastConnectionProps(),
-                        zooInspectorManager.getConnectionPropertiesTemplate(),
-                        ZooInspectorPanel.this);
-                zicpd.setVisible(true);
-            }
-        });
-        toolbar.addActionListener(Toolbar.Button.disconnect, new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                disconnect();
-            }
-        });
-        toolbar.addActionListener(Toolbar.Button.refresh, new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                treeViewer.refreshView();
-            }
-        });
-        toolbar.addActionListener(Toolbar.Button.addNode, new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                final List<String> selectedNodes = treeViewer
-                        .getSelectedNodes();
-                if (selectedNodes.size() == 1) {
-                    final String nodeName = JOptionPane.showInputDialog(
-                            ZooInspectorPanel.this,
-                            "Please Enter a name for the new node",
-                            "Create Node", JOptionPane.INFORMATION_MESSAGE);
-                    if (nodeName != null && nodeName.length() > 0) {
-                        SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
-
-                            @Override
-                            protected Boolean doInBackground() throws Exception {
-                                return ZooInspectorPanel.this.zooInspectorManager
-                                        .createNode(selectedNodes.get(0),
-                                                nodeName);
-                            }
-
-                            @Override
-                            protected void done() {
-                                treeViewer.refreshView();
-                            }
-                        };
-                        worker.execute();
-                    }
-                } else {
-                    JOptionPane.showMessageDialog(ZooInspectorPanel.this,
-                            "Please select 1 parent node for the new node.");
-                }
-            }
-        });
-        toolbar.addActionListener(Toolbar.Button.deleteNode, new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                final List<String> selectedNodes = treeViewer
-                        .getSelectedNodes();
-                if (selectedNodes.size() == 0) {
-                    JOptionPane.showMessageDialog(ZooInspectorPanel.this,
-                            "Please select at least 1 node to be deleted");
-                } else {
-                    int answer = JOptionPane.showConfirmDialog(
-                            ZooInspectorPanel.this,
-                            "Are you sure you want to delete the selected nodes?"
-                                    + "(This action cannot be reverted)",
-                            "Confirm Delete", JOptionPane.YES_NO_OPTION,
-                            JOptionPane.WARNING_MESSAGE);
-                    if (answer == JOptionPane.YES_OPTION) {
-                        SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
-
-                            @Override
-                            protected Boolean doInBackground() throws Exception {
-                                for (String nodePath : selectedNodes) {
-                                    ZooInspectorPanel.this.zooInspectorManager
-                                            .deleteNode(nodePath);
-                                }
-                                return true;
-                            }
-
-                            @Override
-                            protected void done() {
-                                treeViewer.refreshView();
-                            }
-                        };
-                        worker.execute();
-                    }
-                }
-            }
-        });
-        toolbar.addActionListener(Toolbar.Button.nodeViewers, new ActionListener() {
-
-            public void actionPerformed(ActionEvent e) {
-                ZooInspectorNodeViewersDialog nvd = new ZooInspectorNodeViewersDialog(
-                        JOptionPane.getRootFrame(), nodeViewers, listeners,
-                        zooInspectorManager, iconResource);
-                nvd.setVisible(true);
-            }
-        });
-        toolbar.addActionListener(Toolbar.Button.about, new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                ZooInspectorAboutDialog zicpd = new ZooInspectorAboutDialog(
-                        JOptionPane.getRootFrame(), iconResource);
-                zicpd.setVisible(true);
-            }
-        });
-        JScrollPane treeScroller = new JScrollPane(treeViewer);
-        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
-                treeScroller, nodeViewersPanel);
-        splitPane.setResizeWeight(0.25);
-        this.add(splitPane, BorderLayout.CENTER);
-        this.add(toolbar.getJToolBar(), BorderLayout.NORTH);
-    }
-
-    /**
-     * @param connectionProps
-     *            the {@link Properties} for connecting to the zookeeper
-     *            instance
-     */
-    public void connect(final Properties connectionProps) {
-        SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
-
-            @Override
-            protected Boolean doInBackground() throws Exception {
-                zooInspectorManager.setLastConnectionProps(connectionProps);
-                return zooInspectorManager.connect(connectionProps);
-            }
-
-            @Override
-            protected void done() {
-                try {
-                    if (get()) {
-                        treeViewer.refreshView();
-                        toolbar.toggleButtons(true);
-                    } else {
-                        JOptionPane.showMessageDialog(ZooInspectorPanel.this,
-                                "Unable to connect to zookeeper", "Error",
-                                JOptionPane.ERROR_MESSAGE);
-                    }
-                } catch (InterruptedException e) {
-                    LoggerFactory
-                            .getLogger()
-                            .error(
-                                    "Error occurred while connecting to ZooKeeper server",
-                                    e);
-                } catch (ExecutionException e) {
-                    LoggerFactory
-                            .getLogger()
-                            .error(
-                                    "Error occurred while connecting to ZooKeeper server",
-                                    e);
-                }
-            }
-
-        };
-        worker.execute();
-    }
-
-    /**
-	 * 
-	 */
-    public void disconnect() {
-        disconnect(false);
-    }
-
-    /**
-     * @param wait
-     *            - set this to true if the method should only return once the
-     *            application has successfully disconnected
-     */
-    public void disconnect(boolean wait) {
-        SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
-
-            @Override
-            protected Boolean doInBackground() throws Exception {
-                return ZooInspectorPanel.this.zooInspectorManager.disconnect();
-            }
-
-            @Override
-            protected void done() {
-                try {
-                    if (get()) {
-                        treeViewer.clearView();
-                        toolbar.toggleButtons(false);
-                    }
-                } catch (InterruptedException e) {
-                    LoggerFactory
-                            .getLogger()
-                            .error(
-                                    "Error occurred while disconnecting from ZooKeeper server",
-                                    e);
-                } catch (ExecutionException e) {
-                    LoggerFactory
-                            .getLogger()
-                            .error(
-                                    "Error occurred while disconnecting from ZooKeeper server",
-                                    e);
-                }
-            }
-
-        };
-        worker.execute();
-        if (wait) {
-            while (!worker.isDone()) {
-                try {
-                    Thread.sleep(100);
-                } catch (InterruptedException e) {
-                    LoggerFactory
-                            .getLogger()
-                            .error(
-                                    "Error occurred while disconnecting from ZooKeeper server",
-                                    e);
-                }
-            }
-        }
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @seeorg.apache.zookeeper.inspector.gui.NodeViewersChangeListener#
-     * nodeViewersChanged(java.util.List)
-     */
-    public void nodeViewersChanged(List<ZooInspectorNodeViewer> newViewers) {
-        this.nodeViewersPanel.setNodeViewers(newViewers);
-    }
-
-    /**
-     * @param connectionProps
-     * @throws IOException
-     */
-    public void setdefaultConnectionProps(Properties connectionProps)
-            throws IOException {
-        this.zooInspectorManager.saveDefaultConnectionFile(connectionProps);
-    }
-}
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.gui;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.ExecutionException;
+
+import javax.swing.JButton;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JToolBar;
+import javax.swing.SwingWorker;
+
+import org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer;
+import org.apache.zookeeper.inspector.logger.LoggerFactory;
+import org.apache.zookeeper.inspector.manager.ZooInspectorManager;
+
+/**
+ * The parent {@link JPanel} for the whole application
+ */
+public class ZooInspectorPanel extends JPanel implements
+        NodeViewersChangeListener {
+    private final IconResource iconResource;
+    private final Toolbar toolbar;
+    private final ZooInspectorNodeViewersPanel nodeViewersPanel;
+    private final ZooInspectorTreeViewer treeViewer;
+    private final ZooInspectorManager zooInspectorManager;
+
+    private final List<NodeViewersChangeListener> listeners = new ArrayList<NodeViewersChangeListener>();
+    {
+        listeners.add(this);
+    }
+
+    /**
+     * @param zooInspectorManager
+     *            - the {@link ZooInspectorManager} for the application
+     */
+    public ZooInspectorPanel(final ZooInspectorManager zooInspectorManager, final IconResource iconResource) {
+        this.zooInspectorManager = zooInspectorManager;
+        this.iconResource = iconResource;
+        toolbar = new Toolbar(iconResource);
+        final ArrayList<ZooInspectorNodeViewer> nodeViewers = new ArrayList<ZooInspectorNodeViewer>();
+        try {
+            List<String> defaultNodeViewersClassNames = this.zooInspectorManager
+                    .getDefaultNodeViewerConfiguration();
+            for (String className : defaultNodeViewersClassNames) {
+                nodeViewers.add((ZooInspectorNodeViewer) Class.forName(
+                        className).newInstance());
+            }
+        } catch (Exception ex) {
+            LoggerFactory.getLogger().error(
+                    "Error loading default node viewers.", ex);
+            JOptionPane.showMessageDialog(ZooInspectorPanel.this,
+                    "Error loading default node viewers: " + ex.getMessage(),
+                    "Error", JOptionPane.ERROR_MESSAGE);
+        }
+        nodeViewersPanel = new ZooInspectorNodeViewersPanel(
+                zooInspectorManager, nodeViewers);
+        treeViewer = new ZooInspectorTreeViewer(zooInspectorManager,
+                nodeViewersPanel, iconResource);
+        this.setLayout(new BorderLayout());
+        
+        toolbar.addActionListener(Toolbar.Button.connect, new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                ZooInspectorConnectionPropertiesDialog zicpd = new ZooInspectorConnectionPropertiesDialog(
+                        zooInspectorManager.getLastConnectionProps(),
+                        zooInspectorManager.getConnectionPropertiesTemplate(),
+                        ZooInspectorPanel.this);
+                zicpd.setVisible(true);
+            }
+        });
+        toolbar.addActionListener(Toolbar.Button.disconnect, new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                disconnect();
+            }
+        });
+        toolbar.addActionListener(Toolbar.Button.refresh, new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                treeViewer.refreshView();
+            }
+        });
+        toolbar.addActionListener(Toolbar.Button.addNode, new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                final List<String> selectedNodes = treeViewer
+                        .getSelectedNodes();
+                if (selectedNodes.size() == 1) {
+                    final String nodeName = JOptionPane.showInputDialog(
+                            ZooInspectorPanel.this,
+                            "Please Enter a name for the new node",
+                            "Create Node", JOptionPane.INFORMATION_MESSAGE);
+                    if (nodeName != null && nodeName.length() > 0) {
+                        SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
+
+                            @Override
+                            protected Boolean doInBackground() throws Exception {
+                                return ZooInspectorPanel.this.zooInspectorManager
+                                        .createNode(selectedNodes.get(0),
+                                                nodeName);
+                            }
+
+                            @Override
+                            protected void done() {
+                                treeViewer.refreshView();
+                            }
+                        };
+                        worker.execute();
+                    }
+                } else {
+                    JOptionPane.showMessageDialog(ZooInspectorPanel.this,
+                            "Please select 1 parent node for the new node.");
+                }
+            }
+        });
+        toolbar.addActionListener(Toolbar.Button.deleteNode, new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                final List<String> selectedNodes = treeViewer
+                        .getSelectedNodes();
+                if (selectedNodes.size() == 0) {
+                    JOptionPane.showMessageDialog(ZooInspectorPanel.this,
+                            "Please select at least 1 node to be deleted");
+                } else {
+                    int answer = JOptionPane.showConfirmDialog(
+                            ZooInspectorPanel.this,
+                            "Are you sure you want to delete the selected nodes?"
+                                    + "(This action cannot be reverted)",
+                            "Confirm Delete", JOptionPane.YES_NO_OPTION,
+                            JOptionPane.WARNING_MESSAGE);
+                    if (answer == JOptionPane.YES_OPTION) {
+                        SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
+
+                            @Override
+                            protected Boolean doInBackground() throws Exception {
+                                for (String nodePath : selectedNodes) {
+                                    ZooInspectorPanel.this.zooInspectorManager
+                                            .deleteNode(nodePath);
+                                }
+                                return true;
+                            }
+
+                            @Override
+                            protected void done() {
+                                treeViewer.refreshView();
+                            }
+                        };
+                        worker.execute();
+                    }
+                }
+            }
+        });
+        toolbar.addActionListener(Toolbar.Button.nodeViewers, new ActionListener() {
+
+            public void actionPerformed(ActionEvent e) {
+                ZooInspectorNodeViewersDialog nvd = new ZooInspectorNodeViewersDialog(
+                        JOptionPane.getRootFrame(), nodeViewers, listeners,
+                        zooInspectorManager, iconResource);
+                nvd.setVisible(true);
+            }
+        });
+        toolbar.addActionListener(Toolbar.Button.about, new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                ZooInspectorAboutDialog zicpd = new ZooInspectorAboutDialog(
+                        JOptionPane.getRootFrame(), iconResource);
+                zicpd.setVisible(true);
+            }
+        });
+        JScrollPane treeScroller = new JScrollPane(treeViewer);
+        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
+                treeScroller, nodeViewersPanel);
+        splitPane.setResizeWeight(0.25);
+        this.add(splitPane, BorderLayout.CENTER);
+        this.add(toolbar.getJToolBar(), BorderLayout.NORTH);
+    }
+
+    /**
+     * @param connectionProps
+     *            the {@link Properties} for connecting to the zookeeper
+     *            instance
+     */
+    public void connect(final Properties connectionProps) {
+        SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
+
+            @Override
+            protected Boolean doInBackground() throws Exception {
+                zooInspectorManager.setLastConnectionProps(connectionProps);
+                return zooInspectorManager.connect(connectionProps);
+            }
+
+            @Override
+            protected void done() {
+                try {
+                    if (get()) {
+                        treeViewer.refreshView();
+                        toolbar.toggleButtons(true);
+                    } else {
+                        JOptionPane.showMessageDialog(ZooInspectorPanel.this,
+                                "Unable to connect to zookeeper", "Error",
+                                JOptionPane.ERROR_MESSAGE);
+                    }
+                } catch (InterruptedException e) {
+                    LoggerFactory
+                            .getLogger()
+                            .error(
+                                    "Error occurred while connecting to ZooKeeper server",
+                                    e);
+                } catch (ExecutionException e) {
+                    LoggerFactory
+                            .getLogger()
+                            .error(
+                                    "Error occurred while connecting to ZooKeeper server",
+                                    e);
+                }
+            }
+
+        };
+        worker.execute();
+    }
+
+    /**
+	 * 
+	 */
+    public void disconnect() {
+        disconnect(false);
+    }
+
+    /**
+     * @param wait
+     *            - set this to true if the method should only return once the
+     *            application has successfully disconnected
+     */
+    public void disconnect(boolean wait) {
+        SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
+
+            @Override
+            protected Boolean doInBackground() throws Exception {
+                return ZooInspectorPanel.this.zooInspectorManager.disconnect();
+            }
+
+            @Override
+            protected void done() {
+                try {
+                    if (get()) {
+                        treeViewer.clearView();
+                        toolbar.toggleButtons(false);
+                    }
+                } catch (InterruptedException e) {
+                    LoggerFactory
+                            .getLogger()
+                            .error(
+                                    "Error occurred while disconnecting from ZooKeeper server",
+                                    e);
+                } catch (ExecutionException e) {
+                    LoggerFactory
+                            .getLogger()
+                            .error(
+                                    "Error occurred while disconnecting from ZooKeeper server",
+                                    e);
+                }
+            }
+
+        };
+        worker.execute();
+        if (wait) {
+            while (!worker.isDone()) {
+                try {
+                    Thread.sleep(100);
+                } catch (InterruptedException e) {
+                    LoggerFactory
+                            .getLogger()
+                            .error(
+                                    "Error occurred while disconnecting from ZooKeeper server",
+                                    e);
+                }
+            }
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @seeorg.apache.zookeeper.inspector.gui.NodeViewersChangeListener#
+     * nodeViewersChanged(java.util.List)
+     */
+    public void nodeViewersChanged(List<ZooInspectorNodeViewer> newViewers) {
+        this.nodeViewersPanel.setNodeViewers(newViewers);
+    }
+
+    /**
+     * @param connectionProps
+     * @throws IOException
+     */
+    public void setdefaultConnectionProps(Properties connectionProps)
+            throws IOException {
+        this.zooInspectorManager.saveDefaultConnectionFile(connectionProps);
+    }
+}

+ 356 - 356
src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/ZooInspectorTreeViewer.java

@@ -1,356 +1,356 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.zookeeper.inspector.gui;
-
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.swing.ImageIcon;
-import javax.swing.JMenuItem;
-import javax.swing.JPanel;
-import javax.swing.JPopupMenu;
-import javax.swing.JTree;
-import javax.swing.SwingWorker;
-import javax.swing.event.TreeSelectionListener;
-import javax.swing.tree.DefaultMutableTreeNode;
-import javax.swing.tree.DefaultTreeCellRenderer;
-import javax.swing.tree.DefaultTreeModel;
-import javax.swing.tree.TreeNode;
-import javax.swing.tree.TreePath;
-
-import org.apache.zookeeper.inspector.manager.NodeListener;
-import org.apache.zookeeper.inspector.manager.ZooInspectorManager;
-
-import com.nitido.utils.toaster.Toaster;
-
-/**
- * A {@link JPanel} for showing the tree view of all the nodes in the zookeeper
- * instance
- */
-public class ZooInspectorTreeViewer extends JPanel implements NodeListener {
-    private final ZooInspectorManager zooInspectorManager;
-    private final JTree tree;
-    private final Toaster toasterManager;
-    private final ImageIcon toasterIcon;
-
-    /**
-     * @param zooInspectorManager
-     *            - the {@link ZooInspectorManager} for the application
-     * @param listener
-     *            - the {@link TreeSelectionListener} to listen for changes in
-     *            the selected node on the node tree
-     */
-    public ZooInspectorTreeViewer(
-            final ZooInspectorManager zooInspectorManager,
-            TreeSelectionListener listener, IconResource iconResource) {
-        this.zooInspectorManager = zooInspectorManager;
-        this.setLayout(new BorderLayout());
-        final JPopupMenu popupMenu = new JPopupMenu();
-        final JMenuItem addNotify = new JMenuItem("Add Change Notification");
-        this.toasterManager = new Toaster();
-        this.toasterManager.setBorderColor(Color.BLACK);
-        this.toasterManager.setMessageColor(Color.BLACK);
-        this.toasterManager.setToasterColor(Color.WHITE);
-        toasterIcon = iconResource.get(IconResource.ICON_INFORMATION,"");
-        addNotify.addActionListener(new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                List<String> selectedNodes = getSelectedNodes();
-                zooInspectorManager.addWatchers(selectedNodes,
-                        ZooInspectorTreeViewer.this);
-            }
-        });
-        final JMenuItem removeNotify = new JMenuItem(
-                "Remove Change Notification");
-        removeNotify.addActionListener(new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                List<String> selectedNodes = getSelectedNodes();
-                zooInspectorManager.removeWatchers(selectedNodes);
-            }
-        });
-        tree = new JTree(new DefaultMutableTreeNode());
-        tree.setCellRenderer(new ZooInspectorTreeCellRenderer(iconResource));
-        tree.setEditable(false);
-        tree.getSelectionModel().addTreeSelectionListener(listener);
-        tree.addMouseListener(new MouseAdapter() {
-            @Override
-            public void mouseClicked(MouseEvent e) {
-                if (e.isPopupTrigger() || e.getButton() == MouseEvent.BUTTON3) {
-                    // TODO only show add if a selected node isn't being
-                    // watched, and only show remove if a selected node is being
-                    // watched
-                    popupMenu.removeAll();
-                    popupMenu.add(addNotify);
-                    popupMenu.add(removeNotify);
-                    popupMenu.show(ZooInspectorTreeViewer.this, e.getX(), e
-                            .getY());
-                }
-            }
-        });
-        this.add(tree, BorderLayout.CENTER);
-    }
-
-    /**
-     * Refresh the tree view
-     */
-    public void refreshView() {
-        final Set<TreePath> expandedNodes = new LinkedHashSet<TreePath>();
-        int rowCount = tree.getRowCount();
-        for (int i = 0; i < rowCount; i++) {
-            TreePath path = tree.getPathForRow(i);
-            if (tree.isExpanded(path)) {
-                expandedNodes.add(path);
-            }
-        }
-        final TreePath[] selectedNodes = tree.getSelectionPaths();
-        SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
-
-            @Override
-            protected Boolean doInBackground() throws Exception {
-                tree.setModel(new DefaultTreeModel(new ZooInspectorTreeNode(
-                        "/", null)));
-                return true;
-            }
-
-            @Override
-            protected void done() {
-                for (TreePath path : expandedNodes) {
-                    tree.expandPath(path);
-                }
-                tree.getSelectionModel().setSelectionPaths(selectedNodes);
-            }
-        };
-        worker.execute();
-    }
-
-    /**
-     * clear the tree view of all nodes
-     */
-    public void clearView() {
-        tree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode()));
-    }
-
-    private static class ZooInspectorTreeCellRenderer extends
-            DefaultTreeCellRenderer {
-        public ZooInspectorTreeCellRenderer(IconResource iconResource) {
-            setLeafIcon(iconResource.get(IconResource.ICON_TREE_LEAF,""));
-            setOpenIcon(iconResource.get(IconResource.ICON_TREE_OPEN,""));
-            setClosedIcon(iconResource.get(IconResource.ICON_TREE_CLOSE,""));
-        }
-    }
-
-    private class ZooInspectorTreeNode implements TreeNode {
-        private final String nodePath;
-        private final String nodeName;
-        private final ZooInspectorTreeNode parent;
-
-        public ZooInspectorTreeNode(String nodePath, ZooInspectorTreeNode parent) {
-            this.parent = parent;
-            this.nodePath = nodePath;
-            int index = nodePath.lastIndexOf("/");
-            if (index == -1) {
-                throw new IllegalArgumentException("Invalid node path"
-                        + nodePath);
-            }
-            this.nodeName = nodePath.substring(index + 1);
-        }
-
-        /*
-         * (non-Javadoc)
-         * 
-         * @see javax.swing.tree.TreeNode#children()
-         */
-        public Enumeration<TreeNode> children() {
-            List<String> children = zooInspectorManager
-                    .getChildren(this.nodePath);
-            Collections.sort(children);
-            List<TreeNode> returnChildren = new ArrayList<TreeNode>();
-            for (String child : children) {
-                returnChildren.add(new ZooInspectorTreeNode((this.nodePath
-                        .equals("/") ? "" : this.nodePath)
-                        + "/" + child, this));
-            }
-            return Collections.enumeration(returnChildren);
-        }
-
-        /*
-         * (non-Javadoc)
-         * 
-         * @see javax.swing.tree.TreeNode#getAllowsChildren()
-         */
-        public boolean getAllowsChildren() {
-            return zooInspectorManager.isAllowsChildren(this.nodePath);
-        }
-
-        /*
-         * (non-Javadoc)
-         * 
-         * @see javax.swing.tree.TreeNode#getChildAt(int)
-         */
-        public TreeNode getChildAt(int childIndex) {
-            String child = zooInspectorManager.getNodeChild(this.nodePath,
-                    childIndex);
-            if (child != null) {
-                return new ZooInspectorTreeNode((this.nodePath.equals("/") ? ""
-                        : this.nodePath)
-                        + "/" + child, this);
-            }
-            return null;
-        }
-
-        /*
-         * (non-Javadoc)
-         * 
-         * @see javax.swing.tree.TreeNode#getChildCount()
-         */
-        public int getChildCount() {
-            return zooInspectorManager.getNumChildren(this.nodePath);
-        }
-
-        /*
-         * (non-Javadoc)
-         * 
-         * @see javax.swing.tree.TreeNode#getIndex(javax.swing.tree.TreeNode)
-         */
-        public int getIndex(TreeNode node) {
-            return zooInspectorManager.getNodeIndex(this.nodePath);
-        }
-
-        /*
-         * (non-Javadoc)
-         * 
-         * @see javax.swing.tree.TreeNode#getParent()
-         */
-        public TreeNode getParent() {
-            return this.parent;
-        }
-
-        /*
-         * (non-Javadoc)
-         * 
-         * @see javax.swing.tree.TreeNode#isLeaf()
-         */
-        public boolean isLeaf() {
-            return !zooInspectorManager.hasChildren(this.nodePath);
-        }
-
-        @Override
-        public String toString() {
-            return this.nodeName;
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + getOuterType().hashCode();
-            result = prime * result
-                    + ((nodePath == null) ? 0 : nodePath.hashCode());
-            result = prime * result
-                    + ((parent == null) ? 0 : parent.hashCode());
-            return result;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj)
-                return true;
-            if (obj == null)
-                return false;
-            if (getClass() != obj.getClass())
-                return false;
-            ZooInspectorTreeNode other = (ZooInspectorTreeNode) obj;
-            if (!getOuterType().equals(other.getOuterType()))
-                return false;
-            if (nodePath == null) {
-                if (other.nodePath != null)
-                    return false;
-            } else if (!nodePath.equals(other.nodePath))
-                return false;
-            if (parent == null) {
-                if (other.parent != null)
-                    return false;
-            } else if (!parent.equals(other.parent))
-                return false;
-            return true;
-        }
-
-        private ZooInspectorTreeViewer getOuterType() {
-            return ZooInspectorTreeViewer.this;
-        }
-
-    }
-
-    /**
-     * @return {@link List} of the currently selected nodes
-     */
-    public List<String> getSelectedNodes() {
-        TreePath[] paths = tree.getSelectionPaths();
-        List<String> selectedNodes = new ArrayList<String>();
-        if (paths != null) {
-            for (TreePath path : paths) {
-                StringBuilder sb = new StringBuilder();
-                Object[] pathArray = path.getPath();
-                for (Object o : pathArray) {
-                    String nodeName = o.toString();
-                    if (nodeName.length() > 0) {
-                        sb.append("/");
-                        sb.append(o.toString());
-                    }
-                }
-                selectedNodes.add(sb.toString());
-            }
-        }
-        return selectedNodes;
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see
-     * org.apache.zookeeper.inspector.manager.NodeListener#processEvent(java
-     * .lang.String, java.lang.String, java.util.Map)
-     */
-    public void processEvent(String nodePath, String eventType,
-            Map<String, String> eventInfo) {
-        StringBuilder sb = new StringBuilder();
-        sb.append("Node: ");
-        sb.append(nodePath);
-        sb.append("\nEvent: ");
-        sb.append(eventType);
-        if (eventInfo != null) {
-            for (Map.Entry<String, String> entry : eventInfo.entrySet()) {
-                sb.append("\n");
-                sb.append(entry.getKey());
-                sb.append(": ");
-                sb.append(entry.getValue());
-            }
-        }
-        this.toasterManager.showToaster(toasterIcon, sb.toString());
-    }
-}
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.gui;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.swing.ImageIcon;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JTree;
+import javax.swing.SwingWorker;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreePath;
+
+import org.apache.zookeeper.inspector.manager.NodeListener;
+import org.apache.zookeeper.inspector.manager.ZooInspectorManager;
+
+import com.nitido.utils.toaster.Toaster;
+
+/**
+ * A {@link JPanel} for showing the tree view of all the nodes in the zookeeper
+ * instance
+ */
+public class ZooInspectorTreeViewer extends JPanel implements NodeListener {
+    private final ZooInspectorManager zooInspectorManager;
+    private final JTree tree;
+    private final Toaster toasterManager;
+    private final ImageIcon toasterIcon;
+
+    /**
+     * @param zooInspectorManager
+     *            - the {@link ZooInspectorManager} for the application
+     * @param listener
+     *            - the {@link TreeSelectionListener} to listen for changes in
+     *            the selected node on the node tree
+     */
+    public ZooInspectorTreeViewer(
+            final ZooInspectorManager zooInspectorManager,
+            TreeSelectionListener listener, IconResource iconResource) {
+        this.zooInspectorManager = zooInspectorManager;
+        this.setLayout(new BorderLayout());
+        final JPopupMenu popupMenu = new JPopupMenu();
+        final JMenuItem addNotify = new JMenuItem("Add Change Notification");
+        this.toasterManager = new Toaster();
+        this.toasterManager.setBorderColor(Color.BLACK);
+        this.toasterManager.setMessageColor(Color.BLACK);
+        this.toasterManager.setToasterColor(Color.WHITE);
+        toasterIcon = iconResource.get(IconResource.ICON_INFORMATION,"");
+        addNotify.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                List<String> selectedNodes = getSelectedNodes();
+                zooInspectorManager.addWatchers(selectedNodes,
+                        ZooInspectorTreeViewer.this);
+            }
+        });
+        final JMenuItem removeNotify = new JMenuItem(
+                "Remove Change Notification");
+        removeNotify.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                List<String> selectedNodes = getSelectedNodes();
+                zooInspectorManager.removeWatchers(selectedNodes);
+            }
+        });
+        tree = new JTree(new DefaultMutableTreeNode());
+        tree.setCellRenderer(new ZooInspectorTreeCellRenderer(iconResource));
+        tree.setEditable(false);
+        tree.getSelectionModel().addTreeSelectionListener(listener);
+        tree.addMouseListener(new MouseAdapter() {
+            @Override
+            public void mouseClicked(MouseEvent e) {
+                if (e.isPopupTrigger() || e.getButton() == MouseEvent.BUTTON3) {
+                    // TODO only show add if a selected node isn't being
+                    // watched, and only show remove if a selected node is being
+                    // watched
+                    popupMenu.removeAll();
+                    popupMenu.add(addNotify);
+                    popupMenu.add(removeNotify);
+                    popupMenu.show(ZooInspectorTreeViewer.this, e.getX(), e
+                            .getY());
+                }
+            }
+        });
+        this.add(tree, BorderLayout.CENTER);
+    }
+
+    /**
+     * Refresh the tree view
+     */
+    public void refreshView() {
+        final Set<TreePath> expandedNodes = new LinkedHashSet<TreePath>();
+        int rowCount = tree.getRowCount();
+        for (int i = 0; i < rowCount; i++) {
+            TreePath path = tree.getPathForRow(i);
+            if (tree.isExpanded(path)) {
+                expandedNodes.add(path);
+            }
+        }
+        final TreePath[] selectedNodes = tree.getSelectionPaths();
+        SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
+
+            @Override
+            protected Boolean doInBackground() throws Exception {
+                tree.setModel(new DefaultTreeModel(new ZooInspectorTreeNode(
+                        "/", null)));
+                return true;
+            }
+
+            @Override
+            protected void done() {
+                for (TreePath path : expandedNodes) {
+                    tree.expandPath(path);
+                }
+                tree.getSelectionModel().setSelectionPaths(selectedNodes);
+            }
+        };
+        worker.execute();
+    }
+
+    /**
+     * clear the tree view of all nodes
+     */
+    public void clearView() {
+        tree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode()));
+    }
+
+    private static class ZooInspectorTreeCellRenderer extends
+            DefaultTreeCellRenderer {
+        public ZooInspectorTreeCellRenderer(IconResource iconResource) {
+            setLeafIcon(iconResource.get(IconResource.ICON_TREE_LEAF,""));
+            setOpenIcon(iconResource.get(IconResource.ICON_TREE_OPEN,""));
+            setClosedIcon(iconResource.get(IconResource.ICON_TREE_CLOSE,""));
+        }
+    }
+
+    private class ZooInspectorTreeNode implements TreeNode {
+        private final String nodePath;
+        private final String nodeName;
+        private final ZooInspectorTreeNode parent;
+
+        public ZooInspectorTreeNode(String nodePath, ZooInspectorTreeNode parent) {
+            this.parent = parent;
+            this.nodePath = nodePath;
+            int index = nodePath.lastIndexOf("/");
+            if (index == -1) {
+                throw new IllegalArgumentException("Invalid node path"
+                        + nodePath);
+            }
+            this.nodeName = nodePath.substring(index + 1);
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see javax.swing.tree.TreeNode#children()
+         */
+        public Enumeration<TreeNode> children() {
+            List<String> children = zooInspectorManager
+                    .getChildren(this.nodePath);
+            Collections.sort(children);
+            List<TreeNode> returnChildren = new ArrayList<TreeNode>();
+            for (String child : children) {
+                returnChildren.add(new ZooInspectorTreeNode((this.nodePath
+                        .equals("/") ? "" : this.nodePath)
+                        + "/" + child, this));
+            }
+            return Collections.enumeration(returnChildren);
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see javax.swing.tree.TreeNode#getAllowsChildren()
+         */
+        public boolean getAllowsChildren() {
+            return zooInspectorManager.isAllowsChildren(this.nodePath);
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see javax.swing.tree.TreeNode#getChildAt(int)
+         */
+        public TreeNode getChildAt(int childIndex) {
+            String child = zooInspectorManager.getNodeChild(this.nodePath,
+                    childIndex);
+            if (child != null) {
+                return new ZooInspectorTreeNode((this.nodePath.equals("/") ? ""
+                        : this.nodePath)
+                        + "/" + child, this);
+            }
+            return null;
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see javax.swing.tree.TreeNode#getChildCount()
+         */
+        public int getChildCount() {
+            return zooInspectorManager.getNumChildren(this.nodePath);
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see javax.swing.tree.TreeNode#getIndex(javax.swing.tree.TreeNode)
+         */
+        public int getIndex(TreeNode node) {
+            return zooInspectorManager.getNodeIndex(this.nodePath);
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see javax.swing.tree.TreeNode#getParent()
+         */
+        public TreeNode getParent() {
+            return this.parent;
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see javax.swing.tree.TreeNode#isLeaf()
+         */
+        public boolean isLeaf() {
+            return !zooInspectorManager.hasChildren(this.nodePath);
+        }
+
+        @Override
+        public String toString() {
+            return this.nodeName;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + getOuterType().hashCode();
+            result = prime * result
+                    + ((nodePath == null) ? 0 : nodePath.hashCode());
+            result = prime * result
+                    + ((parent == null) ? 0 : parent.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            ZooInspectorTreeNode other = (ZooInspectorTreeNode) obj;
+            if (!getOuterType().equals(other.getOuterType()))
+                return false;
+            if (nodePath == null) {
+                if (other.nodePath != null)
+                    return false;
+            } else if (!nodePath.equals(other.nodePath))
+                return false;
+            if (parent == null) {
+                if (other.parent != null)
+                    return false;
+            } else if (!parent.equals(other.parent))
+                return false;
+            return true;
+        }
+
+        private ZooInspectorTreeViewer getOuterType() {
+            return ZooInspectorTreeViewer.this;
+        }
+
+    }
+
+    /**
+     * @return {@link List} of the currently selected nodes
+     */
+    public List<String> getSelectedNodes() {
+        TreePath[] paths = tree.getSelectionPaths();
+        List<String> selectedNodes = new ArrayList<String>();
+        if (paths != null) {
+            for (TreePath path : paths) {
+                StringBuilder sb = new StringBuilder();
+                Object[] pathArray = path.getPath();
+                for (Object o : pathArray) {
+                    String nodeName = o.toString();
+                    if (nodeName.length() > 0) {
+                        sb.append("/");
+                        sb.append(o.toString());
+                    }
+                }
+                selectedNodes.add(sb.toString());
+            }
+        }
+        return selectedNodes;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.zookeeper.inspector.manager.NodeListener#processEvent(java
+     * .lang.String, java.lang.String, java.util.Map)
+     */
+    public void processEvent(String nodePath, String eventType,
+            Map<String, String> eventInfo) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("Node: ");
+        sb.append(nodePath);
+        sb.append("\nEvent: ");
+        sb.append(eventType);
+        if (eventInfo != null) {
+            for (Map.Entry<String, String> entry : eventInfo.entrySet()) {
+                sb.append("\n");
+                sb.append(entry.getKey());
+                sb.append(": ");
+                sb.append(entry.getValue());
+            }
+        }
+        this.toasterManager.showToaster(toasterIcon, sb.toString());
+    }
+}

+ 21 - 21
src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/about.html

@@ -1,21 +1,21 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
-<title>ZooInspector v0.1</title>
-</head>
-<body>
-<p>ZooInspector was developed by Colin Goodheart-Smithe and is
-available under the Apache Software Licence v2.0.</p>
-<p>The Icons used were sourced from the Eclipse project (<a
-	href="http://www.eclipse.org">http://www.eclipse.org</a>) and licensed
-under the Eclipse Public Licence v1.0. [<a
-	href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/org/documents/epl-v10.php</a>]
-</p>
-<p>ZooKeeper is available from <a
-	href="http://zookeeper.apache.org/">http://zookeeper.apache.org/</a>
-and is licensed under an Apache Software Licence v2.0</p>
-<p>The ApacheSoftware Licence v2.0 can be found at <a
-	href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a></p>
-</body>
-</html>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>ZooInspector v0.1</title>
+</head>
+<body>
+<p>ZooInspector was developed by Colin Goodheart-Smithe and is
+available under the Apache Software Licence v2.0.</p>
+<p>The Icons used were sourced from the Eclipse project (<a
+	href="http://www.eclipse.org">http://www.eclipse.org</a>) and licensed
+under the Eclipse Public Licence v1.0. [<a
+	href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/org/documents/epl-v10.php</a>]
+</p>
+<p>ZooKeeper is available from <a
+	href="http://zookeeper.apache.org/">http://zookeeper.apache.org/</a>
+and is licensed under an Apache Software Licence v2.0</p>
+<p>The ApacheSoftware Licence v2.0 can be found at <a
+	href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a></p>
+</body>
+</html>

+ 187 - 187
src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/nodeviewer/NodeViewerACL.java

@@ -1,187 +1,187 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.zookeeper.inspector.gui.nodeviewer;
-
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Insets;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutionException;
-
-import javax.swing.BorderFactory;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTextField;
-import javax.swing.SwingWorker;
-
-import org.apache.zookeeper.inspector.logger.LoggerFactory;
-import org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager;
-
-/**
- * A node viewer for displaying the ACLs currently applied to the selected node
- */
-public class NodeViewerACL extends ZooInspectorNodeViewer {
-    private ZooInspectorNodeManager zooInspectorManager;
-    private final JPanel aclDataPanel;
-    private String selectedNode;
-
-    /**
-	 * 
-	 */
-    public NodeViewerACL() {
-        this.setLayout(new BorderLayout());
-        this.aclDataPanel = new JPanel();
-        this.aclDataPanel.setBackground(Color.WHITE);
-        JScrollPane scroller = new JScrollPane(this.aclDataPanel);
-        this.add(scroller, BorderLayout.CENTER);
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see
-     * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
-     * getTitle()
-     */
-    @Override
-    public String getTitle() {
-        return "Node ACLs";
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see
-     * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
-     * nodeSelectionChanged(java.util.Set)
-     */
-    @Override
-    public void nodeSelectionChanged(List<String> selectedNodes) {
-        this.aclDataPanel.removeAll();
-        if (selectedNodes.size() > 0) {
-            this.selectedNode = selectedNodes.get(0);
-            SwingWorker<List<Map<String, String>>, Void> worker = new SwingWorker<List<Map<String, String>>, Void>() {
-
-                @Override
-                protected List<Map<String, String>> doInBackground()
-                        throws Exception {
-                    return NodeViewerACL.this.zooInspectorManager
-                            .getACLs(NodeViewerACL.this.selectedNode);
-                }
-
-                @Override
-                protected void done() {
-                    List<Map<String, String>> acls = null;
-                    try {
-                        acls = get();
-                    } catch (InterruptedException e) {
-                        acls = new ArrayList<Map<String, String>>();
-                        LoggerFactory.getLogger().error(
-                                "Error retrieving ACL Information for node: "
-                                        + NodeViewerACL.this.selectedNode, e);
-                    } catch (ExecutionException e) {
-                        acls = new ArrayList<Map<String, String>>();
-                        LoggerFactory.getLogger().error(
-                                "Error retrieving ACL Information for node: "
-                                        + NodeViewerACL.this.selectedNode, e);
-                    }
-                    aclDataPanel.setLayout(new GridBagLayout());
-                    int j = 0;
-                    for (Map<String, String> data : acls) {
-                        int rowPos = 2 * j + 1;
-                        JPanel aclPanel = new JPanel();
-                        aclPanel.setBorder(BorderFactory
-                                .createLineBorder(Color.BLACK));
-                        aclPanel.setBackground(Color.WHITE);
-                        aclPanel.setLayout(new GridBagLayout());
-                        int i = 0;
-                        for (Map.Entry<String, String> entry : data.entrySet()) {
-                            int rowPosACL = 2 * i + 1;
-                            JLabel label = new JLabel(entry.getKey());
-                            JTextField text = new JTextField(entry.getValue());
-                            text.setEditable(false);
-                            GridBagConstraints c1 = new GridBagConstraints();
-                            c1.gridx = 1;
-                            c1.gridy = rowPosACL;
-                            c1.gridwidth = 1;
-                            c1.gridheight = 1;
-                            c1.weightx = 0;
-                            c1.weighty = 0;
-                            c1.anchor = GridBagConstraints.NORTHWEST;
-                            c1.fill = GridBagConstraints.BOTH;
-                            c1.insets = new Insets(5, 5, 5, 5);
-                            c1.ipadx = 0;
-                            c1.ipady = 0;
-                            aclPanel.add(label, c1);
-                            GridBagConstraints c2 = new GridBagConstraints();
-                            c2.gridx = 3;
-                            c2.gridy = rowPosACL;
-                            c2.gridwidth = 1;
-                            c2.gridheight = 1;
-                            c2.weightx = 0;
-                            c2.weighty = 0;
-                            c2.anchor = GridBagConstraints.NORTHWEST;
-                            c2.fill = GridBagConstraints.BOTH;
-                            c2.insets = new Insets(5, 5, 5, 5);
-                            c2.ipadx = 0;
-                            c2.ipady = 0;
-                            aclPanel.add(text, c2);
-                            i++;
-                        }
-                        GridBagConstraints c = new GridBagConstraints();
-                        c.gridx = 1;
-                        c.gridy = rowPos;
-                        c.gridwidth = 1;
-                        c.gridheight = 1;
-                        c.weightx = 1;
-                        c.weighty = 1;
-                        c.anchor = GridBagConstraints.NORTHWEST;
-                        c.fill = GridBagConstraints.NONE;
-                        c.insets = new Insets(5, 5, 5, 5);
-                        c.ipadx = 0;
-                        c.ipady = 0;
-                        aclDataPanel.add(aclPanel, c);
-                    }
-                    NodeViewerACL.this.aclDataPanel.revalidate();
-                    NodeViewerACL.this.aclDataPanel.repaint();
-                }
-            };
-            worker.execute();
-        }
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see
-     * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
-     * setZooInspectorManager
-     * (org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager)
-     */
-    @Override
-    public void setZooInspectorManager(
-            ZooInspectorNodeManager zooInspectorManager) {
-        this.zooInspectorManager = zooInspectorManager;
-    }
-
-}
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.gui.nodeviewer;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+
+import javax.swing.BorderFactory;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.SwingWorker;
+
+import org.apache.zookeeper.inspector.logger.LoggerFactory;
+import org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager;
+
+/**
+ * A node viewer for displaying the ACLs currently applied to the selected node
+ */
+public class NodeViewerACL extends ZooInspectorNodeViewer {
+    private ZooInspectorNodeManager zooInspectorManager;
+    private final JPanel aclDataPanel;
+    private String selectedNode;
+
+    /**
+	 * 
+	 */
+    public NodeViewerACL() {
+        this.setLayout(new BorderLayout());
+        this.aclDataPanel = new JPanel();
+        this.aclDataPanel.setBackground(Color.WHITE);
+        JScrollPane scroller = new JScrollPane(this.aclDataPanel);
+        this.add(scroller, BorderLayout.CENTER);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
+     * getTitle()
+     */
+    @Override
+    public String getTitle() {
+        return "Node ACLs";
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
+     * nodeSelectionChanged(java.util.Set)
+     */
+    @Override
+    public void nodeSelectionChanged(List<String> selectedNodes) {
+        this.aclDataPanel.removeAll();
+        if (selectedNodes.size() > 0) {
+            this.selectedNode = selectedNodes.get(0);
+            SwingWorker<List<Map<String, String>>, Void> worker = new SwingWorker<List<Map<String, String>>, Void>() {
+
+                @Override
+                protected List<Map<String, String>> doInBackground()
+                        throws Exception {
+                    return NodeViewerACL.this.zooInspectorManager
+                            .getACLs(NodeViewerACL.this.selectedNode);
+                }
+
+                @Override
+                protected void done() {
+                    List<Map<String, String>> acls = null;
+                    try {
+                        acls = get();
+                    } catch (InterruptedException e) {
+                        acls = new ArrayList<Map<String, String>>();
+                        LoggerFactory.getLogger().error(
+                                "Error retrieving ACL Information for node: "
+                                        + NodeViewerACL.this.selectedNode, e);
+                    } catch (ExecutionException e) {
+                        acls = new ArrayList<Map<String, String>>();
+                        LoggerFactory.getLogger().error(
+                                "Error retrieving ACL Information for node: "
+                                        + NodeViewerACL.this.selectedNode, e);
+                    }
+                    aclDataPanel.setLayout(new GridBagLayout());
+                    int j = 0;
+                    for (Map<String, String> data : acls) {
+                        int rowPos = 2 * j + 1;
+                        JPanel aclPanel = new JPanel();
+                        aclPanel.setBorder(BorderFactory
+                                .createLineBorder(Color.BLACK));
+                        aclPanel.setBackground(Color.WHITE);
+                        aclPanel.setLayout(new GridBagLayout());
+                        int i = 0;
+                        for (Map.Entry<String, String> entry : data.entrySet()) {
+                            int rowPosACL = 2 * i + 1;
+                            JLabel label = new JLabel(entry.getKey());
+                            JTextField text = new JTextField(entry.getValue());
+                            text.setEditable(false);
+                            GridBagConstraints c1 = new GridBagConstraints();
+                            c1.gridx = 1;
+                            c1.gridy = rowPosACL;
+                            c1.gridwidth = 1;
+                            c1.gridheight = 1;
+                            c1.weightx = 0;
+                            c1.weighty = 0;
+                            c1.anchor = GridBagConstraints.NORTHWEST;
+                            c1.fill = GridBagConstraints.BOTH;
+                            c1.insets = new Insets(5, 5, 5, 5);
+                            c1.ipadx = 0;
+                            c1.ipady = 0;
+                            aclPanel.add(label, c1);
+                            GridBagConstraints c2 = new GridBagConstraints();
+                            c2.gridx = 3;
+                            c2.gridy = rowPosACL;
+                            c2.gridwidth = 1;
+                            c2.gridheight = 1;
+                            c2.weightx = 0;
+                            c2.weighty = 0;
+                            c2.anchor = GridBagConstraints.NORTHWEST;
+                            c2.fill = GridBagConstraints.BOTH;
+                            c2.insets = new Insets(5, 5, 5, 5);
+                            c2.ipadx = 0;
+                            c2.ipady = 0;
+                            aclPanel.add(text, c2);
+                            i++;
+                        }
+                        GridBagConstraints c = new GridBagConstraints();
+                        c.gridx = 1;
+                        c.gridy = rowPos;
+                        c.gridwidth = 1;
+                        c.gridheight = 1;
+                        c.weightx = 1;
+                        c.weighty = 1;
+                        c.anchor = GridBagConstraints.NORTHWEST;
+                        c.fill = GridBagConstraints.NONE;
+                        c.insets = new Insets(5, 5, 5, 5);
+                        c.ipadx = 0;
+                        c.ipady = 0;
+                        aclDataPanel.add(aclPanel, c);
+                    }
+                    NodeViewerACL.this.aclDataPanel.revalidate();
+                    NodeViewerACL.this.aclDataPanel.repaint();
+                }
+            };
+            worker.execute();
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
+     * setZooInspectorManager
+     * (org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager)
+     */
+    @Override
+    public void setZooInspectorManager(
+            ZooInspectorNodeManager zooInspectorManager) {
+        this.zooInspectorManager = zooInspectorManager;
+    }
+
+}

+ 143 - 143
src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/nodeviewer/NodeViewerData.java

@@ -1,143 +1,143 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.zookeeper.inspector.gui.nodeviewer;
-
-import java.awt.BorderLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-
-import javax.swing.JButton;
-import javax.swing.JOptionPane;
-import javax.swing.JScrollPane;
-import javax.swing.JTextPane;
-import javax.swing.JToolBar;
-import javax.swing.SwingWorker;
-
-import org.apache.zookeeper.inspector.ZooInspector;
-import org.apache.zookeeper.inspector.gui.IconResource;
-import org.apache.zookeeper.inspector.logger.LoggerFactory;
-import org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager;
-
-/**
- * A node viewer for displaying the data for the currently selected node
- */
-public class NodeViewerData extends ZooInspectorNodeViewer {
-    private ZooInspectorNodeManager zooInspectorManager;
-    private final JTextPane dataArea;
-    private final JToolBar toolbar;
-    private String selectedNode;
-
-    public NodeViewerData() {
-        this.setLayout(new BorderLayout());
-        this.dataArea = new JTextPane();
-        this.toolbar = new JToolBar();
-        this.toolbar.setFloatable(false);
-        JScrollPane scroller = new JScrollPane(this.dataArea);
-        scroller
-                .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
-        this.add(scroller, BorderLayout.CENTER);
-        this.add(this.toolbar, BorderLayout.NORTH);
-        JButton saveButton = new JButton(ZooInspector.iconResource.get(IconResource.ICON_SAVE,""));
-        saveButton.addActionListener(new ActionListener() {
-
-            public void actionPerformed(ActionEvent e) {
-                if (selectedNode != null) {
-                    if (JOptionPane.showConfirmDialog(NodeViewerData.this,
-                            "Are you sure you want to save this node?"
-                                    + " (this action cannot be reverted)",
-                            "Confirm Save", JOptionPane.YES_NO_OPTION,
-                            JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) {
-                        zooInspectorManager.setData(selectedNode, dataArea
-                                .getText());
-                    }
-                }
-            }
-        });
-        this.toolbar.add(saveButton);
-
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see
-     * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
-     * getTitle()
-     */
-    @Override
-    public String getTitle() {
-        return "Node Data";
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see
-     * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
-     * nodeSelectionChanged(java.util.Set)
-     */
-    @Override
-    public void nodeSelectionChanged(List<String> selectedNodes) {
-        if (selectedNodes.size() > 0) {
-            this.selectedNode = selectedNodes.get(0);
-            SwingWorker<String, Void> worker = new SwingWorker<String, Void>() {
-
-                @Override
-                protected String doInBackground() throws Exception {
-                    return NodeViewerData.this.zooInspectorManager
-                            .getData(NodeViewerData.this.selectedNode);
-                }
-
-                @Override
-                protected void done() {
-                    String data = "";
-                    try {
-                        data = get();
-                    } catch (InterruptedException e) {
-                        LoggerFactory.getLogger().error(
-                                "Error retrieving data for node: "
-                                        + NodeViewerData.this.selectedNode, e);
-                    } catch (ExecutionException e) {
-                        LoggerFactory.getLogger().error(
-                                "Error retrieving data for node: "
-                                        + NodeViewerData.this.selectedNode, e);
-                    }
-                    NodeViewerData.this.dataArea.setText(data);
-                }
-            };
-            worker.execute();
-        }
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see
-     * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
-     * setZooInspectorManager
-     * (org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager)
-     */
-    @Override
-    public void setZooInspectorManager(
-            ZooInspectorNodeManager zooInspectorManager) {
-        this.zooInspectorManager = zooInspectorManager;
-    }
-
-}
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.gui.nodeviewer;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+import javax.swing.JButton;
+import javax.swing.JOptionPane;
+import javax.swing.JScrollPane;
+import javax.swing.JTextPane;
+import javax.swing.JToolBar;
+import javax.swing.SwingWorker;
+
+import org.apache.zookeeper.inspector.ZooInspector;
+import org.apache.zookeeper.inspector.gui.IconResource;
+import org.apache.zookeeper.inspector.logger.LoggerFactory;
+import org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager;
+
+/**
+ * A node viewer for displaying the data for the currently selected node
+ */
+public class NodeViewerData extends ZooInspectorNodeViewer {
+    private ZooInspectorNodeManager zooInspectorManager;
+    private final JTextPane dataArea;
+    private final JToolBar toolbar;
+    private String selectedNode;
+
+    public NodeViewerData() {
+        this.setLayout(new BorderLayout());
+        this.dataArea = new JTextPane();
+        this.toolbar = new JToolBar();
+        this.toolbar.setFloatable(false);
+        JScrollPane scroller = new JScrollPane(this.dataArea);
+        scroller
+                .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+        this.add(scroller, BorderLayout.CENTER);
+        this.add(this.toolbar, BorderLayout.NORTH);
+        JButton saveButton = new JButton(ZooInspector.iconResource.get(IconResource.ICON_SAVE,""));
+        saveButton.addActionListener(new ActionListener() {
+
+            public void actionPerformed(ActionEvent e) {
+                if (selectedNode != null) {
+                    if (JOptionPane.showConfirmDialog(NodeViewerData.this,
+                            "Are you sure you want to save this node?"
+                                    + " (this action cannot be reverted)",
+                            "Confirm Save", JOptionPane.YES_NO_OPTION,
+                            JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) {
+                        zooInspectorManager.setData(selectedNode, dataArea
+                                .getText());
+                    }
+                }
+            }
+        });
+        this.toolbar.add(saveButton);
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
+     * getTitle()
+     */
+    @Override
+    public String getTitle() {
+        return "Node Data";
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
+     * nodeSelectionChanged(java.util.Set)
+     */
+    @Override
+    public void nodeSelectionChanged(List<String> selectedNodes) {
+        if (selectedNodes.size() > 0) {
+            this.selectedNode = selectedNodes.get(0);
+            SwingWorker<String, Void> worker = new SwingWorker<String, Void>() {
+
+                @Override
+                protected String doInBackground() throws Exception {
+                    return NodeViewerData.this.zooInspectorManager
+                            .getData(NodeViewerData.this.selectedNode);
+                }
+
+                @Override
+                protected void done() {
+                    String data = "";
+                    try {
+                        data = get();
+                    } catch (InterruptedException e) {
+                        LoggerFactory.getLogger().error(
+                                "Error retrieving data for node: "
+                                        + NodeViewerData.this.selectedNode, e);
+                    } catch (ExecutionException e) {
+                        LoggerFactory.getLogger().error(
+                                "Error retrieving data for node: "
+                                        + NodeViewerData.this.selectedNode, e);
+                    }
+                    NodeViewerData.this.dataArea.setText(data);
+                }
+            };
+            worker.execute();
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
+     * setZooInspectorManager
+     * (org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager)
+     */
+    @Override
+    public void setZooInspectorManager(
+            ZooInspectorNodeManager zooInspectorManager) {
+        this.zooInspectorManager = zooInspectorManager;
+    }
+
+}

+ 186 - 186
src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/nodeviewer/NodeViewerMetaData.java

@@ -1,186 +1,186 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.zookeeper.inspector.gui.nodeviewer;
-
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Insets;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutionException;
-
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTextField;
-import javax.swing.SwingWorker;
-
-import org.apache.zookeeper.data.Stat;
-import org.apache.zookeeper.inspector.logger.LoggerFactory;
-import org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager;
-
-/**
- * A node viewer for displaying the meta data for the currently selected node.
- * The meta data is essentially the information from the {@link Stat} for the
- * node
- */
-public class NodeViewerMetaData extends ZooInspectorNodeViewer {
-    private ZooInspectorNodeManager zooInspectorManager;
-    private final JPanel metaDataPanel;
-    private String selectedNode;
-
-    /**
-	 * 
-	 */
-    public NodeViewerMetaData() {
-        this.setLayout(new BorderLayout());
-        this.metaDataPanel = new JPanel();
-        this.metaDataPanel.setBackground(Color.WHITE);
-        JScrollPane scroller = new JScrollPane(this.metaDataPanel);
-        this.add(scroller, BorderLayout.CENTER);
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see
-     * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
-     * getTitle()
-     */
-    @Override
-    public String getTitle() {
-        return "Node Metadata";
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see
-     * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
-     * nodeSelectionChanged(java.util.Set)
-     */
-    @Override
-    public void nodeSelectionChanged(List<String> selectedNodes) {
-        this.metaDataPanel.removeAll();
-        if (selectedNodes.size() > 0) {
-            this.selectedNode = selectedNodes.get(0);
-            SwingWorker<Map<String, String>, Void> worker = new SwingWorker<Map<String, String>, Void>() {
-
-                @Override
-                protected Map<String, String> doInBackground() throws Exception {
-                    return NodeViewerMetaData.this.zooInspectorManager
-                            .getNodeMeta(NodeViewerMetaData.this.selectedNode);
-                }
-
-                @Override
-                protected void done() {
-                    Map<String, String> data = null;
-                    try {
-                        data = get();
-                    } catch (InterruptedException e) {
-                        data = new HashMap<String, String>();
-                        LoggerFactory.getLogger().error(
-                                "Error retrieving meta data for node: "
-                                        + NodeViewerMetaData.this.selectedNode,
-                                e);
-                    } catch (ExecutionException e) {
-                        data = new HashMap<String, String>();
-                        LoggerFactory.getLogger().error(
-                                "Error retrieving meta data for node: "
-                                        + NodeViewerMetaData.this.selectedNode,
-                                e);
-                    }
-                    NodeViewerMetaData.this.metaDataPanel
-                            .setLayout(new GridBagLayout());
-                    JPanel infoPanel = new JPanel();
-                    infoPanel.setBackground(Color.WHITE);
-                    infoPanel.setLayout(new GridBagLayout());
-                    int i = 0;
-                    int rowPos = 0;
-                    for (Map.Entry<String, String> entry : data.entrySet()) {
-                        rowPos = 2 * i + 1;
-                        JLabel label = new JLabel(entry.getKey());
-                        JTextField text = new JTextField(entry.getValue());
-                        text.setEditable(false);
-                        GridBagConstraints c1 = new GridBagConstraints();
-                        c1.gridx = 0;
-                        c1.gridy = rowPos;
-                        c1.gridwidth = 1;
-                        c1.gridheight = 1;
-                        c1.weightx = 0;
-                        c1.weighty = 0;
-                        c1.anchor = GridBagConstraints.WEST;
-                        c1.fill = GridBagConstraints.HORIZONTAL;
-                        c1.insets = new Insets(5, 5, 5, 5);
-                        c1.ipadx = 0;
-                        c1.ipady = 0;
-                        infoPanel.add(label, c1);
-                        GridBagConstraints c2 = new GridBagConstraints();
-                        c2.gridx = 2;
-                        c2.gridy = rowPos;
-                        c2.gridwidth = 1;
-                        c2.gridheight = 1;
-                        c2.weightx = 0;
-                        c2.weighty = 0;
-                        c2.anchor = GridBagConstraints.WEST;
-                        c2.fill = GridBagConstraints.HORIZONTAL;
-                        c2.insets = new Insets(5, 5, 5, 5);
-                        c2.ipadx = 0;
-                        c2.ipady = 0;
-                        infoPanel.add(text, c2);
-                        i++;
-                    }
-                    GridBagConstraints c = new GridBagConstraints();
-                    c.gridx = 1;
-                    c.gridy = rowPos;
-                    c.gridwidth = 1;
-                    c.gridheight = 1;
-                    c.weightx = 1;
-                    c.weighty = 1;
-                    c.anchor = GridBagConstraints.NORTHWEST;
-                    c.fill = GridBagConstraints.NONE;
-                    c.insets = new Insets(5, 5, 5, 5);
-                    c.ipadx = 0;
-                    c.ipady = 0;
-                    NodeViewerMetaData.this.metaDataPanel.add(infoPanel, c);
-                    NodeViewerMetaData.this.metaDataPanel.revalidate();
-                    NodeViewerMetaData.this.metaDataPanel.repaint();
-                }
-            };
-            worker.execute();
-        }
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see
-     * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
-     * setZooInspectorManager
-     * (org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager)
-     */
-    @Override
-    public void setZooInspectorManager(
-            ZooInspectorNodeManager zooInspectorManager) {
-        this.zooInspectorManager = zooInspectorManager;
-    }
-
-}
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.gui.nodeviewer;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.SwingWorker;
+
+import org.apache.zookeeper.data.Stat;
+import org.apache.zookeeper.inspector.logger.LoggerFactory;
+import org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager;
+
+/**
+ * A node viewer for displaying the meta data for the currently selected node.
+ * The meta data is essentially the information from the {@link Stat} for the
+ * node
+ */
+public class NodeViewerMetaData extends ZooInspectorNodeViewer {
+    private ZooInspectorNodeManager zooInspectorManager;
+    private final JPanel metaDataPanel;
+    private String selectedNode;
+
+    /**
+	 * 
+	 */
+    public NodeViewerMetaData() {
+        this.setLayout(new BorderLayout());
+        this.metaDataPanel = new JPanel();
+        this.metaDataPanel.setBackground(Color.WHITE);
+        JScrollPane scroller = new JScrollPane(this.metaDataPanel);
+        this.add(scroller, BorderLayout.CENTER);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
+     * getTitle()
+     */
+    @Override
+    public String getTitle() {
+        return "Node Metadata";
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
+     * nodeSelectionChanged(java.util.Set)
+     */
+    @Override
+    public void nodeSelectionChanged(List<String> selectedNodes) {
+        this.metaDataPanel.removeAll();
+        if (selectedNodes.size() > 0) {
+            this.selectedNode = selectedNodes.get(0);
+            SwingWorker<Map<String, String>, Void> worker = new SwingWorker<Map<String, String>, Void>() {
+
+                @Override
+                protected Map<String, String> doInBackground() throws Exception {
+                    return NodeViewerMetaData.this.zooInspectorManager
+                            .getNodeMeta(NodeViewerMetaData.this.selectedNode);
+                }
+
+                @Override
+                protected void done() {
+                    Map<String, String> data = null;
+                    try {
+                        data = get();
+                    } catch (InterruptedException e) {
+                        data = new HashMap<String, String>();
+                        LoggerFactory.getLogger().error(
+                                "Error retrieving meta data for node: "
+                                        + NodeViewerMetaData.this.selectedNode,
+                                e);
+                    } catch (ExecutionException e) {
+                        data = new HashMap<String, String>();
+                        LoggerFactory.getLogger().error(
+                                "Error retrieving meta data for node: "
+                                        + NodeViewerMetaData.this.selectedNode,
+                                e);
+                    }
+                    NodeViewerMetaData.this.metaDataPanel
+                            .setLayout(new GridBagLayout());
+                    JPanel infoPanel = new JPanel();
+                    infoPanel.setBackground(Color.WHITE);
+                    infoPanel.setLayout(new GridBagLayout());
+                    int i = 0;
+                    int rowPos = 0;
+                    for (Map.Entry<String, String> entry : data.entrySet()) {
+                        rowPos = 2 * i + 1;
+                        JLabel label = new JLabel(entry.getKey());
+                        JTextField text = new JTextField(entry.getValue());
+                        text.setEditable(false);
+                        GridBagConstraints c1 = new GridBagConstraints();
+                        c1.gridx = 0;
+                        c1.gridy = rowPos;
+                        c1.gridwidth = 1;
+                        c1.gridheight = 1;
+                        c1.weightx = 0;
+                        c1.weighty = 0;
+                        c1.anchor = GridBagConstraints.WEST;
+                        c1.fill = GridBagConstraints.HORIZONTAL;
+                        c1.insets = new Insets(5, 5, 5, 5);
+                        c1.ipadx = 0;
+                        c1.ipady = 0;
+                        infoPanel.add(label, c1);
+                        GridBagConstraints c2 = new GridBagConstraints();
+                        c2.gridx = 2;
+                        c2.gridy = rowPos;
+                        c2.gridwidth = 1;
+                        c2.gridheight = 1;
+                        c2.weightx = 0;
+                        c2.weighty = 0;
+                        c2.anchor = GridBagConstraints.WEST;
+                        c2.fill = GridBagConstraints.HORIZONTAL;
+                        c2.insets = new Insets(5, 5, 5, 5);
+                        c2.ipadx = 0;
+                        c2.ipady = 0;
+                        infoPanel.add(text, c2);
+                        i++;
+                    }
+                    GridBagConstraints c = new GridBagConstraints();
+                    c.gridx = 1;
+                    c.gridy = rowPos;
+                    c.gridwidth = 1;
+                    c.gridheight = 1;
+                    c.weightx = 1;
+                    c.weighty = 1;
+                    c.anchor = GridBagConstraints.NORTHWEST;
+                    c.fill = GridBagConstraints.NONE;
+                    c.insets = new Insets(5, 5, 5, 5);
+                    c.ipadx = 0;
+                    c.ipady = 0;
+                    NodeViewerMetaData.this.metaDataPanel.add(infoPanel, c);
+                    NodeViewerMetaData.this.metaDataPanel.revalidate();
+                    NodeViewerMetaData.this.metaDataPanel.repaint();
+                }
+            };
+            worker.execute();
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer#
+     * setZooInspectorManager
+     * (org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager)
+     */
+    @Override
+    public void setZooInspectorManager(
+            ZooInspectorNodeManager zooInspectorManager) {
+        this.zooInspectorManager = zooInspectorManager;
+    }
+
+}

+ 138 - 138
src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/gui/nodeviewer/ZooInspectorNodeViewer.java

@@ -1,138 +1,138 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.zookeeper.inspector.gui.nodeviewer;
-
-import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.Transferable;
-import java.awt.datatransfer.UnsupportedFlavorException;
-import java.io.IOException;
-import java.util.List;
-
-import javax.swing.JPanel;
-
-import org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager;
-
-/**
- * A {@link JPanel} for displaying information about the currently selected
- * node(s)
- */
-public abstract class ZooInspectorNodeViewer extends JPanel implements
-        Transferable {
-    /**
-     * The {@link DataFlavor} used for DnD in the node viewer configuration
-     * dialog
-     */
-    public static final DataFlavor nodeViewerDataFlavor = new DataFlavor(
-            ZooInspectorNodeViewer.class, "nodeviewer");
-
-    /**
-     * @param zooInspectorManager
-     */
-    public abstract void setZooInspectorManager(
-            ZooInspectorNodeManager zooInspectorManager);
-
-    /**
-     * Called whenever the selected nodes in the tree view changes.
-     * 
-     * @param selectedNodes
-     *            - the nodes currently selected in the tree view
-     * 
-     */
-    public abstract void nodeSelectionChanged(List<String> selectedNodes);
-
-    /**
-     * @return the title of the node viewer. this will be shown on the tab for
-     *         this node viewer.
-     */
-    public abstract String getTitle();
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see
-     * java.awt.datatransfer.Transferable#getTransferData(java.awt.datatransfer
-     * .DataFlavor)
-     */
-    public Object getTransferData(DataFlavor flavor)
-            throws UnsupportedFlavorException, IOException {
-        if (flavor.equals(nodeViewerDataFlavor)) {
-            return this.getClass().getCanonicalName();
-        } else {
-            return null;
-        }
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see java.awt.datatransfer.Transferable#getTransferDataFlavors()
-     */
-    public DataFlavor[] getTransferDataFlavors() {
-        return new DataFlavor[] { nodeViewerDataFlavor };
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @seejava.awt.datatransfer.Transferable#isDataFlavorSupported(java.awt.
-     * datatransfer.DataFlavor)
-     */
-    public boolean isDataFlavorSupported(DataFlavor flavor) {
-        return flavor.equals(nodeViewerDataFlavor);
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see java.lang.Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result
-                + ((getTitle() == null) ? 0 : getTitle().hashCode());
-        return result;
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        ZooInspectorNodeViewer other = (ZooInspectorNodeViewer) obj;
-        if (getClass().getCanonicalName() != other.getClass()
-                .getCanonicalName()) {
-            return false;
-        }
-        if (getTitle() == null) {
-            if (other.getTitle() != null)
-                return false;
-        } else if (!getTitle().equals(other.getTitle()))
-            return false;
-        return true;
-    }
-}
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.gui.nodeviewer;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+import java.util.List;
+
+import javax.swing.JPanel;
+
+import org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager;
+
+/**
+ * A {@link JPanel} for displaying information about the currently selected
+ * node(s)
+ */
+public abstract class ZooInspectorNodeViewer extends JPanel implements
+        Transferable {
+    /**
+     * The {@link DataFlavor} used for DnD in the node viewer configuration
+     * dialog
+     */
+    public static final DataFlavor nodeViewerDataFlavor = new DataFlavor(
+            ZooInspectorNodeViewer.class, "nodeviewer");
+
+    /**
+     * @param zooInspectorManager
+     */
+    public abstract void setZooInspectorManager(
+            ZooInspectorNodeManager zooInspectorManager);
+
+    /**
+     * Called whenever the selected nodes in the tree view changes.
+     * 
+     * @param selectedNodes
+     *            - the nodes currently selected in the tree view
+     * 
+     */
+    public abstract void nodeSelectionChanged(List<String> selectedNodes);
+
+    /**
+     * @return the title of the node viewer. this will be shown on the tab for
+     *         this node viewer.
+     */
+    public abstract String getTitle();
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * java.awt.datatransfer.Transferable#getTransferData(java.awt.datatransfer
+     * .DataFlavor)
+     */
+    public Object getTransferData(DataFlavor flavor)
+            throws UnsupportedFlavorException, IOException {
+        if (flavor.equals(nodeViewerDataFlavor)) {
+            return this.getClass().getCanonicalName();
+        } else {
+            return null;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.awt.datatransfer.Transferable#getTransferDataFlavors()
+     */
+    public DataFlavor[] getTransferDataFlavors() {
+        return new DataFlavor[] { nodeViewerDataFlavor };
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @seejava.awt.datatransfer.Transferable#isDataFlavorSupported(java.awt.
+     * datatransfer.DataFlavor)
+     */
+    public boolean isDataFlavorSupported(DataFlavor flavor) {
+        return flavor.equals(nodeViewerDataFlavor);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result
+                + ((getTitle() == null) ? 0 : getTitle().hashCode());
+        return result;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        ZooInspectorNodeViewer other = (ZooInspectorNodeViewer) obj;
+        if (getClass().getCanonicalName() != other.getClass()
+                .getCanonicalName()) {
+            return false;
+        }
+        if (getTitle() == null) {
+            if (other.getTitle() != null)
+                return false;
+        } else if (!getTitle().equals(other.getTitle()))
+            return false;
+        return true;
+    }
+}

+ 36 - 36
src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/logger/LoggerFactory.java

@@ -1,36 +1,36 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.zookeeper.inspector.logger;
-
-/**
- * Provides a {@link Logger} for use across the entire application
- * 
- */
-public class LoggerFactory
-{
-	private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger("org.apache.zookeeper.inspector"); //$NON-NLS-1$
-
-	/**
-	 * @return {@link Logger} for ZooInspector
-	 */
-	public static org.slf4j.Logger getLogger()
-	{
-		return logger;
-	}
-
-}
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.logger;
+
+/**
+ * Provides a {@link Logger} for use across the entire application
+ * 
+ */
+public class LoggerFactory
+{
+	private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger("org.apache.zookeeper.inspector"); //$NON-NLS-1$
+
+	/**
+	 * @return {@link Logger} for ZooInspector
+	 */
+	public static org.slf4j.Logger getLogger()
+	{
+		return logger;
+	}
+
+}

+ 37 - 37
src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/manager/NodeListener.java

@@ -1,37 +1,37 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.zookeeper.inspector.manager;
-
-import java.util.Map;
-
-/**
- * A Listener for Events on zookeeper nodes
- */
-public interface NodeListener {
-    /**
-     * @param nodePath
-     *            - the path of the node
-     * @param eventType
-     *            - the event type
-     * @param eventInfo
-     *            - a {@link Map} containing any other information about this
-     *            event
-     */
-    public void processEvent(String nodePath, String eventType,
-            Map<String, String> eventInfo);
-}
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.manager;
+
+import java.util.Map;
+
+/**
+ * A Listener for Events on zookeeper nodes
+ */
+public interface NodeListener {
+    /**
+     * @param nodePath
+     *            - the path of the node
+     * @param eventType
+     *            - the event type
+     * @param eventInfo
+     *            - a {@link Map} containing any other information about this
+     *            event
+     */
+    public void processEvent(String nodePath, String eventType,
+            Map<String, String> eventInfo);
+}

+ 120 - 120
src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/manager/Pair.java

@@ -1,120 +1,120 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.zookeeper.inspector.manager;
-
-/**
- * A utility class for storing a pair of objects
- * 
- * @param <K>
- * @param <V>
- */
-public class Pair<K, V> {
-    private K key;
-    private V value;
-
-    /**
-     * @param key
-     * @param value
-     */
-    public Pair(K key, V value) {
-        this.key = key;
-        this.value = value;
-    }
-
-    /**
-	 * 
-	 */
-    public Pair() {
-        // Do Nothing
-    }
-
-    /**
-     * @return key
-     */
-    public K getKey() {
-        return key;
-    }
-
-    /**
-     * @param key
-     */
-    public void setKey(K key) {
-        this.key = key;
-    }
-
-    /**
-     * @return value
-     */
-    public V getValue() {
-        return value;
-    }
-
-    /**
-     * @param value
-     */
-    public void setValue(V value) {
-        this.value = value;
-    }
-
-    @Override
-    public String toString() {
-        return "Pair [" + key + ", " + value + "]";
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see java.lang.Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((key == null) ? 0 : key.hashCode());
-        result = prime * result + ((value == null) ? 0 : value.hashCode());
-        return result;
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        Pair<?, ?> other = (Pair<?, ?>) obj;
-        if (key == null) {
-            if (other.key != null)
-                return false;
-        } else if (!key.equals(other.key))
-            return false;
-        if (value == null) {
-            if (other.value != null)
-                return false;
-        } else if (!value.equals(other.value))
-            return false;
-        return true;
-    }
-
-}
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.manager;
+
+/**
+ * A utility class for storing a pair of objects
+ * 
+ * @param <K>
+ * @param <V>
+ */
+public class Pair<K, V> {
+    private K key;
+    private V value;
+
+    /**
+     * @param key
+     * @param value
+     */
+    public Pair(K key, V value) {
+        this.key = key;
+        this.value = value;
+    }
+
+    /**
+	 * 
+	 */
+    public Pair() {
+        // Do Nothing
+    }
+
+    /**
+     * @return key
+     */
+    public K getKey() {
+        return key;
+    }
+
+    /**
+     * @param key
+     */
+    public void setKey(K key) {
+        this.key = key;
+    }
+
+    /**
+     * @return value
+     */
+    public V getValue() {
+        return value;
+    }
+
+    /**
+     * @param value
+     */
+    public void setValue(V value) {
+        this.value = value;
+    }
+
+    @Override
+    public String toString() {
+        return "Pair [" + key + ", " + value + "]";
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((key == null) ? 0 : key.hashCode());
+        result = prime * result + ((value == null) ? 0 : value.hashCode());
+        return result;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        Pair<?, ?> other = (Pair<?, ?>) obj;
+        if (key == null) {
+            if (other.key != null)
+                return false;
+        } else if (!key.equals(other.key))
+            return false;
+        if (value == null) {
+            if (other.value != null)
+                return false;
+        } else if (!value.equals(other.value))
+            return false;
+        return true;
+    }
+
+}

+ 139 - 139
src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/manager/ZooInspectorManager.java

@@ -1,139 +1,139 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.zookeeper.inspector.manager;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import javax.swing.JComboBox;
-import javax.swing.JTextField;
-
-/**
- * A Manager for all interactions between the application and the Zookeeper
- * instance
- */
-public interface ZooInspectorManager extends ZooInspectorNodeManager,
-        ZooInspectorNodeTreeManager {
-
-    /**
-     * @param connectionProps
-     * @return true if successfully connected
-     */
-    public boolean connect(Properties connectionProps);
-
-    /**
-     * @return true if successfully disconnected
-     */
-    public boolean disconnect();
-
-    /**
-     * @return a {@link Pair} containing the following:
-     *         <ul>
-     *         <li>a {@link Map} of property keys to list of possible values. If
-     *         the list size is 1 the value is taken to be the default value for
-     *         a {@link JTextField}. If the list size is greater than 1, the
-     *         values are taken to be the possible options to show in a
-     *         {@link JComboBox} with the first selected as default.</li>
-     *         <li>a {@link Map} of property keys to the label to show on the UI
-     *         </li>
-     *         <ul>
-     * 
-     */
-    public Pair<Map<String, List<String>>, Map<String, String>> getConnectionPropertiesTemplate();
-
-    /**
-     * @param selectedNodes
-     *            - the nodes to add the watcher to
-     * @param nodeListener
-     *            - the node listener for this watcher
-     */
-    public void addWatchers(Collection<String> selectedNodes,
-            NodeListener nodeListener);
-
-    /**
-     * @param selectedNodes
-     *            - the nodes to remove the watchers from
-     */
-    public void removeWatchers(Collection<String> selectedNodes);
-
-    /**
-     * @param selectedFile
-     *            - the file to load which contains the node viewers
-     *            configuration
-     * @return nodeViewers - the class names of the node viewers from the
-     *         configuration
-     * @throws IOException
-     *             - if the configuration file cannot be loaded
-     */
-    public List<String> loadNodeViewersFile(File selectedFile)
-            throws IOException;
-
-    /**
-     * @param selectedFile
-     *            - the file to save the configuration to
-     * @param nodeViewersClassNames
-     *            - the class names of the node viewers
-     * @throws IOException
-     *             - if the configuration file cannot be saved
-     */
-    public void saveNodeViewersFile(File selectedFile,
-            List<String> nodeViewersClassNames) throws IOException;
-
-    /**
-     * @param nodeViewersClassNames
-     *            - the class names of the node viewers
-     * @throws IOException
-     *             - if the default configuration file cannot be loaded
-     */
-    public void setDefaultNodeViewerConfiguration(
-            List<String> nodeViewersClassNames) throws IOException;
-
-    /**
-     * @return nodeViewers - the class names of the node viewers from the
-     *         configuration
-     * @throws IOException
-     *             - if the default configuration file cannot be loaded
-     */
-    List<String> getDefaultNodeViewerConfiguration() throws IOException;
-
-    /**
-     * @param connectionProps
-     *            - the connection properties last used to connect to the
-     *            zookeeeper instance
-     */
-    public void setLastConnectionProps(Properties connectionProps);
-
-    /**
-     * @return last connection Properties - the connection properties last used
-     *         to connect to the zookeeeper instance
-     */
-    public Properties getLastConnectionProps();
-
-    /**
-     * @param props
-     *            - the properties to use as the default connection settings
-     * @throws IOException
-     *             - if the default configuration file cannot be saved
-     */
-    public void saveDefaultConnectionFile(Properties props) throws IOException;
-
-}
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.inspector.manager;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.swing.JComboBox;
+import javax.swing.JTextField;
+
+/**
+ * A Manager for all interactions between the application and the Zookeeper
+ * instance
+ */
+public interface ZooInspectorManager extends ZooInspectorNodeManager,
+        ZooInspectorNodeTreeManager {
+
+    /**
+     * @param connectionProps
+     * @return true if successfully connected
+     */
+    public boolean connect(Properties connectionProps);
+
+    /**
+     * @return true if successfully disconnected
+     */
+    public boolean disconnect();
+
+    /**
+     * @return a {@link Pair} containing the following:
+     *         <ul>
+     *         <li>a {@link Map} of property keys to list of possible values. If
+     *         the list size is 1 the value is taken to be the default value for
+     *         a {@link JTextField}. If the list size is greater than 1, the
+     *         values are taken to be the possible options to show in a
+     *         {@link JComboBox} with the first selected as default.</li>
+     *         <li>a {@link Map} of property keys to the label to show on the UI
+     *         </li>
+     *         <ul>
+     * 
+     */
+    public Pair<Map<String, List<String>>, Map<String, String>> getConnectionPropertiesTemplate();
+
+    /**
+     * @param selectedNodes
+     *            - the nodes to add the watcher to
+     * @param nodeListener
+     *            - the node listener for this watcher
+     */
+    public void addWatchers(Collection<String> selectedNodes,
+            NodeListener nodeListener);
+
+    /**
+     * @param selectedNodes
+     *            - the nodes to remove the watchers from
+     */
+    public void removeWatchers(Collection<String> selectedNodes);
+
+    /**
+     * @param selectedFile
+     *            - the file to load which contains the node viewers
+     *            configuration
+     * @return nodeViewers - the class names of the node viewers from the
+     *         configuration
+     * @throws IOException
+     *             - if the configuration file cannot be loaded
+     */
+    public List<String> loadNodeViewersFile(File selectedFile)
+            throws IOException;
+
+    /**
+     * @param selectedFile
+     *            - the file to save the configuration to
+     * @param nodeViewersClassNames
+     *            - the class names of the node viewers
+     * @throws IOException
+     *             - if the configuration file cannot be saved
+     */
+    public void saveNodeViewersFile(File selectedFile,
+            List<String> nodeViewersClassNames) throws IOException;
+
+    /**
+     * @param nodeViewersClassNames
+     *            - the class names of the node viewers
+     * @throws IOException
+     *             - if the default configuration file cannot be loaded
+     */
+    public void setDefaultNodeViewerConfiguration(
+            List<String> nodeViewersClassNames) throws IOException;
+
+    /**
+     * @return nodeViewers - the class names of the node viewers from the
+     *         configuration
+     * @throws IOException
+     *             - if the default configuration file cannot be loaded
+     */
+    List<String> getDefaultNodeViewerConfiguration() throws IOException;
+
+    /**
+     * @param connectionProps
+     *            - the connection properties last used to connect to the
+     *            zookeeeper instance
+     */
+    public void setLastConnectionProps(Properties connectionProps);
+
+    /**
+     * @return last connection Properties - the connection properties last used
+     *         to connect to the zookeeeper instance
+     */
+    public Properties getLastConnectionProps();
+
+    /**
+     * @param props
+     *            - the properties to use as the default connection settings
+     * @throws IOException
+     *             - if the default configuration file cannot be saved
+     */
+    public void saveDefaultConnectionFile(Properties props) throws IOException;
+
+}

+ 885 - 885
src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/manager/ZooInspectorManagerImpl.java

@@ -1,885 +1,885 @@
-/**
- * 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(
-            "./config/defaultNodeViewers.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;
-    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 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 && !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;
-    }
-}
+/**
+ * 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(
+            "./config/defaultNodeViewers.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;
+    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 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 && !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;
+    }
+}

+ 33 - 33
src/contrib/zooinspector/src/java/org/apache/zookeeper/inspector/manager/ZooInspectorNodeManager.java

@@ -1,33 +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);
-}
+/**
+ * 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);
+}

+ 288 - 288
src/contrib/zooinspector/src/java/org/apache/zookeeper/retry/ZooKeeperRetry.java

@@ -1,288 +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 version)
-            throws KeeperException, InterruptedException {
-        int count = 0;
-        do {
-            try {
-                return super.setACL(path, acl, version);
-            } 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;
-    }
-
-}
+/**
+ * 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 version)
+            throws KeeperException, InterruptedException {
+        int count = 0;
+        do {
+            try {
+                return super.setACL(path, acl, version);
+            } 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;
+    }
+
+}

+ 18 - 18
src/contrib/zooinspector/zooInspector.cmd

@@ -1,18 +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\*;lib" org.apache.zookeeper.inspector.ZooInspector
+#!/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\*;lib" org.apache.zookeeper.inspector.ZooInspector

+ 128 - 128
src/java/main/org/apache/zookeeper/server/SnapshotFormatter.java

@@ -1,128 +1,128 @@
-/**
- * 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.server;
-
-import java.io.BufferedInputStream;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.zip.Adler32;
-import java.util.zip.CheckedInputStream;
-
-import org.apache.jute.BinaryInputArchive;
-import org.apache.jute.InputArchive;
-import org.apache.zookeeper.data.StatPersisted;
-import org.apache.zookeeper.server.persistence.FileSnap;
-
-/**
- * Dump a snapshot file to stdout.
- */
-public class SnapshotFormatter {
-
-    /**
-     * USAGE: SnapshotFormatter snapshot_file
-     */
-    public static void main(String[] args) throws Exception {
-        if (args.length != 1) {
-            System.err.println("USAGE: SnapshotFormatter snapshot_file");
-            System.exit(2);
-        }
-
-        new SnapshotFormatter().run(args[0]);
-    }
-    
-    public void run(String snapshotFileName) throws IOException {
-        InputStream is = new CheckedInputStream(
-                new BufferedInputStream(new FileInputStream(snapshotFileName)),
-                new Adler32());
-        InputArchive ia = BinaryInputArchive.getArchive(is);
-        
-        FileSnap fileSnap = new FileSnap(null);
-
-        DataTree dataTree = new DataTree();
-        Map<Long, Integer> sessions = new HashMap<Long, Integer>();
-        
-        fileSnap.deserialize(dataTree, sessions, ia);
-
-        printDetails(dataTree, sessions);
-    }
-
-    private void printDetails(DataTree dataTree, Map<Long, Integer> sessions) {
-        printZnodeDetails(dataTree);
-        printSessionDetails(dataTree, sessions);
-    }
-
-    private void printZnodeDetails(DataTree dataTree) {
-        System.out.println(String.format("ZNode Details (count=%d):",
-                dataTree.getNodeCount()));
-        
-        printZnode(dataTree, "/");
-        System.out.println("----");
-    }
-
-    private void printZnode(DataTree dataTree, String name) {
-        System.out.println("----");
-        DataNode n = dataTree.getNode(name);
-        Set<String> children;
-        synchronized(n) { // keep findbugs happy
-            System.out.println(name);
-            printStat(n.stat);
-            if (n.data != null) {
-                System.out.println("  dataLength = " + n.data.length);
-            } else {
-                System.out.println("  no data");
-            }
-            children = n.getChildren();
-        }
-        if (children != null) {
-            for (String child : children) {
-                printZnode(dataTree, name + (name.equals("/") ? "" : "/") + child);
-            }
-        }
-    }
-
-    private void printSessionDetails(DataTree dataTree, Map<Long, Integer> sessions) {
-        System.out.println("Session Details (sid, timeout, ephemeralCount):");
-        for (Map.Entry<Long, Integer> e : sessions.entrySet()) {
-            long sid = e.getKey();
-            System.out.println(String.format("%#016x, %d, %d",
-                    sid, e.getValue(), dataTree.getEphemerals(sid).size()));
-        }
-    }
-
-    private void printStat(StatPersisted stat) {
-        printHex("cZxid", stat.getCzxid());
-        System.out.println("  ctime = " + new Date(stat.getCtime()).toString());
-        printHex("mZxid", stat.getMzxid());
-        System.out.println("  mtime = " + new Date(stat.getMtime()).toString());
-        printHex("pZxid", stat.getPzxid());
-        System.out.println("  cversion = " + stat.getCversion());
-        System.out.println("  dataVersion = " + stat.getVersion());
-        System.out.println("  aclVersion = " + stat.getAversion());
-        printHex("ephemeralOwner", stat.getEphemeralOwner());
-    }
-
-    private void printHex(String prefix, long value) {
-        System.out.println(String.format("  %s = %#016x", prefix, value));
-    }
-}
+/**
+ * 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.server;
+
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.zip.Adler32;
+import java.util.zip.CheckedInputStream;
+
+import org.apache.jute.BinaryInputArchive;
+import org.apache.jute.InputArchive;
+import org.apache.zookeeper.data.StatPersisted;
+import org.apache.zookeeper.server.persistence.FileSnap;
+
+/**
+ * Dump a snapshot file to stdout.
+ */
+public class SnapshotFormatter {
+
+    /**
+     * USAGE: SnapshotFormatter snapshot_file
+     */
+    public static void main(String[] args) throws Exception {
+        if (args.length != 1) {
+            System.err.println("USAGE: SnapshotFormatter snapshot_file");
+            System.exit(2);
+        }
+
+        new SnapshotFormatter().run(args[0]);
+    }
+    
+    public void run(String snapshotFileName) throws IOException {
+        InputStream is = new CheckedInputStream(
+                new BufferedInputStream(new FileInputStream(snapshotFileName)),
+                new Adler32());
+        InputArchive ia = BinaryInputArchive.getArchive(is);
+        
+        FileSnap fileSnap = new FileSnap(null);
+
+        DataTree dataTree = new DataTree();
+        Map<Long, Integer> sessions = new HashMap<Long, Integer>();
+        
+        fileSnap.deserialize(dataTree, sessions, ia);
+
+        printDetails(dataTree, sessions);
+    }
+
+    private void printDetails(DataTree dataTree, Map<Long, Integer> sessions) {
+        printZnodeDetails(dataTree);
+        printSessionDetails(dataTree, sessions);
+    }
+
+    private void printZnodeDetails(DataTree dataTree) {
+        System.out.println(String.format("ZNode Details (count=%d):",
+                dataTree.getNodeCount()));
+        
+        printZnode(dataTree, "/");
+        System.out.println("----");
+    }
+
+    private void printZnode(DataTree dataTree, String name) {
+        System.out.println("----");
+        DataNode n = dataTree.getNode(name);
+        Set<String> children;
+        synchronized(n) { // keep findbugs happy
+            System.out.println(name);
+            printStat(n.stat);
+            if (n.data != null) {
+                System.out.println("  dataLength = " + n.data.length);
+            } else {
+                System.out.println("  no data");
+            }
+            children = n.getChildren();
+        }
+        if (children != null) {
+            for (String child : children) {
+                printZnode(dataTree, name + (name.equals("/") ? "" : "/") + child);
+            }
+        }
+    }
+
+    private void printSessionDetails(DataTree dataTree, Map<Long, Integer> sessions) {
+        System.out.println("Session Details (sid, timeout, ephemeralCount):");
+        for (Map.Entry<Long, Integer> e : sessions.entrySet()) {
+            long sid = e.getKey();
+            System.out.println(String.format("%#016x, %d, %d",
+                    sid, e.getValue(), dataTree.getEphemerals(sid).size()));
+        }
+    }
+
+    private void printStat(StatPersisted stat) {
+        printHex("cZxid", stat.getCzxid());
+        System.out.println("  ctime = " + new Date(stat.getCtime()).toString());
+        printHex("mZxid", stat.getMzxid());
+        System.out.println("  mtime = " + new Date(stat.getMtime()).toString());
+        printHex("pZxid", stat.getPzxid());
+        System.out.println("  cversion = " + stat.getCversion());
+        System.out.println("  dataVersion = " + stat.getVersion());
+        System.out.println("  aclVersion = " + stat.getAversion());
+        printHex("ephemeralOwner", stat.getEphemeralOwner());
+    }
+
+    private void printHex(String prefix, long value) {
+        System.out.println(String.format("  %s = %#016x", prefix, value));
+    }
+}

+ 149 - 149
src/java/test/org/apache/zookeeper/server/PrepRequestProcessorTest.java

@@ -1,149 +1,149 @@
-/**
- * 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.server;
-
-import static org.junit.Assert.*;
-
-import java.io.File;
-import java.io.PrintWriter;
-import java.nio.ByteBuffer;
-import java.util.concurrent.CountDownLatch;
-
-import org.apache.zookeeper.PortAssignment;
-import org.apache.zookeeper.KeeperException.Code;
-import org.apache.zookeeper.KeeperException.SessionExpiredException;
-import org.apache.zookeeper.KeeperException.SessionMovedException;
-import org.apache.zookeeper.ZooDefs.OpCode;
-import org.apache.zookeeper.server.PrepRequestProcessor;
-import org.apache.zookeeper.server.Request;
-import org.apache.zookeeper.server.RequestProcessor;
-import org.apache.zookeeper.server.ServerCnxnFactory;
-import org.apache.zookeeper.server.SyncRequestProcessor;
-import org.apache.zookeeper.server.ZooKeeperServer;
-import org.apache.zookeeper.test.ClientBase;
-import org.apache.zookeeper.txn.ErrorTxn;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class PrepRequestProcessorTest extends ClientBase {
-    private static String HOSTPORT = "127.0.0.1:" + PortAssignment.unique();
-    private static final int CONNECTION_TIMEOUT = 3000;
-    private final CountDownLatch testEnd = new CountDownLatch(1);
-
-    @Test
-    public void testPRequest() throws Exception {
-        File tmpDir = ClientBase.createTmpDir();
-        ClientBase.setupTestEnv();
-        ZooKeeperServer zks = new ZooKeeperServer(tmpDir, tmpDir, 3000);
-        SyncRequestProcessor.setSnapCount(100);
-        final int PORT = Integer.parseInt(HOSTPORT.split(":")[1]);
-        ServerCnxnFactory f = ServerCnxnFactory.createFactory(PORT, -1);
-        f.startup(zks);
-        Assert.assertTrue("waiting for server being up ",
-                ClientBase.waitForServerUp(HOSTPORT,CONNECTION_TIMEOUT));
-        zks.sessionTracker = new MySessionTracker(); 
-        PrepRequestProcessor processor = new PrepRequestProcessor(zks, new MyRequestProcessor());
-        Request foo = new Request(null, 1l, 1, OpCode.create, ByteBuffer.allocate(3), null);
-        processor.pRequest(foo);
-        testEnd.await(5, java.util.concurrent.TimeUnit.SECONDS);
-        f.shutdown();
-        zks.shutdown();
-    }
- 
-
-    private class MyRequestProcessor implements RequestProcessor {
-        @Override
-        public void processRequest(Request request) {
-            Assert.assertEquals("Request should have marshalling error", new ErrorTxn(Code.MARSHALLINGERROR.intValue()),  request.getTxn());
-            testEnd.countDown();
-        }
-        @Override
-        public void shutdown() {
-            // TODO Auto-generated method stub
-            
-        }
-    }
-    
-    private class MySessionTracker implements SessionTracker {
-        @Override
-        public boolean addGlobalSession(long id, int to) {
-            // TODO Auto-generated method stub
-            return false;
-        }
-        @Override
-        public boolean addSession(long id, int to) {
-            // TODO Auto-generated method stub
-            return false;
-        }
-        @Override
-        public void checkSession(long sessionId, Object owner)
-                throws SessionExpiredException, SessionMovedException {
-            // TODO Auto-generated method stub
-        }
-        @Override
-        public long createSession(int sessionTimeout) {
-            // TODO Auto-generated method stub
-            return 0;
-        }
-        @Override
-        public void dumpSessions(PrintWriter pwriter) {
-            // TODO Auto-generated method stub
-
-        }
-         @Override
-        public void removeSession(long sessionId) {
-            // TODO Auto-generated method stub
-
-        }
-        public int upgradeSession(long sessionId) {
-             // TODO Auto-generated method stub
-             return 0;
-        }
-        @Override
-        public void setOwner(long id, Object owner)
-                throws SessionExpiredException {
-            // TODO Auto-generated method stub
-
-        }
-        @Override
-        public void shutdown() {
-            // TODO Auto-generated method stub
-
-        }
-        @Override
-        public boolean touchSession(long sessionId, int sessionTimeout) {
-            // TODO Auto-generated method stub
-            return false;
-        }
-        @Override
-        public void setSessionClosing(long sessionId) {
-          // TODO Auto-generated method stub
-        }
-        @Override
-        public boolean isTrackingSession(long sessionId) {
-            // TODO Auto-generated method stub
-            return false;
-        }
-        @Override
-        public void checkGlobalSession(long sessionId, Object owner)
-                throws SessionExpiredException, SessionMovedException {
-            // TODO Auto-generated method stub
-        }
-    }
-}
+/**
+ * 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.server;
+
+import static org.junit.Assert.*;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.nio.ByteBuffer;
+import java.util.concurrent.CountDownLatch;
+
+import org.apache.zookeeper.PortAssignment;
+import org.apache.zookeeper.KeeperException.Code;
+import org.apache.zookeeper.KeeperException.SessionExpiredException;
+import org.apache.zookeeper.KeeperException.SessionMovedException;
+import org.apache.zookeeper.ZooDefs.OpCode;
+import org.apache.zookeeper.server.PrepRequestProcessor;
+import org.apache.zookeeper.server.Request;
+import org.apache.zookeeper.server.RequestProcessor;
+import org.apache.zookeeper.server.ServerCnxnFactory;
+import org.apache.zookeeper.server.SyncRequestProcessor;
+import org.apache.zookeeper.server.ZooKeeperServer;
+import org.apache.zookeeper.test.ClientBase;
+import org.apache.zookeeper.txn.ErrorTxn;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class PrepRequestProcessorTest extends ClientBase {
+    private static String HOSTPORT = "127.0.0.1:" + PortAssignment.unique();
+    private static final int CONNECTION_TIMEOUT = 3000;
+    private final CountDownLatch testEnd = new CountDownLatch(1);
+
+    @Test
+    public void testPRequest() throws Exception {
+        File tmpDir = ClientBase.createTmpDir();
+        ClientBase.setupTestEnv();
+        ZooKeeperServer zks = new ZooKeeperServer(tmpDir, tmpDir, 3000);
+        SyncRequestProcessor.setSnapCount(100);
+        final int PORT = Integer.parseInt(HOSTPORT.split(":")[1]);
+        ServerCnxnFactory f = ServerCnxnFactory.createFactory(PORT, -1);
+        f.startup(zks);
+        Assert.assertTrue("waiting for server being up ",
+                ClientBase.waitForServerUp(HOSTPORT,CONNECTION_TIMEOUT));
+        zks.sessionTracker = new MySessionTracker(); 
+        PrepRequestProcessor processor = new PrepRequestProcessor(zks, new MyRequestProcessor());
+        Request foo = new Request(null, 1l, 1, OpCode.create, ByteBuffer.allocate(3), null);
+        processor.pRequest(foo);
+        testEnd.await(5, java.util.concurrent.TimeUnit.SECONDS);
+        f.shutdown();
+        zks.shutdown();
+    }
+ 
+
+    private class MyRequestProcessor implements RequestProcessor {
+        @Override
+        public void processRequest(Request request) {
+            Assert.assertEquals("Request should have marshalling error", new ErrorTxn(Code.MARSHALLINGERROR.intValue()),  request.getTxn());
+            testEnd.countDown();
+        }
+        @Override
+        public void shutdown() {
+            // TODO Auto-generated method stub
+            
+        }
+    }
+    
+    private class MySessionTracker implements SessionTracker {
+        @Override
+        public boolean addGlobalSession(long id, int to) {
+            // TODO Auto-generated method stub
+            return false;
+        }
+        @Override
+        public boolean addSession(long id, int to) {
+            // TODO Auto-generated method stub
+            return false;
+        }
+        @Override
+        public void checkSession(long sessionId, Object owner)
+                throws SessionExpiredException, SessionMovedException {
+            // TODO Auto-generated method stub
+        }
+        @Override
+        public long createSession(int sessionTimeout) {
+            // TODO Auto-generated method stub
+            return 0;
+        }
+        @Override
+        public void dumpSessions(PrintWriter pwriter) {
+            // TODO Auto-generated method stub
+
+        }
+         @Override
+        public void removeSession(long sessionId) {
+            // TODO Auto-generated method stub
+
+        }
+        public int upgradeSession(long sessionId) {
+             // TODO Auto-generated method stub
+             return 0;
+        }
+        @Override
+        public void setOwner(long id, Object owner)
+                throws SessionExpiredException {
+            // TODO Auto-generated method stub
+
+        }
+        @Override
+        public void shutdown() {
+            // TODO Auto-generated method stub
+
+        }
+        @Override
+        public boolean touchSession(long sessionId, int sessionTimeout) {
+            // TODO Auto-generated method stub
+            return false;
+        }
+        @Override
+        public void setSessionClosing(long sessionId) {
+          // TODO Auto-generated method stub
+        }
+        @Override
+        public boolean isTrackingSession(long sessionId) {
+            // TODO Auto-generated method stub
+            return false;
+        }
+        @Override
+        public void checkGlobalSession(long sessionId, Object owner)
+                throws SessionExpiredException, SessionMovedException {
+            // TODO Auto-generated method stub
+        }
+    }
+}

+ 107 - 107
src/java/test/org/apache/zookeeper/test/FLEPredicateTest.java

@@ -1,107 +1,107 @@
-/**
- * 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.test;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.util.HashMap;
-
-import org.apache.zookeeper.server.quorum.FastLeaderElection;
-import org.apache.zookeeper.server.quorum.QuorumCnxManager;
-import org.apache.zookeeper.server.quorum.QuorumPeer;
-import org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer;
-import org.apache.zookeeper.PortAssignment;
-import org.apache.zookeeper.ZKTestCase;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-public class FLEPredicateTest extends ZKTestCase {
-    
-    protected static final Logger LOG = LoggerFactory.getLogger(FLEPredicateTest.class);
-    
-    class MockFLE extends FastLeaderElection {
-        MockFLE(QuorumPeer peer){
-            super(peer, new QuorumCnxManager(peer));
-        }
-        
-        boolean predicate(long newId, long newZxid, long newEpoch, long curId, long curZxid, long curEpoch){
-            return this.totalOrderPredicate(newId, newZxid, newEpoch, curId, curZxid, curEpoch);
-        }
-    }
-    
-    
-    HashMap<Long,QuorumServer> peers;
-    
-    @Test
-    public void testPredicate() throws IOException {
-        
-        peers = new HashMap<Long,QuorumServer>(3);
-        
-        /*
-         * Creates list of peers.
-         */
-        for(int i = 0; i < 3; i++) {
-            peers.put(Long.valueOf(i),
-                new QuorumServer(i,
-                    new InetSocketAddress(
-                        "127.0.0.1", PortAssignment.unique()),
-                    new InetSocketAddress(
-                        "127.0.0.1", PortAssignment.unique())));
-        }
-
-        /*
-         * Creating peer.
-         */
-        try{
-            File tmpDir = ClientBase.createTmpDir();
-            QuorumPeer peer = new QuorumPeer(peers, tmpDir, tmpDir,
-                                        PortAssignment.unique(), 3, 0, 1000, 2, 2);
-        
-            MockFLE mock = new MockFLE(peer);
-            
-            /*
-             * Lower epoch must return false
-             */
-            
-            Assert.assertFalse (mock.predicate(4L, 0L, 0L, 3L, 0L, 2L));
-            
-            /*
-             * Later epoch
-             */
-            Assert.assertTrue (mock.predicate(0L, 0L, 1L, 1L, 0L, 0L));
-        
-            /*
-             * Higher zxid
-             */
-            Assert.assertTrue(mock.predicate(0L, 1L, 0L, 1L, 0L, 0L));
-        
-            /*
-             * Higher id
-             */
-            Assert.assertTrue(mock.predicate(1L, 1L, 0L, 0L, 1L, 0L));
-        } catch (IOException e) {
-            LOG.error("Exception while creating quorum peer", e);
-            Assert.fail("Exception while creating quorum peer");
-        }
-    }
-}
+/**
+ * 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.test;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.HashMap;
+
+import org.apache.zookeeper.server.quorum.FastLeaderElection;
+import org.apache.zookeeper.server.quorum.QuorumCnxManager;
+import org.apache.zookeeper.server.quorum.QuorumPeer;
+import org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer;
+import org.apache.zookeeper.PortAssignment;
+import org.apache.zookeeper.ZKTestCase;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class FLEPredicateTest extends ZKTestCase {
+    
+    protected static final Logger LOG = LoggerFactory.getLogger(FLEPredicateTest.class);
+    
+    class MockFLE extends FastLeaderElection {
+        MockFLE(QuorumPeer peer){
+            super(peer, new QuorumCnxManager(peer));
+        }
+        
+        boolean predicate(long newId, long newZxid, long newEpoch, long curId, long curZxid, long curEpoch){
+            return this.totalOrderPredicate(newId, newZxid, newEpoch, curId, curZxid, curEpoch);
+        }
+    }
+    
+    
+    HashMap<Long,QuorumServer> peers;
+    
+    @Test
+    public void testPredicate() throws IOException {
+        
+        peers = new HashMap<Long,QuorumServer>(3);
+        
+        /*
+         * Creates list of peers.
+         */
+        for(int i = 0; i < 3; i++) {
+            peers.put(Long.valueOf(i),
+                new QuorumServer(i,
+                    new InetSocketAddress(
+                        "127.0.0.1", PortAssignment.unique()),
+                    new InetSocketAddress(
+                        "127.0.0.1", PortAssignment.unique())));
+        }
+
+        /*
+         * Creating peer.
+         */
+        try{
+            File tmpDir = ClientBase.createTmpDir();
+            QuorumPeer peer = new QuorumPeer(peers, tmpDir, tmpDir,
+                                        PortAssignment.unique(), 3, 0, 1000, 2, 2);
+        
+            MockFLE mock = new MockFLE(peer);
+            
+            /*
+             * Lower epoch must return false
+             */
+            
+            Assert.assertFalse (mock.predicate(4L, 0L, 0L, 3L, 0L, 2L));
+            
+            /*
+             * Later epoch
+             */
+            Assert.assertTrue (mock.predicate(0L, 0L, 1L, 1L, 0L, 0L));
+        
+            /*
+             * Higher zxid
+             */
+            Assert.assertTrue(mock.predicate(0L, 1L, 0L, 1L, 0L, 0L));
+        
+            /*
+             * Higher id
+             */
+            Assert.assertTrue(mock.predicate(1L, 1L, 0L, 0L, 1L, 0L));
+        } catch (IOException e) {
+            LOG.error("Exception while creating quorum peer", e);
+            Assert.fail("Exception while creating quorum peer");
+        }
+    }
+}

+ 736 - 736
src/java/test/org/apache/zookeeper/test/ReconfigTest.java

@@ -1,736 +1,736 @@
-/**
- * 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.test;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.apache.zookeeper.CreateMode;
-import org.apache.zookeeper.KeeperException;
-import org.apache.zookeeper.PortAssignment;
-import org.apache.zookeeper.WatchedEvent;
-import org.apache.zookeeper.Watcher;
-import org.apache.zookeeper.ZKTestCase;
-import org.apache.zookeeper.ZooDefs;
-import org.apache.zookeeper.ZooKeeper;
-import org.apache.zookeeper.AsyncCallback.DataCallback;
-import org.apache.zookeeper.data.Stat;
-import org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer;
-import org.apache.zookeeper.server.quorum.QuorumPeer.ServerState;
-import org.apache.zookeeper.server.quorum.flexible.QuorumHierarchical;
-import org.apache.zookeeper.server.quorum.flexible.QuorumMaj;
-import org.apache.zookeeper.server.quorum.flexible.QuorumVerifier;
-import org.junit.Assert;
-import org.junit.After;
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ReconfigTest extends ZKTestCase implements DataCallback{
-    private static final Logger LOG = LoggerFactory
-            .getLogger(ReconfigTest.class);
-
-    private QuorumUtil qu;
-
-    @After
-    public void tearDown() throws Exception {
-        if (qu != null) {
-            qu.tearDown();
-        }
-    }
-
-    public static String reconfig(ZooKeeper zk, List<String> joiningServers,
-            List<String> leavingServers, List<String> newMembers, long fromConfig)
-            throws KeeperException, InterruptedException {
-        byte[] config = null;
-        for (int j = 0; j < 30; j++) {
-            try {
-                config = zk.reconfig(joiningServers, leavingServers,
-                        newMembers, fromConfig, new Stat());
-                break;
-            } catch (KeeperException.ConnectionLossException e) {
-                if (j < 29) {
-                    Thread.sleep(1000);
-                } else {
-                    // test fails if we still can't connect to the quorum after
-                    // 30 seconds.
-                    Assert.fail("client could not connect to reestablished quorum: giving up after 30+ seconds.");
-                }
-            }
-        }
-
-        String configStr = new String(config);
-        if (joiningServers != null) {
-            for (String joiner : joiningServers)
-                Assert.assertTrue(configStr.contains(joiner));
-        }
-        if (leavingServers != null) {
-            for (String leaving : leavingServers)
-                Assert.assertFalse(configStr.contains("server.".concat(leaving)));
-        }
-
-        return configStr;
-    }
-
-    public static String testServerHasConfig(ZooKeeper zk,
-            List<String> joiningServers, List<String> leavingServers)
-            throws KeeperException, InterruptedException {
-        byte[] config = null;
-        for (int j = 0; j < 30; j++) {
-            try {
-                zk.sync("/", null, null);
-                config = zk.getConfig(false, new Stat());
-                break;
-            } catch (KeeperException.ConnectionLossException e) {
-                if (j < 29) {
-                    Thread.sleep(1000);
-                } else {
-                    // test fails if we still can't connect to the quorum after
-                    // 30 seconds.
-                    Assert.fail("client could not connect to reestablished quorum: giving up after 30+ seconds.");
-                }
-            }
-
-        }
-        String configStr = new String(config);
-        if (joiningServers != null) {
-            for (String joiner : joiningServers) {
-               Assert.assertTrue(configStr.contains(joiner));
-            }
-        }
-        if (leavingServers != null) {
-            for (String leaving : leavingServers)
-                Assert.assertFalse(configStr.contains("server.".concat(leaving)));
-        }
-
-        return configStr;
-    }
-    
-    public static void testNormalOperation(ZooKeeper writer, ZooKeeper reader)
-            throws KeeperException, InterruptedException {
-        boolean testNodeExists = false;
-       
-       for (int j = 0; j < 30; j++) {
-            try {
-               if (!testNodeExists) {
-                   try{ 
-                       writer.create("/test", "test".getBytes(),
-                           ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
-                   } catch (KeeperException.NodeExistsException e) {                       
-                   }
-                   testNodeExists = true;
-               }
-                String data = "test" + j;
-                writer.setData("/test", data.getBytes(), -1);
-                reader.sync("/", null, null);
-                byte[] res = reader.getData("/test", null, new Stat());
-                Assert.assertEquals(data, new String(res));
-                break;
-            } catch (KeeperException.ConnectionLossException e) {
-                if (j < 29) {
-                    Thread.sleep(1000);
-                } else {
-                    // test fails if we still can't connect to the quorum after
-                    // 30 seconds.
-                    Assert.fail("client could not connect to reestablished quorum: giving up after 30+ seconds.");
-                }
-            }
-
-        }
-
-    }    
-    
-    private int getLeaderId(QuorumUtil qu) {
-        int leaderId = 1;
-        while (qu.getPeer(leaderId).peer.leader == null)
-            leaderId++;
-        return leaderId;
-    }
-
-    private ZooKeeper[] createHandles(QuorumUtil qu) throws IOException {
-        // create an extra handle, so we can index the handles from 1 to qu.ALL
-        // using the server id.
-        ZooKeeper[] zkArr = new ZooKeeper[qu.ALL + 1];
-        zkArr[0] = null; // not used.
-        for (int i = 1; i <= qu.ALL; i++) {
-            // server ids are 1, 2 and 3
-            zkArr[i] = new ZooKeeper("127.0.0.1:"
-                    + qu.getPeer(i).peer.getClientPort(),
-                    ClientBase.CONNECTION_TIMEOUT, new Watcher() {
-                        public void process(WatchedEvent event) {
-                        }});
-        }
-        return zkArr;
-    }
-
-    private void closeAllHandles(ZooKeeper[] zkArr) throws InterruptedException {
-        for (ZooKeeper zk : zkArr)
-            if (zk != null)
-                zk.close();
-    }
-
- 
-    @Test
-    public void testRemoveAddOne() throws Exception {
-        qu = new QuorumUtil(1); // create 3 servers
-        qu.disableJMXTest = true;
-        qu.startAll();
-        ZooKeeper[] zkArr = createHandles(qu);
-
-        List<String> leavingServers = new ArrayList<String>();
-        List<String> joiningServers = new ArrayList<String>();
-
-        int leaderIndex = getLeaderId(qu);
-
-        // during first iteration, leavingIndex will correspond to a follower
-        // during second iteration leavingIndex will be the index of the leader
-        int leavingIndex = (leaderIndex == 1) ? 2 : 1;
-
-        for (int i = 0; i < 2; i++) {
-            // some of the operations will be executed by a client connected to
-            // the removed server
-            // while others are invoked by a client connected to some other
-            // server.
-            // when we're removing the leader, zk1 will be the client connected
-            // to removed server
-            ZooKeeper zk1 = (leavingIndex == leaderIndex) ? zkArr[leaderIndex]
-                    : zkArr[(leaderIndex % qu.ALL) + 1];
-            ZooKeeper zk2 = (leavingIndex == leaderIndex) ? zkArr[(leaderIndex % qu.ALL) + 1]
-                    : zkArr[leaderIndex];
-
-            leavingServers.add(Integer.toString(leavingIndex));
-
-            // remember this server so we can add it back later
-            joiningServers.add("server."
-                    + leavingIndex
-                    + "=localhost:"
-                    + qu.getPeer(leavingIndex).peer.getQuorumAddress()
-                            .getPort()
-                    + ":"
-                    + qu.getPeer(leavingIndex).peer.getElectionAddress()
-                            .getPort() + ":participant;localhost:"
-                    + qu.getPeer(leavingIndex).peer.getClientPort());
-
-            String configStr = reconfig(zk1, null, leavingServers, null, -1);
-            testServerHasConfig(zk2, null, leavingServers);
-            testNormalOperation(zk2, zk1);
-
-            QuorumVerifier qv = qu.getPeer(1).peer.configFromString(configStr);
-            long version = qv.getVersion();
-
-            // checks that conditioning on version works properly
-            try {
-                reconfig(zk2, joiningServers, null, null, version + 1);
-                Assert.fail("reconfig succeeded even though version condition was incorrect!");
-            } catch (KeeperException.BadVersionException e) {
-
-            }
-
-            reconfig(zk2, joiningServers, null, null, version);
-
-            testNormalOperation(zk1, zk2);
-            testServerHasConfig(zk1, joiningServers, null);
-
-            // second iteration of the loop will remove the leader
-            // and add it back (as follower)
-            leavingIndex = leaderIndex = getLeaderId(qu);
-            leavingServers.clear();
-            joiningServers.clear();
-        }
-
-        closeAllHandles(zkArr);
-    }
-
-    /**
-     * 1. removes and adds back two servers (incl leader). One of the servers is added back as observer
-     * 2. tests that reconfig fails if quorum of new config is not up
-     * 3. tests that a server that's not up during reconfig learns the new config when it comes up
-     * @throws Exception
-     */
-    @Test
-    public void testRemoveAddTwo() throws Exception {
-        qu = new QuorumUtil(2); // create 5 servers
-        qu.disableJMXTest = true;
-        qu.startAll();
-        ZooKeeper[] zkArr = createHandles(qu);
-
-        List<String> leavingServers = new ArrayList<String>();
-        List<String> joiningServers = new ArrayList<String>();
-
-        int leaderIndex = getLeaderId(qu);
-
-        // lets remove the leader and some other server
-        int leavingIndex1 = leaderIndex;
-        int leavingIndex2 = (leaderIndex == 1) ? 2 : 1;
-
-        // find some server that's staying
-        int stayingIndex1 = 1, stayingIndex2 = 1, stayingIndex3 = 1;
-        while (stayingIndex1 == leavingIndex1 || stayingIndex1 == leavingIndex2)
-            stayingIndex1++;
-
-        while (stayingIndex2 == leavingIndex1 || stayingIndex2 == leavingIndex2
-                || stayingIndex2 == stayingIndex1)
-            stayingIndex2++;
-
-        while (stayingIndex3 == leavingIndex1 || stayingIndex3 == leavingIndex2
-                || stayingIndex3 == stayingIndex1
-                || stayingIndex3 == stayingIndex2)
-            stayingIndex3++;
-
-        leavingServers.add(Integer.toString(leavingIndex1));
-        leavingServers.add(Integer.toString(leavingIndex2));
-
-        // remember these servers so we can add them back later
-        joiningServers.add("server." + leavingIndex1 + "=localhost:"
-                + qu.getPeer(leavingIndex1).peer.getQuorumAddress().getPort()
-                + ":"
-                + qu.getPeer(leavingIndex1).peer.getElectionAddress().getPort()
-                + ":participant;localhost:"
-                + qu.getPeer(leavingIndex1).peer.getClientPort());
-
-        // this server will be added back as an observer
-        joiningServers.add("server." + leavingIndex2 + "=localhost:"
-                + qu.getPeer(leavingIndex2).peer.getQuorumAddress().getPort()
-                + ":"
-                + qu.getPeer(leavingIndex2).peer.getElectionAddress().getPort()
-                + ":observer;localhost:"
-                + qu.getPeer(leavingIndex2).peer.getClientPort());
-
-        qu.shutdown(leavingIndex1);
-        qu.shutdown(leavingIndex2);
-
-        // 3 servers still up so this should work
-        reconfig(zkArr[stayingIndex2], null, leavingServers, null, -1);
-        
-        qu.shutdown(stayingIndex2);
-
-        // the following commands would not work in the original
-        // cluster of 5, but now that we've removed 2 servers
-        // we have a cluster of 3 servers and one of them is allowed to fail
-
-        testServerHasConfig(zkArr[stayingIndex1], null, leavingServers);
-        testServerHasConfig(zkArr[stayingIndex3], null, leavingServers);
-        testNormalOperation(zkArr[stayingIndex1], zkArr[stayingIndex3]);
-        
-        // this is a test that a reconfig will only succeed
-        // if there is a quorum up in new config. Below there is no
-        // quorum so it should fail
-        
-        // the sleep is necessary so that the leader figures out
-        // that the switched off servers are down
-        Thread.sleep(10000);
-
-        try {
-            reconfig(zkArr[stayingIndex1], joiningServers, null, null, -1);
-            Assert.fail("reconfig completed successfully even though there is no quorum up in new config!");
-        } catch (KeeperException.NewConfigNoQuorum e) {
-
-        }
-        
-        // now start the third server so that new config has quorum
-        qu.restart(stayingIndex2);
-
-        reconfig(zkArr[stayingIndex1], joiningServers, null, null, -1);
-        testNormalOperation(zkArr[stayingIndex2], zkArr[stayingIndex3]);
-        testServerHasConfig(zkArr[stayingIndex2], joiningServers, null);
-
-        // this server wasn't around during the configuration change
-        // we should check that it is able to connect, finds out
-        // about the change and becomes an observer.
-
-        qu.restart(leavingIndex2);
-        Assert.assertTrue(qu.getPeer(leavingIndex2).peer.getPeerState() == ServerState.OBSERVING);
-        testNormalOperation(zkArr[stayingIndex2], zkArr[leavingIndex2]);
-        testServerHasConfig(zkArr[leavingIndex2], joiningServers, null);
-
-        closeAllHandles(zkArr);
-    }
-
-    @Test
-    public void testBulkReconfig() throws Exception {
-        qu = new QuorumUtil(3); // create 7 servers
-        qu.disableJMXTest = true;
-        qu.startAll();
-        ZooKeeper[] zkArr = createHandles(qu);
-
-        // new config will have three of the servers as followers
-        // two of the servers as observers, and all ports different
-        ArrayList<String> newServers = new ArrayList<String>();
-        for (int i = 1; i <= 5; i++) {
-            String server = "server." + i + "=localhost:" + PortAssignment.unique()
-                    + ":" + PortAssignment.unique() + ":"
-                    + ((i == 4 || i == 5) ? "observer" : "participant")
-                    + ";localhost:" + qu.getPeer(i).peer.getClientPort();
-            newServers.add(server);
-        }
-
-        qu.shutdown(3);
-        qu.shutdown(6);
-        qu.shutdown(7);
-        
-        reconfig(zkArr[1], null, null, newServers, -1);
-        testNormalOperation(zkArr[1], zkArr[2]);
-       
-        testServerHasConfig(zkArr[1], newServers, null);
-        testServerHasConfig(zkArr[2], newServers, null);
-        testServerHasConfig(zkArr[4], newServers, null);
-        testServerHasConfig(zkArr[5], newServers, null);
-    
-        qu.shutdown(5);
-        qu.shutdown(4);
-        
-        testNormalOperation(zkArr[1], zkArr[2]);
-
-        closeAllHandles(zkArr);
-    }
-
-    @Test
-    public void testRemoveOneAsynchronous() throws Exception {
-        qu = new QuorumUtil(2); 
-        qu.disableJMXTest = true;
-        qu.startAll();
-        ZooKeeper[] zkArr = createHandles(qu);
-
-        List<String> leavingServers = new ArrayList<String>();
-       
-        // lets remove someone who's not the leader
-        leavingServers.add(getLeaderId(qu) == 5 ? "4": "5");
- 
-        LinkedList<Integer> results = new LinkedList<Integer>();
-        
-        zkArr[1].reconfig(null, leavingServers, null, -1, this, results);   
-        
-        synchronized (results) {
-            while (results.size() < 1) {
-               results.wait();
-            }
-        }        
-        Assert.assertEquals(0, (int) results.get(0));
-        
-        testNormalOperation(zkArr[1], zkArr[2]);       
-        for (int i=1; i<=5; i++)
-            testServerHasConfig(zkArr[i], null, leavingServers);
-
-        closeAllHandles(zkArr);
-    }
-
-    @SuppressWarnings("unchecked")
-    public void processResult(int rc, String path, Object ctx, byte[] data,
-            Stat stat) {
-        synchronized(ctx) {
-            ((LinkedList<Integer>)ctx).add(rc);
-            ctx.notifyAll();
-        }
-    }
-    
-    
-    @Test
-    public void testRoleChange() throws Exception {
-        qu = new QuorumUtil(1); // create 3 servers
-        qu.disableJMXTest = true;
-        qu.startAll();
-        ZooKeeper[] zkArr = createHandles(qu);
-
-        // changing a server's role / port is done by "adding" it with the same
-        // id but different role / port
-        List<String> joiningServers = new ArrayList<String>();
-
-        int leaderIndex = getLeaderId(qu);
-
-        // during first and second iteration, leavingIndex will correspond to a
-        // follower
-        // during third and fouth iteration leavingIndex will be the index of
-        // the leader
-        int changingIndex = (leaderIndex == 1) ? 2 : 1;
-
-        // first convert participant to observer, then observer to participant,
-        // and so on
-        String newRole = "observer";
-
-        for (int i = 0; i < 4; i++) {
-            // some of the operations will be executed by a client connected to
-            // the removed server
-            // while others are invoked by a client connected to some other
-            // server.
-            // when we're removing the leader, zk1 will be the client connected
-            // to removed server
-            ZooKeeper zk1 = (changingIndex == leaderIndex) ? zkArr[leaderIndex]
-                    : zkArr[(leaderIndex % qu.ALL) + 1];
-
-            // exactly as it is now, except for role change
-            joiningServers.add("server."
-                    + changingIndex
-                    + "=localhost:"
-                    + qu.getPeer(changingIndex).peer.getQuorumAddress()
-                            .getPort()
-                    + ":"
-                    + qu.getPeer(changingIndex).peer.getElectionAddress()
-                            .getPort() + ":" + newRole + ";localhost:"
-                    + qu.getPeer(changingIndex).peer.getClientPort());
-
-            reconfig(zk1, joiningServers, null, null, -1);
-            testNormalOperation(zkArr[changingIndex], zk1);
-
-            if (newRole.equals("observer")) {
-                Assert.assertTrue(qu.getPeer(changingIndex).peer.observer != null
-                        && qu.getPeer(changingIndex).peer.follower == null
-                        && qu.getPeer(changingIndex).peer.leader == null);
-                Assert.assertTrue(qu.getPeer(changingIndex).peer.getPeerState() == ServerState.OBSERVING);
-            } else {
-                Assert.assertTrue(qu.getPeer(changingIndex).peer.observer == null
-                        && (qu.getPeer(changingIndex).peer.follower != null || qu
-                                .getPeer(changingIndex).peer.leader != null));
-                Assert.assertTrue(qu.getPeer(changingIndex).peer.getPeerState() == ServerState.FOLLOWING
-                        || qu.getPeer(changingIndex).peer.getPeerState() == ServerState.LEADING);
-            }
-
-            joiningServers.clear();
-
-            if (newRole.equals("observer")) {
-                newRole = "participant";
-            } else {
-                // lets change leader to observer
-                newRole = "observer";
-                leaderIndex = getLeaderId(qu);
-                changingIndex = leaderIndex;
-            }
-        }
-        closeAllHandles(zkArr);
-    }
-
-    @Test
-    public void testPortChange() throws Exception {
-        qu = new QuorumUtil(1); // create 3 servers
-        qu.disableJMXTest = true;
-        qu.startAll();
-        ZooKeeper[] zkArr = createHandles(qu);
-
-        List<String> joiningServers = new ArrayList<String>();
-
-        int leaderIndex = getLeaderId(qu);
-        int followerIndex = leaderIndex == 1 ? 2 : 1;
-
-        // change leader into observer, and modify all its ports at the same
-        // time
-        int observerIndex = leaderIndex;
-
-        // new ports
-        int port1 = PortAssignment.unique();
-        int port2 = PortAssignment.unique();
-        int port3 = PortAssignment.unique();
-        joiningServers.add("server." + observerIndex + "=localhost:" + port1
-                + ":" + port2 + ":observer;localhost:" + port3);
-
-        // create a /test znode and check that read/write works before
-        // any reconfig is invoked
-        testNormalOperation(zkArr[observerIndex], zkArr[followerIndex]);
-
-        reconfig(zkArr[followerIndex], joiningServers, null, null, -1);
-
-        // the change of port may not be immediate -- we repeatedly
-        // invoke an operation expecting it to eventually fail once
-        // the client port of observerIndex changes. If it didn't
-        // change -- that's an error.
-        try {
-          for (int i=0; i < 30; i++) {
-            Thread.sleep(1000);
-            zkArr[observerIndex].setData("/test", "teststr".getBytes(), -1);
-          }
-          Assert.fail("client port didn't change");
-        } catch (KeeperException.ConnectionLossException e) {
-            zkArr[observerIndex] = new ZooKeeper("127.0.0.1:"
-                    + qu.getPeer(observerIndex).peer.getClientPort(),
-                    ClientBase.CONNECTION_TIMEOUT, new Watcher() {
-                        public void process(WatchedEvent event) {}});
-        }
-
-        leaderIndex = getLeaderId(qu);
-
-        followerIndex = 1;
-        while (followerIndex == leaderIndex || followerIndex == observerIndex)
-            followerIndex++;
-
-        testNormalOperation(zkArr[observerIndex], zkArr[followerIndex]);
-
-        testServerHasConfig(zkArr[observerIndex], joiningServers, null);
-
-        Assert.assertTrue(qu.getPeer(observerIndex).peer.getQuorumAddress()
-                .getPort() == port1);
-        Assert.assertTrue(qu.getPeer(observerIndex).peer.getElectionAddress()
-                .getPort() == port2);
-        Assert.assertTrue(qu.getPeer(observerIndex).peer.getClientPort() == port3);
-        Assert.assertTrue(qu.getPeer(observerIndex).peer.getPeerState() == ServerState.OBSERVING);
-
-        joiningServers.clear();
-
-        // change leader's leading port - should renounce leadership
-
-        port1 = PortAssignment.unique();
-        joiningServers.add("server." + leaderIndex + "=localhost:" + port1
-                + ":"
-                + qu.getPeer(leaderIndex).peer.getElectionAddress().getPort()
-                + ":participant;localhost:"
-                + qu.getPeer(leaderIndex).peer.getClientPort());
-
-        reconfig(zkArr[followerIndex], joiningServers, null, null, -1);
-
-        testNormalOperation(zkArr[observerIndex], zkArr[followerIndex]);
-
-        Assert.assertTrue(qu.getPeer(leaderIndex).peer.getQuorumAddress()
-                .getPort() == port1);
-        Assert.assertTrue(qu.getPeer(leaderIndex).peer.leader == null
-                && qu.getPeer(leaderIndex).peer.follower != null);
-        Assert.assertTrue(qu.getPeer(followerIndex).peer.leader != null
-                && qu.getPeer(followerIndex).peer.follower == null);
-
-        joiningServers.clear();
-
-        // change in leader election port
-
-        for (int i = 1; i <= 3; i++) {
-            joiningServers.add("server." + i + "=localhost:"
-                    + qu.getPeer(i).peer.getQuorumAddress().getPort() + ":"
-                    + PortAssignment.unique() + ":participant;localhost:"
-                    + qu.getPeer(i).peer.getClientPort());
-        }
-
-        reconfig(zkArr[1], joiningServers, null, null, -1);
-
-        leaderIndex = getLeaderId(qu);
-        int follower1 = leaderIndex == 1 ? 2 : 1;
-        int follower2 = 1;
-        while (follower2 == leaderIndex || follower2 == follower1)
-            follower2++;
-
-        // lets kill the leader and see if a new one is elected
-
-        qu.shutdown(getLeaderId(qu));
-
-        testNormalOperation(zkArr[follower2], zkArr[follower1]);
-        testServerHasConfig(zkArr[follower1], joiningServers, null);
-        testServerHasConfig(zkArr[follower2], joiningServers, null);
-
-        closeAllHandles(zkArr);
-    }
-
-    @Test
-    public void testUnspecifiedClientAddress() throws Exception {
-    	int[] ports = new int[3];
-    	for (int port : ports) {
-    		port = PortAssignment.unique();
-    	}
-    	String server = "server.0=localhost:" + ports[0] + ":" + ports[1] + ";" + ports[2];
-    	QuorumServer qs = new QuorumServer(0, server);
-    	Assert.assertEquals(qs.clientAddr.getHostName(), "0.0.0.0");
-    	Assert.assertEquals(qs.clientAddr.getPort(), ports[2]);
-    }
-    
-    @Test
-    public void testQuorumSystemChange() throws Exception {
-        qu = new QuorumUtil(3); // create 7 servers
-        qu.disableJMXTest = true;
-        qu.startAll();
-        ZooKeeper[] zkArr = createHandles(qu);
-
-        ArrayList<String> members = new ArrayList<String>();
-        members.add("group.1=3:4:5");
-        members.add("group.2=1:2");
-        members.add("weight.1=0");
-        members.add("weight.2=0");
-        members.add("weight.3=1");
-        members.add("weight.4=1");
-        members.add("weight.5=1");
-
-        for (int i = 1; i <= 5; i++) {
-            members.add("server." + i + "=127.0.0.1:"
-                    + qu.getPeer(i).peer.getQuorumAddress().getPort() + ":"
-                    + qu.getPeer(i).peer.getElectionAddress().getPort() + ";"
-                    + "127.0.0.1:" + qu.getPeer(i).peer.getClientPort());
-        }
-
-        reconfig(zkArr[1], null, null, members, -1);
-
-        // this should flush the config to servers 2, 3, 4 and 5
-        testNormalOperation(zkArr[2], zkArr[3]);
-        testNormalOperation(zkArr[4], zkArr[5]);
-
-        for (int i = 1; i <= 5; i++) {
-            if (!(qu.getPeer(i).peer.quorumVerifier instanceof QuorumHierarchical))
-                Assert.fail("peer " + i
-                        + " doesn't think the quorum system is Hieararchical!");
-        }
-
-        qu.shutdown(1);
-        qu.shutdown(2);
-        qu.shutdown(3);
-        qu.shutdown(7);
-        qu.shutdown(6);
-
-        // servers 4 and 5 should be able to work independently
-        testNormalOperation(zkArr[4], zkArr[5]);
-
-        qu.restart(1);
-        qu.restart(2);
-
-        members.clear();
-        for (int i = 1; i <= 3; i++) {
-            members.add("server." + i + "=127.0.0.1:"
-                    + qu.getPeer(i).peer.getQuorumAddress().getPort() + ":"
-                    + qu.getPeer(i).peer.getElectionAddress().getPort() + ";"
-                    + "127.0.0.1:" + qu.getPeer(i).peer.getClientPort());
-        }
-
-        reconfig(zkArr[1], null, null, members, -1);
-
-        // flush the config to server 2
-        testNormalOperation(zkArr[1], zkArr[2]);
-
-        qu.shutdown(4);
-        qu.shutdown(5);
-
-        // servers 1 and 2 should be able to work independently
-        testNormalOperation(zkArr[1], zkArr[2]);
-
-        for (int i = 1; i <= 2; i++) {
-            if (!(qu.getPeer(i).peer.quorumVerifier instanceof QuorumMaj))
-                Assert.fail("peer "
-                        + i
-                        + " doesn't think the quorum system is a majority quorum system!");
-        }
-
-        closeAllHandles(zkArr);
-    }
-    
-    @Test
-    public void testInitialConfigHasPositiveVersion() throws Exception {
-        qu = new QuorumUtil(1); // create 3 servers
-        qu.disableJMXTest = true;
-        qu.startAll();
-        ZooKeeper[] zkArr = createHandles(qu);
-        testNormalOperation(zkArr[1], zkArr[2]);
-        for (int i=1; i<4; i++) {
-            String configStr = testServerHasConfig(zkArr[i], null, null);
-            QuorumVerifier qv = qu.getPeer(i).peer.configFromString(configStr);
-            long version = qv.getVersion();
-            Assert.assertTrue(version == 0x100000000L);
-        }
-    }
-}
+/**
+ * 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.test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.PortAssignment;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZKTestCase;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.AsyncCallback.DataCallback;
+import org.apache.zookeeper.data.Stat;
+import org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer;
+import org.apache.zookeeper.server.quorum.QuorumPeer.ServerState;
+import org.apache.zookeeper.server.quorum.flexible.QuorumHierarchical;
+import org.apache.zookeeper.server.quorum.flexible.QuorumMaj;
+import org.apache.zookeeper.server.quorum.flexible.QuorumVerifier;
+import org.junit.Assert;
+import org.junit.After;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ReconfigTest extends ZKTestCase implements DataCallback{
+    private static final Logger LOG = LoggerFactory
+            .getLogger(ReconfigTest.class);
+
+    private QuorumUtil qu;
+
+    @After
+    public void tearDown() throws Exception {
+        if (qu != null) {
+            qu.tearDown();
+        }
+    }
+
+    public static String reconfig(ZooKeeper zk, List<String> joiningServers,
+            List<String> leavingServers, List<String> newMembers, long fromConfig)
+            throws KeeperException, InterruptedException {
+        byte[] config = null;
+        for (int j = 0; j < 30; j++) {
+            try {
+                config = zk.reconfig(joiningServers, leavingServers,
+                        newMembers, fromConfig, new Stat());
+                break;
+            } catch (KeeperException.ConnectionLossException e) {
+                if (j < 29) {
+                    Thread.sleep(1000);
+                } else {
+                    // test fails if we still can't connect to the quorum after
+                    // 30 seconds.
+                    Assert.fail("client could not connect to reestablished quorum: giving up after 30+ seconds.");
+                }
+            }
+        }
+
+        String configStr = new String(config);
+        if (joiningServers != null) {
+            for (String joiner : joiningServers)
+                Assert.assertTrue(configStr.contains(joiner));
+        }
+        if (leavingServers != null) {
+            for (String leaving : leavingServers)
+                Assert.assertFalse(configStr.contains("server.".concat(leaving)));
+        }
+
+        return configStr;
+    }
+
+    public static String testServerHasConfig(ZooKeeper zk,
+            List<String> joiningServers, List<String> leavingServers)
+            throws KeeperException, InterruptedException {
+        byte[] config = null;
+        for (int j = 0; j < 30; j++) {
+            try {
+                zk.sync("/", null, null);
+                config = zk.getConfig(false, new Stat());
+                break;
+            } catch (KeeperException.ConnectionLossException e) {
+                if (j < 29) {
+                    Thread.sleep(1000);
+                } else {
+                    // test fails if we still can't connect to the quorum after
+                    // 30 seconds.
+                    Assert.fail("client could not connect to reestablished quorum: giving up after 30+ seconds.");
+                }
+            }
+
+        }
+        String configStr = new String(config);
+        if (joiningServers != null) {
+            for (String joiner : joiningServers) {
+               Assert.assertTrue(configStr.contains(joiner));
+            }
+        }
+        if (leavingServers != null) {
+            for (String leaving : leavingServers)
+                Assert.assertFalse(configStr.contains("server.".concat(leaving)));
+        }
+
+        return configStr;
+    }
+    
+    public static void testNormalOperation(ZooKeeper writer, ZooKeeper reader)
+            throws KeeperException, InterruptedException {
+        boolean testNodeExists = false;
+       
+       for (int j = 0; j < 30; j++) {
+            try {
+               if (!testNodeExists) {
+                   try{ 
+                       writer.create("/test", "test".getBytes(),
+                           ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
+                   } catch (KeeperException.NodeExistsException e) {                       
+                   }
+                   testNodeExists = true;
+               }
+                String data = "test" + j;
+                writer.setData("/test", data.getBytes(), -1);
+                reader.sync("/", null, null);
+                byte[] res = reader.getData("/test", null, new Stat());
+                Assert.assertEquals(data, new String(res));
+                break;
+            } catch (KeeperException.ConnectionLossException e) {
+                if (j < 29) {
+                    Thread.sleep(1000);
+                } else {
+                    // test fails if we still can't connect to the quorum after
+                    // 30 seconds.
+                    Assert.fail("client could not connect to reestablished quorum: giving up after 30+ seconds.");
+                }
+            }
+
+        }
+
+    }    
+    
+    private int getLeaderId(QuorumUtil qu) {
+        int leaderId = 1;
+        while (qu.getPeer(leaderId).peer.leader == null)
+            leaderId++;
+        return leaderId;
+    }
+
+    private ZooKeeper[] createHandles(QuorumUtil qu) throws IOException {
+        // create an extra handle, so we can index the handles from 1 to qu.ALL
+        // using the server id.
+        ZooKeeper[] zkArr = new ZooKeeper[qu.ALL + 1];
+        zkArr[0] = null; // not used.
+        for (int i = 1; i <= qu.ALL; i++) {
+            // server ids are 1, 2 and 3
+            zkArr[i] = new ZooKeeper("127.0.0.1:"
+                    + qu.getPeer(i).peer.getClientPort(),
+                    ClientBase.CONNECTION_TIMEOUT, new Watcher() {
+                        public void process(WatchedEvent event) {
+                        }});
+        }
+        return zkArr;
+    }
+
+    private void closeAllHandles(ZooKeeper[] zkArr) throws InterruptedException {
+        for (ZooKeeper zk : zkArr)
+            if (zk != null)
+                zk.close();
+    }
+
+ 
+    @Test
+    public void testRemoveAddOne() throws Exception {
+        qu = new QuorumUtil(1); // create 3 servers
+        qu.disableJMXTest = true;
+        qu.startAll();
+        ZooKeeper[] zkArr = createHandles(qu);
+
+        List<String> leavingServers = new ArrayList<String>();
+        List<String> joiningServers = new ArrayList<String>();
+
+        int leaderIndex = getLeaderId(qu);
+
+        // during first iteration, leavingIndex will correspond to a follower
+        // during second iteration leavingIndex will be the index of the leader
+        int leavingIndex = (leaderIndex == 1) ? 2 : 1;
+
+        for (int i = 0; i < 2; i++) {
+            // some of the operations will be executed by a client connected to
+            // the removed server
+            // while others are invoked by a client connected to some other
+            // server.
+            // when we're removing the leader, zk1 will be the client connected
+            // to removed server
+            ZooKeeper zk1 = (leavingIndex == leaderIndex) ? zkArr[leaderIndex]
+                    : zkArr[(leaderIndex % qu.ALL) + 1];
+            ZooKeeper zk2 = (leavingIndex == leaderIndex) ? zkArr[(leaderIndex % qu.ALL) + 1]
+                    : zkArr[leaderIndex];
+
+            leavingServers.add(Integer.toString(leavingIndex));
+
+            // remember this server so we can add it back later
+            joiningServers.add("server."
+                    + leavingIndex
+                    + "=localhost:"
+                    + qu.getPeer(leavingIndex).peer.getQuorumAddress()
+                            .getPort()
+                    + ":"
+                    + qu.getPeer(leavingIndex).peer.getElectionAddress()
+                            .getPort() + ":participant;localhost:"
+                    + qu.getPeer(leavingIndex).peer.getClientPort());
+
+            String configStr = reconfig(zk1, null, leavingServers, null, -1);
+            testServerHasConfig(zk2, null, leavingServers);
+            testNormalOperation(zk2, zk1);
+
+            QuorumVerifier qv = qu.getPeer(1).peer.configFromString(configStr);
+            long version = qv.getVersion();
+
+            // checks that conditioning on version works properly
+            try {
+                reconfig(zk2, joiningServers, null, null, version + 1);
+                Assert.fail("reconfig succeeded even though version condition was incorrect!");
+            } catch (KeeperException.BadVersionException e) {
+
+            }
+
+            reconfig(zk2, joiningServers, null, null, version);
+
+            testNormalOperation(zk1, zk2);
+            testServerHasConfig(zk1, joiningServers, null);
+
+            // second iteration of the loop will remove the leader
+            // and add it back (as follower)
+            leavingIndex = leaderIndex = getLeaderId(qu);
+            leavingServers.clear();
+            joiningServers.clear();
+        }
+
+        closeAllHandles(zkArr);
+    }
+
+    /**
+     * 1. removes and adds back two servers (incl leader). One of the servers is added back as observer
+     * 2. tests that reconfig fails if quorum of new config is not up
+     * 3. tests that a server that's not up during reconfig learns the new config when it comes up
+     * @throws Exception
+     */
+    @Test
+    public void testRemoveAddTwo() throws Exception {
+        qu = new QuorumUtil(2); // create 5 servers
+        qu.disableJMXTest = true;
+        qu.startAll();
+        ZooKeeper[] zkArr = createHandles(qu);
+
+        List<String> leavingServers = new ArrayList<String>();
+        List<String> joiningServers = new ArrayList<String>();
+
+        int leaderIndex = getLeaderId(qu);
+
+        // lets remove the leader and some other server
+        int leavingIndex1 = leaderIndex;
+        int leavingIndex2 = (leaderIndex == 1) ? 2 : 1;
+
+        // find some server that's staying
+        int stayingIndex1 = 1, stayingIndex2 = 1, stayingIndex3 = 1;
+        while (stayingIndex1 == leavingIndex1 || stayingIndex1 == leavingIndex2)
+            stayingIndex1++;
+
+        while (stayingIndex2 == leavingIndex1 || stayingIndex2 == leavingIndex2
+                || stayingIndex2 == stayingIndex1)
+            stayingIndex2++;
+
+        while (stayingIndex3 == leavingIndex1 || stayingIndex3 == leavingIndex2
+                || stayingIndex3 == stayingIndex1
+                || stayingIndex3 == stayingIndex2)
+            stayingIndex3++;
+
+        leavingServers.add(Integer.toString(leavingIndex1));
+        leavingServers.add(Integer.toString(leavingIndex2));
+
+        // remember these servers so we can add them back later
+        joiningServers.add("server." + leavingIndex1 + "=localhost:"
+                + qu.getPeer(leavingIndex1).peer.getQuorumAddress().getPort()
+                + ":"
+                + qu.getPeer(leavingIndex1).peer.getElectionAddress().getPort()
+                + ":participant;localhost:"
+                + qu.getPeer(leavingIndex1).peer.getClientPort());
+
+        // this server will be added back as an observer
+        joiningServers.add("server." + leavingIndex2 + "=localhost:"
+                + qu.getPeer(leavingIndex2).peer.getQuorumAddress().getPort()
+                + ":"
+                + qu.getPeer(leavingIndex2).peer.getElectionAddress().getPort()
+                + ":observer;localhost:"
+                + qu.getPeer(leavingIndex2).peer.getClientPort());
+
+        qu.shutdown(leavingIndex1);
+        qu.shutdown(leavingIndex2);
+
+        // 3 servers still up so this should work
+        reconfig(zkArr[stayingIndex2], null, leavingServers, null, -1);
+        
+        qu.shutdown(stayingIndex2);
+
+        // the following commands would not work in the original
+        // cluster of 5, but now that we've removed 2 servers
+        // we have a cluster of 3 servers and one of them is allowed to fail
+
+        testServerHasConfig(zkArr[stayingIndex1], null, leavingServers);
+        testServerHasConfig(zkArr[stayingIndex3], null, leavingServers);
+        testNormalOperation(zkArr[stayingIndex1], zkArr[stayingIndex3]);
+        
+        // this is a test that a reconfig will only succeed
+        // if there is a quorum up in new config. Below there is no
+        // quorum so it should fail
+        
+        // the sleep is necessary so that the leader figures out
+        // that the switched off servers are down
+        Thread.sleep(10000);
+
+        try {
+            reconfig(zkArr[stayingIndex1], joiningServers, null, null, -1);
+            Assert.fail("reconfig completed successfully even though there is no quorum up in new config!");
+        } catch (KeeperException.NewConfigNoQuorum e) {
+
+        }
+        
+        // now start the third server so that new config has quorum
+        qu.restart(stayingIndex2);
+
+        reconfig(zkArr[stayingIndex1], joiningServers, null, null, -1);
+        testNormalOperation(zkArr[stayingIndex2], zkArr[stayingIndex3]);
+        testServerHasConfig(zkArr[stayingIndex2], joiningServers, null);
+
+        // this server wasn't around during the configuration change
+        // we should check that it is able to connect, finds out
+        // about the change and becomes an observer.
+
+        qu.restart(leavingIndex2);
+        Assert.assertTrue(qu.getPeer(leavingIndex2).peer.getPeerState() == ServerState.OBSERVING);
+        testNormalOperation(zkArr[stayingIndex2], zkArr[leavingIndex2]);
+        testServerHasConfig(zkArr[leavingIndex2], joiningServers, null);
+
+        closeAllHandles(zkArr);
+    }
+
+    @Test
+    public void testBulkReconfig() throws Exception {
+        qu = new QuorumUtil(3); // create 7 servers
+        qu.disableJMXTest = true;
+        qu.startAll();
+        ZooKeeper[] zkArr = createHandles(qu);
+
+        // new config will have three of the servers as followers
+        // two of the servers as observers, and all ports different
+        ArrayList<String> newServers = new ArrayList<String>();
+        for (int i = 1; i <= 5; i++) {
+            String server = "server." + i + "=localhost:" + PortAssignment.unique()
+                    + ":" + PortAssignment.unique() + ":"
+                    + ((i == 4 || i == 5) ? "observer" : "participant")
+                    + ";localhost:" + qu.getPeer(i).peer.getClientPort();
+            newServers.add(server);
+        }
+
+        qu.shutdown(3);
+        qu.shutdown(6);
+        qu.shutdown(7);
+        
+        reconfig(zkArr[1], null, null, newServers, -1);
+        testNormalOperation(zkArr[1], zkArr[2]);
+       
+        testServerHasConfig(zkArr[1], newServers, null);
+        testServerHasConfig(zkArr[2], newServers, null);
+        testServerHasConfig(zkArr[4], newServers, null);
+        testServerHasConfig(zkArr[5], newServers, null);
+    
+        qu.shutdown(5);
+        qu.shutdown(4);
+        
+        testNormalOperation(zkArr[1], zkArr[2]);
+
+        closeAllHandles(zkArr);
+    }
+
+    @Test
+    public void testRemoveOneAsynchronous() throws Exception {
+        qu = new QuorumUtil(2); 
+        qu.disableJMXTest = true;
+        qu.startAll();
+        ZooKeeper[] zkArr = createHandles(qu);
+
+        List<String> leavingServers = new ArrayList<String>();
+       
+        // lets remove someone who's not the leader
+        leavingServers.add(getLeaderId(qu) == 5 ? "4": "5");
+ 
+        LinkedList<Integer> results = new LinkedList<Integer>();
+        
+        zkArr[1].reconfig(null, leavingServers, null, -1, this, results);   
+        
+        synchronized (results) {
+            while (results.size() < 1) {
+               results.wait();
+            }
+        }        
+        Assert.assertEquals(0, (int) results.get(0));
+        
+        testNormalOperation(zkArr[1], zkArr[2]);       
+        for (int i=1; i<=5; i++)
+            testServerHasConfig(zkArr[i], null, leavingServers);
+
+        closeAllHandles(zkArr);
+    }
+
+    @SuppressWarnings("unchecked")
+    public void processResult(int rc, String path, Object ctx, byte[] data,
+            Stat stat) {
+        synchronized(ctx) {
+            ((LinkedList<Integer>)ctx).add(rc);
+            ctx.notifyAll();
+        }
+    }
+    
+    
+    @Test
+    public void testRoleChange() throws Exception {
+        qu = new QuorumUtil(1); // create 3 servers
+        qu.disableJMXTest = true;
+        qu.startAll();
+        ZooKeeper[] zkArr = createHandles(qu);
+
+        // changing a server's role / port is done by "adding" it with the same
+        // id but different role / port
+        List<String> joiningServers = new ArrayList<String>();
+
+        int leaderIndex = getLeaderId(qu);
+
+        // during first and second iteration, leavingIndex will correspond to a
+        // follower
+        // during third and fouth iteration leavingIndex will be the index of
+        // the leader
+        int changingIndex = (leaderIndex == 1) ? 2 : 1;
+
+        // first convert participant to observer, then observer to participant,
+        // and so on
+        String newRole = "observer";
+
+        for (int i = 0; i < 4; i++) {
+            // some of the operations will be executed by a client connected to
+            // the removed server
+            // while others are invoked by a client connected to some other
+            // server.
+            // when we're removing the leader, zk1 will be the client connected
+            // to removed server
+            ZooKeeper zk1 = (changingIndex == leaderIndex) ? zkArr[leaderIndex]
+                    : zkArr[(leaderIndex % qu.ALL) + 1];
+
+            // exactly as it is now, except for role change
+            joiningServers.add("server."
+                    + changingIndex
+                    + "=localhost:"
+                    + qu.getPeer(changingIndex).peer.getQuorumAddress()
+                            .getPort()
+                    + ":"
+                    + qu.getPeer(changingIndex).peer.getElectionAddress()
+                            .getPort() + ":" + newRole + ";localhost:"
+                    + qu.getPeer(changingIndex).peer.getClientPort());
+
+            reconfig(zk1, joiningServers, null, null, -1);
+            testNormalOperation(zkArr[changingIndex], zk1);
+
+            if (newRole.equals("observer")) {
+                Assert.assertTrue(qu.getPeer(changingIndex).peer.observer != null
+                        && qu.getPeer(changingIndex).peer.follower == null
+                        && qu.getPeer(changingIndex).peer.leader == null);
+                Assert.assertTrue(qu.getPeer(changingIndex).peer.getPeerState() == ServerState.OBSERVING);
+            } else {
+                Assert.assertTrue(qu.getPeer(changingIndex).peer.observer == null
+                        && (qu.getPeer(changingIndex).peer.follower != null || qu
+                                .getPeer(changingIndex).peer.leader != null));
+                Assert.assertTrue(qu.getPeer(changingIndex).peer.getPeerState() == ServerState.FOLLOWING
+                        || qu.getPeer(changingIndex).peer.getPeerState() == ServerState.LEADING);
+            }
+
+            joiningServers.clear();
+
+            if (newRole.equals("observer")) {
+                newRole = "participant";
+            } else {
+                // lets change leader to observer
+                newRole = "observer";
+                leaderIndex = getLeaderId(qu);
+                changingIndex = leaderIndex;
+            }
+        }
+        closeAllHandles(zkArr);
+    }
+
+    @Test
+    public void testPortChange() throws Exception {
+        qu = new QuorumUtil(1); // create 3 servers
+        qu.disableJMXTest = true;
+        qu.startAll();
+        ZooKeeper[] zkArr = createHandles(qu);
+
+        List<String> joiningServers = new ArrayList<String>();
+
+        int leaderIndex = getLeaderId(qu);
+        int followerIndex = leaderIndex == 1 ? 2 : 1;
+
+        // change leader into observer, and modify all its ports at the same
+        // time
+        int observerIndex = leaderIndex;
+
+        // new ports
+        int port1 = PortAssignment.unique();
+        int port2 = PortAssignment.unique();
+        int port3 = PortAssignment.unique();
+        joiningServers.add("server." + observerIndex + "=localhost:" + port1
+                + ":" + port2 + ":observer;localhost:" + port3);
+
+        // create a /test znode and check that read/write works before
+        // any reconfig is invoked
+        testNormalOperation(zkArr[observerIndex], zkArr[followerIndex]);
+
+        reconfig(zkArr[followerIndex], joiningServers, null, null, -1);
+
+        // the change of port may not be immediate -- we repeatedly
+        // invoke an operation expecting it to eventually fail once
+        // the client port of observerIndex changes. If it didn't
+        // change -- that's an error.
+        try {
+          for (int i=0; i < 30; i++) {
+            Thread.sleep(1000);
+            zkArr[observerIndex].setData("/test", "teststr".getBytes(), -1);
+          }
+          Assert.fail("client port didn't change");
+        } catch (KeeperException.ConnectionLossException e) {
+            zkArr[observerIndex] = new ZooKeeper("127.0.0.1:"
+                    + qu.getPeer(observerIndex).peer.getClientPort(),
+                    ClientBase.CONNECTION_TIMEOUT, new Watcher() {
+                        public void process(WatchedEvent event) {}});
+        }
+
+        leaderIndex = getLeaderId(qu);
+
+        followerIndex = 1;
+        while (followerIndex == leaderIndex || followerIndex == observerIndex)
+            followerIndex++;
+
+        testNormalOperation(zkArr[observerIndex], zkArr[followerIndex]);
+
+        testServerHasConfig(zkArr[observerIndex], joiningServers, null);
+
+        Assert.assertTrue(qu.getPeer(observerIndex).peer.getQuorumAddress()
+                .getPort() == port1);
+        Assert.assertTrue(qu.getPeer(observerIndex).peer.getElectionAddress()
+                .getPort() == port2);
+        Assert.assertTrue(qu.getPeer(observerIndex).peer.getClientPort() == port3);
+        Assert.assertTrue(qu.getPeer(observerIndex).peer.getPeerState() == ServerState.OBSERVING);
+
+        joiningServers.clear();
+
+        // change leader's leading port - should renounce leadership
+
+        port1 = PortAssignment.unique();
+        joiningServers.add("server." + leaderIndex + "=localhost:" + port1
+                + ":"
+                + qu.getPeer(leaderIndex).peer.getElectionAddress().getPort()
+                + ":participant;localhost:"
+                + qu.getPeer(leaderIndex).peer.getClientPort());
+
+        reconfig(zkArr[followerIndex], joiningServers, null, null, -1);
+
+        testNormalOperation(zkArr[observerIndex], zkArr[followerIndex]);
+
+        Assert.assertTrue(qu.getPeer(leaderIndex).peer.getQuorumAddress()
+                .getPort() == port1);
+        Assert.assertTrue(qu.getPeer(leaderIndex).peer.leader == null
+                && qu.getPeer(leaderIndex).peer.follower != null);
+        Assert.assertTrue(qu.getPeer(followerIndex).peer.leader != null
+                && qu.getPeer(followerIndex).peer.follower == null);
+
+        joiningServers.clear();
+
+        // change in leader election port
+
+        for (int i = 1; i <= 3; i++) {
+            joiningServers.add("server." + i + "=localhost:"
+                    + qu.getPeer(i).peer.getQuorumAddress().getPort() + ":"
+                    + PortAssignment.unique() + ":participant;localhost:"
+                    + qu.getPeer(i).peer.getClientPort());
+        }
+
+        reconfig(zkArr[1], joiningServers, null, null, -1);
+
+        leaderIndex = getLeaderId(qu);
+        int follower1 = leaderIndex == 1 ? 2 : 1;
+        int follower2 = 1;
+        while (follower2 == leaderIndex || follower2 == follower1)
+            follower2++;
+
+        // lets kill the leader and see if a new one is elected
+
+        qu.shutdown(getLeaderId(qu));
+
+        testNormalOperation(zkArr[follower2], zkArr[follower1]);
+        testServerHasConfig(zkArr[follower1], joiningServers, null);
+        testServerHasConfig(zkArr[follower2], joiningServers, null);
+
+        closeAllHandles(zkArr);
+    }
+
+    @Test
+    public void testUnspecifiedClientAddress() throws Exception {
+    	int[] ports = new int[3];
+    	for (int port : ports) {
+    		port = PortAssignment.unique();
+    	}
+    	String server = "server.0=localhost:" + ports[0] + ":" + ports[1] + ";" + ports[2];
+    	QuorumServer qs = new QuorumServer(0, server);
+    	Assert.assertEquals(qs.clientAddr.getHostName(), "0.0.0.0");
+    	Assert.assertEquals(qs.clientAddr.getPort(), ports[2]);
+    }
+    
+    @Test
+    public void testQuorumSystemChange() throws Exception {
+        qu = new QuorumUtil(3); // create 7 servers
+        qu.disableJMXTest = true;
+        qu.startAll();
+        ZooKeeper[] zkArr = createHandles(qu);
+
+        ArrayList<String> members = new ArrayList<String>();
+        members.add("group.1=3:4:5");
+        members.add("group.2=1:2");
+        members.add("weight.1=0");
+        members.add("weight.2=0");
+        members.add("weight.3=1");
+        members.add("weight.4=1");
+        members.add("weight.5=1");
+
+        for (int i = 1; i <= 5; i++) {
+            members.add("server." + i + "=127.0.0.1:"
+                    + qu.getPeer(i).peer.getQuorumAddress().getPort() + ":"
+                    + qu.getPeer(i).peer.getElectionAddress().getPort() + ";"
+                    + "127.0.0.1:" + qu.getPeer(i).peer.getClientPort());
+        }
+
+        reconfig(zkArr[1], null, null, members, -1);
+
+        // this should flush the config to servers 2, 3, 4 and 5
+        testNormalOperation(zkArr[2], zkArr[3]);
+        testNormalOperation(zkArr[4], zkArr[5]);
+
+        for (int i = 1; i <= 5; i++) {
+            if (!(qu.getPeer(i).peer.quorumVerifier instanceof QuorumHierarchical))
+                Assert.fail("peer " + i
+                        + " doesn't think the quorum system is Hieararchical!");
+        }
+
+        qu.shutdown(1);
+        qu.shutdown(2);
+        qu.shutdown(3);
+        qu.shutdown(7);
+        qu.shutdown(6);
+
+        // servers 4 and 5 should be able to work independently
+        testNormalOperation(zkArr[4], zkArr[5]);
+
+        qu.restart(1);
+        qu.restart(2);
+
+        members.clear();
+        for (int i = 1; i <= 3; i++) {
+            members.add("server." + i + "=127.0.0.1:"
+                    + qu.getPeer(i).peer.getQuorumAddress().getPort() + ":"
+                    + qu.getPeer(i).peer.getElectionAddress().getPort() + ";"
+                    + "127.0.0.1:" + qu.getPeer(i).peer.getClientPort());
+        }
+
+        reconfig(zkArr[1], null, null, members, -1);
+
+        // flush the config to server 2
+        testNormalOperation(zkArr[1], zkArr[2]);
+
+        qu.shutdown(4);
+        qu.shutdown(5);
+
+        // servers 1 and 2 should be able to work independently
+        testNormalOperation(zkArr[1], zkArr[2]);
+
+        for (int i = 1; i <= 2; i++) {
+            if (!(qu.getPeer(i).peer.quorumVerifier instanceof QuorumMaj))
+                Assert.fail("peer "
+                        + i
+                        + " doesn't think the quorum system is a majority quorum system!");
+        }
+
+        closeAllHandles(zkArr);
+    }
+    
+    @Test
+    public void testInitialConfigHasPositiveVersion() throws Exception {
+        qu = new QuorumUtil(1); // create 3 servers
+        qu.disableJMXTest = true;
+        qu.startAll();
+        ZooKeeper[] zkArr = createHandles(qu);
+        testNormalOperation(zkArr[1], zkArr[2]);
+        for (int i=1; i<4; i++) {
+            String configStr = testServerHasConfig(zkArr[i], null, null);
+            QuorumVerifier qv = qu.getPeer(i).peer.configFromString(configStr);
+            long version = qv.getVersion();
+            Assert.assertTrue(version == 0x100000000L);
+        }
+    }
+}

+ 105 - 105
src/java/test/org/apache/zookeeper/test/SessionInvalidationTest.java

@@ -1,105 +1,105 @@
-/**
- * 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.test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.Socket;
-
-import junit.framework.Assert;
-
-import org.apache.jute.BinaryOutputArchive;
-import org.apache.zookeeper.ZooDefs;
-import org.apache.zookeeper.ZooDefs.Ids;
-import org.apache.zookeeper.ZooDefs.OpCode;
-import org.apache.zookeeper.ZooKeeper;
-import org.apache.zookeeper.proto.ConnectRequest;
-import org.apache.zookeeper.proto.CreateRequest;
-import org.apache.zookeeper.proto.RequestHeader;
-import org.junit.Test;
-
-public class SessionInvalidationTest extends ClientBase {
-    /**
-     * Test solution for ZOOKEEPER-1208. Verify that operations are not
-     * accepted after a close session.
-     * 
-     * We're using our own marshalling here in order to force an operation
-     * after the session is closed (ZooKeeper.class will not allow this). Also
-     * by filling the pipe with operations it increases the likelyhood that
-     * the server will process the create before FinalRequestProcessor
-     * removes the session from the tracker.
-     */
-    @Test
-    public void testCreateAfterCloseShouldFail() throws Exception {
-        for (int i = 0; i < 10; i++) {
-            ByteArrayOutputStream baos = new ByteArrayOutputStream();
-            BinaryOutputArchive boa = BinaryOutputArchive.getArchive(baos);
-
-            // open a connection
-            boa.writeInt(44, "len");
-            ConnectRequest conReq = new ConnectRequest(0, 0, 30000, 0, new byte[16]);
-            conReq.serialize(boa, "connect");
-
-            // close connection
-            boa.writeInt(8, "len");
-            RequestHeader h = new RequestHeader(1, ZooDefs.OpCode.closeSession);
-            h.serialize(boa, "header");
-
-            // create ephemeral znode
-            boa.writeInt(52, "len"); // We'll fill this in later
-            RequestHeader header = new RequestHeader(2, OpCode.create);
-            header.serialize(boa, "header");
-            CreateRequest createReq = new CreateRequest("/foo" + i, new byte[0],
-                    Ids.OPEN_ACL_UNSAFE, 1);
-            createReq.serialize(boa, "request");
-            baos.close();
-            
-            System.out.println("Length:" + baos.toByteArray().length);
-            
-            String hp[] = hostPort.split(":");
-            Socket sock = new Socket(hp[0], Integer.parseInt(hp[1]));
-            InputStream resultStream = null;
-            try {
-                OutputStream outstream = sock.getOutputStream();
-                byte[] data = baos.toByteArray();
-                outstream.write(data);
-                outstream.flush();
-                
-                resultStream = sock.getInputStream();
-                byte[] b = new byte[10000];
-                int len;
-                while ((len = resultStream.read(b)) >= 0) {
-                    // got results
-                    System.out.println("gotlen:" + len);
-                }
-            } finally {
-                if (resultStream != null) {
-                    resultStream.close();
-                }
-                sock.close();
-            }
-        }
-        
-        ZooKeeper zk = createClient();
-        Assert.assertEquals(1, zk.getChildren("/", false).size());
-
-        zk.close();
-    }
-}
+/**
+ * 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.test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+
+import junit.framework.Assert;
+
+import org.apache.jute.BinaryOutputArchive;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.ZooDefs.Ids;
+import org.apache.zookeeper.ZooDefs.OpCode;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.proto.ConnectRequest;
+import org.apache.zookeeper.proto.CreateRequest;
+import org.apache.zookeeper.proto.RequestHeader;
+import org.junit.Test;
+
+public class SessionInvalidationTest extends ClientBase {
+    /**
+     * Test solution for ZOOKEEPER-1208. Verify that operations are not
+     * accepted after a close session.
+     * 
+     * We're using our own marshalling here in order to force an operation
+     * after the session is closed (ZooKeeper.class will not allow this). Also
+     * by filling the pipe with operations it increases the likelyhood that
+     * the server will process the create before FinalRequestProcessor
+     * removes the session from the tracker.
+     */
+    @Test
+    public void testCreateAfterCloseShouldFail() throws Exception {
+        for (int i = 0; i < 10; i++) {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            BinaryOutputArchive boa = BinaryOutputArchive.getArchive(baos);
+
+            // open a connection
+            boa.writeInt(44, "len");
+            ConnectRequest conReq = new ConnectRequest(0, 0, 30000, 0, new byte[16]);
+            conReq.serialize(boa, "connect");
+
+            // close connection
+            boa.writeInt(8, "len");
+            RequestHeader h = new RequestHeader(1, ZooDefs.OpCode.closeSession);
+            h.serialize(boa, "header");
+
+            // create ephemeral znode
+            boa.writeInt(52, "len"); // We'll fill this in later
+            RequestHeader header = new RequestHeader(2, OpCode.create);
+            header.serialize(boa, "header");
+            CreateRequest createReq = new CreateRequest("/foo" + i, new byte[0],
+                    Ids.OPEN_ACL_UNSAFE, 1);
+            createReq.serialize(boa, "request");
+            baos.close();
+            
+            System.out.println("Length:" + baos.toByteArray().length);
+            
+            String hp[] = hostPort.split(":");
+            Socket sock = new Socket(hp[0], Integer.parseInt(hp[1]));
+            InputStream resultStream = null;
+            try {
+                OutputStream outstream = sock.getOutputStream();
+                byte[] data = baos.toByteArray();
+                outstream.write(data);
+                outstream.flush();
+                
+                resultStream = sock.getInputStream();
+                byte[] b = new byte[10000];
+                int len;
+                while ((len = resultStream.read(b)) >= 0) {
+                    // got results
+                    System.out.println("gotlen:" + len);
+                }
+            } finally {
+                if (resultStream != null) {
+                    resultStream.close();
+                }
+                sock.close();
+            }
+        }
+        
+        ZooKeeper zk = createClient();
+        Assert.assertEquals(1, zk.getChildren("/", false).size());
+
+        zk.close();
+    }
+}