zookeeper-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From f..@apache.org
Subject svn commit: r1742002 [1/2] - in /zookeeper/trunk: ./ src/java/main/org/apache/zookeeper/ src/java/main/org/apache/zookeeper/client/ src/java/main/org/apache/zookeeper/common/ src/java/main/org/apache/zookeeper/server/ src/java/main/org/apache/zookeeper...
Date Mon, 02 May 2016 16:15:29 GMT
Author: fpj
Date: Mon May  2 16:15:28 2016
New Revision: 1742002

URL: http://svn.apache.org/viewvc?rev=1742002&view=rev
Log:
ZOOKEEPER-2139: Support multiple ZooKeeper client with different configurations in a single JVM (Arshad Mohammad via fpj)


Added:
    zookeeper/trunk/src/java/main/org/apache/zookeeper/client/ZKClientConfig.java
    zookeeper/trunk/src/java/main/org/apache/zookeeper/common/ZKConfig.java
    zookeeper/trunk/src/java/test/org/apache/zookeeper/client/
    zookeeper/trunk/src/java/test/org/apache/zookeeper/client/ZKClientConfigTest.java
Modified:
    zookeeper/trunk/CHANGES.txt
    zookeeper/trunk/src/java/main/org/apache/zookeeper/ClientCnxn.java
    zookeeper/trunk/src/java/main/org/apache/zookeeper/ClientCnxnSocket.java
    zookeeper/trunk/src/java/main/org/apache/zookeeper/ClientCnxnSocketNIO.java
    zookeeper/trunk/src/java/main/org/apache/zookeeper/ClientCnxnSocketNetty.java
    zookeeper/trunk/src/java/main/org/apache/zookeeper/Login.java
    zookeeper/trunk/src/java/main/org/apache/zookeeper/ZooKeeper.java
    zookeeper/trunk/src/java/main/org/apache/zookeeper/ZooKeeperMain.java
    zookeeper/trunk/src/java/main/org/apache/zookeeper/client/ZooKeeperSaslClient.java
    zookeeper/trunk/src/java/main/org/apache/zookeeper/common/X509Util.java
    zookeeper/trunk/src/java/main/org/apache/zookeeper/server/NettyServerCnxnFactory.java
    zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ServerCnxnFactory.java
    zookeeper/trunk/src/java/main/org/apache/zookeeper/server/auth/X509AuthenticationProvider.java
    zookeeper/trunk/src/java/main/org/apache/zookeeper/server/util/VerifyingFileFactory.java
    zookeeper/trunk/src/java/test/org/apache/zookeeper/ClientReconnectTest.java
    zookeeper/trunk/src/java/test/org/apache/zookeeper/RemoveWatchesTest.java
    zookeeper/trunk/src/java/test/org/apache/zookeeper/test/NettyNettySuiteBase.java
    zookeeper/trunk/src/java/test/org/apache/zookeeper/test/SSLAuthTest.java
    zookeeper/trunk/src/java/test/org/apache/zookeeper/test/SSLTest.java
    zookeeper/trunk/src/java/test/org/apache/zookeeper/test/SaslAuthDesignatedClientTest.java
    zookeeper/trunk/src/java/test/org/apache/zookeeper/test/SaslAuthFailDesignatedClientTest.java
    zookeeper/trunk/src/java/test/org/apache/zookeeper/test/SaslAuthMissingClientConfigTest.java
    zookeeper/trunk/src/java/test/org/apache/zookeeper/test/SaslClientTest.java
    zookeeper/trunk/src/java/test/org/apache/zookeeper/test/WatcherTest.java

Modified: zookeeper/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/zookeeper/trunk/CHANGES.txt?rev=1742002&r1=1742001&r2=1742002&view=diff
==============================================================================
--- zookeeper/trunk/CHANGES.txt (original)
+++ zookeeper/trunk/CHANGES.txt Mon May  2 16:15:28 2016
@@ -411,6 +411,9 @@ IMPROVEMENTS:
 
   ZOOKEEPER-2240 Make the three-node minimum more explicit in 
   documentation and on website (Shawn Heisey and Arshad Mohammad via phunt)
+ 
+  ZOOKEEPER-2139: Support multiple ZooKeeper client with different configurations
+  in a single JVM (Arshad Mohammad via fpj)
 
 Release 3.5.0 - 8/4/2014
 

Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/ClientCnxn.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/ClientCnxn.java?rev=1742002&r1=1742001&r2=1742002&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/ClientCnxn.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/ClientCnxn.java Mon May  2 16:15:28 2016
@@ -63,6 +63,7 @@ import org.apache.zookeeper.Watcher.Even
 import org.apache.zookeeper.ZooDefs.OpCode;
 import org.apache.zookeeper.ZooKeeper.States;
 import org.apache.zookeeper.ZooKeeper.WatchRegistration;
+import org.apache.zookeeper.client.ZKClientConfig;
 import org.apache.zookeeper.client.HostProvider;
 import org.apache.zookeeper.client.ZooKeeperSaslClient;
 import org.apache.zookeeper.common.Time;
@@ -98,9 +99,6 @@ import org.slf4j.MDC;
 public class ClientCnxn {
     private static final Logger LOG = LoggerFactory.getLogger(ClientCnxn.class);
 
-    private static final String ZK_SASL_CLIENT_USERNAME =
-        "zookeeper.sasl.client.username";
-
     /* ZOOKEEPER-706: If a session has a large number of watches set then
      * attempting to re-establish those watches after a connection loss may
      * fail due to the SetWatches request exceeding the server's configured
@@ -111,22 +109,6 @@ public class ClientCnxn {
      */
     private static final int SET_WATCHES_MAX_LENGTH = 128 * 1024;
 
-    /** This controls whether automatic watch resetting is enabled.
-     * Clients automatically reset watches during session reconnect, this
-     * option allows the client to turn off this behavior by setting
-     * the environment variable "zookeeper.disableAutoWatchReset" to "true" */
-    private static boolean disableAutoWatchReset;
-    static {
-        // this var should not be public, but otw there is no easy way
-        // to test
-        disableAutoWatchReset =
-            Boolean.getBoolean("zookeeper.disableAutoWatchReset");
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("zookeeper.disableAutoWatchReset is "
-                    + disableAutoWatchReset);
-        }
-    }
-
     static class AuthData {
         AuthData(String scheme, byte data[]) {
             this.scheme = scheme;
@@ -217,6 +199,8 @@ public class ClientCnxn {
 
     public ZooKeeperSaslClient zooKeeperSaslClient;
 
+    private final ZKClientConfig clientConfig;
+
     public long getSessionId() {
         return sessionId;
     }
@@ -409,23 +393,9 @@ public class ClientCnxn {
 
         sendThread = new SendThread(clientCnxnSocket);
         eventThread = new EventThread();
-
+        this.clientConfig=zooKeeper.getClientConfig();
     }
 
-    /**
-     * tests use this to check on reset of watches
-     * @return if the auto reset of watches are disabled
-     */
-    public static boolean getDisableAutoResetWatch() {
-        return disableAutoWatchReset;
-    }
-    /**
-     * tests use this to set the auto reset
-     * @param b the value to set disable watches to
-     */
-    public static void setDisableAutoResetWatch(boolean b) {
-        disableAutoWatchReset = b;
-    }
     public void start() {
         sendThread.start();
         eventThread.start();
@@ -818,9 +788,6 @@ public class ClientCnxn {
         }
     }
     
-    public static final int packetLen = Integer.getInteger("jute.maxbuffer",
-            4096 * 1024);
-
     /**
      * This class services the outgoing request queue and generates the heart
      * beats. It also spawns the ReadThread.
@@ -989,7 +956,7 @@ public class ClientCnxn {
             // Only send if there's a pending watch
             // TODO: here we have the only remaining use of zooKeeper in
             // this class. It's to be eliminated!
-            if (!disableAutoWatchReset) {
+            if (!clientConfig.getBoolean(ZKClientConfig.DISABLE_AUTO_WATCH_RESET)) {
                 List<String> dataWatches = zooKeeper.getDataWatches();
                 List<String> existWatches = zooKeeper.getExistWatches();
                 List<String> childWatches = zooKeeper.getChildWatches();
@@ -1107,13 +1074,12 @@ public class ClientCnxn {
             String hostPort = addr.getHostString() + ":" + addr.getPort();
             MDC.put("myid", hostPort);
             setName(getName().replaceAll("\\(.*\\)", "(" + hostPort + ")"));
-            if (ZooKeeperSaslClient.isEnabled()) {
+            if (clientConfig.isSaslClientEnabled()) {
                 try {
-                    String principalUserName = System.getProperty(
-                            ZK_SASL_CLIENT_USERNAME, "zookeeper");
-                    zooKeeperSaslClient =
-                        new ZooKeeperSaslClient(
-                                principalUserName+"/"+addr.getHostString());
+                    if (zooKeeperSaslClient != null) {
+                        zooKeeperSaslClient.shutdown();
+                    }
+                    zooKeeperSaslClient = new ZooKeeperSaslClient(getServerPrincipal(addr), clientConfig);
                 } catch (LoginException e) {
                     // An authentication error occurred when the SASL client tried to initialize:
                     // for Kerberos this means that the client failed to authenticate with the KDC.
@@ -1132,6 +1098,13 @@ public class ClientCnxn {
             clientCnxnSocket.connect(addr);
         }
 
+        private String getServerPrincipal(InetSocketAddress addr) {
+            String principalUserName = clientConfig.getProperty(ZKClientConfig.ZK_SASL_CLIENT_USERNAME,
+                    ZKClientConfig.ZK_SASL_CLIENT_USERNAME_DEFAULT);
+            String serverPrincipal = principalUserName + "/" + addr.getHostString();
+            return serverPrincipal;
+        }
+
         private void logStartConnect(InetSocketAddress addr) {
             String msg = "Opening socket connection to server " + addr;
             if (zooKeeperSaslClient != null) {
@@ -1428,7 +1401,7 @@ public class ClientCnxn {
 
         public boolean tunnelAuthInProgress() {
             // 1. SASL client is disabled.
-            if (!ZooKeeperSaslClient.isEnabled()) {
+            if (!clientConfig.isSaslClientEnabled()) {
                 return false;
             }
 
@@ -1466,7 +1439,7 @@ public class ClientCnxn {
 
         sendThread.close();
         eventThread.queueEventOfDeath();
-        if (null != zooKeeperSaslClient) {
+        if (zooKeeperSaslClient != null) {
             zooKeeperSaslClient.shutdown();
         }
     }

Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/ClientCnxnSocket.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/ClientCnxnSocket.java?rev=1742002&r1=1742001&r2=1742002&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/ClientCnxnSocket.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/ClientCnxnSocket.java Mon May  2 16:15:28 2016
@@ -27,6 +27,8 @@ import java.util.concurrent.LinkedBlocki
 
 import org.apache.jute.BinaryInputArchive;
 import org.apache.zookeeper.ClientCnxn.Packet;
+import org.apache.zookeeper.client.ZKClientConfig;
+import org.apache.zookeeper.common.ZKConfig;
 import org.apache.zookeeper.common.Time;
 import org.apache.zookeeper.proto.ConnectResponse;
 import org.apache.zookeeper.server.ByteBufferInputStream;
@@ -63,6 +65,8 @@ abstract class ClientCnxnSocket {
     protected long now;
     protected ClientCnxn.SendThread sendThread;
     protected LinkedBlockingDeque<Packet> outgoingQueue;
+    protected ZKClientConfig clientConfig;
+    private int packetLen = ZKClientConfig.CLIENT_MAX_PACKET_LENGTH_DEFAULT;
 
     /**
      * The sessionId is only available here for Log and Exception messages.
@@ -112,7 +116,7 @@ abstract class ClientCnxnSocket {
 
     protected void readLength() throws IOException {
         int len = incomingBuffer.getInt();
-        if (len < 0 || len >= ClientCnxn.packetLen) {
+        if (len < 0 || len >= packetLen) {
             throw new IOException("Packet len" + len + " is out of range!");
         }
         incomingBuffer = ByteBuffer.allocate(len);
@@ -223,4 +227,15 @@ abstract class ClientCnxnSocket {
      * finally unblock it when finished.
      */
     abstract void sendPacket(Packet p) throws IOException;
+
+    protected void initProperties() {
+        packetLen = Integer.getInteger(
+                clientConfig.getProperty(ZKConfig.JUTE_MAXBUFFER),
+                ZKClientConfig.CLIENT_MAX_PACKET_LENGTH_DEFAULT);
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("{} is {}", ZKConfig.JUTE_MAXBUFFER, packetLen);
+        }
+    }
+
+
 }

Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/ClientCnxnSocketNIO.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/ClientCnxnSocketNIO.java?rev=1742002&r1=1742001&r2=1742002&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/ClientCnxnSocketNIO.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/ClientCnxnSocketNIO.java Mon May  2 16:15:28 2016
@@ -34,6 +34,7 @@ import java.util.concurrent.LinkedBlocki
 import org.apache.zookeeper.ClientCnxn.EndOfStreamException;
 import org.apache.zookeeper.ClientCnxn.Packet;
 import org.apache.zookeeper.ZooDefs.OpCode;
+import org.apache.zookeeper.client.ZKClientConfig;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -49,8 +50,9 @@ public class ClientCnxnSocketNIO extends
 
     private SocketAddress remoteSocketAddress;
 
-    ClientCnxnSocketNIO() throws IOException {
-        super();
+    ClientCnxnSocketNIO(ZKClientConfig clientConfig) throws IOException {
+        this.clientConfig = clientConfig;
+        initProperties();
     }
 
     @Override

Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/ClientCnxnSocketNetty.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/ClientCnxnSocketNetty.java?rev=1742002&r1=1742001&r2=1742002&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/ClientCnxnSocketNetty.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/ClientCnxnSocketNetty.java Mon May  2 16:15:28 2016
@@ -20,6 +20,7 @@ package org.apache.zookeeper;
 
 import org.apache.zookeeper.ClientCnxn.EndOfStreamException;
 import org.apache.zookeeper.ClientCnxn.Packet;
+import org.apache.zookeeper.client.ZKClientConfig;
 import org.apache.zookeeper.common.X509Util;
 import org.jboss.netty.bootstrap.ClientBootstrap;
 import org.jboss.netty.buffer.ChannelBuffer;
@@ -43,6 +44,7 @@ import org.slf4j.LoggerFactory;
 
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLEngine;
+
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
@@ -76,6 +78,11 @@ public class ClientCnxnSocketNetty exten
     AtomicBoolean needSasl = new AtomicBoolean();
     Semaphore waitSasl = new Semaphore(0);
 
+    ClientCnxnSocketNetty(ZKClientConfig clientConfig) {
+        this.clientConfig = clientConfig;
+        initProperties();
+    }
+
     /**
      * lifecycles diagram:
      * <p/>
@@ -344,7 +351,7 @@ public class ClientCnxnSocketNetty exten
         @Override
         public ChannelPipeline getPipeline() throws Exception {
             ChannelPipeline pipeline = Channels.pipeline();
-            if (Boolean.getBoolean(ZooKeeper.SECURE_CLIENT)) {
+            if (clientConfig.getBoolean(ZKClientConfig.SECURE_CLIENT)) {
                 initSSL(pipeline);
             }
             pipeline.addLast("handler", new ZKClientHandler());
@@ -355,7 +362,7 @@ public class ClientCnxnSocketNetty exten
         // Basically we only need to create it once.
         private synchronized void initSSL(ChannelPipeline pipeline) throws SSLContextException {
             if (sslContext == null || sslEngine == null) {
-                sslContext = X509Util.createSSLContext();
+                sslContext = X509Util.createSSLContext(clientConfig);
                 sslEngine = sslContext.createSSLEngine();
                 sslEngine.setUseClientMode(true);
             }

Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/Login.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/Login.java?rev=1742002&r1=1742001&r2=1742002&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/Login.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/Login.java Mon May  2 16:15:28 2016
@@ -32,7 +32,9 @@ import javax.security.auth.login.LoginCo
 import javax.security.auth.login.LoginException;
 import javax.security.auth.callback.CallbackHandler;
 
-import org.apache.zookeeper.client.ZooKeeperSaslClient;
+import org.apache.zookeeper.client.ZKClientConfig;
+import org.apache.zookeeper.common.ZKConfig;
+import org.apache.zookeeper.server.ZooKeeperSaslServer;
 import org.apache.zookeeper.common.Time;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -45,6 +47,7 @@ import java.util.Random;
 import java.util.Set;
 
 public class Login {
+    private static final String KINIT_COMMAND_DEFAULT = "/usr/bin/kinit";
     private static final Logger LOG = LoggerFactory.getLogger(Login.class);
     public CallbackHandler callbackHandler;
 
@@ -77,21 +80,27 @@ public class Login {
 
     // Initialize 'lastLogin' to do a login at first time
     private long lastLogin = Time.currentElapsedTime() - MIN_TIME_BEFORE_RELOGIN;
+    private final ZKConfig zkConfig;
 
     /**
-     * LoginThread constructor. The constructor starts the thread used
-     * to periodically re-login to the Kerberos Ticket Granting Server.
+     * LoginThread constructor. The constructor starts the thread used to
+     * periodically re-login to the Kerberos Ticket Granting Server.
+     * 
      * @param loginContextName
-     *               name of section in JAAS file that will be use to login.
-     *               Passed as first param to javax.security.auth.login.LoginContext().
+     *            name of section in JAAS file that will be use to login. Passed
+     *            as first param to javax.security.auth.login.LoginContext().
      *
      * @param callbackHandler
-     *               Passed as second param to javax.security.auth.login.LoginContext().
+     *            Passed as second param to
+     *            javax.security.auth.login.LoginContext().
+     * @param zkConfig
+     *            client or server configurations
      * @throws javax.security.auth.login.LoginException
-     *               Thrown if authentication fails.
+     *             Thrown if authentication fails.
      */
-    public Login(final String loginContextName, CallbackHandler callbackHandler)
+    public Login(final String loginContextName, CallbackHandler callbackHandler, final ZKConfig zkConfig)
             throws LoginException {
+        this.zkConfig=zkConfig;
         this.callbackHandler = callbackHandler;
         login = login(loginContextName);
         this.loginContextName = loginContextName;
@@ -197,10 +206,7 @@ public class Login {
                         break;
                     }
                     if (isUsingTicketCache) {
-                        String cmd = "/usr/bin/kinit";
-                        if (System.getProperty("zookeeper.kinit") != null) {
-                            cmd = System.getProperty("zookeeper.kinit");
-                        }
+                        String cmd = zkConfig.getProperty(ZKConfig.KINIT_COMMAND, KINIT_COMMAND_DEFAULT);
                         String kinitArgs = "-R";
                         int retry = 1;
                         while (retry >= 0) {
@@ -289,8 +295,7 @@ public class Login {
             throw new LoginException("loginContext name (JAAS file section header) was null. " +
                     "Please check your java.security.login.auth.config (=" +
                     System.getProperty("java.security.login.auth.config") +
-                    ") and your " + ZooKeeperSaslClient.LOGIN_CONTEXT_NAME_KEY + "(=" + 
-                    System.getProperty(ZooKeeperSaslClient.LOGIN_CONTEXT_NAME_KEY, "Client") + ")");
+                    ") and your " + getLoginContextMessage());
         }
         LoginContext loginContext = new LoginContext(loginContextName,callbackHandler);
         loginContext.login();
@@ -298,6 +303,16 @@ public class Login {
         return loginContext;
     }
 
+    private String getLoginContextMessage() {
+        if (zkConfig instanceof ZKClientConfig) {
+            return ZKClientConfig.LOGIN_CONTEXT_NAME_KEY + "(=" + zkConfig.getProperty(
+                    ZKClientConfig.LOGIN_CONTEXT_NAME_KEY, ZKClientConfig.LOGIN_CONTEXT_NAME_KEY_DEFAULT) + ")";
+        } else {
+            return ZooKeeperSaslServer.LOGIN_CONTEXT_NAME_KEY + "(=" + System.getProperty(
+                    ZooKeeperSaslServer.LOGIN_CONTEXT_NAME_KEY, ZooKeeperSaslServer.DEFAULT_LOGIN_CONTEXT_NAME) + ")";
+        }
+    }
+
     // c.f. org.apache.hadoop.security.UserGroupInformation.
     private long getRefreshTime(KerberosTicket tgt) {
         long start = tgt.getStartTime().getTime();

Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/ZooKeeper.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/ZooKeeper.java?rev=1742002&r1=1742001&r2=1742002&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/ZooKeeper.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/ZooKeeper.java Mon May  2 16:15:28 2016
@@ -19,6 +19,7 @@
 package org.apache.zookeeper;
 
 import java.io.IOException;
+import java.lang.reflect.Constructor;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 import java.util.ArrayList;
@@ -44,6 +45,7 @@ import org.apache.zookeeper.KeeperExcept
 import org.apache.zookeeper.OpResult.ErrorResult;
 import org.apache.zookeeper.Watcher.Event.EventType;
 import org.apache.zookeeper.Watcher.WatcherType;
+import org.apache.zookeeper.client.ZKClientConfig;
 import org.apache.zookeeper.client.ConnectStringParser;
 import org.apache.zookeeper.client.HostProvider;
 import org.apache.zookeeper.client.StaticHostProvider;
@@ -129,8 +131,19 @@ import org.slf4j.LoggerFactory;
  */
 public class ZooKeeper {
 
+    /**
+     * @deprecated Use {@link ZKClientConfig#ZOOKEEPER_CLIENT_CNXN_SOCKET}
+     *             instead.
+     */
+    @Deprecated
     public static final String ZOOKEEPER_CLIENT_CNXN_SOCKET = "zookeeper.clientCnxnSocket";
     // Setting this to "true" will enable encrypted client-server communication.
+
+    /**
+     * @deprecated Use {@link ZKClientConfig#SECURE_CLIENT}
+     *             instead.
+     */
+    @Deprecated
     public static final String SECURE_CLIENT = "zookeeper.client.secure";
 
     protected final ClientCnxn cnxn;
@@ -202,6 +215,12 @@ public class ZooKeeper {
 
     private final ZKWatchManager watchManager;
 
+    private final ZKClientConfig clientConfig;
+
+    public ZKClientConfig getClientConfig() {
+        return clientConfig;
+    }
+
     List<String> getDataWatches() {
         synchronized(watchManager.dataWatches) {
             List<String> rc = new ArrayList<String>(watchManager.dataWatches.keySet());
@@ -235,6 +254,11 @@ public class ZooKeeper {
             new HashMap<String, Set<Watcher>>();
         private final Map<String, Set<Watcher>> childWatches =
             new HashMap<String, Set<Watcher>>();
+        private boolean disableAutoWatchReset;
+
+        ZKWatchManager(boolean disableAutoWatchReset) {
+            this.disableAutoWatchReset = disableAutoWatchReset;
+        }
 
         private volatile Watcher defaultWatcher;
 
@@ -430,9 +454,7 @@ public class ZooKeeper {
             switch (type) {
             case None:
                 result.add(defaultWatcher);
-                boolean clear = ClientCnxn.getDisableAutoResetWatch() &&
-                        state != Watcher.Event.KeeperState.SyncConnected;
-
+                boolean clear = disableAutoWatchReset && state != Watcher.Event.KeeperState.SyncConnected;
                 synchronized(dataWatches) {
                     for(Set<Watcher> ws: dataWatches.values()) {
                         result.addAll(ws);
@@ -675,6 +697,56 @@ public class ZooKeeper {
      * Added in 3.2.0: An optional "chroot" suffix may also be appended to the
      * connection string. This will run the client commands while interpreting
      * all paths relative to this root (similar to the unix chroot command).
+     *
+     * @param connectString
+     *            comma separated host:port pairs, each corresponding to a zk
+     *            server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002" If
+     *            the optional chroot suffix is used the example would look
+     *            like: "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002/app/a"
+     *            where the client would be rooted at "/app/a" and all paths
+     *            would be relative to this root - ie getting/setting/etc...
+     *            "/foo/bar" would result in operations being run on
+     *            "/app/a/foo/bar" (from the server perspective).
+     * @param sessionTimeout
+     *            session timeout in milliseconds
+     * @param watcher
+     *            a watcher object which will be notified of state changes, may
+     *            also be notified for node events
+     * @param conf
+     *            (added in 3.5.2) passing this conf object gives each client the flexibility of
+     *            configuring properties differently compared to other instances
+     * @throws IOException
+     *             in cases of network failure
+     * @throws IllegalArgumentException
+     *             if an invalid chroot path is specified
+     */
+    public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher,
+            ZKClientConfig conf) throws IOException {
+        this(connectString, sessionTimeout, watcher, false, conf);
+    }
+
+    /**
+     * To create a ZooKeeper client object, the application needs to pass a
+     * connection string containing a comma separated list of host:port pairs,
+     * each corresponding to a ZooKeeper server.
+     * <p>
+     * Session establishment is asynchronous. This constructor will initiate
+     * connection to the server and return immediately - potentially (usually)
+     * before the session is fully established. The watcher argument specifies
+     * the watcher that will be notified of any changes in state. This
+     * notification can come at any point before or after the constructor call
+     * has returned.
+     * <p>
+     * The instantiated ZooKeeper client object will pick an arbitrary server
+     * from the connectString and attempt to connect to it. If establishment of
+     * the connection fails, another server in the connect string will be tried
+     * (the order is non-deterministic, as we random shuffle the list), until a
+     * connection is established. The client will continue attempts until the
+     * session is explicitly closed.
+     * <p>
+     * Added in 3.2.0: An optional "chroot" suffix may also be appended to the
+     * connection string. This will run the client commands while interpreting
+     * all paths relative to this root (similar to the unix chroot command).
      * <p>
      * For backward compatibility, there is another version
      * {@link #ZooKeeper(String, int, Watcher, boolean)} which uses
@@ -713,12 +785,82 @@ public class ZooKeeper {
     public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher,
             boolean canBeReadOnly, HostProvider aHostProvider)
             throws IOException {
+        this(connectString, sessionTimeout, watcher, canBeReadOnly,
+                aHostProvider, null);
+    }
+
+
+    /**
+     * To create a ZooKeeper client object, the application needs to pass a
+     * connection string containing a comma separated list of host:port pairs,
+     * each corresponding to a ZooKeeper server.
+     * <p>
+     * Session establishment is asynchronous. This constructor will initiate
+     * connection to the server and return immediately - potentially (usually)
+     * before the session is fully established. The watcher argument specifies
+     * the watcher that will be notified of any changes in state. This
+     * notification can come at any point before or after the constructor call
+     * has returned.
+     * <p>
+     * The instantiated ZooKeeper client object will pick an arbitrary server
+     * from the connectString and attempt to connect to it. If establishment of
+     * the connection fails, another server in the connect string will be tried
+     * (the order is non-deterministic, as we random shuffle the list), until a
+     * connection is established. The client will continue attempts until the
+     * session is explicitly closed.
+     * <p>
+     * Added in 3.2.0: An optional "chroot" suffix may also be appended to the
+     * connection string. This will run the client commands while interpreting
+     * all paths relative to this root (similar to the unix chroot command).
+     * <p>
+     * For backward compatibility, there is another version
+     * {@link #ZooKeeper(String, int, Watcher, boolean)} which uses default
+     * {@link StaticHostProvider}
+     *
+     * @param connectString
+     *            comma separated host:port pairs, each corresponding to a zk
+     *            server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002" If
+     *            the optional chroot suffix is used the example would look
+     *            like: "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002/app/a"
+     *            where the client would be rooted at "/app/a" and all paths
+     *            would be relative to this root - ie getting/setting/etc...
+     *            "/foo/bar" would result in operations being run on
+     *            "/app/a/foo/bar" (from the server perspective).
+     * @param sessionTimeout
+     *            session timeout in milliseconds
+     * @param watcher
+     *            a watcher object which will be notified of state changes, may
+     *            also be notified for node events
+     * @param canBeReadOnly
+     *            (added in 3.4) whether the created client is allowed to go to
+     *            read-only mode in case of partitioning. Read-only mode
+     *            basically means that if the client can't find any majority
+     *            servers but there's partitioned server it could reach, it
+     *            connects to one in read-only mode, i.e. read requests are
+     *            allowed while write requests are not. It continues seeking for
+     *            majority in the background.
+     * @param aHostProvider
+     *            use this as HostProvider to enable custom behaviour.
+     * @param clientConfig
+     *            (added in 3.5.2) passing this conf object gives each client the flexibility of
+     *            configuring properties differently compared to other instances
+     * @throws IOException
+     *             in cases of network failure
+     * @throws IllegalArgumentException
+     *             if an invalid chroot path is specified
+     */
+    public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher,
+            boolean canBeReadOnly, HostProvider aHostProvider,
+            ZKClientConfig clientConfig) throws IOException {
         LOG.info("Initiating client connection, connectString=" + connectString
                 + " sessionTimeout=" + sessionTimeout + " watcher=" + watcher);
 
+        if (clientConfig == null) {
+            clientConfig = new ZKClientConfig();
+        }
+        this.clientConfig = clientConfig;
         watchManager = defaultWatchManager();
         watchManager.defaultWatcher = watcher;
-
         ConnectStringParser connectStringParser = new ConnectStringParser(
                 connectString);
         hostProvider = aHostProvider;
@@ -804,6 +946,66 @@ public class ZooKeeper {
      * the connection fails, another server in the connect string will be tried
      * (the order is non-deterministic, as we random shuffle the list), until a
      * connection is established. The client will continue attempts until the
+     * session is explicitly closed.
+     * <p>
+     * Added in 3.2.0: An optional "chroot" suffix may also be appended to the
+     * connection string. This will run the client commands while interpreting
+     * all paths relative to this root (similar to the unix chroot command).
+     * <p>
+     *
+     * @param connectString
+     *            comma separated host:port pairs, each corresponding to a zk
+     *            server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002" If
+     *            the optional chroot suffix is used the example would look
+     *            like: "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002/app/a"
+     *            where the client would be rooted at "/app/a" and all paths
+     *            would be relative to this root - ie getting/setting/etc...
+     *            "/foo/bar" would result in operations being run on
+     *            "/app/a/foo/bar" (from the server perspective).
+     * @param sessionTimeout
+     *            session timeout in milliseconds
+     * @param watcher
+     *            a watcher object which will be notified of state changes, may
+     *            also be notified for node events
+     * @param canBeReadOnly
+     *            (added in 3.4) whether the created client is allowed to go to
+     *            read-only mode in case of partitioning. Read-only mode
+     *            basically means that if the client can't find any majority
+     *            servers but there's partitioned server it could reach, it
+     *            connects to one in read-only mode, i.e. read requests are
+     *            allowed while write requests are not. It continues seeking for
+     *            majority in the background.
+     * @param conf
+     *            (added in 3.5.2) passing this conf object gives each client the flexibility of
+     *            configuring properties differently compared to other instances
+     * @throws IOException
+     *             in cases of network failure
+     * @throws IllegalArgumentException
+     *             if an invalid chroot path is specified
+     */
+    public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher,
+            boolean canBeReadOnly, ZKClientConfig conf) throws IOException {
+        this(connectString, sessionTimeout, watcher, canBeReadOnly,
+                createDefaultHostProvider(connectString), conf);
+    }
+
+    /**
+     * To create a ZooKeeper client object, the application needs to pass a
+     * connection string containing a comma separated list of host:port pairs,
+     * each corresponding to a ZooKeeper server.
+     * <p>
+     * Session establishment is asynchronous. This constructor will initiate
+     * connection to the server and return immediately - potentially (usually)
+     * before the session is fully established. The watcher argument specifies
+     * the watcher that will be notified of any changes in state. This
+     * notification can come at any point before or after the constructor call
+     * has returned.
+     * <p>
+     * The instantiated ZooKeeper client object will pick an arbitrary server
+     * from the connectString and attempt to connect to it. If establishment of
+     * the connection fails, another server in the connect string will be tried
+     * (the order is non-deterministic, as we random shuffle the list), until a
+     * connection is established. The client will continue attempts until the
      * session is explicitly closed (or the session is expired by the server).
      * <p>
      * Added in 3.2.0: An optional "chroot" suffix may also be appended to the
@@ -920,6 +1122,7 @@ public class ZooKeeper {
                 + " sessionPasswd="
                 + (sessionPasswd == null ? "<null>" : "<hidden>"));
 
+        this.clientConfig = new ZKClientConfig();
         watchManager = defaultWatchManager();
         watchManager.defaultWatcher = watcher;
        
@@ -1015,7 +1218,7 @@ public class ZooKeeper {
 
     /* Useful for testing watch handling behavior */
     protected ZKWatchManager defaultWatchManager() {
-        return new ZKWatchManager();
+        return new ZKWatchManager(getClientConfig().getBoolean(ZKClientConfig.DISABLE_AUTO_WATCH_RESET));
     }
 
     /**
@@ -2719,15 +2922,16 @@ public class ZooKeeper {
         return cnxn.sendThread.getClientCnxnSocket().getLocalSocketAddress();
     }
 
-    private static ClientCnxnSocket getClientCnxnSocket() throws IOException {
-        String clientCnxnSocketName = System
-                .getProperty(ZOOKEEPER_CLIENT_CNXN_SOCKET);
+    private ClientCnxnSocket getClientCnxnSocket() throws IOException {
+        String clientCnxnSocketName = getClientConfig().getProperty(
+                ZKClientConfig.ZOOKEEPER_CLIENT_CNXN_SOCKET);
         if (clientCnxnSocketName == null) {
             clientCnxnSocketName = ClientCnxnSocketNIO.class.getName();
         }
         try {
-            return (ClientCnxnSocket) Class.forName(clientCnxnSocketName)
-                    .newInstance();
+            Constructor<?> clientCxnConstructor = Class.forName(clientCnxnSocketName).getDeclaredConstructor(ZKClientConfig.class);
+            ClientCnxnSocket clientCxnSocket = (ClientCnxnSocket) clientCxnConstructor.newInstance(getClientConfig());
+            return clientCxnSocket;
         } catch (Exception e) {
             IOException ioe = new IOException("Couldn't instantiate "
                     + clientCnxnSocketName);

Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/ZooKeeperMain.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/ZooKeeperMain.java?rev=1742002&r1=1742001&r2=1742002&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/ZooKeeperMain.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/ZooKeeperMain.java Mon May  2 16:15:28 2016
@@ -38,6 +38,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.zookeeper.ZooDefs.Ids;
 import org.apache.zookeeper.data.Stat;
+
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -62,6 +63,7 @@ import org.apache.zookeeper.cli.SetComma
 import org.apache.zookeeper.cli.SetQuotaCommand;
 import org.apache.zookeeper.cli.StatCommand;
 import org.apache.zookeeper.cli.SyncCommand;
+import org.apache.zookeeper.client.ZKClientConfig;
 
 /**
  * The command line client to ZooKeeper.
@@ -273,7 +275,7 @@ public class ZooKeeperMain {
         host = newHost;
         boolean readOnly = cl.getOption("readonly") != null;
         if (cl.getOption("secure") != null) {
-            System.setProperty(ZooKeeper.SECURE_CLIENT, "true");
+            System.setProperty(ZKClientConfig.SECURE_CLIENT, "true");
             System.out.println("Secure connection is enabled");
         }
         zk = new ZooKeeper(host,

Added: zookeeper/trunk/src/java/main/org/apache/zookeeper/client/ZKClientConfig.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/client/ZKClientConfig.java?rev=1742002&view=auto
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/client/ZKClientConfig.java (added)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/client/ZKClientConfig.java Mon May  2 16:15:28 2016
@@ -0,0 +1,101 @@
+/**
+ * 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.client;
+
+import java.io.File;
+
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.common.ZKConfig;
+import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException;
+
+/**
+ * Handles client specific properties
+ * @since 3.5.2
+ */
+public class ZKClientConfig extends ZKConfig {
+    public static final String ZK_SASL_CLIENT_USERNAME = "zookeeper.sasl.client.username";
+    public static final String ZK_SASL_CLIENT_USERNAME_DEFAULT = "zookeeper";
+    @SuppressWarnings("deprecation")
+    public static final String LOGIN_CONTEXT_NAME_KEY = ZooKeeperSaslClient.LOGIN_CONTEXT_NAME_KEY;;
+    public static final String LOGIN_CONTEXT_NAME_KEY_DEFAULT = "Client";
+    @SuppressWarnings("deprecation")
+    public static final String ENABLE_CLIENT_SASL_KEY = ZooKeeperSaslClient.ENABLE_CLIENT_SASL_KEY;
+    @SuppressWarnings("deprecation")
+    public static final String ENABLE_CLIENT_SASL_DEFAULT = ZooKeeperSaslClient.ENABLE_CLIENT_SASL_DEFAULT;
+    public static final String ZOOKEEPER_SERVER_REALM = "zookeeper.server.realm";
+    /**
+     * This controls whether automatic watch resetting is enabled. Clients
+     * automatically reset watches during session reconnect, this option allows
+     * the client to turn off this behavior by setting the property
+     * "zookeeper.disableAutoWatchReset" to "true"
+     */
+    public static final String DISABLE_AUTO_WATCH_RESET = "zookeeper.disableAutoWatchReset";
+    @SuppressWarnings("deprecation")
+    public static final String ZOOKEEPER_CLIENT_CNXN_SOCKET = ZooKeeper.ZOOKEEPER_CLIENT_CNXN_SOCKET;
+    /**
+     * Setting this to "true" will enable encrypted client-server communication.
+     */
+    @SuppressWarnings("deprecation")
+    public static final String SECURE_CLIENT = ZooKeeper.SECURE_CLIENT;
+    public static final int CLIENT_MAX_PACKET_LENGTH_DEFAULT = 4096 * 1024; /* 4 MB */
+
+    public ZKClientConfig() {
+        super();
+    }
+
+    public ZKClientConfig(File configFile) throws ConfigException {
+        super(configFile);
+    }
+
+    public ZKClientConfig(String configPath) throws ConfigException {
+        super(configPath);
+    }
+
+    @Override
+    protected void handleBackwardCompatibility() {
+        /**
+         * backward compatibility for properties which are common to both client
+         * and server
+         */
+        super.handleBackwardCompatibility();
+
+        /**
+         * backward compatibility for client specific properties
+         */
+        setProperty(ZK_SASL_CLIENT_USERNAME, System.getProperty(ZK_SASL_CLIENT_USERNAME));
+        setProperty(LOGIN_CONTEXT_NAME_KEY, System.getProperty(LOGIN_CONTEXT_NAME_KEY));
+        setProperty(ENABLE_CLIENT_SASL_KEY, System.getProperty(ENABLE_CLIENT_SASL_KEY));
+        setProperty(ZOOKEEPER_SERVER_REALM, System.getProperty(ZOOKEEPER_SERVER_REALM));
+        setProperty(DISABLE_AUTO_WATCH_RESET, System.getProperty(DISABLE_AUTO_WATCH_RESET));
+        setProperty(ZOOKEEPER_CLIENT_CNXN_SOCKET, System.getProperty(ZOOKEEPER_CLIENT_CNXN_SOCKET));
+        setProperty(SECURE_CLIENT, System.getProperty(SECURE_CLIENT));
+    }
+
+    /**
+     * Returns true if the SASL client is enabled. By default, the client is
+     * enabled but can be disabled by setting the system property
+     * <code>zookeeper.sasl.client</code> to <code>false</code>. See
+     * ZOOKEEPER-1657 for more information.
+     *
+     * @return true if the SASL client is enabled.
+     */
+    public boolean isSaslClientEnabled() {
+        return Boolean.valueOf(getProperty(ENABLE_CLIENT_SASL_KEY, ENABLE_CLIENT_SASL_DEFAULT));
+    }
+}

Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/client/ZooKeeperSaslClient.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/client/ZooKeeperSaslClient.java?rev=1742002&r1=1742001&r2=1742002&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/client/ZooKeeperSaslClient.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/client/ZooKeeperSaslClient.java Mon May  2 16:15:28 2016
@@ -40,10 +40,10 @@ import javax.security.sasl.SaslException
 
 import org.apache.zookeeper.AsyncCallback;
 import org.apache.zookeeper.ClientCnxn;
-import org.apache.zookeeper.Environment;
 import org.apache.zookeeper.Login;
 import org.apache.zookeeper.Watcher.Event.KeeperState;
 import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.common.ZKConfig;
 import org.apache.zookeeper.data.Stat;
 import org.apache.zookeeper.proto.GetSASLRequest;
 import org.apache.zookeeper.proto.SetSASLResponse;
@@ -58,13 +58,28 @@ import org.slf4j.LoggerFactory;
 
 /**
  * This class manages SASL authentication for the client. It
- * allows ClientCnxn to authenticate using SASL with a Zookeeper server.
+ * allows ClientCnxn to authenticate using SASL with a ZooKeeper server.
  */
 public class ZooKeeperSaslClient {
+    /**
+     * @deprecated Use {@link ZKClientConfig#LOGIN_CONTEXT_NAME_KEY}
+     *             instead.
+     */
+    @Deprecated
     public static final String LOGIN_CONTEXT_NAME_KEY = "zookeeper.sasl.clientconfig";
+    /**
+     * @deprecated Use {@link ZKClientConfig#ENABLE_CLIENT_SASL_KEY}
+     *             instead.
+     */
+    @Deprecated
     public static final String ENABLE_CLIENT_SASL_KEY = "zookeeper.sasl.client";
+    /**
+     * @deprecated Use {@link ZKClientConfig#ENABLE_CLIENT_SASL_DEFAULT}
+     *             instead.
+     */
+    @Deprecated
     public static final String ENABLE_CLIENT_SASL_DEFAULT = "true";
-    private static volatile boolean initializedLogin = false; 
+    private volatile boolean initializedLogin = false; 
 
     /**
      * Returns true if the SASL client is enabled. By default, the client
@@ -72,16 +87,21 @@ public class ZooKeeperSaslClient {
      * <code>zookeeper.sasl.client</code> to <code>false</code>. See
      * ZOOKEEPER-1657 for more information.
      *
-     * @return If the SASL client is enabled.
+     * @return true if the SASL client is enabled.
+     * @deprecated Use {@link ZKClientConfig#isSaslClientEnabled} instead
      */
+    @Deprecated
     public static boolean isEnabled() {
-        return Boolean.valueOf(System.getProperty(ENABLE_CLIENT_SASL_KEY, ENABLE_CLIENT_SASL_DEFAULT));
+        return Boolean.valueOf(System.getProperty(
+                ZKClientConfig.ENABLE_CLIENT_SASL_KEY,
+                ZKClientConfig.ENABLE_CLIENT_SASL_DEFAULT));
     }
 
     private static final Logger LOG = LoggerFactory.getLogger(ZooKeeperSaslClient.class);
-    private static Login login = null;
+    private Login login = null;
     private SaslClient saslClient;
     private boolean isSASLConfigured = true;
+    private final ZKClientConfig clientConfig;
 
     private byte[] saslToken = new byte[0];
 
@@ -105,19 +125,22 @@ public class ZooKeeperSaslClient {
         return null;
     }
 
-    public ZooKeeperSaslClient(final String serverPrincipal)
-            throws LoginException {
+    public ZooKeeperSaslClient(final String serverPrincipal, ZKClientConfig clientConfig) throws LoginException {
         /**
          * ZOOKEEPER-1373: allow system property to specify the JAAS
          * configuration section that the zookeeper client should use.
          * Default to "Client".
          */
-        String clientSection = System.getProperty(ZooKeeperSaslClient.LOGIN_CONTEXT_NAME_KEY, "Client");
+        String clientSection = clientConfig.getProperty(
+                ZKClientConfig.LOGIN_CONTEXT_NAME_KEY,
+                ZKClientConfig.LOGIN_CONTEXT_NAME_KEY_DEFAULT);
+        this.clientConfig = clientConfig;
         // Note that 'Configuration' here refers to javax.security.auth.login.Configuration.
         AppConfigurationEntry entries[] = null;
         RuntimeException runtimeException = null;
         try {
-            entries = Configuration.getConfiguration().getAppConfigurationEntry(clientSection);
+            entries = Configuration.getConfiguration()
+                    .getAppConfigurationEntry(clientSection);
         } catch (SecurityException e) {
             // handle below: might be harmless if the user doesn't intend to use JAAS authentication.
             runtimeException = e;
@@ -134,15 +157,18 @@ public class ZooKeeperSaslClient {
             // Handle situation of clientSection's being null: it might simply because the client does not intend to 
             // use SASL, so not necessarily an error.
             saslState = SaslState.FAILED;
-            String explicitClientSection = System.getProperty(ZooKeeperSaslClient.LOGIN_CONTEXT_NAME_KEY);
+            String explicitClientSection = clientConfig
+                    .getProperty(ZKClientConfig.LOGIN_CONTEXT_NAME_KEY);
             if (explicitClientSection != null) {
                 // If the user explicitly overrides the default Login Context, they probably expected SASL to
                 // succeed. But if we got here, SASL failed.
                 if (runtimeException != null) {
-                    throw new LoginException("Zookeeper client cannot authenticate using the " + explicitClientSection +
-                            " section of the supplied JAAS configuration: '" +
-                            System.getProperty(Environment.JAAS_CONF_KEY) + "' because of a " +
-                            "RuntimeException: " + runtimeException);
+                    throw new LoginException(
+                            "Zookeeper client cannot authenticate using the "
+                                    + explicitClientSection
+                                    + " section of the supplied JAAS configuration: '"
+                                    + clientConfig.getJaasConfKey() + "' because of a "
+                                    + "RuntimeException: " + runtimeException);
                 } else {
                     throw new LoginException("Client cannot SASL-authenticate because the specified JAAS configuration " +
                             "section '" + explicitClientSection + "' could not be found.");
@@ -159,19 +185,26 @@ public class ZooKeeperSaslClient {
                 this.configStatus = msg;
                 this.isSASLConfigured = false;
             }
-            if (System.getProperty(Environment.JAAS_CONF_KEY)  != null) {
-                // Again, the user explicitly set something SASL-related, so they probably expected SASL to succeed.
+            if (clientConfig.getJaasConfKey() != null) {
+                // Again, the user explicitly set something SASL-related, so
+                // they probably expected SASL to succeed.
                 if (runtimeException != null) {
-                    throw new LoginException("Zookeeper client cannot authenticate using the '" +
-                            System.getProperty(ZooKeeperSaslClient.LOGIN_CONTEXT_NAME_KEY, "Client") +
-                            "' section of the supplied JAAS configuration: '" +
-                            System.getProperty(Environment.JAAS_CONF_KEY) + "' because of a " +
-                            "RuntimeException: " + runtimeException);
+                    throw new LoginException(
+                            "Zookeeper client cannot authenticate using the '"
+                                    + clientConfig.getProperty(
+                                            ZKClientConfig.LOGIN_CONTEXT_NAME_KEY,
+                                            ZKClientConfig.LOGIN_CONTEXT_NAME_KEY_DEFAULT)
+                                    + "' section of the supplied JAAS configuration: '"
+                                    + clientConfig.getJaasConfKey() + "' because of a "
+                                    + "RuntimeException: " + runtimeException);
                 } else {
-                    throw new LoginException("No JAAS configuration section named '" +
-                            System.getProperty(ZooKeeperSaslClient.LOGIN_CONTEXT_NAME_KEY, "Client") +
-                            "' was found in specified JAAS configuration file: '" +
-                            System.getProperty(Environment.JAAS_CONF_KEY) + "'.");
+                    throw new LoginException(
+                            "No JAAS configuration section named '"
+                                    + clientConfig.getProperty(
+                                            ZKClientConfig.LOGIN_CONTEXT_NAME_KEY,
+                                            ZKClientConfig.LOGIN_CONTEXT_NAME_KEY_DEFAULT)
+                                    + "' was found in specified JAAS configuration file: '"
+                                    + clientConfig.getJaasConfKey() + "'.");
                 }
             }
         }
@@ -215,18 +248,18 @@ public class ZooKeeperSaslClient {
         }
     }
 
-    private SaslClient createSaslClient(final String servicePrincipal,
-                                                     final String loginContext) throws LoginException {
+    private SaslClient createSaslClient(final String servicePrincipal, final String loginContext)
+            throws LoginException {
         try {
             if (!initializedLogin) {
-                synchronized (ZooKeeperSaslClient.class) {
+                synchronized (this) {
                     if (login == null) {
                         if (LOG.isDebugEnabled()) {
                             LOG.debug("JAAS loginContext is: " + loginContext);
                         }
                         // note that the login object is static: it's shared amongst all zookeeper-related connections.
                         // in order to ensure the login is initialized only once, it must be synchronized the code snippet.
-                        login = new Login(loginContext, new ClientCallbackHandler(null));
+                        login = new Login(loginContext, new ClientCallbackHandler(null), clientConfig);
                         login.startThreadIfNeeded();
                         initializedLogin = true;
                     }
@@ -247,8 +280,7 @@ public class ZooKeeperSaslClient {
                 return saslClient;
             }
             else { // GSSAPI.
-            	boolean usingNativeJgss =
-            			Boolean.getBoolean("sun.security.jgss.native");
+                boolean usingNativeJgss = clientConfig.getBoolean(ZKConfig.JGSS_NATIVE);
             	if (usingNativeJgss) {
             		// http://docs.oracle.com/javase/6/docs/technotes/guides/security/jgss/jgss-features.html
             		// """
@@ -280,7 +312,9 @@ public class ZooKeeperSaslClient {
                 final KerberosName clientKerberosName = new KerberosName(clientPrincipal.getName());
                 // assume that server and client are in the same realm (by default; unless the system property
                 // "zookeeper.server.realm" is set).
-                String serverRealm = System.getProperty("zookeeper.server.realm",clientKerberosName.getRealm());
+                String serverRealm = clientConfig.getProperty(
+                        ZKClientConfig.ZOOKEEPER_SERVER_REALM,
+                        clientKerberosName.getRealm());
                 KerberosName serviceKerberosName = new KerberosName(servicePrincipal+"@"+serverRealm);
                 final String serviceName = serviceKerberosName.getServiceName();
                 final String serviceHostname = serviceKerberosName.getHostName();
@@ -548,12 +582,10 @@ public class ZooKeeperSaslClient {
         // variable or method in this class to determine whether the client is
         // configured to use SASL. (see also ZOOKEEPER-1455).
         try {
-  	    if ((System.getProperty(Environment.JAAS_CONF_KEY) != null) ||
-              ((javax.security.auth.login.Configuration.getConfiguration() != null) &&
-                  (javax.security.auth.login.Configuration.getConfiguration().
-                       getAppConfigurationEntry(System.
-                       getProperty(ZooKeeperSaslClient.LOGIN_CONTEXT_NAME_KEY,"Client")) 
-                           != null))) {
+            if ((clientConfig.getJaasConfKey() != null)
+                    || ((Configuration.getConfiguration() != null) && (Configuration.getConfiguration()
+                            .getAppConfigurationEntry(clientConfig.getProperty(ZKClientConfig.LOGIN_CONTEXT_NAME_KEY,
+                                    ZKClientConfig.LOGIN_CONTEXT_NAME_KEY_DEFAULT)) != null))) {
                 // Client is configured to use a valid login Configuration, so
                 // authentication is either in progress, successful, or failed.
 

Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/common/X509Util.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/common/X509Util.java?rev=1742002&r1=1742001&r2=1742002&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/common/X509Util.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/common/X509Util.java Mon May  2 16:15:28 2016
@@ -43,18 +43,53 @@ import static org.apache.zookeeper.commo
 public class X509Util {
     private static final Logger LOG = LoggerFactory.getLogger(X509Util.class);
 
+    /**
+     * @deprecated Use {@link ZKConfig#SSL_KEYSTORE_LOCATION}
+     *             instead.
+     */
+    @Deprecated
     public static final String SSL_KEYSTORE_LOCATION = "zookeeper.ssl.keyStore.location";
+    /**
+     * @deprecated Use {@link ZKConfig#SSL_KEYSTORE_PASSWD}
+     *             instead.
+     */
+    @Deprecated
     public static final String SSL_KEYSTORE_PASSWD = "zookeeper.ssl.keyStore.password";
+    /**
+     * @deprecated Use {@link ZKConfig#SSL_TRUSTSTORE_LOCATION}
+     *             instead.
+     */
+    @Deprecated
     public static final String SSL_TRUSTSTORE_LOCATION = "zookeeper.ssl.trustStore.location";
+    /**
+     * @deprecated Use {@link ZKConfig#SSL_TRUSTSTORE_PASSWD}
+     *             instead.
+     */
+    @Deprecated
     public static final String SSL_TRUSTSTORE_PASSWD = "zookeeper.ssl.trustStore.password";
+    /**
+     * @deprecated Use {@link ZKConfig#SSL_AUTHPROVIDER}
+     *             instead.
+     */
+    @Deprecated
     public static final String SSL_AUTHPROVIDER = "zookeeper.ssl.authProvider";
 
     public static SSLContext createSSLContext() throws SSLContextException {
+        /**
+         * Since Configuration initializes the key store and trust store related
+         * configuration from system property. Reading property from
+         * configuration will be same reading from system property
+         */
+        ZKConfig config=new ZKConfig();
+        return createSSLContext(config);
+    }
+
+    public static SSLContext createSSLContext(ZKConfig config) throws SSLContextException {
         KeyManager[] keyManagers = null;
         TrustManager[] trustManagers = null;
 
-        String keyStoreLocationProp = System.getProperty(SSL_KEYSTORE_LOCATION);
-        String keyStorePasswordProp = System.getProperty(SSL_KEYSTORE_PASSWD);
+        String keyStoreLocationProp = config.getProperty(ZKConfig.SSL_KEYSTORE_LOCATION);
+        String keyStorePasswordProp = config.getProperty(ZKConfig.SSL_KEYSTORE_PASSWD);
 
         // There are legal states in some use cases for null KeyManager or TrustManager.
         // But if a user wanna specify one, location and password are required.
@@ -76,8 +111,8 @@ public class X509Util {
             }
         }
 
-        String trustStoreLocationProp = System.getProperty(SSL_TRUSTSTORE_LOCATION);
-        String trustStorePasswordProp = System.getProperty(SSL_TRUSTSTORE_PASSWD);
+        String trustStoreLocationProp = config.getProperty(ZKConfig.SSL_TRUSTSTORE_LOCATION);
+        String trustStorePasswordProp = config.getProperty(ZKConfig.SSL_TRUSTSTORE_PASSWD);
 
         if (trustStoreLocationProp == null && trustStorePasswordProp == null) {
             LOG.warn("keystore not specified for client connection");

Added: zookeeper/trunk/src/java/main/org/apache/zookeeper/common/ZKConfig.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/common/ZKConfig.java?rev=1742002&view=auto
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/common/ZKConfig.java (added)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/common/ZKConfig.java Mon May  2 16:15:28 2016
@@ -0,0 +1,226 @@
+/**
+ * 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.common;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+
+import org.apache.zookeeper.Environment;
+import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException;
+import org.apache.zookeeper.server.util.VerifyingFileFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class is a base class for the configurations of both client and server.
+ * It supports reading client configuration from both system properties and
+ * configuration file. A user can override any system property by calling
+ * {@link #setProperty(String, String)}.
+ * @since 3.5.2
+ */
+public class ZKConfig {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ZKConfig.class);
+    @SuppressWarnings("deprecation")
+    public static final String SSL_KEYSTORE_LOCATION = X509Util.SSL_KEYSTORE_LOCATION;
+    @SuppressWarnings("deprecation")
+    public static final String SSL_KEYSTORE_PASSWD = X509Util.SSL_KEYSTORE_PASSWD;
+    @SuppressWarnings("deprecation")
+    public static final String SSL_TRUSTSTORE_LOCATION = X509Util.SSL_TRUSTSTORE_LOCATION;
+    @SuppressWarnings("deprecation")
+    public static final String SSL_TRUSTSTORE_PASSWD = X509Util.SSL_TRUSTSTORE_PASSWD;
+    @SuppressWarnings("deprecation")
+    public static final String SSL_AUTHPROVIDER = X509Util.SSL_AUTHPROVIDER;
+    public static final String JUTE_MAXBUFFER = "jute.maxbuffer";
+    /**
+     * Path to a kinit binary: {@value}. Defaults to
+     * <code>"/usr/bin/kinit"</code>
+     */
+    public static final String KINIT_COMMAND = "zookeeper.kinit";
+    public static final String JGSS_NATIVE = "sun.security.jgss.native";
+
+    private final Map<String, String> properties = new HashMap<String, String>();
+
+    /**
+     * properties, which are common to both client and server, are initialized
+     * from system properties
+     */
+    public ZKConfig() {
+        init();
+    }
+
+    /**
+     * @param configPath
+     *            Configuration file path
+     * @throws ConfigException
+     *             if failed to load configuration properties
+     */
+
+    public ZKConfig(String configPath) throws ConfigException {
+        this(new File(configPath));
+    }
+
+    /**
+     *
+     * @param configFile
+     *            Configuration file
+     * @throws ConfigException
+     *             if failed to load configuration properties
+     */
+    public ZKConfig(File configFile) throws ConfigException {
+        this();
+        addConfiguration(configFile);
+    }
+
+    private void init() {
+        /**
+         * backward compatibility for all currently available client properties
+         */
+        handleBackwardCompatibility();
+    }
+
+    /**
+     * Now onwards client code will use properties from this class but older
+     * clients still be setting properties through system properties. So to make
+     * this change backward compatible we should set old system properties in
+     * this configuration.
+     */
+    protected void handleBackwardCompatibility() {
+        properties.put(SSL_KEYSTORE_LOCATION, System.getProperty(SSL_KEYSTORE_LOCATION));
+        properties.put(SSL_KEYSTORE_PASSWD, System.getProperty(SSL_KEYSTORE_PASSWD));
+        properties.put(SSL_TRUSTSTORE_LOCATION, System.getProperty(SSL_TRUSTSTORE_LOCATION));
+        properties.put(SSL_TRUSTSTORE_PASSWD, System.getProperty(SSL_TRUSTSTORE_PASSWD));
+        properties.put(SSL_AUTHPROVIDER, System.getProperty(SSL_AUTHPROVIDER));
+        properties.put(JUTE_MAXBUFFER, System.getProperty(JUTE_MAXBUFFER));
+        properties.put(KINIT_COMMAND, System.getProperty(KINIT_COMMAND));
+        properties.put(JGSS_NATIVE, System.getProperty(JGSS_NATIVE));
+    }
+
+    /**
+     * Get the property value
+     *
+     * @param key
+     * @return property value
+     */
+    public String getProperty(String key) {
+        return properties.get(key);
+    }
+
+    /**
+     * Get the property value, if it is null return default value
+     *
+     * @param key
+     *            property key
+     * @param defaultValue
+     * @return property value or default value
+     */
+    public String getProperty(String key, String defaultValue) {
+        String value = properties.get(key);
+        return (value == null) ? defaultValue : value;
+    }
+
+    /**
+     * Return the value of "java.security.auth.login.config" system property
+     *
+     * @return value
+     */
+    public String getJaasConfKey() {
+        return System.getProperty(Environment.JAAS_CONF_KEY);
+    }
+
+    /**
+     * Maps the specified <code>key</code> to the specified <code>value</code>.
+     * key can not be <code>null</code>. If key is already mapped then the old
+     * value of the <code>key</code> is replaced by the specified
+     * <code>value</code>.
+     * 
+     * @param key
+     * @param value
+     */
+    public void setProperty(String key, String value) {
+        if (null == key) {
+            throw new IllegalArgumentException("property key is null.");
+        }
+        String oldValue = properties.put(key, value);
+        if (LOG.isDebugEnabled()) {
+            if (null != oldValue && !oldValue.equals(value)) {
+                LOG.debug("key {}'s value {} is replaced with new value {}", key, oldValue, value);
+            }
+        }
+    }
+
+    /**
+     * Add a configuration resource. The properties form this configuration will
+     * overwrite corresponding already loaded property and system property
+     *
+     * @param configFile
+     *            Configuration file.
+     */
+    public void addConfiguration(File configFile) throws ConfigException {
+        LOG.info("Reading configuration from: {}", configFile.getAbsolutePath());
+        try {
+            configFile = (new VerifyingFileFactory.Builder(LOG).warnForRelativePath().failForNonExistingPath().build())
+                    .validate(configFile);
+            Properties cfg = new Properties();
+            FileInputStream in = new FileInputStream(configFile);
+            try {
+                cfg.load(in);
+            } finally {
+                in.close();
+            }
+            parseProperties(cfg);
+        } catch (IOException | IllegalArgumentException e) {
+            LOG.error("Error while configuration from: {}", configFile.getAbsolutePath(), e);
+            throw new ConfigException("Error while processing " + configFile.getAbsolutePath(), e);
+        }
+    }
+
+    /**
+     * Add a configuration resource. The properties form this configuration will
+     * overwrite corresponding already loaded property and system property
+     *
+     * @param configPath
+     *            Configuration file path.
+     */
+    public void addConfiguration(String configPath) throws ConfigException {
+        addConfiguration(new File(configPath));
+    }
+
+    private void parseProperties(Properties cfg) {
+        for (Entry<Object, Object> entry : cfg.entrySet()) {
+            String key = entry.getKey().toString().trim();
+            String value = entry.getValue().toString().trim();
+            setProperty(key, value);
+        }
+    }
+
+    /**
+     * Returns {@code true} if and only if the property named by the argument
+     * exists and is equal to the string {@code "true"}.
+     */
+    public boolean getBoolean(String key) {
+        return Boolean.parseBoolean(getProperty(key));
+    }
+
+}

Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/NettyServerCnxnFactory.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/NettyServerCnxnFactory.java?rev=1742002&r1=1742001&r2=1742002&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/NettyServerCnxnFactory.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/NettyServerCnxnFactory.java Mon May  2 16:15:28 2016
@@ -39,6 +39,7 @@ import javax.net.ssl.X509KeyManager;
 import javax.net.ssl.X509TrustManager;
 
 import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.common.ZKConfig;
 import org.apache.zookeeper.common.X509Exception;
 import org.apache.zookeeper.common.X509Exception.SSLContextException;
 import org.apache.zookeeper.common.X509Util;
@@ -291,7 +292,7 @@ public class NettyServerCnxnFactory exte
                     cnxn.setClientCertificateChain(session.getPeerCertificates());
 
                     String authProviderProp
-                            = System.getProperty(X509Util.SSL_AUTHPROVIDER, "x509");
+                            = System.getProperty(ZKConfig.SSL_AUTHPROVIDER, "x509");
 
                     X509AuthenticationProvider authProvider =
                             (X509AuthenticationProvider)
@@ -351,7 +352,7 @@ public class NettyServerCnxnFactory exte
 
     private synchronized void initSSL(ChannelPipeline p)
             throws X509Exception, KeyManagementException, NoSuchAlgorithmException {
-        String authProviderProp = System.getProperty(X509Util.SSL_AUTHPROVIDER);
+        String authProviderProp = System.getProperty(ZKConfig.SSL_AUTHPROVIDER);
         SSLContext sslContext;
         if (authProviderProp == null) {
             sslContext = X509Util.createSSLContext();
@@ -359,7 +360,7 @@ public class NettyServerCnxnFactory exte
             sslContext = SSLContext.getInstance("TLSv1");
             X509AuthenticationProvider authProvider =
                     (X509AuthenticationProvider)ProviderRegistry.getProvider(
-                            System.getProperty(X509Util.SSL_AUTHPROVIDER,
+                            System.getProperty(ZKConfig.SSL_AUTHPROVIDER,
                                     "x509"));
 
             if (authProvider == null)

Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ServerCnxnFactory.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ServerCnxnFactory.java?rev=1742002&r1=1742001&r2=1742002&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ServerCnxnFactory.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ServerCnxnFactory.java Mon May  2 16:15:28 2016
@@ -33,6 +33,7 @@ import javax.security.auth.login.LoginEx
 
 import org.apache.zookeeper.Environment;
 import org.apache.zookeeper.Login;
+import org.apache.zookeeper.common.ZKConfig;
 import org.apache.zookeeper.jmx.MBeanRegistry;
 import org.apache.zookeeper.server.auth.SaslServerCallbackHandler;
 import org.slf4j.Logger;
@@ -234,7 +235,7 @@ public abstract class ServerCnxnFactory
         // jaas.conf entry available
         try {
             saslServerCallbackHandler = new SaslServerCallbackHandler(Configuration.getConfiguration());
-            login = new Login(serverSection, saslServerCallbackHandler);
+            login = new Login(serverSection, saslServerCallbackHandler, new ZKConfig() );
             login.startThreadIfNeeded();
         } catch (LoginException e) {
             throw new IOException("Could not configure server because SASL configuration did not allow the "

Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/auth/X509AuthenticationProvider.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/auth/X509AuthenticationProvider.java?rev=1742002&r1=1742001&r2=1742002&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/auth/X509AuthenticationProvider.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/auth/X509AuthenticationProvider.java Mon May  2 16:15:28 2016
@@ -26,6 +26,7 @@ import javax.net.ssl.X509TrustManager;
 import javax.security.auth.x500.X500Principal;
 
 import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.common.ZKConfig;
 import org.apache.zookeeper.common.X509Exception.KeyManagerException;
 import org.apache.zookeeper.common.X509Exception.TrustManagerException;
 import org.apache.zookeeper.common.X509Util;
@@ -65,9 +66,9 @@ public class X509AuthenticationProvider
      */
     public X509AuthenticationProvider() {
         String keyStoreLocationProp = System.getProperty(
-                X509Util.SSL_KEYSTORE_LOCATION);
+                ZKConfig.SSL_KEYSTORE_LOCATION);
         String keyStorePasswordProp = System.getProperty(
-                X509Util.SSL_KEYSTORE_PASSWD);
+                ZKConfig.SSL_KEYSTORE_PASSWD);
 
         X509KeyManager km = null;
         X509TrustManager tm = null;
@@ -79,9 +80,9 @@ public class X509AuthenticationProvider
         }
 
         String trustStoreLocationProp = System.getProperty(
-                X509Util.SSL_TRUSTSTORE_LOCATION);
+                ZKConfig.SSL_TRUSTSTORE_LOCATION);
         String trustStorePasswordProp = System.getProperty(
-                X509Util.SSL_TRUSTSTORE_PASSWD);
+                ZKConfig.SSL_TRUSTSTORE_PASSWD);
 
         try {
             tm = X509Util.createTrustManager(

Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/util/VerifyingFileFactory.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/util/VerifyingFileFactory.java?rev=1742002&r1=1742001&r2=1742002&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/util/VerifyingFileFactory.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/util/VerifyingFileFactory.java Mon May  2 16:15:28 2016
@@ -37,6 +37,10 @@ public final class VerifyingFileFactory
 
     public File create(String path) {
         File file = new File(path);
+        return validate(file);
+    }
+
+    public File validate(File file) {
         if(warnForRelativePath) doWarnForRelativePath(file);
         if(failForNonExistingPath) doFailForNonExistingPath(file);
         return file;

Modified: zookeeper/trunk/src/java/test/org/apache/zookeeper/ClientReconnectTest.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/test/org/apache/zookeeper/ClientReconnectTest.java?rev=1742002&r1=1742001&r2=1742002&view=diff
==============================================================================
--- zookeeper/trunk/src/java/test/org/apache/zookeeper/ClientReconnectTest.java (original)
+++ zookeeper/trunk/src/java/test/org/apache/zookeeper/ClientReconnectTest.java Mon May  2 16:15:28 2016
@@ -28,6 +28,7 @@ import java.nio.channels.SocketChannel;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
+import org.apache.zookeeper.client.ZKClientConfig;
 import org.apache.zookeeper.client.HostProvider;
 import org.junit.Assert;
 import org.junit.Test;
@@ -38,7 +39,7 @@ public class ClientReconnectTest extends
     
     class MockCnxn extends ClientCnxnSocketNIO {
         MockCnxn() throws IOException {
-            super();
+            super(new ZKClientConfig());
         }
 
         @Override
@@ -61,6 +62,7 @@ public class ClientReconnectTest extends
         InetSocketAddress inaddr = new InetSocketAddress("127.0.0.1", 1111);
         when(hostProvider.next(anyLong())).thenReturn(inaddr);
         ZooKeeper zk = mock(ZooKeeper.class);
+        when(zk.getClientConfig()).thenReturn(new ZKClientConfig());
         sc =  SocketChannel.open();
 
         ClientCnxnSocketNIO nioCnxn = new MockCnxn();

Modified: zookeeper/trunk/src/java/test/org/apache/zookeeper/RemoveWatchesTest.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/test/org/apache/zookeeper/RemoveWatchesTest.java?rev=1742002&r1=1742001&r2=1742002&view=diff
==============================================================================
--- zookeeper/trunk/src/java/test/org/apache/zookeeper/RemoveWatchesTest.java (original)
+++ zookeeper/trunk/src/java/test/org/apache/zookeeper/RemoveWatchesTest.java Mon May  2 16:15:28 2016
@@ -36,6 +36,7 @@ import org.apache.zookeeper.KeeperExcept
 import org.apache.zookeeper.Watcher.Event.EventType;
 import org.apache.zookeeper.Watcher.WatcherType;
 import org.apache.zookeeper.ZooDefs.Ids;
+import org.apache.zookeeper.client.ZKClientConfig;
 import org.apache.zookeeper.server.ServerCnxn;
 import org.apache.zookeeper.test.ClientBase;
 import org.junit.Assert;
@@ -1111,6 +1112,10 @@ public class RemoveWatchesTest extends C
      * before/after calling removeWatches */
     private class MyZooKeeper extends ZooKeeper {
         class MyWatchManager extends ZKWatchManager {
+            public MyWatchManager(boolean disableAutoWatchReset) {
+                super(disableAutoWatchReset);
+            }
+
             public int lastrc;
 
             /* Pretend that any watcher exists */
@@ -1136,7 +1141,7 @@ public class RemoveWatchesTest extends C
         private MyWatchManager myWatchManager;
 
         protected ZKWatchManager defaultWatchManager() {
-            myWatchManager = new MyWatchManager();
+            myWatchManager = new MyWatchManager(getClientConfig().getBoolean(ZKClientConfig.DISABLE_AUTO_WATCH_RESET));
             return myWatchManager;
         }
 
@@ -1150,7 +1155,7 @@ public class RemoveWatchesTest extends C
         private String eventPath;
         private CountDownLatch latch;
         private List<EventType> eventsAfterWatchRemoval = new ArrayList<EventType>();
-        public MyWatcher(String path, int count) {
+        MyWatcher(String path, int count) {
             this.path = path;
             latch = new CountDownLatch(count);
         }

Added: zookeeper/trunk/src/java/test/org/apache/zookeeper/client/ZKClientConfigTest.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/test/org/apache/zookeeper/client/ZKClientConfigTest.java?rev=1742002&view=auto
==============================================================================
--- zookeeper/trunk/src/java/test/org/apache/zookeeper/client/ZKClientConfigTest.java (added)
+++ zookeeper/trunk/src/java/test/org/apache/zookeeper/client/ZKClientConfigTest.java Mon May  2 16:15:28 2016
@@ -0,0 +1,155 @@
+/**
+ * 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.client;
+
+import static org.apache.zookeeper.client.ZKClientConfig.DISABLE_AUTO_WATCH_RESET;
+import static org.apache.zookeeper.client.ZKClientConfig.ENABLE_CLIENT_SASL_KEY;
+import static org.apache.zookeeper.client.ZKClientConfig.LOGIN_CONTEXT_NAME_KEY;
+import static org.apache.zookeeper.client.ZKClientConfig.SECURE_CLIENT;
+import static org.apache.zookeeper.client.ZKClientConfig.ZK_SASL_CLIENT_USERNAME;
+import static org.apache.zookeeper.client.ZKClientConfig.ZOOKEEPER_CLIENT_CNXN_SOCKET;
+import static org.apache.zookeeper.client.ZKClientConfig.ZOOKEEPER_SERVER_REALM;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.Timeout;
+
+public class ZKClientConfigTest {
+    private static final File testData = new File(System.getProperty("test.data.dir", "build/test/data"));
+    @Rule
+    public Timeout timeout = new Timeout(10, TimeUnit.SECONDS);
+
+    @BeforeClass
+    public static void init() {
+        if (!testData.exists()) {
+            testData.mkdirs();
+        }
+    }
+
+    @Test
+    public void testDefaultConfiguration() {
+        Map<String, String> properties = new HashMap<>();
+        properties.put(ZK_SASL_CLIENT_USERNAME, "zookeeper1");
+        properties.put(LOGIN_CONTEXT_NAME_KEY, "Client1");
+        properties.put(ENABLE_CLIENT_SASL_KEY, "true");
+        properties.put(ZOOKEEPER_SERVER_REALM, "zookeeper/hadoop.hadoop.com");
+        properties.put(DISABLE_AUTO_WATCH_RESET, "true");
+        properties.put(ZOOKEEPER_CLIENT_CNXN_SOCKET, "ClientCnxnSocketNetty");
+        properties.put(SECURE_CLIENT, "true");
+
+        for (Map.Entry<String, String> e : properties.entrySet()) {
+            System.setProperty(e.getKey(), e.getValue());
+        }
+        /**
+         * ZKClientConfig should get initialized with system properties
+         */
+        ZKClientConfig conf = new ZKClientConfig();
+        for (Map.Entry<String, String> e : properties.entrySet()) {
+            assertEquals(e.getValue(), conf.getProperty(e.getKey()));
+        }
+        /**
+         * clear properties
+         */
+        for (Map.Entry<String, String> e : properties.entrySet()) {
+            System.clearProperty(e.getKey());
+        }
+
+        conf = new ZKClientConfig();
+        /**
+         * test that all the properties are null
+         */
+        for (Map.Entry<String, String> e : properties.entrySet()) {
+            String result = conf.getProperty(e.getKey());
+            assertNull(result);
+        }
+    }
+
+    @Test
+    public void testSystemPropertyValue() {
+        String clientName = "zookeeper1";
+        System.setProperty(ZK_SASL_CLIENT_USERNAME, clientName);
+
+        ZKClientConfig conf = new ZKClientConfig();
+        assertEquals(conf.getProperty(ZK_SASL_CLIENT_USERNAME), clientName);
+
+        String newClientName = "zookeeper2";
+        conf.setProperty(ZK_SASL_CLIENT_USERNAME, newClientName);
+
+        assertEquals(conf.getProperty(ZK_SASL_CLIENT_USERNAME), newClientName);
+    }
+
+    @Test
+    public void testReadConfigurationFile() throws IOException, ConfigException {
+        File file = File.createTempFile("clientConfig", ".conf", testData);
+        file.deleteOnExit();
+        Properties clientConfProp = new Properties();
+        clientConfProp.setProperty(ENABLE_CLIENT_SASL_KEY, "true");
+        clientConfProp.setProperty(ZK_SASL_CLIENT_USERNAME, "ZK");
+        clientConfProp.setProperty(LOGIN_CONTEXT_NAME_KEY, "MyClient");
+        clientConfProp.setProperty(ZOOKEEPER_SERVER_REALM, "HADOOP.COM");
+        clientConfProp.setProperty("dummyProperty", "dummyValue");
+        OutputStream io = new FileOutputStream(file);
+        try {
+            clientConfProp.store(io, "Client Configurations");
+        } finally {
+            io.close();
+        }
+
+        ZKClientConfig conf = new ZKClientConfig();
+        conf.addConfiguration(file.getAbsolutePath());
+        assertEquals(conf.getProperty(ENABLE_CLIENT_SASL_KEY), "true");
+        assertEquals(conf.getProperty(ZK_SASL_CLIENT_USERNAME), "ZK");
+        assertEquals(conf.getProperty(LOGIN_CONTEXT_NAME_KEY), "MyClient");
+        assertEquals(conf.getProperty(ZOOKEEPER_SERVER_REALM), "HADOOP.COM");
+        assertEquals(conf.getProperty("dummyProperty"), "dummyValue");
+
+        // try to delete it now as we have done with the created file, why to
+        // wait for deleteOnExit() deletion
+        file.delete();
+
+    }
+
+    @Test
+    public void testSetConfiguration() {
+        ZKClientConfig conf = new ZKClientConfig();
+        String defaultValue = conf.getProperty(ZKClientConfig.ENABLE_CLIENT_SASL_KEY,
+                ZKClientConfig.ENABLE_CLIENT_SASL_DEFAULT);
+        if (defaultValue.equals("true")) {
+            conf.setProperty(ENABLE_CLIENT_SASL_KEY, "false");
+        } else {
+            conf.setProperty(ENABLE_CLIENT_SASL_KEY, "true");
+        }
+        assertTrue(conf.getProperty(ENABLE_CLIENT_SASL_KEY) != defaultValue);
+    }
+
+}

Modified: zookeeper/trunk/src/java/test/org/apache/zookeeper/test/NettyNettySuiteBase.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/NettyNettySuiteBase.java?rev=1742002&r1=1742001&r2=1742002&view=diff
==============================================================================
--- zookeeper/trunk/src/java/test/org/apache/zookeeper/test/NettyNettySuiteBase.java (original)
+++ zookeeper/trunk/src/java/test/org/apache/zookeeper/test/NettyNettySuiteBase.java Mon May  2 16:15:28 2016
@@ -19,7 +19,7 @@
 package org.apache.zookeeper.test;
 
 import org.apache.zookeeper.ClientCnxnSocketNetty;
-import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.client.ZKClientConfig;
 import org.apache.zookeeper.server.NettyServerCnxnFactory;
 import org.apache.zookeeper.server.ServerCnxnFactory;
 import org.junit.AfterClass;
@@ -36,7 +36,7 @@ public class NettyNettySuiteBase {
     public static void setUp() {
         System.setProperty(ServerCnxnFactory.ZOOKEEPER_SERVER_CNXN_FACTORY,
                 NettyServerCnxnFactory.class.getName());
-        System.setProperty(ZooKeeper.ZOOKEEPER_CLIENT_CNXN_SOCKET,
+        System.setProperty(ZKClientConfig.ZOOKEEPER_CLIENT_CNXN_SOCKET,
                 ClientCnxnSocketNetty.class.getName());
         System.setProperty("zookeeper.admin.enableServer", "false");
     }
@@ -44,6 +44,6 @@ public class NettyNettySuiteBase {
     @AfterClass
     public static void tearDown() {
         System.clearProperty(ServerCnxnFactory.ZOOKEEPER_SERVER_CNXN_FACTORY);
-        System.clearProperty(ZooKeeper.ZOOKEEPER_CLIENT_CNXN_SOCKET);
+        System.clearProperty(ZKClientConfig.ZOOKEEPER_CLIENT_CNXN_SOCKET);
     }
 }



Mime
View raw message