Package ca.carleton.gcrc.couch.command

Source Code of ca.carleton.gcrc.couch.command.CommandConfig

package ca.carleton.gcrc.couch.command;

import java.io.BufferedReader;
import java.io.File;
import java.io.PrintStream;
import java.net.URL;
import java.security.SecureRandom;
import java.util.Properties;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.codec.binary.Base64;

import ca.carleton.gcrc.couch.command.impl.PathComputer;
import ca.carleton.gcrc.couch.fsentry.FSEntryFile;
import ca.carleton.gcrc.security.rng.RngFactory;

public class CommandConfig implements Command {
 
  final static private Pattern patternAtlasName = Pattern.compile("^[a-zA-Z][a-zA-Z0-9_]*$");
  final static private Pattern patternDbName = Pattern.compile("^[a-z][a-z0-9]*$");

  @Override
  public String getCommandString() {
    return "config";
  }

  @Override
  public boolean matchesKeyword(String keyword) {
    if( getCommandString().equalsIgnoreCase(keyword) ) {
      return true;
    }
    return false;
  }

  @Override
  public boolean isDeprecated() {
    return false;
  }

  @Override
  public boolean requiresAtlasDir() {
    return true;
  }

  @Override
  public void reportHelp(PrintStream ps) {
    ps.println("Nunaliit2 Atlas Framework - Configuration Command");
    ps.println();
    ps.println("The configuration command allows a user to changes the parameters");
    ps.println("used to access and update an atlas.");
    ps.println();
    ps.println("Command Syntax:");
    ps.println("  nunaliit [<global-options>] config");
    ps.println();
    ps.println("Global Options");
    CommandHelp.reportGlobalSettingAtlasDir(ps);
  }

  @Override
  public void runCommand(
    GlobalSettings gs
    ,Stack<String> argumentStack
    ) throws Exception {
   
    // Check that atlas directory exists
    File atlasDir = gs.getAtlasDir();
   
    // Load up properties
    Properties props = getDefaultProperties();
    AtlasProperties.readProperties(atlasDir, props);
   
    // Create a server key, if one does not exist
    String serverKey = props.getProperty("server.key",null);
    if( null == serverKey ){
      SecureRandom rng = (new RngFactory()).createRng();
      byte[] key = new byte[16];
      rng.nextBytes(key);
     
      serverKey = Base64.encodeBase64String(key);
      props.setProperty("server.key", serverKey);
    }
   
    // Get user to enter properties
    userInputProperties(gs, props);
   
    // Write properties
    AtlasProperties.writeProperties(atlasDir, props);
    writeExtras(gs, atlasDir, props);
  }
 
  private void userInputProperties(GlobalSettings gs, Properties props) throws Exception {
   
    // Atlas Name
    {
      String atlasName = null;
      String defaultValue = props.getProperty("atlas.name");
      if( null == defaultValue || "".equals(defaultValue) ){
        defaultValue = gs.getAtlasDir().getName();
      }
      while( null == atlasName ) {
        atlasName = getUserStringInput(gs, "Enter the name of the atlas", defaultValue);
        if( null == atlasName ){
          gs.getErrStream().println("An atlas name must be provided");
        } else {
          Matcher matcher = patternAtlasName.matcher(atlasName);
          if( false == matcher.matches() ) {
            gs.getErrStream().println("An atlas name must start with a letter and be composed alpha-numerical characters");
            atlasName = null;
          }
        }
      }
      props.put("atlas.name", atlasName);
    }
   
    // CouchDB protocol
    {
      URL url = null;
      String urlString = null;
      while( null == url ) {
        urlString = getUserStringInput(gs, "Enter the URL to CouchDB", props, "couchdb.url");
        if( null == urlString ){
          gs.getErrStream().println("A URL must be provided for CouchDB");
        } else {
          try {
            url = new URL(urlString);
          } catch(Exception e) {
            gs.getErrStream().println("An invalid URL was entered");
          }
        }
      }
      props.put("couchdb.url", urlString);
      props.put("couchdb.url.protocol", url.getProtocol());
      props.put("couchdb.url.port", ""+url.getPort());
      props.put("couchdb.url.domain", url.getHost());
      props.put("couchdb.url.path", url.getPath());
    }

    // CouchDB main database name
    {
      String dbName = null;
      String defaultValue = props.getProperty("couchdb.dbName");
      if( null == defaultValue || "".equals(defaultValue) ){
        defaultValue = gs.getAtlasDir().getName();
      }
      while( null == dbName ) {
        dbName = getUserStringInput(gs, "Enter the name of the main database where atlas resides", defaultValue);
        if( null == dbName ){
          gs.getErrStream().println("A name for the database must be provided");
        } else {
          Matcher matcher = patternDbName.matcher(dbName);
          if( false == matcher.matches() ) {
            gs.getErrStream().println("A database name must start with a lowercase letter and be composed lowercase alpha-numerical characters");
            dbName = null;
          }
        }
      }
      props.put("couchdb.dbName", dbName);
    }

    // Submission database enabled?
    boolean submissionDbEnabled = false;
    {
      String defaultStringValue = props.getProperty("couchdb.submission.enabled");
      if( null == defaultStringValue || "".equals(defaultStringValue) ){
        defaultStringValue = "false";
      }
      boolean defaultValue = Boolean.parseBoolean(defaultStringValue);
      submissionDbEnabled = getUserBooleanInput(gs, "Do you wish to manually verify each document submission?", defaultValue);
      props.put("couchdb.submission.enabled", ""+submissionDbEnabled);
    }
   
    // CouchDB submission database name
    if( submissionDbEnabled ){
      String dbName = null;
      String defaultValue = props.getProperty("couchdb.submission.dbName");
      if( null == defaultValue || "".equals(defaultValue) ){
        String mainDbName = props.getProperty("couchdb.dbName");
        if( mainDbName != null && false == "".equals(mainDbName) ) {
          defaultValue = mainDbName + "submissions";
        } else {
          defaultValue = "submissions";
        }
      }
      while( null == dbName ) {
        dbName = getUserStringInput(gs, "Enter the name of the database where submissions will be uploaded", defaultValue);
        if( null == dbName ){
          gs.getErrStream().println("A name for the database must be provided");
        } else {
          Matcher matcher = patternDbName.matcher(dbName);
          if( false == matcher.matches() ) {
            gs.getErrStream().println("A database name must start with a lowercase letter and be composed lowercase alpha-numerical characters");
            dbName = null;
          }
        }
      }
      props.put("couchdb.submission.dbName", dbName);
    }
   
    // CouchDB admin name
    {
      String adminName = null;
      while( null == adminName ) {
        adminName = getUserStringInput(gs, "Enter the name of the admin user for CouchDB", props, "couchdb.admin.user");
        if( null == adminName ){
          gs.getErrStream().println("A name for the admin user must be provided");
        }
      }
      props.put("couchdb.admin.user", adminName);
    }
   
    // CouchDB admin password
    {
      String adminPassword = null;
      while( null == adminPassword ) {
        adminPassword = getUserStringInput(gs, "Enter the password for the admin user", props, "couchdb.admin.password");
        if( null == adminPassword ){
          gs.getErrStream().println("A password for the admin user must be provided");
        }
      }
      props.put("couchdb.admin.password", adminPassword);
    }
   
    // Servlet port
    {
      String portString = null;
      while( null == portString ) {
        portString = getUserStringInput(gs, "Enter the port where the atlas is served", props, "servlet.url.port");
        if( null == portString ){
          gs.getErrStream().println("A service port must be provided");
        } else {
          try {
            int port = Integer.parseInt(portString);
            if( 0 == port || port > 65535 ) {
              portString = null;
            }
          } catch(Exception e){
            portString = null;
          }
         
          if( null == portString ) {
            gs.getErrStream().println("Invalid port. It must be a positive integer up to 65535");
          }
        }
      }
      props.put("servlet.url.port", portString);
    }
  }
 
  private String getUserStringInput(GlobalSettings gs, String prompt, Properties props, String propName) throws Exception {
    String defaultValue = props.getProperty(propName);
    return getUserStringInput(gs, prompt, defaultValue);
  }

  private String getUserStringInput(GlobalSettings gs, String prompt, String defaultValue) throws Exception {
    BufferedReader reader = gs.getInReader();

    // Prompt user
    gs.getOutStream().print(prompt);
    if( null != defaultValue ){
      gs.getOutStream().print(" [");
      gs.getOutStream().print(defaultValue);
      gs.getOutStream().print("]");
    }
    gs.getOutStream().print(": ");
   
    // Read answer
    String line = null;
    try {
      line = reader.readLine();
    } catch(Exception e) {
      throw new Exception("Error while reading configuration information from user",e);
    }
    String atlasName = null;
    if( null == line ) {
      // End of stream reached
      throw new Exception("End of input stream reached");
    } else {
      line = line.trim();
      if( "".equals(line) ){
        atlasName = defaultValue;
      } else {
        atlasName = line;
      }
    }
   
    return atlasName;
  }

  private boolean getUserBooleanInput(GlobalSettings gs, String prompt, boolean defaultValue) throws Exception {
    BufferedReader reader = gs.getInReader();

    // Read answer
    boolean response = false;
    boolean validResponse = false;
    while( false == validResponse ) {
      // Prompt user
      gs.getOutStream().print(prompt);
      gs.getOutStream().print("(Y/N)");
      if( defaultValue ) {
        gs.getOutStream().print(" [Y]");
      } else {
        gs.getOutStream().print(" [N]");
      }
      gs.getOutStream().print(": ");
     
      String line = null;
      try {
        line = reader.readLine();
      } catch(Exception e) {
        throw new Exception("Error while reading configuration information from user",e);
      }
      if( null == line ) {
        // End of stream reached
        throw new Exception("End of input stream reached");
      } else {
        line = line.trim();
        if( "".equals(line) ){
          response = defaultValue;
          validResponse = true;
        } else {
          // Analyze response
          if( "y".equalsIgnoreCase(line) ) {
            response = true;
            validResponse = true;
          } else if( "yes".equalsIgnoreCase(line) ) {
            response = true;
            validResponse = true;
          } else if( "n".equalsIgnoreCase(line) ) {
            response = false;
            validResponse = true;
          } else if( "no".equalsIgnoreCase(line) ) {
            response = false;
            validResponse = true;
          }
        }
      }
     
      if( !validResponse ){
        gs.getErrStream().println("A valid response must be provided: Y, N or blank to accept previous value.");
      }
    }
   
    return response;
  }

  private Properties getDefaultProperties() {
    Properties props = new Properties();
   
    return props;
  }
 
  private void writeExtras(GlobalSettings gs, File atlasDir, Properties props) throws Exception {
    CopyMachine copyMachine = new CopyMachine();
    copyMachine.setAcceptFileFilter(gs.getFsEntryNameFilter());
   
    File binDir = PathComputer.computeBinDir(gs.getInstallDir());
    if( null != binDir ) {
      copyMachine.addTextConversion("NUNALIIT_BIN_DIR", binDir.getAbsolutePath());
    }
    copyMachine.addTextConversion("ATLAS_DIR", atlasDir.getAbsolutePath());
    copyMachine.addTextConversion("ATLAS_NAME", props.getProperty("atlas.name"));

    File templateDir = PathComputer.computeTemplatesDir( gs.getInstallDir() );
    File sourceExtra = new File(templateDir, "extra");
    File destExtra = new File(atlasDir, "extra");
    copyMachine.copyDir(new FSEntryFile(sourceExtra), destExtra);
   
   
  }
}
TOP

Related Classes of ca.carleton.gcrc.couch.command.CommandConfig

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.