Bläddra i källkod

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
萧易客 8 månader sedan
förälder
incheckning
b64146d3d3

+ 31 - 0
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);
+    }
+}

+ 17 - 1
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);
     }
 
     /**

+ 42 - 0
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();
+    }
+}

+ 13 - 5
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);
         }

+ 34 - 0
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);
+    }
+}

+ 24 - 0
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);
+}

+ 31 - 0
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);
+    }
+}

+ 11 - 4
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"));