<commit_before>/*
 * 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.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

import jline.ConsoleReader;

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.conf.AccumuloConfiguration;
import org.apache.accumulo.core.conf.Property;
import org.apache.accumulo.core.security.ColumnVisibility;
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.Shell.PrintFile;
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;

public class ConfigCommand extends Command {
  private Option tableOpt, deleteOpt, setOpt, filterOpt, disablePaginationOpt, outputFileOpt;
  
  private int COL1 = 8, COL2 = 7;
  private ConsoleReader reader;
  
  @Override
  public void registerCompletion(final Token root, final Map<Command.CompletionSet,Set<String>> completionSet) {
    final Token cmd = new Token(getName());
    final Token sub = new Token("-" + setOpt.getOpt());
    for (Property p : Property.values()) {
      if (!(p.getKey().endsWith(".")) && !p.isExperimental()) {
        sub.addSubcommand(new Token(p.toString()));
      }
    }
    cmd.addSubcommand(sub);
    root.addSubcommand(cmd);
  }
  
  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws AccumuloException, AccumuloSecurityException,
      TableNotFoundException, IOException, ClassNotFoundException {
    reader = shellState.getReader();
    
    final String tableName = cl.getOptionValue(tableOpt.getOpt());
    if (tableName != null && !shellState.getConnector().tableOperations().exists(tableName)) {
      throw new TableNotFoundException(null, tableName, null);
    }
    if (cl.hasOption(deleteOpt.getOpt())) {
      // delete property from table
      String property = cl.getOptionValue(deleteOpt.getOpt());
      if (property.contains("=")) {
        throw new BadArgumentException("Invalid '=' operator in delete operation.", fullCommand, fullCommand.indexOf('='));
      }
      if (tableName != null) {
        if (!Property.isValidTablePropertyKey(property)) {
          Shell.log.warn("Invalid per-table property : " + property + ", still removing from zookeeper if it's there.");
        }
        shellState.getConnector().tableOperations().removeProperty(tableName, property);
        Shell.log.debug("Successfully deleted table configuration option.");
      } else {
        if (!Property.isValidZooPropertyKey(property)) {
          Shell.log.warn("Invalid per-table property : " + property + ", still removing from zookeeper if it's there.");
        }
        shellState.getConnector().instanceOperations().removeProperty(property);
        Shell.log.debug("Successfully deleted system configuration option");
      }
    } else if (cl.hasOption(setOpt.getOpt())) {
      // set property on table
      String property = cl.getOptionValue(setOpt.getOpt()), value = null;
      if (!property.contains("=")) {
        throw new BadArgumentException("Missing '=' operator in set operation.", fullCommand, fullCommand.indexOf(property));
      }
      final String pair[] = property.split("=", 2);
      property = pair[0];
      value = pair[1];
      
      if (tableName != null) {
        if (!Property.isValidTablePropertyKey(property)) {
          throw new BadArgumentException("Invalid per-table property.", fullCommand, fullCommand.indexOf(property));
        }
        if (property.equals(Property.TABLE_DEFAULT_SCANTIME_VISIBILITY.getKey())) {
          new ColumnVisibility(value); // validate that it is a valid expression
        }
        shellState.getConnector().tableOperations().setProperty(tableName, property, value);
        Shell.log.debug("Successfully set table configuration option.");
      } else {
        if (!Property.isValidZooPropertyKey(property)) {
          throw new BadArgumentException("Property cannot be modified in zookeeper", fullCommand, fullCommand.indexOf(property));
        }
        shellState.getConnector().instanceOperations().setProperty(property, value);
        Shell.log.debug("Successfully set system configuration option");
      }
    } else {
      // display properties
      final TreeMap<String,String> systemConfig = new TreeMap<String,String>();
      systemConfig.putAll(shellState.getConnector().instanceOperations().getSystemConfiguration());
      
      final String outputFile = cl.getOptionValue(outputFileOpt.getOpt());
      final PrintFile printFile = outputFile == null ? null : new PrintFile(outputFile);
      
      final TreeMap<String,String> siteConfig = new TreeMap<String,String>();
      siteConfig.putAll(shellState.getConnector().instanceOperations().getSiteConfiguration());
      
      final TreeMap<String,String> defaults = new TreeMap<String,String>();
      for (Entry<String,String> defaultEntry : AccumuloConfiguration.getDefaultConfiguration()) {
        defaults.put(defaultEntry.getKey(), defaultEntry.getValue());
      }
      Iterable<Entry<String,String>> acuconf = shellState.getConnector().instanceOperations().getSystemConfiguration().entrySet();
      if (tableName != null) {
        acuconf = shellState.getConnector().tableOperations().getProperties(tableName);
      }
      final TreeMap<String,String> sortedConf = new TreeMap<String,String>();
      for (Entry<String,String> propEntry : acuconf) {
        sortedConf.put(propEntry.getKey(), propEntry.getValue());
      }
      
      for (Entry<String,String> propEntry : acuconf) {
        final String key = propEntry.getKey();
        // only show properties with similar names to that
        // specified, or all of them if none specified
        if (cl.hasOption(filterOpt.getOpt()) && !key.contains(cl.getOptionValue(filterOpt.getOpt()))) {
          continue;
        }
        if (tableName != null && !Property.isValidTablePropertyKey(key)) {
          continue;
        }
        COL2 = Math.max(COL2, propEntry.getKey().length() + 3);
      }
      
      final ArrayList<String> output = new ArrayList<String>();
      printConfHeader(output);
      
      for (Entry<String,String> propEntry : sortedConf.entrySet()) {
        final String key = propEntry.getKey();
        
        // only show properties with similar names to that
        // specified, or all of them if none specified
        if (cl.hasOption(filterOpt.getOpt()) && !key.contains(cl.getOptionValue(filterOpt.getOpt()))) {
          continue;
        }
        if (tableName != null && !Property.isValidTablePropertyKey(key)) {
          continue;
        }
        final String siteVal = siteConfig.get(key);
        final String sysVal = systemConfig.get(key);
        String curVal = propEntry.getValue();
        String dfault = defaults.get(key);
        boolean printed = false;
        
        if (dfault != null && key.toLowerCase().contains("password")) {
          dfault = curVal = curVal.replaceAll(".", "*");
        }<commit_msg>ACCUMULO-114 hide the tracer password if it is not set to the default<commit_after>/*
 * 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.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

import jline.ConsoleReader;

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.conf.AccumuloConfiguration;
import org.apache.accumulo.core.conf.Property;
import org.apache.accumulo.core.security.ColumnVisibility;
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.Shell.PrintFile;
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;

public class ConfigCommand extends Command {
  private Option tableOpt, deleteOpt, setOpt, filterOpt, disablePaginationOpt, outputFileOpt;
  
  private int COL1 = 8, COL2 = 7;
  private ConsoleReader reader;
  
  @Override
  public void registerCompletion(final Token root, final Map<Command.CompletionSet,Set<String>> completionSet) {
    final Token cmd = new Token(getName());
    final Token sub = new Token("-" + setOpt.getOpt());
    for (Property p : Property.values()) {
      if (!(p.getKey().endsWith(".")) && !p.isExperimental()) {
        sub.addSubcommand(new Token(p.toString()));
      }
    }
    cmd.addSubcommand(sub);
    root.addSubcommand(cmd);
  }
  
  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws AccumuloException, AccumuloSecurityException,
      TableNotFoundException, IOException, ClassNotFoundException {
    reader = shellState.getReader();
    
    final String tableName = cl.getOptionValue(tableOpt.getOpt());
    if (tableName != null && !shellState.getConnector().tableOperations().exists(tableName)) {
      throw new TableNotFoundException(null, tableName, null);
    }
    if (cl.hasOption(deleteOpt.getOpt())) {
      // delete property from table
      String property = cl.getOptionValue(deleteOpt.getOpt());
      if (property.contains("=")) {
        throw new BadArgumentException("Invalid '=' operator in delete operation.", fullCommand, fullCommand.indexOf('='));
      }
      if (tableName != null) {
        if (!Property.isValidTablePropertyKey(property)) {
          Shell.log.warn("Invalid per-table property : " + property + ", still removing from zookeeper if it's there.");
        }
        shellState.getConnector().tableOperations().removeProperty(tableName, property);
        Shell.log.debug("Successfully deleted table configuration option.");
      } else {
        if (!Property.isValidZooPropertyKey(property)) {
          Shell.log.warn("Invalid per-table property : " + property + ", still removing from zookeeper if it's there.");
        }
        shellState.getConnector().instanceOperations().removeProperty(property);
        Shell.log.debug("Successfully deleted system configuration option");
      }
    } else if (cl.hasOption(setOpt.getOpt())) {
      // set property on table
      String property = cl.getOptionValue(setOpt.getOpt()), value = null;
      if (!property.contains("=")) {
        throw new BadArgumentException("Missing '=' operator in set operation.", fullCommand, fullCommand.indexOf(property));
      }
      final String pair[] = property.split("=", 2);
      property = pair[0];
      value = pair[1];
      
      if (tableName != null) {
        if (!Property.isValidTablePropertyKey(property)) {
          throw new BadArgumentException("Invalid per-table property.", fullCommand, fullCommand.indexOf(property));
        }
        if (property.equals(Property.TABLE_DEFAULT_SCANTIME_VISIBILITY.getKey())) {
          new ColumnVisibility(value); // validate that it is a valid expression
        }
        shellState.getConnector().tableOperations().setProperty(tableName, property, value);
        Shell.log.debug("Successfully set table configuration option.");
      } else {
        if (!Property.isValidZooPropertyKey(property)) {
          throw new BadArgumentException("Property cannot be modified in zookeeper", fullCommand, fullCommand.indexOf(property));
        }
        shellState.getConnector().instanceOperations().setProperty(property, value);
        Shell.log.debug("Successfully set system configuration option");
      }
    } else {
      // display properties
      final TreeMap<String,String> systemConfig = new TreeMap<String,String>();
      systemConfig.putAll(shellState.getConnector().instanceOperations().getSystemConfiguration());
      
      final String outputFile = cl.getOptionValue(outputFileOpt.getOpt());
      final PrintFile printFile = outputFile == null ? null : new PrintFile(outputFile);
      
      final TreeMap<String,String> siteConfig = new TreeMap<String,String>();
      siteConfig.putAll(shellState.getConnector().instanceOperations().getSiteConfiguration());
      
      final TreeMap<String,String> defaults = new TreeMap<String,String>();
      for (Entry<String,String> defaultEntry : AccumuloConfiguration.getDefaultConfiguration()) {
        defaults.put(defaultEntry.getKey(), defaultEntry.getValue());
      }
      Iterable<Entry<String,String>> acuconf = shellState.getConnector().instanceOperations().getSystemConfiguration().entrySet();
      if (tableName != null) {
        acuconf = shellState.getConnector().tableOperations().getProperties(tableName);
      }
      final TreeMap<String,String> sortedConf = new TreeMap<String,String>();
      for (Entry<String,String> propEntry : acuconf) {
        sortedConf.put(propEntry.getKey(), propEntry.getValue());
      }
      
      for (Entry<String,String> propEntry : acuconf) {
        final String key = propEntry.getKey();
        // only show properties with similar names to that
        // specified, or all of them if none specified
        if (cl.hasOption(filterOpt.getOpt()) && !key.contains(cl.getOptionValue(filterOpt.getOpt()))) {
          continue;
        }
        if (tableName != null && !Property.isValidTablePropertyKey(key)) {
          continue;
        }
        COL2 = Math.max(COL2, propEntry.getKey().length() + 3);
      }
      
      final ArrayList<String> output = new ArrayList<String>();
      printConfHeader(output);
      
      for (Entry<String,String> propEntry : sortedConf.entrySet()) {
        final String key = propEntry.getKey();
        
        // only show properties with similar names to that
        // specified, or all of them if none specified
        if (cl.hasOption(filterOpt.getOpt()) && !key.contains(cl.getOptionValue(filterOpt.getOpt()))) {
          continue;
        }
        if (tableName != null && !Property.isValidTablePropertyKey(key)) {
          continue;
        }
        String siteVal = siteConfig.get(key);
        String sysVal = systemConfig.get(key);
        String curVal = propEntry.getValue();
        String dfault = defaults.get(key);
        boolean printed = false;
        
        if (dfault != null && key.toLowerCase().contains("password")) {
          siteVal = sysVal = dfault = curVal = curVal.replaceAll(".", "*");
        }
{'fraction_non_alphanumeric': 0.11543325103871861, 'fraction_numerical': 0.0018666827241524658, 'mean_word_length': 3.4886486486486485, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3319806', 'n_tokens_mistral': 4367, 'n_tokens_neox': 4384, 'n_words': 1112}