/* * Copyright (C) 2012 Facebook, Inc. * * Licensed 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 com.facebook.zookeeper.convenience; import com.facebook.zookeeper.ZooKeeperIface; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.GnuParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import java.io.IOException; import java.util.Collection; import java.util.concurrent.TimeoutException; /** * This abstract base class provides a template-and-hook style for writing * scripts interacting with ZooKeeper. Provided that subclasses implement * the abstracted methods, this class will handle initiating/terminating the * ZooKeeper connection as well as parsing relevant command line parameters. * The script may be executed via the runMain(...) method. */ public abstract class ZkScript { private final ZkQuickConnectionManager zkQuickConnectionManager; protected ZkScript(ZkQuickConnectionManager zkQuickConnectionManager) { this.zkQuickConnectionManager = zkQuickConnectionManager; } public void connect(String server, int timeout) throws IOException, InterruptedException, TimeoutException { zkQuickConnectionManager.connect(server, timeout); } public void close() throws InterruptedException { zkQuickConnectionManager.close(); } protected ZooKeeperIface getZk() { return zkQuickConnectionManager.getZk(); } /* * Derived scripts must fill in the templated methods below: */ /** * @return Name of the derived class */ protected abstract String getName(); /** * @return Command line options specific to the derived script */ protected abstract Options getSpecificOptions(); /** * Verifies the integrity of the script specific command line parameters * @param cmd * @return true, if verified, false if there is an issue */ protected abstract boolean verifySpecificOptions(CommandLine cmd); /** * Executes the script (assuming already connected to ZooKeeper) * @param cmd * @throws Exception */ protected abstract void runScript(CommandLine cmd) throws Exception; private Options getOptions() { Options options = new Options(); options.addOption( "s", "server", true, "Zookeeper server as host:port string" ); options.addOption( "i", "tier", true, "Zookeeper SMC tier name (alternative to server parameter)" ); options.addOption( "t", "timeout", true, "Session timeout in milliseconds [Default: 5000]" ); options.addOption( "h", "help", false, "Prints this message" ); // Incorporate the specific options from the derived script for (Option opt : (Collection<Option>) getSpecificOptions().getOptions()) { options.addOption(opt); } return options; } private void printUsage() { HelpFormatter formatter = new HelpFormatter(); formatter.printHelp(getName(), getOptions()); System.out.println( "Note: You must specify either a specific ZooKeeper server (-s) or an " + "SMC ZooKeeper tier (-i)" ); } /** * Main method to launch any script that derives from this abstract class * @param args * @throws Exception */ public void runMain(String[] args) throws Exception { Options options = getOptions(); CommandLineParser parser = new GnuParser(); CommandLine cmd = parser.parse(options, args); if (cmd.hasOption("help")) { printUsage(); return; } // Verify script specific options if (!verifySpecificOptions(cmd)) { printUsage(); return; } // Get connection parameters String servers; if (cmd.hasOption("server")) { servers = cmd.getOptionValue("server"); } else { System.err.println( "You did not specify a ZooKeeper server or an SMC ZooKeeper tier!" ); printUsage(); return; } int timeout = Integer.parseInt(cmd.getOptionValue("timeout", "5000")); // Run the script connect(servers, timeout); try { runScript(cmd); } finally { close(); } } }