accumulo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From els...@apache.org
Subject [31/53] [abbrv] Revert "ACCUMULO-1897 Move shell into new package and module"
Date Tue, 08 Apr 2014 03:03:27 GMT
http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/CreateTableCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/CreateTableCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/CreateTableCommand.java
new file mode 100644
index 0000000..bc5f1d1
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/CreateTableCommand.java
@@ -0,0 +1,203 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.apache.accumulo.core.client.AccumuloException;
+import org.apache.accumulo.core.client.AccumuloSecurityException;
+import org.apache.accumulo.core.client.TableExistsException;
+import org.apache.accumulo.core.client.TableNotFoundException;
+import org.apache.accumulo.core.client.admin.TimeType;
+import org.apache.accumulo.core.client.impl.Tables;
+import org.apache.accumulo.core.conf.Property;
+import org.apache.accumulo.core.iterators.IteratorUtil;
+import org.apache.accumulo.core.security.VisibilityConstraint;
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.accumulo.core.util.shell.Shell.Command;
+import org.apache.accumulo.core.util.shell.ShellUtil;
+import org.apache.accumulo.core.util.shell.Token;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionGroup;
+import org.apache.commons.cli.Options;
+import org.apache.hadoop.io.Text;
+
+public class CreateTableCommand extends Command {
+  private Option createTableOptCopySplits;
+  private Option createTableOptCopyConfig;
+  private Option createTableOptSplit;
+  private Option createTableOptTimeLogical;
+  private Option createTableOptTimeMillis;
+  private Option createTableNoDefaultIters;
+  private Option createTableOptEVC;
+  private Option base64Opt;
+  private Option createTableOptFormatter;
+
+  @Override
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws AccumuloException, AccumuloSecurityException,
+      TableExistsException, TableNotFoundException, IOException, ClassNotFoundException {
+
+    final String testTableName = cl.getArgs()[0];
+
+    if (!testTableName.matches(Tables.VALID_NAME_REGEX)) {
+      shellState.getReader().println("Only letters, numbers and underscores are allowed for use in table names.");
+      throw new IllegalArgumentException();
+    }
+
+    final String tableName = cl.getArgs()[0];
+    if (shellState.getConnector().tableOperations().exists(tableName)) {
+      throw new TableExistsException(null, tableName, null);
+    }
+    final SortedSet<Text> partitions = new TreeSet<Text>();
+    final boolean decode = cl.hasOption(base64Opt.getOpt());
+
+    if (cl.hasOption(createTableOptSplit.getOpt())) {
+      partitions.addAll(ShellUtil.scanFile(cl.getOptionValue(createTableOptSplit.getOpt()), decode));
+    } else if (cl.hasOption(createTableOptCopySplits.getOpt())) {
+      final String oldTable = cl.getOptionValue(createTableOptCopySplits.getOpt());
+      if (!shellState.getConnector().tableOperations().exists(oldTable)) {
+        throw new TableNotFoundException(null, oldTable, null);
+      }
+      partitions.addAll(shellState.getConnector().tableOperations().listSplits(oldTable));
+    }
+
+    if (cl.hasOption(createTableOptCopyConfig.getOpt())) {
+      final String oldTable = cl.getOptionValue(createTableOptCopyConfig.getOpt());
+      if (!shellState.getConnector().tableOperations().exists(oldTable)) {
+        throw new TableNotFoundException(null, oldTable, null);
+      }
+    }
+
+    TimeType timeType = TimeType.MILLIS;
+    if (cl.hasOption(createTableOptTimeLogical.getOpt())) {
+      timeType = TimeType.LOGICAL;
+    }
+
+    // create table
+    shellState.getConnector().tableOperations().create(tableName, true, timeType);
+    if (partitions.size() > 0) {
+      shellState.getConnector().tableOperations().addSplits(tableName, partitions);
+    }
+
+    shellState.setTableName(tableName); // switch shell to new table context
+
+    if (cl.hasOption(createTableNoDefaultIters.getOpt())) {
+      for (String key : IteratorUtil.generateInitialTableProperties(true).keySet()) {
+        shellState.getConnector().tableOperations().removeProperty(tableName, key);
+      }
+    }
+
+    // Copy options if flag was set
+    if (cl.hasOption(createTableOptCopyConfig.getOpt())) {
+      if (shellState.getConnector().tableOperations().exists(tableName)) {
+        final Iterable<Entry<String,String>> configuration = shellState.getConnector().tableOperations()
+            .getProperties(cl.getOptionValue(createTableOptCopyConfig.getOpt()));
+        for (Entry<String,String> entry : configuration) {
+          if (Property.isValidTablePropertyKey(entry.getKey())) {
+            shellState.getConnector().tableOperations().setProperty(tableName, entry.getKey(), entry.getValue());
+          }
+        }
+      }
+    }
+
+    if (cl.hasOption(createTableOptEVC.getOpt())) {
+      try {
+        shellState.getConnector().tableOperations().addConstraint(tableName, VisibilityConstraint.class.getName());
+      } catch (AccumuloException e) {
+        Shell.log.warn(e.getMessage() + " while setting visibility constraint, but table was created");
+      }
+    }
+
+    // Load custom formatter if set
+    if (cl.hasOption(createTableOptFormatter.getOpt())) {
+      final String formatterClass = cl.getOptionValue(createTableOptFormatter.getOpt());
+
+      shellState.getConnector().tableOperations().setProperty(tableName, Property.TABLE_FORMATTER_CLASS.toString(), formatterClass);
+    }
+
+    return 0;
+  }
+
+  @Override
+  public String description() {
+    return "creates a new table, with optional aggregators and optionally pre-split";
+  }
+
+  @Override
+  public String usage() {
+    return getName() + " <tableName>";
+  }
+
+  @Override
+  public Options getOptions() {
+    final Options o = new Options();
+
+    createTableOptCopyConfig = new Option("cc", "copy-config", true, "table to copy configuration from");
+    createTableOptCopySplits = new Option("cs", "copy-splits", true, "table to copy current splits from");
+    createTableOptSplit = new Option("sf", "splits-file", true, "file with a newline-separated list of rows to split the table with");
+    createTableOptTimeLogical = new Option("tl", "time-logical", false, "use logical time");
+    createTableOptTimeMillis = new Option("tm", "time-millis", false, "use time in milliseconds");
+    createTableNoDefaultIters = new Option("ndi", "no-default-iterators", false, "prevent creation of the normal default iterator set");
+    createTableOptEVC = new Option("evc", "enable-visibility-constraint", false,
+        "prevent users from writing data they cannot read.  When enabling this, consider disabling bulk import and alter table.");
+    createTableOptFormatter = new Option("f", "formatter", true, "default formatter to set");
+
+    createTableOptCopyConfig.setArgName("table");
+    createTableOptCopySplits.setArgName("table");
+    createTableOptSplit.setArgName("filename");
+    createTableOptFormatter.setArgName("className");
+
+    // Splits and CopySplits are put in an optionsgroup to make them
+    // mutually exclusive
+    final OptionGroup splitOrCopySplit = new OptionGroup();
+    splitOrCopySplit.addOption(createTableOptSplit);
+    splitOrCopySplit.addOption(createTableOptCopySplits);
+
+    final OptionGroup timeGroup = new OptionGroup();
+    timeGroup.addOption(createTableOptTimeLogical);
+    timeGroup.addOption(createTableOptTimeMillis);
+
+    base64Opt = new Option("b64", "base64encoded", false, "decode encoded split points");
+    o.addOption(base64Opt);
+
+    o.addOptionGroup(splitOrCopySplit);
+    o.addOptionGroup(timeGroup);
+    o.addOption(createTableOptSplit);
+    o.addOption(createTableOptCopyConfig);
+    o.addOption(createTableNoDefaultIters);
+    o.addOption(createTableOptEVC);
+    o.addOption(createTableOptFormatter);
+
+    return o;
+  }
+
+  @Override
+  public int numArgs() {
+    return 1;
+  }
+
+  @Override
+  public void registerCompletion(final Token root, final Map<Command.CompletionSet,Set<String>> special) {
+    registerCompletionForNamespaces(root, special);
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/CreateUserCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/CreateUserCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/CreateUserCommand.java
new file mode 100644
index 0000000..aa3d7b9
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/CreateUserCommand.java
@@ -0,0 +1,76 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+import java.io.IOException;
+
+import org.apache.accumulo.core.client.AccumuloException;
+import org.apache.accumulo.core.client.AccumuloSecurityException;
+import org.apache.accumulo.core.client.TableExistsException;
+import org.apache.accumulo.core.client.TableNotFoundException;
+import org.apache.accumulo.core.client.security.tokens.PasswordToken;
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.accumulo.core.util.shell.Shell.Command;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Options;
+
+public class CreateUserCommand extends Command {
+  @Override
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws AccumuloException, TableNotFoundException,
+      AccumuloSecurityException, TableExistsException, IOException {
+    final String user = cl.getArgs()[0];
+    
+    final String password = shellState.readMaskedLine("Enter new password for '" + user + "': ", '*');
+    if (password == null) {
+      shellState.getReader().println();
+      return 0;
+    } // user canceled
+    String passwordConfirm = shellState.readMaskedLine("Please confirm new password for '" + user + "': ", '*');
+    if (passwordConfirm == null) {
+      shellState.getReader().println();
+      return 0;
+    } // user canceled
+    
+    if (!password.equals(passwordConfirm)) {
+      throw new IllegalArgumentException("Passwords do not match");
+    }
+    shellState.getConnector().securityOperations().createLocalUser(user, new PasswordToken(password));
+    Shell.log.debug("Created user " + user);
+    return 0;
+  }
+  
+  @Override
+  public String usage() {
+    return getName() + " <username>";
+  }
+  
+  @Override
+  public String description() {
+    return "creates a new user";
+  }
+  
+  @Override
+  public Options getOptions() {
+    final Options o = new Options();
+    return o;
+  }
+  
+  @Override
+  public int numArgs() {
+    return 1;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DUCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DUCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DUCommand.java
new file mode 100644
index 0000000..660ec6c
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DUCommand.java
@@ -0,0 +1,124 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.apache.accumulo.core.client.Instance;
+import org.apache.accumulo.core.client.NamespaceNotFoundException;
+import org.apache.accumulo.core.client.TableNotFoundException;
+import org.apache.accumulo.core.client.admin.DiskUsage;
+import org.apache.accumulo.core.client.impl.Namespaces;
+import org.apache.accumulo.core.util.NumUtil;
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.accumulo.core.util.shell.Shell.Command;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+
+public class DUCommand extends Command {
+
+  private Option optTablePattern, optHumanReadble, optNamespace;
+
+  @Override
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws IOException, TableNotFoundException,
+      NamespaceNotFoundException {
+
+    final SortedSet<String> tables = new TreeSet<String>(Arrays.asList(cl.getArgs()));
+
+    if (cl.hasOption(Shell.tableOption)) {
+      String tableName = cl.getOptionValue(Shell.tableOption);
+      if (!shellState.getConnector().tableOperations().exists(tableName)) {
+        throw new TableNotFoundException(tableName, tableName, "specified table that doesn't exist");
+      }
+      tables.add(tableName);
+    }
+
+    if (cl.hasOption(optNamespace.getOpt())) {
+      Instance instance = shellState.getInstance();
+      String namespaceId = Namespaces.getNamespaceId(instance, cl.getOptionValue(optNamespace.getOpt()));
+      tables.addAll(Namespaces.getTableNames(instance, namespaceId));
+    }
+
+    boolean prettyPrint = cl.hasOption(optHumanReadble.getOpt()) ? true : false;
+
+    // Add any patterns
+    if (cl.hasOption(optTablePattern.getOpt())) {
+      for (String table : shellState.getConnector().tableOperations().list()) {
+        if (table.matches(cl.getOptionValue(optTablePattern.getOpt()))) {
+          tables.add(table);
+        }
+      }
+    }
+
+    // If we didn't get any tables, and we have a table selected, add the current table
+    if (tables.isEmpty() && !shellState.getTableName().isEmpty()) {
+      tables.add(shellState.getTableName());
+    }
+
+    try {
+      String valueFormat = prettyPrint ? "%9s" : "%,24d";
+      for (DiskUsage usage : shellState.getConnector().tableOperations().getDiskUsage(tables)) {
+        Object value = prettyPrint ? NumUtil.bigNumberForSize(usage.getUsage()) : usage.getUsage();
+        shellState.getReader().println(String.format(valueFormat + " %s", value, usage.getTables()));
+      }
+    } catch (Exception ex) {
+      throw new RuntimeException(ex);
+    }
+    return 0;
+  }
+
+  @Override
+  public String description() {
+    return "prints how much space, in bytes, is used by files referenced by a table.  When multiple tables are specified it prints how much space, in bytes, is used by files shared between tables, if any.";
+  }
+
+  @Override
+  public Options getOptions() {
+    final Options o = new Options();
+
+    optTablePattern = new Option("p", "pattern", true, "regex pattern of table names");
+    optTablePattern.setArgName("pattern");
+
+    optHumanReadble = new Option("h", "human-readable", false, "format large sizes to human readable units");
+    optHumanReadble.setArgName("human readable output");
+
+    optNamespace = new Option(Shell.namespaceOption, "namespace", true, "name of a namespace");
+    optNamespace.setArgName("namespace");
+
+    o.addOption(OptUtil.tableOpt("table to examine"));
+
+    o.addOption(optTablePattern);
+    o.addOption(optHumanReadble);
+    o.addOption(optNamespace);
+
+    return o;
+  }
+
+  @Override
+  public String usage() {
+    return getName() + " <table>{ <table>}";
+  }
+
+  @Override
+  public int numArgs() {
+    return Shell.NO_FIXED_ARG_LENGTH_CHECK;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DebugCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DebugCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DebugCommand.java
new file mode 100644
index 0000000..206b5901
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DebugCommand.java
@@ -0,0 +1,71 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.accumulo.core.util.BadArgumentException;
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.accumulo.core.util.shell.Shell.Command;
+import org.apache.accumulo.core.util.shell.Token;
+import org.apache.commons.cli.CommandLine;
+
+public class DebugCommand extends Command {
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws IOException {
+    if (cl.getArgs().length == 1) {
+      if (cl.getArgs()[0].equalsIgnoreCase("on")) {
+        Shell.setDebugging(true);
+      } else if (cl.getArgs()[0].equalsIgnoreCase("off")) {
+        Shell.setDebugging(false);
+      } else {
+        throw new BadArgumentException("Argument must be 'on' or 'off'", fullCommand, fullCommand.indexOf(cl.getArgs()[0]));
+      }
+    } else if (cl.getArgs().length == 0) {
+      shellState.getReader().println(Shell.isDebuggingEnabled() ? "on" : "off");
+    } else {
+      shellState.printException(new IllegalArgumentException("Expected 0 or 1 argument. There were " + cl.getArgs().length + "."));
+      printHelp(shellState);
+      return 1;
+    }
+    return 0;
+  }
+  
+  @Override
+  public String description() {
+    return "turns debug logging on or off";
+  }
+  
+  @Override
+  public void registerCompletion(final Token root, final Map<Command.CompletionSet,Set<String>> special) {
+    final Token debug_command = new Token(getName());
+    debug_command.addSubcommand(Arrays.asList(new String[] {"on", "off"}));
+    root.addSubcommand(debug_command);
+  }
+  
+  @Override
+  public String usage() {
+    return getName() + " [ on | off ]";
+  }
+  
+  @Override
+  public int numArgs() {
+    return Shell.NO_FIXED_ARG_LENGTH_CHECK;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteCommand.java
new file mode 100644
index 0000000..b409ccc
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteCommand.java
@@ -0,0 +1,112 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.accumulo.core.client.AccumuloException;
+import org.apache.accumulo.core.client.AccumuloSecurityException;
+import org.apache.accumulo.core.client.BatchWriter;
+import org.apache.accumulo.core.client.BatchWriterConfig;
+import org.apache.accumulo.core.client.TableNotFoundException;
+import org.apache.accumulo.core.conf.AccumuloConfiguration;
+import org.apache.accumulo.core.data.Mutation;
+import org.apache.accumulo.core.security.ColumnVisibility;
+import org.apache.accumulo.core.tabletserver.thrift.ConstraintViolationException;
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.accumulo.core.util.shell.Shell.Command;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.hadoop.io.Text;
+
+public class DeleteCommand extends Command {
+  private Option deleteOptAuths, timestampOpt;
+  private Option timeoutOption;
+  
+  protected long getTimeout(final CommandLine cl) {
+    if (cl.hasOption(timeoutOption.getLongOpt())) {
+      return AccumuloConfiguration.getTimeInMillis(cl.getOptionValue(timeoutOption.getLongOpt()));
+    }
+    
+    return Long.MAX_VALUE;
+  }
+  
+  @Override
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws AccumuloException, AccumuloSecurityException,
+      TableNotFoundException, IOException, ConstraintViolationException {
+    shellState.checkTableState();
+    
+    final Mutation m = new Mutation(new Text(cl.getArgs()[0].getBytes(Shell.CHARSET)));
+    final Text colf = new Text(cl.getArgs()[1].getBytes(Shell.CHARSET));
+    final Text colq = new Text(cl.getArgs()[2].getBytes(Shell.CHARSET));
+    
+    if (cl.hasOption(deleteOptAuths.getOpt())) {
+      final ColumnVisibility le = new ColumnVisibility(cl.getOptionValue(deleteOptAuths.getOpt()));
+      if (cl.hasOption(timestampOpt.getOpt())) {
+        m.putDelete(colf, colq, le, Long.parseLong(cl.getOptionValue(timestampOpt.getOpt())));
+      } else {
+        m.putDelete(colf, colq, le);
+      }
+    } else if (cl.hasOption(timestampOpt.getOpt())) {
+      m.putDelete(colf, colq, Long.parseLong(cl.getOptionValue(timestampOpt.getOpt())));
+    } else {
+      m.putDelete(colf, colq);
+    }
+    final BatchWriter bw = shellState.getConnector().createBatchWriter(shellState.getTableName(),
+        new BatchWriterConfig().setMaxMemory(Math.max(m.estimatedMemoryUsed(), 1024)).setMaxWriteThreads(1).setTimeout(getTimeout(cl), TimeUnit.MILLISECONDS));
+    bw.addMutation(m);
+    bw.close();
+    return 0;
+  }
+  
+  @Override
+  public String description() {
+    return "deletes a record from a table";
+  }
+  
+  @Override
+  public String usage() {
+    return getName() + " <row> <colfamily> <colqualifier>";
+  }
+  
+  @Override
+  public Options getOptions() {
+    final Options o = new Options();
+    
+    deleteOptAuths = new Option("l", "visibility-label", true, "formatted visibility");
+    deleteOptAuths.setArgName("expression");
+    o.addOption(deleteOptAuths);
+    
+    timestampOpt = new Option("ts", "timestamp", true, "timestamp to use for deletion");
+    timestampOpt.setArgName("timestamp");
+    o.addOption(timestampOpt);
+    
+    timeoutOption = new Option(null, "timeout", true,
+        "time before insert should fail if no data is written. If no unit is given assumes seconds.  Units d,h,m,s,and ms are supported.  e.g. 30s or 100ms");
+    timeoutOption.setArgName("timeout");
+    o.addOption(timeoutOption);
+    
+    return o;
+  }
+  
+  @Override
+  public int numArgs() {
+    return 3;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteIterCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteIterCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteIterCommand.java
new file mode 100644
index 0000000..c100325
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteIterCommand.java
@@ -0,0 +1,114 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+import java.util.EnumSet;
+
+import org.apache.accumulo.core.iterators.IteratorUtil.IteratorScope;
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.accumulo.core.util.shell.Shell.Command;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionGroup;
+import org.apache.commons.cli.Options;
+
+public class DeleteIterCommand extends Command {
+  private Option allScopeOpt, mincScopeOpt, majcScopeOpt, scanScopeOpt, nameOpt;
+
+  @Override
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws Exception {
+
+    boolean tables = cl.hasOption(OptUtil.tableOpt().getOpt()) || !shellState.getTableName().isEmpty();
+    boolean namespaces = cl.hasOption(OptUtil.namespaceOpt().getOpt());
+
+    final String name = cl.getOptionValue(nameOpt.getOpt());
+
+    if (namespaces) {
+      if (!shellState.getConnector().namespaceOperations().listIterators(OptUtil.getNamespaceOpt(cl, shellState)).containsKey(name)) {
+        Shell.log.warn("no iterators found that match your criteria");
+        return 0;
+      }
+    } else if (tables) {
+      if (!shellState.getConnector().tableOperations().listIterators(OptUtil.getTableOpt(cl, shellState)).containsKey(name)) {
+        Shell.log.warn("no iterators found that match your criteria");
+        return 0;
+      }
+    } else {
+      throw new IllegalArgumentException("No table or namespace specified");
+    }
+
+    final EnumSet<IteratorScope> scopes = EnumSet.noneOf(IteratorScope.class);
+    if (cl.hasOption(allScopeOpt.getOpt()) || cl.hasOption(mincScopeOpt.getOpt())) {
+      scopes.add(IteratorScope.minc);
+    }
+    if (cl.hasOption(allScopeOpt.getOpt()) || cl.hasOption(majcScopeOpt.getOpt())) {
+      scopes.add(IteratorScope.majc);
+    }
+    if (cl.hasOption(allScopeOpt.getOpt()) || cl.hasOption(scanScopeOpt.getOpt())) {
+      scopes.add(IteratorScope.scan);
+    }
+    if (scopes.isEmpty()) {
+      throw new IllegalArgumentException("You must select at least one scope to configure");
+    }
+
+    if (namespaces) {
+      shellState.getConnector().namespaceOperations().removeIterator(OptUtil.getNamespaceOpt(cl, shellState), name, scopes);
+    } else if (tables) {
+      shellState.getConnector().tableOperations().removeIterator(OptUtil.getTableOpt(cl, shellState), name, scopes);
+    } else {
+      throw new IllegalArgumentException("No table or namespace specified");
+    }
+    return 0;
+  }
+
+  @Override
+  public String description() {
+    return "deletes a table-specific or namespace-specific iterator";
+  }
+
+  @Override
+  public Options getOptions() {
+    final Options o = new Options();
+
+    nameOpt = new Option("n", "name", true, "iterator to delete");
+    nameOpt.setArgName("itername");
+    nameOpt.setRequired(true);
+
+    allScopeOpt = new Option("all", "all-scopes", false, "remove from all scopes");
+    mincScopeOpt = new Option(IteratorScope.minc.name(), "minor-compaction", false, "remove from minor compaction scope");
+    majcScopeOpt = new Option(IteratorScope.majc.name(), "major-compaction", false, "remove from major compaction scope");
+    scanScopeOpt = new Option(IteratorScope.scan.name(), "scan-time", false, "remove from scan scope");
+
+    OptionGroup grp = new OptionGroup();
+    grp.addOption(OptUtil.tableOpt("table to delete the iterator from"));
+    grp.addOption(OptUtil.namespaceOpt("namespace to delete the iterator from"));
+    o.addOptionGroup(grp);
+    o.addOption(nameOpt);
+
+    o.addOption(allScopeOpt);
+    o.addOption(mincScopeOpt);
+    o.addOption(majcScopeOpt);
+    o.addOption(scanScopeOpt);
+
+    return o;
+  }
+
+  @Override
+  public int numArgs() {
+    return 0;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteManyCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteManyCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteManyCommand.java
new file mode 100644
index 0000000..7518bf9
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteManyCommand.java
@@ -0,0 +1,82 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.accumulo.core.client.BatchWriter;
+import org.apache.accumulo.core.client.BatchWriterConfig;
+import org.apache.accumulo.core.client.IteratorSetting;
+import org.apache.accumulo.core.client.Scanner;
+import org.apache.accumulo.core.iterators.SortedKeyIterator;
+import org.apache.accumulo.core.security.Authorizations;
+import org.apache.accumulo.core.util.format.DeleterFormatter;
+import org.apache.accumulo.core.util.interpret.ScanInterpreter;
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+
+public class DeleteManyCommand extends ScanCommand {
+  private Option forceOpt;
+  
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws Exception {
+    final String tableName = OptUtil.getTableOpt(cl, shellState);
+    
+    final ScanInterpreter interpeter = getInterpreter(cl, tableName, shellState);
+
+    // handle first argument, if present, the authorizations list to
+    // scan with
+    final Authorizations auths = getAuths(cl, shellState);
+    final Scanner scanner = shellState.getConnector().createScanner(tableName, auths);
+    
+    scanner.addScanIterator(new IteratorSetting(Integer.MAX_VALUE, "NOVALUE", SortedKeyIterator.class));
+    
+    // handle session-specific scan iterators
+    addScanIterators(shellState, cl, scanner, tableName);
+    
+    // handle remaining optional arguments
+    scanner.setRange(getRange(cl, interpeter));
+    
+    scanner.setTimeout(getTimeout(cl), TimeUnit.MILLISECONDS);
+
+    // handle columns
+    fetchColumns(cl, scanner, interpeter);
+    
+    // output / delete the records
+    final BatchWriter writer = shellState.getConnector()
+        .createBatchWriter(tableName, new BatchWriterConfig().setTimeout(getTimeout(cl), TimeUnit.MILLISECONDS));
+    shellState.printLines(new DeleterFormatter(writer, scanner, cl.hasOption(timestampOpt.getOpt()), shellState, cl.hasOption(forceOpt.getOpt())), false);
+    
+    return 0;
+  }
+  
+  @Override
+  public String description() {
+    return "scans a table and deletes the resulting records";
+  }
+  
+  @Override
+  public Options getOptions() {
+    forceOpt = new Option("f", "force", false, "force deletion without prompting");
+    final Options opts = super.getOptions();
+    opts.addOption(forceOpt);
+    opts.addOption(OptUtil.tableOpt("table to delete entries from"));
+    return opts;
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteNamespaceCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteNamespaceCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteNamespaceCommand.java
new file mode 100644
index 0000000..01d7fc0
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteNamespaceCommand.java
@@ -0,0 +1,100 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.accumulo.core.client.NamespaceNotFoundException;
+import org.apache.accumulo.core.client.impl.Namespaces;
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.accumulo.core.util.shell.Shell.Command;
+import org.apache.accumulo.core.util.shell.Token;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+
+public class DeleteNamespaceCommand extends Command {
+  private Option forceOpt;
+
+  @Override
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws Exception {
+    boolean force = false;
+    boolean operate = true;
+    if (cl.hasOption(forceOpt.getOpt())) {
+      force = true;
+    }
+    String namespace = cl.getArgs()[0];
+
+    if (!force) {
+      shellState.getReader().flush();
+      String line = shellState.getReader().readLine(getName() + " { " + namespace + " } (yes|no)? ");
+      operate = line != null && (line.equalsIgnoreCase("y") || line.equalsIgnoreCase("yes"));
+    }
+    if (operate) {
+      doTableOp(shellState, namespace, force);
+    }
+    return 0;
+  }
+
+  @Override
+  public String description() {
+    return "deletes a namespace";
+  }
+
+  protected void doTableOp(final Shell shellState, final String namespace, boolean force) throws Exception {
+    boolean resetContext = false;
+    String currentTable = shellState.getTableName();
+    if (!Namespaces.getNameToIdMap(shellState.getInstance()).containsKey(namespace)) {
+      throw new NamespaceNotFoundException(null, namespace, null);
+    }
+
+    String namespaceId = Namespaces.getNamespaceId(shellState.getInstance(), namespace);
+    List<String> tables = Namespaces.getTableNames(shellState.getInstance(), namespaceId);
+    resetContext = tables.contains(currentTable);
+
+    if (force)
+      for (String table : shellState.getConnector().tableOperations().list())
+        if (table.startsWith(namespace + "."))
+          shellState.getConnector().tableOperations().delete(table);
+
+    shellState.getConnector().namespaceOperations().delete(namespace);
+    if (resetContext) {
+      shellState.setTableName("");
+    }
+  }
+
+  @Override
+  public Options getOptions() {
+    forceOpt = new Option("f", "force", false, "force deletion without prompting");
+    final Options opts = super.getOptions();
+
+    opts.addOption(forceOpt);
+    return opts;
+  }
+
+  @Override
+  public int numArgs() {
+    return 1;
+  }
+
+  @Override
+  public void registerCompletion(final Token root, final Map<Command.CompletionSet,Set<String>> special) {
+    registerCompletionForNamespaces(root, special);
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteRowsCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteRowsCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteRowsCommand.java
new file mode 100644
index 0000000..1414b4d
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteRowsCommand.java
@@ -0,0 +1,65 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.accumulo.core.util.shell.Shell.Command;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.hadoop.io.Text;
+
+public class DeleteRowsCommand extends Command {
+  private Option forceOpt;
+  private Option startRowOptExclusive;
+ 
+  @Override
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws Exception {
+    final String tableName = OptUtil.getTableOpt(cl, shellState);
+    final Text startRow = OptUtil.getStartRow(cl);
+    final Text endRow = OptUtil.getEndRow(cl);
+    if (!cl.hasOption(forceOpt.getOpt()) && (startRow == null || endRow == null)) {
+      shellState.getReader().println("Not deleting unbounded range. Specify both ends, or use --force");
+      return 1;
+    }
+    shellState.getConnector().tableOperations().deleteRows(tableName, startRow, endRow);
+    return 0;
+  }
+  
+  @Override
+  public String description() {
+    return "deletes a range of rows in a table.  Note that rows matching the start row ARE NOT deleted, but rows matching the end row ARE deleted.";
+  }
+  
+  @Override
+  public int numArgs() {
+    return 0;
+  }
+  
+  @Override
+  public Options getOptions() {
+    final Options o = new Options();
+    forceOpt = new Option("f", "force", false, "delete data even if start or end are not specified");
+    startRowOptExclusive = new Option(OptUtil.START_ROW_OPT, "begin-row", true, "begin row (exclusive)");
+    startRowOptExclusive.setArgName("begin-row");
+    o.addOption(startRowOptExclusive);
+    o.addOption(OptUtil.endRowOpt());
+    o.addOption(OptUtil.tableOpt("table to delete a row range from"));
+    o.addOption(forceOpt);
+    return o;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteScanIterCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteScanIterCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteScanIterCommand.java
new file mode 100644
index 0000000..9b8699b
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteScanIterCommand.java
@@ -0,0 +1,102 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.accumulo.core.client.IteratorSetting;
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.accumulo.core.util.shell.Shell.Command;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionGroup;
+import org.apache.commons.cli.Options;
+
+public class DeleteScanIterCommand extends Command {
+  private Option nameOpt, allOpt;
+  
+  @Override
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws Exception {
+    final String tableName = OptUtil.getTableOpt(cl, shellState);
+    
+    if (cl.hasOption(allOpt.getOpt())) {
+      final List<IteratorSetting> tableScanIterators = shellState.scanIteratorOptions.remove(tableName);
+      if (tableScanIterators == null) {
+        Shell.log.info("No scan iterators set on table " + tableName);
+      } else {
+        Shell.log.info("Removed the following scan iterators from table " + tableName + ":" + tableScanIterators);
+      }
+    } else if (cl.hasOption(nameOpt.getOpt())) {
+      final String name = cl.getOptionValue(nameOpt.getOpt());
+      final List<IteratorSetting> tableScanIterators = shellState.scanIteratorOptions.get(tableName);
+      if (tableScanIterators != null) {
+        boolean found = false;
+        for (Iterator<IteratorSetting> iter = tableScanIterators.iterator(); iter.hasNext();) {
+          if (iter.next().getName().equals(name)) {
+            iter.remove();
+            found = true;
+            break;
+          }
+        }
+        if (!found) {
+          Shell.log.info("No iterator named " + name + " found for table " + tableName);
+        } else {
+          Shell.log.info("Removed scan iterator " + name + " from table " + tableName + " (" + shellState.scanIteratorOptions.get(tableName).size() + " left)");
+          if (shellState.scanIteratorOptions.get(tableName).size() == 0) {
+            shellState.scanIteratorOptions.remove(tableName);
+          }
+        }
+      } else {
+        Shell.log.info("No iterator named " + name + " found for table " + tableName);
+      }
+    }
+    
+    return 0;
+  }
+  
+  @Override
+  public String description() {
+    return "deletes a table-specific scan iterator so it is no longer used during this shell session";
+  }
+  
+  @Override
+  public Options getOptions() {
+    final Options o = new Options();
+    
+    OptionGroup nameGroup = new OptionGroup();
+    
+    nameOpt = new Option("n", "name", true, "iterator to delete");
+    nameOpt.setArgName("itername");
+    
+    allOpt = new Option("a", "all", false, "delete all scan iterators");
+    allOpt.setArgName("all");
+    
+    nameGroup.addOption(nameOpt);
+    nameGroup.addOption(allOpt);
+    nameGroup.setRequired(true);
+    o.addOptionGroup(nameGroup);
+    o.addOption(OptUtil.tableOpt("table to delete scan iterators from"));
+    
+    return o;
+  }
+  
+  @Override
+  public int numArgs() {
+    return 0;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteShellIterCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteShellIterCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteShellIterCommand.java
new file mode 100644
index 0000000..89060c1
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteShellIterCommand.java
@@ -0,0 +1,100 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.accumulo.core.client.IteratorSetting;
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.accumulo.core.util.shell.Shell.Command;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionGroup;
+import org.apache.commons.cli.Options;
+
+public class DeleteShellIterCommand extends Command {
+  private Option nameOpt, allOpt, profileOpt;
+  
+  @Override
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws Exception {
+
+    String profile = cl.getOptionValue(profileOpt.getOpt());
+    if (shellState.iteratorProfiles.containsKey(profile)) {
+      if (cl.hasOption(allOpt.getOpt())) {
+        shellState.iteratorProfiles.remove(profile);
+        Shell.log.info("Removed profile " + profile);
+      } else {
+        List<IteratorSetting> iterSettings = shellState.iteratorProfiles.get(profile);
+        String name = cl.getOptionValue(nameOpt.getOpt());
+        boolean found = false;
+        for (Iterator<IteratorSetting> iter = iterSettings.iterator(); iter.hasNext();) {
+          if (iter.next().getName().equals(name)) {
+            iter.remove();
+            found = true;
+            break;
+          }
+        }
+        if (!found) {
+          Shell.log.info("No iterator named " + name + " found");
+        } else {
+          Shell.log.info("Removed iterator " + name + " from profile " + profile + " (" + iterSettings.size() + " left)");
+        }
+      }
+      
+    } else {
+      Shell.log.info("No profile named " + profile);
+    }
+    
+    return 0;
+  }
+  
+  @Override
+  public String description() {
+    return "deletes iterators profiles configured in this shell session";
+  }
+  
+  @Override
+  public Options getOptions() {
+    final Options o = new Options();
+    
+    OptionGroup nameGroup = new OptionGroup();
+    
+    nameOpt = new Option("n", "name", true, "iterator to delete");
+    nameOpt.setArgName("itername");
+    
+    allOpt = new Option("a", "all", false, "delete all scan iterators");
+    allOpt.setArgName("all");
+    
+    nameGroup.addOption(nameOpt);
+    nameGroup.addOption(allOpt);
+    nameGroup.setRequired(true);
+    o.addOptionGroup(nameGroup);
+    
+    profileOpt = new Option("pn", "profile", true, "iterator profile name");
+    profileOpt.setRequired(true);
+    profileOpt.setArgName("profile");
+    o.addOption(profileOpt);
+
+    return o;
+  }
+  
+  @Override
+  public int numArgs() {
+    return 0;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteTableCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteTableCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteTableCommand.java
new file mode 100644
index 0000000..a5aa32a
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteTableCommand.java
@@ -0,0 +1,60 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+
+public class DeleteTableCommand extends TableOperation {
+  private Option forceOpt;
+
+  @Override
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws Exception {
+    if (cl.hasOption(forceOpt.getOpt())) {
+      super.force();
+    } else {
+      super.noForce();
+    }
+    return super.execute(fullCommand, cl, shellState);
+  }
+
+  @Override
+  public String description() {
+    return "deletes a table";
+  }
+
+  @Override
+  protected void doTableOp(final Shell shellState, final String tableName) throws Exception {
+    shellState.getConnector().tableOperations().delete(tableName);
+    shellState.getReader().println("Table: [" + tableName + "] has been deleted.");
+
+    if (shellState.getTableName().equals(tableName)) {
+      shellState.setTableName("");
+    }
+  }
+
+  @Override
+  public Options getOptions() {
+    forceOpt = new Option("f", "force", false, "force deletion without prompting");
+    final Options opts = super.getOptions();
+
+    opts.addOption(forceOpt);
+    return opts;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteUserCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteUserCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteUserCommand.java
new file mode 100644
index 0000000..4bc563e
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteUserCommand.java
@@ -0,0 +1,19 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+public class DeleteUserCommand extends DropUserCommand {}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DropTableCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DropTableCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DropTableCommand.java
new file mode 100644
index 0000000..3120d6b
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DropTableCommand.java
@@ -0,0 +1,19 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+public class DropTableCommand extends DeleteTableCommand {}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DropUserCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DropUserCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DropUserCommand.java
new file mode 100644
index 0000000..5aa0fb6
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DropUserCommand.java
@@ -0,0 +1,61 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.accumulo.core.client.AccumuloException;
+import org.apache.accumulo.core.client.AccumuloSecurityException;
+import org.apache.accumulo.core.util.BadArgumentException;
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.accumulo.core.util.shell.Shell.Command;
+import org.apache.accumulo.core.util.shell.Token;
+import org.apache.commons.cli.CommandLine;
+
+public class DropUserCommand extends Command {
+  @Override
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws AccumuloException, AccumuloSecurityException {
+    final String user = cl.getArgs()[0];
+    if (shellState.getConnector().whoami().equals(user)) {
+      throw new BadArgumentException("You cannot delete yourself", fullCommand, fullCommand.indexOf(user));
+    }
+    shellState.getConnector().securityOperations().dropLocalUser(user);
+    Shell.log.debug("Deleted user " + user);
+    return 0;
+  }
+  
+  @Override
+  public String description() {
+    return "deletes a user";
+  }
+  
+  @Override
+  public String usage() {
+    return getName() + " <username>";
+  }
+  
+  @Override
+  public void registerCompletion(final Token root, final Map<Command.CompletionSet,Set<String>> completionSet) {
+    registerCompletionForUsers(root, completionSet);
+  }
+  
+  @Override
+  public int numArgs() {
+    return 1;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/EGrepCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/EGrepCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/EGrepCommand.java
new file mode 100644
index 0000000..d63991a
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/EGrepCommand.java
@@ -0,0 +1,59 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+import java.io.IOException;
+
+import org.apache.accumulo.core.client.BatchScanner;
+import org.apache.accumulo.core.client.IteratorSetting;
+import org.apache.accumulo.core.iterators.user.RegExFilter;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+
+public class EGrepCommand extends GrepCommand {
+  
+  private Option matchSubstringOption;
+  
+  @Override
+  protected void setUpIterator(final int prio, final String name, final String term, final BatchScanner scanner, CommandLine cl) throws IOException {
+    if (prio < 0) {
+      throw new IllegalArgumentException("Priority < 0 " + prio);
+    }
+    final IteratorSetting si = new IteratorSetting(prio, name, RegExFilter.class);
+    RegExFilter.setRegexs(si, term, term, term, term, true, cl.hasOption(matchSubstringOption.getOpt()));
+    scanner.addScanIterator(si);
+  }
+  
+  @Override
+  public String description() {
+    return "searches each row, column family, column qualifier and value, in parallel, on the server side (using a java Matcher, so put .* before and after your term if you're not matching the whole element)";
+  }
+  
+  @Override
+  public String usage() {
+    return getName() + " <regex>{ <regex>}";
+  }
+  
+  @Override
+  public Options getOptions() {
+    final Options opts = super.getOptions();
+    matchSubstringOption = new Option("g", "global", false, "forces the use of the find() expression matcher, causing substring matches to return true");
+    opts.addOption(matchSubstringOption);
+    return opts;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/ExecfileCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/ExecfileCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/ExecfileCommand.java
new file mode 100644
index 0000000..f4a2632
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/ExecfileCommand.java
@@ -0,0 +1,67 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+import java.io.File;
+import java.nio.charset.StandardCharsets;
+import java.util.Scanner;
+
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.accumulo.core.util.shell.Shell.Command;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+
+public class ExecfileCommand extends Command {
+  private Option verboseOption;
+  
+  @Override
+  public String description() {
+    return "specifies a file containing accumulo commands to execute";
+  }
+  
+  @Override
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws Exception {
+    Scanner scanner = new Scanner(new File(cl.getArgs()[0]), StandardCharsets.UTF_8.name());
+    try {
+      while (scanner.hasNextLine()) {
+        shellState.execCommand(scanner.nextLine(), true, cl.hasOption(verboseOption.getOpt()));
+      }
+    } finally {
+      scanner.close();
+    }
+    return 0;
+  }
+  
+  @Override
+  public String usage() {
+    return getName() + " <fileName>";
+  }
+  
+  @Override
+  public int numArgs() {
+    return 1;
+  }
+  
+  @Override
+  public Options getOptions() {
+    final Options opts = new Options();
+    verboseOption = new Option("v", "verbose", false, "display command prompt as commands are executed");
+    opts.addOption(verboseOption);
+    return opts;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/ExitCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/ExitCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/ExitCommand.java
new file mode 100644
index 0000000..c78b020
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/ExitCommand.java
@@ -0,0 +1,39 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.accumulo.core.util.shell.Shell.Command;
+import org.apache.commons.cli.CommandLine;
+
+public class ExitCommand extends Command {
+  @Override
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) {
+    shellState.setExit(true);
+    return 0;
+  }
+  
+  @Override
+  public String description() {
+    return "exits the shell";
+  }
+  
+  @Override
+  public int numArgs() {
+    return 0;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/ExportTableCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/ExportTableCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/ExportTableCommand.java
new file mode 100644
index 0000000..5fd5abb
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/ExportTableCommand.java
@@ -0,0 +1,78 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.accumulo.core.client.AccumuloException;
+import org.apache.accumulo.core.client.AccumuloSecurityException;
+import org.apache.accumulo.core.client.TableExistsException;
+import org.apache.accumulo.core.client.TableNotFoundException;
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.accumulo.core.util.shell.Shell.Command;
+import org.apache.accumulo.core.util.shell.Token;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+
+public class ExportTableCommand extends Command {
+  
+  private Option tableOpt;
+
+  @Override
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws AccumuloException, AccumuloSecurityException, TableNotFoundException,
+      TableExistsException {
+    
+    final String tableName = OptUtil.getTableOpt(cl, shellState);
+
+    shellState.getConnector().tableOperations().exportTable(tableName, cl.getArgs()[0]);
+    return 0;
+  }
+  
+  @Override
+  public String usage() {
+    return getName() + " <export dir>";
+  }
+  
+  @Override
+  public Options getOptions() {
+    final Options o = new Options();
+    
+    tableOpt = new Option(Shell.tableOption, "table", true, "table to export");
+    
+    tableOpt.setArgName("table");
+    
+    o.addOption(tableOpt);
+
+    return o;
+  }
+  
+  @Override
+  public String description() {
+    return "exports a table";
+  }
+  
+  public void registerCompletion(final Token root, final Map<Command.CompletionSet,Set<String>> completionSet) {
+    registerCompletionForTables(root, completionSet);
+  }
+  
+  @Override
+  public int numArgs() {
+    return 1;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/ExtensionCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/ExtensionCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/ExtensionCommand.java
new file mode 100644
index 0000000..ab29d19
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/ExtensionCommand.java
@@ -0,0 +1,102 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+import java.util.HashSet;
+import java.util.ServiceLoader;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.accumulo.core.util.shell.Shell.Command;
+import org.apache.accumulo.core.util.shell.ShellExtension;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+
+public class ExtensionCommand extends Command {
+  
+  protected Option enable, disable, list;
+  
+  private static ServiceLoader<ShellExtension> extensions = null;
+  
+  private Set<String> loadedHeaders = new HashSet<String>();
+  private Set<String> loadedCommands = new HashSet<String>();
+  private Set<String> loadedExtensions = new TreeSet<String>();
+  
+  public int execute(String fullCommand, CommandLine cl, Shell shellState) throws Exception {
+    if (cl.hasOption(enable.getOpt())) {
+      extensions = ServiceLoader.load(ShellExtension.class);
+      for (ShellExtension se : extensions) {
+        
+        loadedExtensions.add(se.getExtensionName());
+        String header = "-- " + se.getExtensionName() + " Extension Commands ---------";
+        loadedHeaders.add(header);
+        shellState.commandGrouping.put(header, se.getCommands());
+        
+        for (Command cmd : se.getCommands()) {
+          String name = se.getExtensionName() + "::" + cmd.getName();
+          loadedCommands.add(name);
+          shellState.commandFactory.put(name, cmd);
+        }
+      }
+    } else if (cl.hasOption(disable.getOpt())) {
+      //Remove the headers
+      for (String header : loadedHeaders) {
+        shellState.commandGrouping.remove(header);
+      }
+      //remove the commands
+      for (String name : loadedCommands) {
+        shellState.commandFactory.remove(name);
+      }
+      //Reset state
+      loadedExtensions.clear();
+      extensions.reload();
+    } else if (cl.hasOption(list.getOpt())) {
+      shellState.printLines(loadedExtensions.iterator(), true);
+    } else {
+      printHelp(shellState);
+    }
+    return 0;
+  }
+  
+  public String description() {
+    return "Enable, disable, or list shell extensions";
+  }
+  
+  public int numArgs() {
+    return 0;
+  }
+  
+  @Override
+  public String getName() {
+    return "extensions";
+  }
+
+  @Override
+  public Options getOptions() {
+    final Options o = new Options();
+    enable = new Option("e", "enable", false, "enable shell extensions");
+    disable = new Option("d", "disable", false, "disable shell extensions");
+    list = new Option("l", "list", false, "list shell extensions");
+    o.addOption(enable);
+    o.addOption(disable);
+    o.addOption(list);
+    return o;
+  }
+    
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/FateCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/FateCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/FateCommand.java
new file mode 100644
index 0000000..0196baf
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/FateCommand.java
@@ -0,0 +1,180 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Formatter;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.client.Instance;
+import org.apache.accumulo.core.conf.AccumuloConfiguration;
+import org.apache.accumulo.core.conf.Property;
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.accumulo.core.util.shell.Shell.Command;
+import org.apache.accumulo.core.zookeeper.ZooUtil;
+import org.apache.accumulo.fate.AdminUtil;
+import org.apache.accumulo.fate.ReadOnlyTStore.TStatus;
+import org.apache.accumulo.fate.ZooStore;
+import org.apache.accumulo.fate.zookeeper.IZooReaderWriter;
+import org.apache.accumulo.fate.zookeeper.ZooReaderWriter;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.zookeeper.KeeperException;
+
+/**
+ * Manage FATE transactions
+ * 
+ */
+public class FateCommand extends Command {
+  
+  private static final String SCHEME = "digest";
+  
+  private static final String USER = "accumulo";
+  
+  private Option secretOption;
+  private Option statusOption;
+  
+  @Override
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws ParseException, KeeperException, InterruptedException,
+      IOException {
+    Instance instance = shellState.getInstance();
+    String[] args = cl.getArgs();
+    if (args.length <= 0) {
+      throw new ParseException("Must provide a command to execute");
+    }
+    String cmd = args[0];
+    boolean failedCommand = false;
+    
+    AdminUtil<FateCommand> admin = new AdminUtil<FateCommand>(false);
+    
+    String path = ZooUtil.getRoot(instance) + Constants.ZFATE;
+    String masterPath = ZooUtil.getRoot(instance) + Constants.ZMASTER_LOCK;
+    IZooReaderWriter zk = getZooReaderWriter(shellState.getInstance(), cl.getOptionValue(secretOption.getOpt()));
+    ZooStore<FateCommand> zs = new ZooStore<FateCommand>(path, zk);
+    
+    if ("fail".equals(cmd)) {
+      if (args.length <= 1) {
+        throw new ParseException("Must provide transaction ID");
+      }
+      for (int i = 1; i < args.length; i++) {
+        if (!admin.prepFail(zs, zk, masterPath, args[i])) {
+          System.out.printf("Could not fail transaction: %s%n", args[i]);
+          failedCommand = true;
+        }
+      }
+    } else if ("delete".equals(cmd)) {
+      if (args.length <= 1) {
+        throw new ParseException("Must provide transaction ID");
+      }
+      for (int i = 1; i < args.length; i++) {
+        if (admin.prepDelete(zs, zk, masterPath, args[i])) {
+          admin.deleteLocks(zs, zk, ZooUtil.getRoot(instance) + Constants.ZTABLE_LOCKS, args[i]);
+        } else {
+          System.out.printf("Could not delete transaction: %s%n", args[i]);
+          failedCommand = true;
+        }
+      }
+    } else if ("list".equals(cmd) || "print".equals(cmd)) {
+      // Parse transaction ID filters for print display
+      Set<Long> filterTxid = null;
+      if (args.length >= 2) {
+        filterTxid = new HashSet<Long>(args.length);
+        for (int i = 1; i < args.length; i++) {
+          try {
+            Long val = Long.parseLong(args[i], 16);
+            filterTxid.add(val);
+          } catch (NumberFormatException nfe) {
+            // Failed to parse, will exit instead of displaying everything since the intention was to potentially filter some data
+            System.out.printf("Invalid transaction ID format: %s%n", args[i]);
+            return 1;
+          }
+        }
+      }
+      
+      // Parse TStatus filters for print display
+      EnumSet<TStatus> filterStatus = null;
+      if (cl.hasOption(statusOption.getOpt())) {
+        filterStatus = EnumSet.noneOf(TStatus.class);
+        String[] tstat = cl.getOptionValues(statusOption.getOpt());
+        for (int i = 0; i < tstat.length; i++) {
+          try {
+            filterStatus.add(TStatus.valueOf(tstat[i]));
+          } catch (IllegalArgumentException iae) {
+            System.out.printf("Invalid transaction status name: %s%n", tstat[i]);
+            return 1;
+          }
+        }
+      }
+      
+      StringBuilder buf = new StringBuilder(8096);
+      Formatter fmt = new Formatter(buf);
+      admin.print(zs, zk, ZooUtil.getRoot(instance) + Constants.ZTABLE_LOCKS, fmt, filterTxid, filterStatus);
+      shellState.printLines(Collections.singletonList(buf.toString()).iterator(), true);
+    } else {
+      throw new ParseException("Invalid command option");
+    }
+    
+    return failedCommand ? 1 : 0;
+  }
+  
+  protected synchronized IZooReaderWriter getZooReaderWriter(Instance instance, String secret) {
+    
+    if (secret == null) {
+      @SuppressWarnings("deprecation")
+      AccumuloConfiguration conf = AccumuloConfiguration.getSiteConfiguration();
+      secret = conf.get(Property.INSTANCE_SECRET);
+    }
+    
+    return new ZooReaderWriter(instance.getZooKeepers(), instance.getZooKeepersSessionTimeOut(), SCHEME, (USER + ":" + secret).getBytes());
+  }
+  
+  @Override
+  public String description() {
+    return "manage FATE transactions";
+  }
+  
+  @Override
+  public String usage() {
+    return getName() + " fail <txid>... | delete <txid>... | print [<txid>...]";
+  }
+  
+  @Override
+  public Options getOptions() {
+    final Options o = new Options();
+    secretOption = new Option("s", "secret", true, "specify the instance secret to use");
+    secretOption.setOptionalArg(false);
+    o.addOption(secretOption);
+    statusOption = new Option("t", "status-type", true,
+        "filter 'print' on the transaction status type(s) {NEW, IN_PROGRESS, FAILED_IN_PROGRESS, FAILED, SUCCESSFUL}");
+    statusOption.setArgs(Option.UNLIMITED_VALUES);
+    statusOption.setOptionalArg(false);
+    o.addOption(statusOption);
+    return o;
+  }
+  
+  @Override
+  public int numArgs() {
+    // Arg length varies between 1 to n
+    return -1;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/b2b985e2/core/src/main/java/org/apache/accumulo/core/util/shell/commands/FlushCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/FlushCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/FlushCommand.java
new file mode 100644
index 0000000..de175eb
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/FlushCommand.java
@@ -0,0 +1,63 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+import org.apache.accumulo.core.client.AccumuloException;
+import org.apache.accumulo.core.client.AccumuloSecurityException;
+import org.apache.accumulo.core.client.TableNotFoundException;
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.hadoop.io.Text;
+
+public class FlushCommand extends TableOperation {
+  private Text startRow;
+  private Text endRow;
+  
+  private boolean wait;
+  private Option waitOpt;
+  
+  @Override
+  public String description() {
+    return "flushes a tables data that is currently in memory to disk";
+  }
+  
+  protected void doTableOp(final Shell shellState, final String tableName) throws AccumuloException, AccumuloSecurityException, TableNotFoundException {
+    shellState.getConnector().tableOperations().flush(tableName, startRow, endRow, wait);
+    Shell.log.info("Flush of table " + tableName + (wait ? " completed." : " initiated..."));
+  }
+  
+  @Override
+  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws Exception {
+    wait = cl.hasOption(waitOpt.getLongOpt());
+    startRow = OptUtil.getStartRow(cl);
+    endRow = OptUtil.getEndRow(cl);
+    return super.execute(fullCommand, cl, shellState);
+  }
+  
+  @Override
+  public Options getOptions() {
+    final Options opts = super.getOptions();
+    waitOpt = new Option("w", "wait", false, "wait for flush to finish");
+    opts.addOption(waitOpt);
+    opts.addOption(OptUtil.startRowOpt());
+    opts.addOption(OptUtil.endRowOpt());
+    
+    return opts;
+  }
+}


Mime
View raw message