This is an automated email from the ASF dual-hosted git repository.
ddiederen pushed a commit to branch branch-3.8
in repository https://gitbox.apache.org/repos/asf/zookeeper.git
The following commit(s) were added to refs/heads/branch-3.8 by this push:
new 5da65c999 ZOOKEEPER-4850: Enhance zkCli Tool to Support Reading and
Writing Binary Data
5da65c999 is described below
commit 5da65c9995880b4712be07b91651eede4bd9f42f
Author: 萧易客 <[email protected]>
AuthorDate: Mon Aug 19 19:08:27 2024 +0800
ZOOKEEPER-4850: Enhance zkCli Tool to Support Reading and Writing Binary
Data
Add license header
Fix Checkstyle violation
Improve get set command usage
Remove redundant characters in set command usage
Separate command syntax and detailed usage, prevent break overall usage
message.
Reviewers: eolivelli, shoothzj, ztzg
Author: Shawyeok
Closes #2180 from Shawyeok/enhanced-get-set-command
(cherry picked from commit b64146d3d337e830f8fd4f5ce6a960a50b9e363c)
Signed-off-by: Damien Diederen <[email protected]>
---
.../zookeeper/cli/Base64OutputFormatter.java | 31 ++++++++++++++++
.../java/org/apache/zookeeper/cli/CliCommand.java | 18 +++++++++-
.../apache/zookeeper/cli/CommandUsageHelper.java | 42 ++++++++++++++++++++++
.../java/org/apache/zookeeper/cli/GetCommand.java | 18 +++++++---
.../zookeeper/cli/HexDumpOutputFormatter.java | 34 ++++++++++++++++++
.../org/apache/zookeeper/cli/OutputFormatter.java | 24 +++++++++++++
.../apache/zookeeper/cli/PlainOutputFormatter.java | 31 ++++++++++++++++
.../java/org/apache/zookeeper/cli/SetCommand.java | 15 +++++---
8 files changed, 203 insertions(+), 10 deletions(-)
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/cli/Base64OutputFormatter.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/Base64OutputFormatter.java
new file mode 100644
index 000000000..a2224beac
--- /dev/null
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/Base64OutputFormatter.java
@@ -0,0 +1,31 @@
+/*
+ * 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.cli;
+
+import java.util.Base64;
+
+public class Base64OutputFormatter implements OutputFormatter {
+
+ public static final Base64OutputFormatter INSTANCE = new
Base64OutputFormatter();
+
+ @Override
+ public String format(byte[] data) {
+ return Base64.getEncoder().encodeToString(data);
+ }
+}
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/cli/CliCommand.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/CliCommand.java
index 6386bb9b4..192841f84 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/cli/CliCommand.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/CliCommand.java
@@ -20,6 +20,8 @@ package org.apache.zookeeper.cli;
import java.io.PrintStream;
import java.util.Map;
+import javax.annotation.Nullable;
+import org.apache.commons.cli.Options;
import org.apache.zookeeper.ZooKeeper;
/**
@@ -32,6 +34,8 @@ public abstract class CliCommand {
protected PrintStream err;
private String cmdStr;
private String optionStr;
+ @Nullable
+ private Options options;
/**
* a CLI command with command string and options.
@@ -40,10 +44,22 @@ public abstract class CliCommand {
* @param optionStr the string used to call this command
*/
public CliCommand(String cmdStr, String optionStr) {
+ this(cmdStr, optionStr, null);
+ }
+
+ /**
+ * a CLI command with command string and options.
+ * Using System.out and System.err for printing
+ * @param cmdStr the string used to call this command
+ * @param optionStr the string used to call this command
+ * @param options the command options
+ */
+ public CliCommand(String cmdStr, String optionStr, Options options) {
this.out = System.out;
this.err = System.err;
this.cmdStr = cmdStr;
this.optionStr = optionStr;
+ this.options = options;
}
/**
@@ -88,7 +104,7 @@ public abstract class CliCommand {
* get a usage string, contains the command and the options
*/
public String getUsageStr() {
- return cmdStr + " " + optionStr;
+ return CommandUsageHelper.getUsage(cmdStr + " " + optionStr, options);
}
/**
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/cli/CommandUsageHelper.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/CommandUsageHelper.java
new file mode 100644
index 000000000..95eb13569
--- /dev/null
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/CommandUsageHelper.java
@@ -0,0 +1,42 @@
+/*
+ * 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.cli;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import javax.annotation.Nullable;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Options;
+
+public class CommandUsageHelper {
+
+ public static String getUsage(String commandSyntax, @Nullable Options
options) {
+ StringBuilder buffer = new StringBuilder();
+ buffer.append(commandSyntax);
+ if (options != null && !options.getOptions().isEmpty()) {
+ buffer.append(System.lineSeparator());
+ StringWriter out = new StringWriter();
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printOptions(new PrintWriter(out), formatter.getWidth(),
options, formatter.getLeftPadding(),
+ formatter.getDescPadding());
+ buffer.append(out);
+ }
+ return buffer.toString();
+ }
+}
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/cli/GetCommand.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/GetCommand.java
index a10272e6b..2de0a0bde 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/cli/GetCommand.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/GetCommand.java
@@ -18,7 +18,6 @@
package org.apache.zookeeper.cli;
-import static java.nio.charset.StandardCharsets.UTF_8;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Options;
@@ -36,12 +35,14 @@ public class GetCommand extends CliCommand {
private CommandLine cl;
static {
- options.addOption("s", false, "stats");
- options.addOption("w", false, "watch");
+ options.addOption("s", false, "Print znode stats additionally");
+ options.addOption("w", false, "Watch for changes on the znode");
+ options.addOption("b", false, "Output data in base64 format");
+ options.addOption("x", false, "Output data in hexdump format");
}
public GetCommand() {
- super("get", "[-s] [-w] path");
+ super("get", "[-s] [-w] [-b] [-x] path", options);
}
@Override
@@ -92,8 +93,15 @@ public class GetCommand extends CliCommand {
} catch (KeeperException | InterruptedException ex) {
throw new CliWrapperException(ex);
}
+ OutputFormatter formatter = PlainOutputFormatter.INSTANCE;
+ if (cl.hasOption("b")) {
+ formatter = Base64OutputFormatter.INSTANCE;
+ }
+ if (cl.hasOption("x")) {
+ formatter = HexDumpOutputFormatter.INSTANCE;
+ }
data = (data == null) ? "null".getBytes() : data;
- out.println(new String(data, UTF_8));
+ out.println(formatter.format(data));
if (cl.hasOption("s")) {
new StatPrinter(out).print(stat);
}
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/cli/HexDumpOutputFormatter.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/HexDumpOutputFormatter.java
new file mode 100644
index 000000000..d545a422e
--- /dev/null
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/HexDumpOutputFormatter.java
@@ -0,0 +1,34 @@
+/*
+ * 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.cli;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.buffer.Unpooled;
+
+public class HexDumpOutputFormatter implements OutputFormatter {
+
+ public static final HexDumpOutputFormatter INSTANCE = new
HexDumpOutputFormatter();
+
+ @Override
+ public String format(byte[] data) {
+ ByteBuf buf = Unpooled.wrappedBuffer(data);
+ return ByteBufUtil.prettyHexDump(buf);
+ }
+}
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/cli/OutputFormatter.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/OutputFormatter.java
new file mode 100644
index 000000000..d306ac42f
--- /dev/null
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/OutputFormatter.java
@@ -0,0 +1,24 @@
+/*
+ * 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.cli;
+
+public interface OutputFormatter {
+
+ String format(byte[] data);
+}
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/cli/PlainOutputFormatter.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/PlainOutputFormatter.java
new file mode 100644
index 000000000..c536f2ba9
--- /dev/null
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/PlainOutputFormatter.java
@@ -0,0 +1,31 @@
+/*
+ * 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.cli;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+public class PlainOutputFormatter implements OutputFormatter {
+
+ public static final PlainOutputFormatter INSTANCE = new
PlainOutputFormatter();
+
+ @Override
+ public String format(byte[] data) {
+ return new String(data, UTF_8);
+ }
+}
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/cli/SetCommand.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/SetCommand.java
index 035d82aad..34ac14e74 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/cli/SetCommand.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/SetCommand.java
@@ -19,6 +19,7 @@
package org.apache.zookeeper.cli;
import static java.nio.charset.StandardCharsets.UTF_8;
+import java.util.Base64;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Options;
@@ -36,12 +37,13 @@ public class SetCommand extends CliCommand {
private CommandLine cl;
static {
- options.addOption("s", false, "stats");
- options.addOption("v", true, "version");
+ options.addOption("s", false, "Print znode stats additionally");
+ options.addOption("v", true, "Set with an expected version");
+ options.addOption("b", false, "Supply data in base64 format");
}
public SetCommand() {
- super("set", "[-s] [-v version] path data");
+ super("set", "path data [-s] [-v version] [-b]", options);
}
@Override
@@ -63,7 +65,12 @@ public class SetCommand extends CliCommand {
@Override
public boolean exec() throws CliException {
String path = args[1];
- byte[] data = args[2].getBytes(UTF_8);
+ byte[] data;
+ if (cl.hasOption("b")) {
+ data = Base64.getDecoder().decode(args[2]);
+ } else {
+ data = args[2].getBytes(UTF_8);
+ }
int version;
if (cl.hasOption("v")) {
version = Integer.parseInt(cl.getOptionValue("v"));