package org.ngbw.utils; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.List; import java.util.regex.Pattern; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.ngbw.sdk.Workbench; import org.ngbw.sdk.common.util.StringUtils; import org.ngbw.sdk.database.Country; import org.ngbw.sdk.database.User; import org.ngbw.sdk.phoenix.CipresPhoenixUserAccountManager; /** * This is the new version 2 utilizing Apache Commons CLI library. By utilizing the library, * it effectively eliminates "Array out of bound" exception when parsing command line options and parameters. * * @author Tony Chen * * @version 2.0.0 */ public class UserCountryIs { private static final Logger logger = Logger.getLogger(UserCountryIs.class); private static final String VERSION = "2.1.1"; private String log4jFile = null; private static CommandLine cmdln = null; private List argsList = null; public UserCountryIs () {} private static synchronized void usage ( final Options options ) { HelpFormatter formatter = new HelpFormatter(); formatter.printHelp("UserCountryIs", options, Boolean.TRUE); } private static synchronized void printHelp ( final Options options ) { final String baseCommand = "> java -cp [classpath-to-this-jar] " + UserCountryIs.class.getName() + " "; System.out.println(); System.out.println("Run as:"); System.out.println(baseCommand + "-u [function] [option-values ...]"); System.out.println(); usage(options); System.out.println(); System.out.println(); System.out.println("Functions"); System.out.println("---------"); System.out.println("Supported functions are:"); System.out.println(" -list List user's info."); System.out.println(" -c or -country COUNTRY Change the user's country."); System.out.println(" -sync Sync user's information with Phoenix Bioinformatics."); System.out.println(); System.out.println("Examples:"); System.out.println(" UserCountryIs -u johndoe -list"); System.out.println(" UserCountryIs -u johndoe -sync"); System.out.println(" UserCountryIs -u johndoe -c CA"); System.out.println(" UserCountryIs -u johndoe -c CA -sync"); System.out.println(); System.out.println("Additional Options:"); System.out.println("-----------------"); System.out.println("Additional (optional) options are:"); System.out.println(" -help Show this help information."); System.out.println(" -version Show this application version numbers."); System.out.println(" -log LOG4J A Log4j config file (in XML) to output logs."); System.out.println(); System.out.println("Examples:"); System.out.println(" UserCountryIs -log /path/to/log4j.xml -u johndoe -list"); System.out.println(" UserCountryIs -log /path/to/log4j.xml -u johndoe -c CA"); System.out.println(); } private static synchronized void printVersion () { System.out.println("CIPRES " + UserCountryIs.class.getSimpleName() + " " + VERSION); } private synchronized void loadLog4jConfigs ( final String log4jConfigsFile ) throws IOException { try { if (null == log4jConfigsFile || log4jConfigsFile.trim().isEmpty()) { throw new IllegalArgumentException("Log4j configs filename cannot be empty or null. "); } else if (!Files.exists(Paths.get(log4jConfigsFile))) { throw new FileNotFoundException(String.format("Log4j properties file [%s] not found.", log4jConfigsFile)); } org.apache.log4j.xml.DOMConfigurator.configureAndWatch(log4jConfigsFile, (1000 * 15)); // 15 sec } catch ( IOException e ) { throw e; } } private static synchronized Options buildOptions () { final Options options = new Options(); options.addOption(Option.builder("u").hasArg().argName("user").desc("The user's ID, username, or identifier.").build()); options.addOption(Option.builder("c").hasArg().argName("country").desc("Set the user's country to this.").build()); options.addOption(Option.builder("list").hasArg(false).desc("List details of the user.").build()); options.addOption(Option.builder("query").hasArg().argName("ip-address").desc("Query user's country from the IP address.").build()); options.addOption(Option.builder("sync").hasArg(false).desc("Sync user's info with Phoenix Bioinformatics.").build()); options.addOption(Option.builder("help").hasArg(false).desc("Print help information.").build()); options.addOption(Option.builder("version").hasArg(false).desc("Show version and description.").build()); options.addOption(Option.builder("log").hasArg().argName("log4j").desc("Configure Log4j with this Log4j XML file (optional).").build()); return options; } private static synchronized CommandLine getCommandLine ( final String[] args ) throws ParseException { CommandLineParser parser = new DefaultParser(); return parser.parse(buildOptions(), args, Boolean.FALSE); } private static synchronized boolean processOptions ( final CommandLine cmdln, final UserCountryIs userCountryIs ) throws Throwable { boolean shouldQuit = false; if (null == cmdln.getOptions() || cmdln.getOptions().length == 0) { printHelp(buildOptions()); shouldQuit = true; } else if (cmdln.hasOption("help")) { printHelp(buildOptions()); shouldQuit = true; } else if (cmdln.hasOption("version")) { printVersion(); shouldQuit = true; } else { if (cmdln.hasOption("log")) { userCountryIs.log4jFile = cmdln.getOptionValue("log"); } userCountryIs.argsList = cmdln.getArgList(); } // Surpress uncessary warning messages from Log4j lib. userCountryIs.surpressLogsToStdOutput(); return shouldQuit; } private static synchronized void configOptions ( final UserCountryIs userCountryIs ) { if (null != userCountryIs.log4jFile && !userCountryIs.log4jFile.trim().isEmpty()) { try { userCountryIs.loadLog4jConfigs(userCountryIs.log4jFile); } catch ( Throwable t ) { System.err.println(t.getMessage()); Logger.getRootLogger().setLevel(Level.OFF); } } } private synchronized void surpressLogsToStdOutput () { if (log4jFile == null || log4jFile.trim().isEmpty()) { Logger.getRootLogger().setLevel(Level.OFF); } } private synchronized void list ( final User user ) throws Throwable { if (null != user) { final Country country = (user.getCountry() == null) ? null : Country.getCountry(user.getCountry()); System.out.println(); System.out.println("UserID: " + user.getUserId()); System.out.println("Username: " + user.getUsername()); System.out.println("Identifier: " + user.getUUID()); System.out.println("Email: " + user.getEmail()); System.out.println("Name: " + user.getFirstName() + " " + user.getLastName()); System.out.println("Country: " + (country == null? "?" : String.format("%s (%s)", country.getName(), country.getAbbreviation()))); } } private synchronized void syncWithPhoenix ( final User user ) throws Throwable { if (null != user) { if (null == CipresPhoenixUserAccountManager.checkUserExistence(user)) { throw new RuntimeException(String.format( "The user, %s, has never been registered with Phoenix Bioinformatics. " + "Registering with Phoenix Bioinformatics requires the user's password.", user.getUsername())); } else if (StringUtils.isNullOrEmpty(user.getCountry(), true)) { throw new RuntimeException(String.format( "The country of the user, %s, is not populated correctly. Please update " + "the user's country before syncing with Phoenix's system.", user.getUsername())); } else { try { System.out.println(); System.out.println("Syncing user's information with Phoenix Bioinformatics ..."); CipresPhoenixUserAccountManager.update(user, null); // not updating the password. user.setPhoenixSyncReq("N"); user.save(); System.out.println("User's information synced successfully with Phoenix Bioinformatics."); } catch ( Throwable t ) { System.err.println( "Error when syncing user's info with Phoenix Bioinformatics:\n" + t.getMessage()); } } System.out.flush(); System.err.flush(); } } private synchronized void setCountry ( final User user, final String countryCode ) throws Throwable { if (null != user) { final Country newCountry = Country.getCountry(countryCode); final Country currCountry = (user.getCountry() == null? null : Country.getCountry(user.getCountry())); System.out.println(); if (null == newCountry) { System.out.println("Unknown country: " + countryCode); } else if (newCountry.equals(currCountry)) { System.out.println("The new country, '" + newCountry.getName() + "' is the same as current country."); } else { if (currCountry == null) { System.out.print(String.format("Changing user's country to '%s' ", newCountry.getName())); } else { System.out.print(String.format( "Changing user's country from '%s' to '%s' ", currCountry.getName(), newCountry.getName())); } System.out.flush(); for (int i = 0; i < 2; i++) { Thread.sleep(1000); System.out.print("."); System.out.flush(); } user.setCountry(newCountry.getAbbreviation()); user.setPhoenixSyncReq("Y"); user.save(); for (int i = 0; i < 3; i++) { Thread.sleep(1000); System.out.print("."); System.out.flush(); } Thread.sleep(1000); System.out.println(" done."); System.out.flush(); } } } /** * Queries user's country from the IP address. * *

* The IP is in IPv4 format. * * @param ipAddress the user's IP address * * @throws Throwable */ private synchronized void query ( final String ipAddress ) throws Throwable { try { final String countryCode = Workbench.getInstance().getCountryCodeFromIP(ipAddress); if (null != countryCode) { System.out.println("The country code of the IP " + ipAddress + " is " + countryCode + "."); } else { System.err.println("Unable to find country code of the IP: " + ipAddress); } } catch ( Throwable t ) { logger.error(t.getMessage(), t); throw t; } } public static void main ( String[] args ) { logger.debug("BEGIN: main(String[])::void"); int status = 0; UserCountryIs userCountryIs = null; try { userCountryIs = new UserCountryIs(); cmdln = getCommandLine(args); if (!processOptions(cmdln, userCountryIs)) { configOptions(userCountryIs); if (cmdln.hasOption("query")) { userCountryIs.query(cmdln.getOptionValue("query")); } else { if (!cmdln.hasOption("u")) { throw new RuntimeException("You must specify a username with the option 'u'."); } Workbench.getInstance(); Long userId = null; String userIdentifier = null; final User user; final String value = cmdln.getOptionValue("u"); // userId | userUUID | username if (StringUtils.hasPattern(value.trim(), Pattern.compile("^[0-9]+$"))) { userId = Long.parseLong(value.trim()); } else { userIdentifier = value.trim(); } // User findUser(userId, userName, email, uuid, activatedUserOnly, enforceUniqueness) user = User.findUser(userId, userIdentifier, userIdentifier, userIdentifier, false, true); if (null == user) { throw new RuntimeException("User '" + value.trim() + "' not found."); } final boolean hasAction = (cmdln.hasOption("c")) || (cmdln.hasOption("sync")); if (!hasAction) { userCountryIs.list(user); } else { if (cmdln.hasOption("c")) { userCountryIs.setCountry(user, cmdln.getOptionValue("c")); } if (cmdln.hasOption("sync")) { userCountryIs.syncWithPhoenix(user); } } System.out.println(); } } } catch ( Throwable t ) { status = 1; userCountryIs.surpressLogsToStdOutput(); System.err.println(t.getMessage()); logger.error(t.getMessage(), t); } userCountryIs = null; logger.trace("BEGIN: main(String[])::void"); System.exit(status); } }