Java tutorial
// Copyright 2007 Hitachi Data Systems // All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. You may obtain // a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations // under the License. package com.archivas.clienttools.arcmover.cli; import com.archivas.clienttools.arcutils.api.ArcMoverEngine; import com.archivas.clienttools.arcutils.api.ArcMoverFactory; import com.archivas.clienttools.arcutils.config.ConfigurationException; import com.archivas.clienttools.arcutils.config.ConfigurationHelper; import com.archivas.clienttools.arcutils.impl.adapter.ConnectionTestException; import com.archivas.clienttools.arcutils.profile.*; import com.archivas.clienttools.arcutils.utils.StringUtils; import com.archivas.clienttools.arcutils.utils.database.DBUtils; import org.apache.commons.cli.*; import org.apache.commons.lang.text.StrBuilder; import java.io.PrintWriter; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; public class ArcProfileMgr extends AbstractArcCli { public static final String PACKAGE_NAME = ArcProfileMgr.class.getPackage().getName(); public static final String CLASS_FULL_NAME = ArcProfileMgr.class.getName(); public static final String CLASS_NAME = CLASS_FULL_NAME.substring(PACKAGE_NAME.length() + 1); public static Logger LOG = Logger.getLogger(CLASS_FULL_NAME); // Help Constants private static String HELP_USAGE_LINE; private static final String HELP_HEADER = "Creates, deletes, or displays information about namespace profiles.\n"; private static final String HELP_FOOTER = ""; /** Command Line Options **/ private static Options cliOptions; // Program Options boolean printHelp = false; boolean listProfiles = false; boolean printProfile = false; boolean createProfile = false; boolean deleteProfile = false; String profileName = null; ProfileType newProfileType = null; String newProfileHostname = null; boolean dontTest; boolean newProfileRequireSSL = false; String newProfileTenant = null; String newProfileNamespace = null; String newProfileUsername = null; String newProfilePassword = null; List<String> newProfileIPList = null; boolean newProfileUseIPs = false; Integer newProfilePort = null; boolean authAnon = false; boolean validateCustomMetadata = true; // Command Data private Map<String, Integer> columnWidths; public static final String COL_SEP = " "; public static final String KEY_PROFILE_NAME = "Name"; public static final String KEY_PROFILE_ID = "ID"; public static final String KEY_TYPE = "Type"; public static final String KEY_HOSTNAME = "Host Name"; public static final String KEY_TENANT = "Tenant"; public static final String KEY_NAMESPACE = "Namespace"; public static final String KEY_USERNAME = "User Name"; public static final String KEY_SSL = "SSL Enabled"; public static final boolean ALLOW_PORT = Boolean.getBoolean("portChoice"); static { cliOrder.put("help", 0); cliOrder.put("list", 1); cliOrder.put("delete", 2); cliOrder.put("create", 3); cliOrder.put("type", 4); cliOrder.put("hostname", 5); cliOrder.put("ips", 6); cliOrder.put("tenant", 7); cliOrder.put("namespace", 8); cliOrder.put("username", 9); cliOrder.put("password", 10); cliOrder.put("anon", 11); cliOrder.put("ssl", 12); cliOrder.put("check-cm", 13); cliOrder.put("notest", 14); if (ALLOW_PORT) { cliOrder.put("port", 15); } } public ArcProfileMgr(String args[]) { super(args); // Always allow insecure so we can test the profile ProfileManager.initialize(new AbstractArcCli.ArcCliSSLCertificateCallback(true)); HELP_USAGE_LINE = commandName + " profile -c <profile_name> | -d <profile_name> | -l [profile_name] [options]"; } @SuppressWarnings({ "static-access" }) public Options getOptions() { if (cliOptions == null) { Options options = new Options(); OptionGroup operations = new OptionGroup(); // *** Adding a new option needs to be added to the cliOrder list operations.addOption(OptionBuilder.withDescription("Displays this help text (the default behavior).") .withLongOpt("help").create("h")); operations.addOption(OptionBuilder.hasOptionalArg().withArgName("profile_name").withDescription( "Lists information about the specified namespace profile. If <profile_name> is omitted, lists information about all namespace profiles.") .withLongOpt("list").create("l")); operations.addOption(OptionBuilder.hasArg().withArgName("profile_name") .withDescription("Deletes the specified namespace profile.").withLongOpt("delete").create("d")); operations.addOption(OptionBuilder.hasArg().withArgName("profile_name") .withDescription("Creates a namespace profile with the specified name.").withLongOpt("create") .create("c")); options.addOptionGroup(operations); // List the valid profile types dynamically String profileTypesToString = "Type of namespace for which you are creating the namespace profile: "; for (ProfileType type : ProfileType.values()) { if (type != ProfileType.FILESYSTEM) { // Filesystem is already createdcd profileTypesToString += (type.toString() + " | "); } } profileTypesToString = profileTypesToString.substring(0, profileTypesToString.length() - 3); options.addOption(OptionBuilder.withArgName("profile_type").hasArg() .withDescription(profileTypesToString).withLongOpt("type").create()); options.addOption(OptionBuilder.withArgName("tenant_name").hasArg().withDescription( "Name of the tenant that owns the namespace for which you are creating the namespace profile.") .withLongOpt("tenant").create()); options.addOption(OptionBuilder.withArgName("namespace_name").hasArg() .withDescription("Name of the namespace for which you are creating the namespace profile.") .withLongOpt("namespace").create()); options.addOption(OptionBuilder.withArgName("username").hasArg() .withDescription("Username of the data access account to use for namespace access.") .withLongOpt("username").create()); options.addOption(OptionBuilder.withArgName("password").hasArg() .withDescription("Password of the data access account to use for namespace access.") .withLongOpt("password").create()); options.addOption(OptionBuilder.withArgName("hostname").hasArg() .withDescription("The fully qualified domain name of the HCP system.").withLongOpt("hostname") .create()); options.addOption( OptionBuilder.withDescription("Tells HCP-DM to use SSL when communicating with the HCP system.") .withLongOpt("ssl").create()); options.addOption(OptionBuilder.withDescription( "Tells HCP-DM to check whether custom metadata XML is well-formed prior to communicating with the HCP system.") .withLongOpt("check-cm").create()); options.addOption(OptionBuilder .withDescription("Log into namespace anonymously. Only valid with HCP 5.0 or later profile.") .withLongOpt("anon").create()); options.addOption(OptionBuilder.withDescription( "Does not test if the namespace configuration provided can access HCP while creating the profile.") .withLongOpt("notest").create()); options.addOption(OptionBuilder.withArgName("address1[,address2]...").hasArg().withDescription( "Comma-separated list of one or more IP addresses to use to connect to the HCP system. If omitted, HCP-DM uses the hostname.") .withLongOpt("ips").create()); if (ALLOW_PORT) { options.addOption(OptionBuilder.withArgName("port").hasArg() .withDescription("Port to connect to HCP on").withLongOpt("port").create()); } cliOptions = options; } return cliOptions; } public String getHelpFooter() { return HELP_FOOTER; } public String getHelpHeader() { return HELP_HEADER; } public String getHelpUsageLine() { return HELP_USAGE_LINE; } @SuppressWarnings({ "UseOfSystemOutOrSystemErr" }) public static void main(String args[]) { ArcProfileMgr arcProfileMgr = null; ConfigurationHelper.validateLaunchOK(); try { arcProfileMgr = new ArcProfileMgr(args); arcProfileMgr.parseArgs(); if (arcProfileMgr.printHelp) { System.out.println(arcProfileMgr.helpScreen()); } else { arcProfileMgr.execute(new PrintWriter(System.out), new PrintWriter(System.err)); } } catch (ParseException e) { System.out.println("Error: " + e.getMessage()); System.out.println(); System.out.println(arcProfileMgr.helpScreen()); arcProfileMgr.setExitCode(EXIT_CODE_OPTION_PARSE_ERROR); } catch (Exception e) { LOG.log(Level.SEVERE, "Unexpected Exception.", e); System.out.println(); System.out.println("Failed to create a new profile " + e.getMessage()); arcProfileMgr.setExitCode(EXIT_CODE_DM_ERROR); } finally { if (arcProfileMgr != null) { arcProfileMgr.exit(); } } } @SuppressWarnings({ "UnusedCatchParameter" }) protected void parseArgs() throws ParseException { // create the command cmdLine parser CommandLineParser parser = new PosixParser(); CommandLine cmdLine; // parse the command cmdLine arguments cmdLine = parser.parse(getOptions(), getArgs()); List<String> argList = cmdLine.getArgList(); printHelp = cmdLine.hasOption("h"); if (printHelp) { return; } listProfiles = cmdLine.hasOption("l"); printProfile = cmdLine.hasOption("p"); createProfile = cmdLine.hasOption("c"); deleteProfile = cmdLine.hasOption("d"); // Make sure only one of these is set if ((listProfiles && printProfile) || (listProfiles && createProfile) || (listProfiles && createProfile) || (printProfile && createProfile) || (printProfile && deleteProfile) || (createProfile && deleteProfile)) { throw new ParseException(" You may not specify more than one '-lpcd' option"); } // Do validation if (printProfile) { profileName = getProfileNameFromCmdLineAndValidateExistance(cmdLine, "p"); } if (createProfile) { profileName = getProfileNameAndValidateItDoesNotExist(cmdLine, "c"); newProfileType = validateProfileType(cmdLine); dontTest = cmdLine.hasOption("notest"); authAnon = cmdLine.hasOption("anon"); validateCustomMetadata = cmdLine.hasOption("check-cm"); newProfileIPList = validateIPs(cmdLine); newProfileUseIPs = newProfileIPList != null && newProfileIPList.size() > 0; if (newProfileType.equals(HCAPProfile.HCAP_TYPE) || newProfileType.equals(Hcp3DefaultNamespaceProfile.HCAP_TYPE)) { // Default Namespace if (!newProfileUseIPs) { // Only use hostname when not using IPs newProfileHostname = validateHostname(cmdLine); } newProfileRequireSSL = validateRequireSSL(cmdLine); if (authAnon) { throw new ParseException("Anonymous access only allowed with HCP 5.0 or later profile type."); } } else if (newProfileType.equals(Hcp3AuthNamespaceProfile.HCAP_TYPE) || newProfileType.equals(Hcp5AuthNamespaceProfile.HCAP_TYPE) || newProfileType.equals(Hcp6AuthNamespaceProfile.HCAP_TYPE)) { // Authenticated Namespace newProfileHostname = validateHostname(cmdLine); newProfileRequireSSL = validateRequireSSL(cmdLine); newProfileTenant = validateTenant(cmdLine); newProfileNamespace = validateNamespace(cmdLine); if (authAnon) { if (cmdLine.hasOption("username") || cmdLine.hasOption("password")) { throw new ParseException("Cannot specify ANON and a username or password!"); } } else { newProfileUsername = validateUsername(cmdLine); newProfilePassword = validatePassword(cmdLine); } } if (ALLOW_PORT) { newProfilePort = validatePort(cmdLine); } } if (deleteProfile) { profileName = getProfileNameFromCmdLineAndValidateExistance(cmdLine, "d"); if (profileName.equalsIgnoreCase(LFS) || profileName.equalsIgnoreCase(FileSystemProfile.DEFAULT_FILESYSTEM_PROFILE_NAME)) { throw new ParseException("Cannot delete the default file system profile."); } } if (listProfiles) { // If there is a profile name we are just printing info about that profile if (argList.size() > 1) { throw new ParseException("-l takes 0 or 1 arguments"); } else if (argList.size() == 1) { String namePassedIn = cmdLine.getOptionValue('l'); if (namePassedIn != null) { listProfiles = false; printProfile = true; profileName = validateProfileNameExists(namePassedIn); } } } } public ProfileType validateProfileType(CommandLine cmdLine) throws ParseException { String option = "type"; if (!cmdLine.hasOption(option)) { throw new ParseException("Missing Option: " + option); } String value = cmdLine.getOptionValue(option); ProfileType retval = null; boolean validType = false; for (ProfileType type : ProfileType.values()) { if (type.toString().equals(value) && type != ProfileType.FILESYSTEM) { // Filesystem is // already // created validType = true; } } if (!validType) { throw new ParseException("Invalid Profile Type: " + value); } retval = ProfileType.valueOf(value); if (retval == null) { throw new ParseException("Invalid Profile Type: " + newProfileType); } return retval; } public List<String> validateIPs(CommandLine cmdLine) throws ParseException { List<String> ipList = null; String option = "ips"; if (cmdLine.hasOption(option)) { String value = cmdLine.getOptionValue(option); String[] ipArray = org.apache.commons.lang.StringUtils.split(value, ","); // Convert since create profile wants a list if (ipArray != null) { ipList = new ArrayList<String>(); for (int i = 0; i < ipArray.length; ++i) { ipList.add(ipArray[i]); } } } return ipList; } public String validateHostname(CommandLine cmdLine) throws ParseException { String option = "hostname"; if (!cmdLine.hasOption(option)) { throw new ParseException("Missing Option: " + option); } String value = cmdLine.getOptionValue(option); String retval = null; if (value != null) { retval = value; } if (retval == null) { throw new ParseException("Invalid " + option + " : " + value); } return retval; } public boolean validateRequireSSL(CommandLine cmdLine) throws ParseException { String option = "ssl"; return cmdLine.hasOption(option); } public Integer validatePort(CommandLine cmdLine) throws ParseException { String option = "port"; if (!cmdLine.hasOption(option)) { return null; } Integer port = null; String value = cmdLine.getOptionValue(option); if (value != null) { try { port = Integer.valueOf(value); if (port < 0) { throw new NumberFormatException(); } } catch (NumberFormatException nfe) { throw new ParseException("Invalid " + option + " : " + value); } } return port; } public String validateTenant(CommandLine cmdLine) throws ParseException { String option = "tenant"; if (!cmdLine.hasOption(option)) { throw new ParseException("Missing Option: " + option); } String value = cmdLine.getOptionValue(option); String retval = null; if (value != null) { retval = value; } if (retval == null) { throw new ParseException("Invalid " + option + " : " + value); } return retval; } public String validateNamespace(CommandLine cmdLine) throws ParseException { String option = "namespace"; if (!cmdLine.hasOption(option)) { throw new ParseException("Missing Option: " + option); } String value = cmdLine.getOptionValue(option); String retval = null; if (value != null) { retval = value; } if (retval == null) { throw new ParseException(""); } return retval; } public String validateUsername(CommandLine cmdLine) throws ParseException { String option = "username"; if (!cmdLine.hasOption(option)) { throw new ParseException("Missing Option: " + option); } String value = cmdLine.getOptionValue(option); String retval = null; if (value != null) { retval = value; } if (retval == null) { throw new ParseException("Invalid " + option + " : " + value); } return retval; } public String validatePassword(CommandLine cmdLine) throws ParseException { String option = "password"; if (!cmdLine.hasOption(option)) { throw new ParseException("Missing Option: " + option); } String value = cmdLine.getOptionValue(option); String retval = null; if (value != null) { retval = Hcp3AuthNamespaceProfile.getMD5Password(value.toCharArray()); } if (retval == null) { throw new ParseException("Invalid " + option + " : " + value); } return retval; } /** * Entry point for generating a directory listing. */ public void execute(PrintWriter out, PrintWriter err) { StrBuilder output = new StrBuilder(); if (listProfiles) { output.append(createProfileListing()); } else if (printProfile) { output.append(getProfileDetails(profileName)); } else if (createProfile) { output.append(createProfile()); } else if (deleteProfile) { output.append(deleteProfile()); } else { output.append(helpScreen()); } out.println(output.toString()); out.flush(); err.flush(); } /** * Helper Method to load the profile list. */ protected List<AbstractProfileBase> getProfiles() { List<AbstractProfileBase> profileList = ProfileManager.getProfiles(); profileList.add(0, FileSystemProfile.LOCAL_FILESYSTEM_PROFILE); return profileList; } /** * Delete an existing Profile */ protected String deleteProfile() { StrBuilder output = new StrBuilder(); AbstractProfileBase profile = ProfileManager.getProfileByName(profileName); try { ProfileManager.deleteProfile(profile, true); } catch (Exception e) { String errMsg = "Error deleting profile '" + profile + "'"; errMsg = DBUtils.getErrorMessage(errMsg, e); LOG.log(Level.WARNING, errMsg, e); output.append(errMsg); setExitCode(EXIT_CODE_DM_ERROR); } return output.toString(); } /** * Create a new Profile. * * @return */ protected String createProfile() { StrBuilder output = new StrBuilder(); AbstractProfileBase profile = ProfileManager.getInstance().createProfile(newProfileType); profile.setName(profileName); if (profile instanceof HCAPProfile) { HCAPProfile fcfsProfile = (HCAPProfile) profile; fcfsProfile.setSSLRequired(newProfileRequireSSL); fcfsProfile.setValidateCustomMetadata(validateCustomMetadata); if (newProfileUseIPs) { fcfsProfile.setIpAddressList(newProfileIPList); fcfsProfile.setConnectByDns(false); } else { // Only set hostname if not using IPs fcfsProfile.setHostname(newProfileHostname); } fcfsProfile.setPort(newProfilePort); } if ((profile instanceof Hcp3AuthNamespaceProfile) || (profile instanceof Hcp5AuthNamespaceProfile)) { Hcp3AuthNamespaceProfile restProfile = (Hcp3AuthNamespaceProfile) profile; restProfile.setHostname(newProfileHostname); // Always set on HCP3Auth no matter what restProfile.setTenant(newProfileTenant); restProfile.setNamespace(newProfileNamespace); if (!restProfile.getType().supportsAnonymousAccess() && authAnon) { String errMsg = "Profile does not support anonymous access."; LOG.log(Level.WARNING, errMsg, "errMsg"); output.append(errMsg); setExitCode(EXIT_CODE_DM_ERROR); } if (restProfile.getType().supportsAnonymousAccess() && authAnon) { Hcp5AuthNamespaceProfile hcp5profile = (Hcp5AuthNamespaceProfile) restProfile; hcp5profile.setAnonymousAccess(true); } else { restProfile.setUsername(newProfileUsername); restProfile.setPassword(newProfilePassword); } } String badConnectionErrMsg = "Error connecting using the values passed in"; try { boolean canConnect = true; if (!dontTest) { ArcMoverEngine arcMover = ArcMoverFactory.getInstance(); canConnect = arcMover.testConnection(profile); } if (canConnect) { ProfileManager.saveProfile(profile); } else { output.append(badConnectionErrMsg); } } catch (ConfigurationException e) { String errMsg = "Error updating/saving new Profile: " + profile; LOG.log(Level.WARNING, errMsg, e); output.append(errMsg); setExitCode(EXIT_CODE_DM_ERROR); } catch (ConnectionTestException e) { LOG.log(Level.WARNING, badConnectionErrMsg, e); output.append(badConnectionErrMsg + ": " + e.getMessage()); setExitCode(EXIT_CODE_DM_ERROR); } return output.toString(); } /** * get details for the profile specified. * * @return */ protected String getProfileDetails(String profileName) { StrBuilder output = new StrBuilder(); AbstractProfileBase profile = ProfileManager.getProfileByName(profileName); if (profile == null) { output.append("Profile does not exist: ").append(profileName); output.append(NEWLINE); output.append(helpScreen()); } else { output.append("Name : ").append(profile.getName()).append(" ").append(NEWLINE); output.append("Type : ").append(profile.getType()).append(" ").append(NEWLINE); if (profile instanceof HCAPProfile) { HCAPProfile fcfsProfile = (HCAPProfile) profile; // Connect-by-DNS and Authenticated namespaces have a domain name to display if (fcfsProfile.isConnectByDns() || fcfsProfile.isAuthNamespace()) { output.append("Domain Name : ").append(fcfsProfile.getHostname()).append(" ").append(NEWLINE); } if (!fcfsProfile.isConnectByDns()) { output.append("IP List : ").append(StringUtils.createCSV(fcfsProfile.getIpAddressList())) .append(" ").append(NEWLINE); } output.append("SSL : "); if (fcfsProfile.isSSLRequired()) { output.append("Enabled"); } else { output.append("Disabled"); } output.append(" ").append(NEWLINE); output.append("Validate CM : "); if (fcfsProfile.isValidateCustomMetadata()) { output.append("Enabled"); } else { output.append("Disabled"); } output.append(" ").append(NEWLINE); if (ALLOW_PORT) { output.append("Port : ").append(fcfsProfile.getPort()).append(" ").append(NEWLINE); } } if (profile instanceof Hcp3AuthNamespaceProfile) { Hcp3AuthNamespaceProfile restProfile = (Hcp3AuthNamespaceProfile) profile; output.append("Tenant : ").append(restProfile.getTenant()).append(" ").append(NEWLINE); output.append("Namespace : ").append(restProfile.getNamespace()).append(" ").append(NEWLINE); output.append("User Name : ").append(restProfile.getUsername()).append(" ").append(NEWLINE); } } return output.toString(); } /** * Create the Profile listing output */ protected String createProfileListing() { StrBuilder sb = new StrBuilder(); List<AbstractProfileBase> profileList = getProfiles(); columnWidths = calcColumnWidths(profileList); for (Map.Entry<String, Integer> entry : columnWidths.entrySet()) { sb.appendFixedWidthPadRight(entry.getKey(), entry.getValue(), ' ').append(COL_SEP); } sb.append(NEWLINE); for (AbstractProfileBase profile : profileList) { sb.appendFixedWidthPadRight("" + profile.getName(), columnWidths.get(KEY_PROFILE_NAME), ' ') .append(COL_SEP); sb.appendFixedWidthPadRight("" + profile.getType(), columnWidths.get(KEY_TYPE), ' ').append(COL_SEP); sb.append(NEWLINE); } return sb.toString(); } /** * Crude mechanism to calculate column widths. * * TODO: This could be made more efficient. */ protected Map<String, Integer> calcColumnWidths(List<AbstractProfileBase> profileList) { Map<String, Integer> columnWidths = new LinkedHashMap<String, Integer>(); columnWidths.put(KEY_PROFILE_NAME, KEY_PROFILE_NAME.length()); columnWidths.put(KEY_TYPE, KEY_TYPE.length()); String key = null; for (AbstractProfileBase profile : profileList) { key = KEY_PROFILE_NAME; columnWidths.put(key, Math.max(columnWidths.get(key), ("" + profile.getName()).length())); key = KEY_TYPE; columnWidths.put(key, Math.max(columnWidths.get(key), ("" + profile.getType()).length())); } return columnWidths; } }