Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 09663200ACC for ; Mon, 2 May 2016 18:18:40 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 0607B1609B0; Mon, 2 May 2016 18:18:40 +0200 (CEST) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id AB4491609A6 for ; Mon, 2 May 2016 18:18:37 +0200 (CEST) Received: (qmail 22095 invoked by uid 500); 2 May 2016 16:18:36 -0000 Mailing-List: contact commits-help@zookeeper.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@ Delivered-To: mailing list commits@zookeeper.apache.org Received: (qmail 22084 invoked by uid 99); 2 May 2016 16:18:36 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd2-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 02 May 2016 16:18:36 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd2-us-west.apache.org (ASF Mail Server at spamd2-us-west.apache.org) with ESMTP id 449911A0B05 for ; Mon, 2 May 2016 16:18:36 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd2-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 1.799 X-Spam-Level: * X-Spam-Status: No, score=1.799 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RP_MATCHES_RCVD=-0.001] autolearn=disabled Received: from mx1-lw-us.apache.org ([10.40.0.8]) by localhost (spamd2-us-west.apache.org [10.40.0.9]) (amavisd-new, port 10024) with ESMTP id HO6o9i2bq4dv for ; Mon, 2 May 2016 16:18:27 +0000 (UTC) Received: from mailrelay1-us-west.apache.org (mailrelay1-us-west.apache.org [209.188.14.139]) by mx1-lw-us.apache.org (ASF Mail Server at mx1-lw-us.apache.org) with ESMTP id 697105F24F for ; Mon, 2 May 2016 16:18:26 +0000 (UTC) Received: from svn01-us-west.apache.org (svn.apache.org [10.41.0.6]) by mailrelay1-us-west.apache.org (ASF Mail Server at mailrelay1-us-west.apache.org) with ESMTP id 98C55E03BB for ; Mon, 2 May 2016 16:18:25 +0000 (UTC) Received: from svn01-us-west.apache.org (localhost [127.0.0.1]) by svn01-us-west.apache.org (ASF Mail Server at svn01-us-west.apache.org) with ESMTP id A4DC63A0056 for ; Mon, 2 May 2016 16:18:24 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1742003 [1/2] - in /zookeeper/branches/branch-3.5: ./ 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/ap... Date: Mon, 02 May 2016 16:18:23 -0000 To: commits@zookeeper.apache.org From: fpj@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20160502161824.A4DC63A0056@svn01-us-west.apache.org> archived-at: Mon, 02 May 2016 16:18:40 -0000 Author: fpj Date: Mon May 2 16:18:22 2016 New Revision: 1742003 URL: http://svn.apache.org/viewvc?rev=1742003&view=rev Log: ZOOKEEPER-2139: Support multiple ZooKeeper client with different configurations in a single JVM (Arshad Mohammad via fpj) Added: zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/client/ZKClientConfig.java zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/common/ZKConfig.java zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/client/ zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/client/ZKClientConfigTest.java Modified: zookeeper/branches/branch-3.5/CHANGES.txt zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ClientCnxn.java zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ClientCnxnSocket.java zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ClientCnxnSocketNIO.java zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ClientCnxnSocketNetty.java zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/Login.java zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ZooKeeper.java zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ZooKeeperMain.java zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/client/ZooKeeperSaslClient.java zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/common/X509Util.java zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/NettyServerCnxnFactory.java zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/ServerCnxnFactory.java zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/auth/X509AuthenticationProvider.java zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/util/VerifyingFileFactory.java zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/ClientReconnectTest.java zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/RemoveWatchesTest.java zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/test/NettyNettySuiteBase.java zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/test/SSLAuthTest.java zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/test/SSLTest.java zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/test/SaslAuthDesignatedClientTest.java zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/test/SaslAuthFailDesignatedClientTest.java zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/test/SaslAuthMissingClientConfigTest.java zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/test/SaslClientTest.java zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/test/WatcherTest.java Modified: zookeeper/branches/branch-3.5/CHANGES.txt URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/CHANGES.txt?rev=1742003&r1=1742002&r2=1742003&view=diff ============================================================================== --- zookeeper/branches/branch-3.5/CHANGES.txt (original) +++ zookeeper/branches/branch-3.5/CHANGES.txt Mon May 2 16:18:22 2016 @@ -175,6 +175,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.1 - 07/27/2015 Modified: zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ClientCnxn.java URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ClientCnxn.java?rev=1742003&r1=1742002&r2=1742003&view=diff ============================================================================== --- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ClientCnxn.java (original) +++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ClientCnxn.java Mon May 2 16:18:22 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 dataWatches = zooKeeper.getDataWatches(); List existWatches = zooKeeper.getExistWatches(); List 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/branches/branch-3.5/src/java/main/org/apache/zookeeper/ClientCnxnSocket.java URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ClientCnxnSocket.java?rev=1742003&r1=1742002&r2=1742003&view=diff ============================================================================== --- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ClientCnxnSocket.java (original) +++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ClientCnxnSocket.java Mon May 2 16:18:22 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 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/branches/branch-3.5/src/java/main/org/apache/zookeeper/ClientCnxnSocketNIO.java URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ClientCnxnSocketNIO.java?rev=1742003&r1=1742002&r2=1742003&view=diff ============================================================================== --- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ClientCnxnSocketNIO.java (original) +++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ClientCnxnSocketNIO.java Mon May 2 16:18:22 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/branches/branch-3.5/src/java/main/org/apache/zookeeper/ClientCnxnSocketNetty.java URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ClientCnxnSocketNetty.java?rev=1742003&r1=1742002&r2=1742003&view=diff ============================================================================== --- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ClientCnxnSocketNetty.java (original) +++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ClientCnxnSocketNetty.java Mon May 2 16:18:22 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: *

@@ -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/branches/branch-3.5/src/java/main/org/apache/zookeeper/Login.java URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/Login.java?rev=1742003&r1=1742002&r2=1742003&view=diff ============================================================================== --- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/Login.java (original) +++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/Login.java Mon May 2 16:18:22 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/branches/branch-3.5/src/java/main/org/apache/zookeeper/ZooKeeper.java URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ZooKeeper.java?rev=1742003&r1=1742002&r2=1742003&view=diff ============================================================================== --- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ZooKeeper.java (original) +++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ZooKeeper.java Mon May 2 16:18:22 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 getDataWatches() { synchronized(watchManager.dataWatches) { List rc = new ArrayList(watchManager.dataWatches.keySet()); @@ -235,6 +254,11 @@ public class ZooKeeper { new HashMap>(); private final Map> childWatches = new HashMap>(); + 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 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. + *

+ * 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. + *

+ * 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. + *

+ * 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). *

* 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. + *

+ * 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. + *

+ * 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. + *

+ * 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). + *

+ * 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. + *

+ * 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 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. + *

+ * 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. + *

+ * 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). *

* 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 ? "" : "")); + 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/branches/branch-3.5/src/java/main/org/apache/zookeeper/ZooKeeperMain.java URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ZooKeeperMain.java?rev=1742003&r1=1742002&r2=1742003&view=diff ============================================================================== --- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ZooKeeperMain.java (original) +++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/ZooKeeperMain.java Mon May 2 16:18:22 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/branches/branch-3.5/src/java/main/org/apache/zookeeper/client/ZKClientConfig.java URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/client/ZKClientConfig.java?rev=1742003&view=auto ============================================================================== --- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/client/ZKClientConfig.java (added) +++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/client/ZKClientConfig.java Mon May 2 16:18:22 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 + * zookeeper.sasl.client to false. 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/branches/branch-3.5/src/java/main/org/apache/zookeeper/client/ZooKeeperSaslClient.java URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/client/ZooKeeperSaslClient.java?rev=1742003&r1=1742002&r2=1742003&view=diff ============================================================================== --- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/client/ZooKeeperSaslClient.java (original) +++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/client/ZooKeeperSaslClient.java Mon May 2 16:18:22 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 { * zookeeper.sasl.client to false. 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/branches/branch-3.5/src/java/main/org/apache/zookeeper/common/X509Util.java URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/common/X509Util.java?rev=1742003&r1=1742002&r2=1742003&view=diff ============================================================================== --- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/common/X509Util.java (original) +++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/common/X509Util.java Mon May 2 16:18:22 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/branches/branch-3.5/src/java/main/org/apache/zookeeper/common/ZKConfig.java URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/common/ZKConfig.java?rev=1742003&view=auto ============================================================================== --- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/common/ZKConfig.java (added) +++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/common/ZKConfig.java Mon May 2 16:18:22 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 + * "/usr/bin/kinit" + */ + public static final String KINIT_COMMAND = "zookeeper.kinit"; + public static final String JGSS_NATIVE = "sun.security.jgss.native"; + + private final Map properties = new HashMap(); + + /** + * 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 key to the specified value. + * key can not be null. If key is already mapped then the old + * value of the key is replaced by the specified + * value. + * + * @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 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/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/NettyServerCnxnFactory.java URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/NettyServerCnxnFactory.java?rev=1742003&r1=1742002&r2=1742003&view=diff ============================================================================== --- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/NettyServerCnxnFactory.java (original) +++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/NettyServerCnxnFactory.java Mon May 2 16:18:22 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/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/ServerCnxnFactory.java URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/ServerCnxnFactory.java?rev=1742003&r1=1742002&r2=1742003&view=diff ============================================================================== --- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/ServerCnxnFactory.java (original) +++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/ServerCnxnFactory.java Mon May 2 16:18:22 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/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/auth/X509AuthenticationProvider.java URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/auth/X509AuthenticationProvider.java?rev=1742003&r1=1742002&r2=1742003&view=diff ============================================================================== --- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/auth/X509AuthenticationProvider.java (original) +++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/auth/X509AuthenticationProvider.java Mon May 2 16:18:22 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/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/util/VerifyingFileFactory.java URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/util/VerifyingFileFactory.java?rev=1742003&r1=1742002&r2=1742003&view=diff ============================================================================== --- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/util/VerifyingFileFactory.java (original) +++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/util/VerifyingFileFactory.java Mon May 2 16:18:22 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/branches/branch-3.5/src/java/test/org/apache/zookeeper/ClientReconnectTest.java URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/ClientReconnectTest.java?rev=1742003&r1=1742002&r2=1742003&view=diff ============================================================================== --- zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/ClientReconnectTest.java (original) +++ zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/ClientReconnectTest.java Mon May 2 16:18:22 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/branches/branch-3.5/src/java/test/org/apache/zookeeper/RemoveWatchesTest.java URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/RemoveWatchesTest.java?rev=1742003&r1=1742002&r2=1742003&view=diff ============================================================================== --- zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/RemoveWatchesTest.java (original) +++ zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/RemoveWatchesTest.java Mon May 2 16:18:22 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 eventsAfterWatchRemoval = new ArrayList(); - public MyWatcher(String path, int count) { + MyWatcher(String path, int count) { this.path = path; latch = new CountDownLatch(count); } Added: zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/client/ZKClientConfigTest.java URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/client/ZKClientConfigTest.java?rev=1742003&view=auto ============================================================================== --- zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/client/ZKClientConfigTest.java (added) +++ zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/client/ZKClientConfigTest.java Mon May 2 16:18:22 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 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 e : properties.entrySet()) { + System.setProperty(e.getKey(), e.getValue()); + } + /** + * ZKClientConfig should get initialized with system properties + */ + ZKClientConfig conf = new ZKClientConfig(); + for (Map.Entry e : properties.entrySet()) { + assertEquals(e.getValue(), conf.getProperty(e.getKey())); + } + /** + * clear properties + */ + for (Map.Entry e : properties.entrySet()) { + System.clearProperty(e.getKey()); + } + + conf = new ZKClientConfig(); + /** + * test that all the properties are null + */ + for (Map.Entry 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/branches/branch-3.5/src/java/test/org/apache/zookeeper/test/NettyNettySuiteBase.java URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/test/NettyNettySuiteBase.java?rev=1742003&r1=1742002&r2=1742003&view=diff ============================================================================== --- zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/test/NettyNettySuiteBase.java (original) +++ zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/test/NettyNettySuiteBase.java Mon May 2 16:18:22 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); } }