package org.solrmarc.driver; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; import org.solrmarc.index.indexer.IndexerSpecException; import joptsimple.OptionException; import joptsimple.OptionParser; import joptsimple.OptionSet; import joptsimple.OptionSpec; /** * This class is the common parent for top level executable programs included as a part of SolrMarc, * most notably IndexDriver, and SolrMarcDebug. Its purpose is to handle command-line arguments * that are passed to any of those programs. It relies on the external library joptsimple. * https://pholser.github.io/jopt-simple/ * * @author rh9ec * */ public class BootableMain { private final static Logger logger = Logger.getLogger(BootableMain.class); protected String homeDirStrs[]; protected String addnlLibDirStrs[]; protected OptionSpec<String> readOpts; protected OptionSpec<String> configSpecs; protected OptionSpec<String> homeDirs; protected OptionSpec<String> addnlLibDirs; protected OptionSpec<File> solrjDir; protected OptionSpec<String> solrjClass; protected OptionSpec<File> deleteRecordByIdFile; protected OptionSpec<File> errorMarcErrOutFile; protected OptionSpec<File> errorIndexErrOutFile; protected OptionSpec<File> errorSolrErrOutFile; protected OptionSpec<String> files; protected OptionSet options = null; /** * Extract command line arguments and store them in various protected variables. * * @param args - the command line arguments passed to the Boot class, except for the first one * which specifies which main program is to be executed. * * @param failOnZeroArgs - true will cause the program to exit and print a help message * detailing the valid command-line arguments. false will simply do nothing * and return. */ protected void processArgs(String args[], boolean failOnZeroArgs) { OptionParser parser = new OptionParser( ); readOpts = parser.acceptsAll(Arrays.asList( "r", "reader_opts"), "file containing MARC Reader options").withRequiredArg().defaultsTo("marcreader.properties"); configSpecs = parser.acceptsAll(Arrays.asList( "c", "config"), "index specification file to use").withRequiredArg(); homeDirs = parser.accepts("dir", "directory to look in for scripts, mixins, and translation maps").withRequiredArg().ofType( String.class ); addnlLibDirs = parser.accepts("lib_local", "directory to look in for additional jars and libraries").withRequiredArg().defaultsTo("lib_local"); solrjDir = parser.accepts("solrj", "directory to look in for jars required for SolrJ").withRequiredArg().ofType( File.class ); solrjClass = parser.accepts("solrjClassName", "Classname of class to use for talking to solr").withRequiredArg(); errorMarcErrOutFile = parser.accepts("marcerr", "File to write records with errors.(not yet implemented)").withRequiredArg().ofType( File.class ); errorIndexErrOutFile = parser.accepts("indexerr", "File to write the solr documents for records with errors.(not yet implemented)").withRequiredArg().ofType( File.class ); errorSolrErrOutFile = parser.accepts("solrerr", "File to write the solr documents for records with errors.(not yet implemented)").withRequiredArg().ofType( File.class ); deleteRecordByIdFile = parser.accepts("del", "File to read list of document ids that are to be deleted").withRequiredArg().ofType( File.class ); parser.accepts("debug", "non-multithreaded debug mode"); parser.acceptsAll(Arrays.asList( "solrURL", "u"), "URL of Remote Solr to use").withRequiredArg(); parser.acceptsAll(Arrays.asList("print", "stdout"), "write output to stdout in user readable format");//.availableUnless("sorlURL"); parser.acceptsAll(Arrays.asList("null"), "discard all output, and merely show errors and warnings");//.availableUnless("sorlURL"); parser.acceptsAll(Arrays.asList("?", "help"), "show this usage information").forHelp(); //parser.mutuallyExclusive("stdout", "solrURL"); files = parser.nonOptions().ofType( String.class ); options = null; try { options = parser.parse(args ); } catch (OptionException uoe) { try { System.err.println(uoe.getMessage()); parser.printHelpOn(System.err); } catch (IOException e) { } System.exit(1); } if ((failOnZeroArgs && args.length == 0) || options.has("help")) { try { parser.printHelpOn(System.err); } catch (IOException e) { } System.exit(0); } if (options.has("dir")) { File defDir = new File(Boot.getDefaultHomeDir()); List<String> homeDirList = new ArrayList<>(); boolean hasDefDir = false; for (String dir : (options.valueOf(homeDirs).replaceAll("[,;]", "|").split("[|]"))) { File dirAsFile = new File(dir); if (dirAsFile.getAbsolutePath().equals(defDir.getAbsolutePath())) { hasDefDir = true; } homeDirList.add(dirAsFile.getAbsolutePath()); } if (!hasDefDir) homeDirList.add(defDir.getAbsolutePath()); homeDirStrs = homeDirList.toArray(new String[0]); } else { homeDirStrs = new String[]{ Boot.getDefaultHomeDir() }; } System.setProperty("solrmarc.home.dir", homeDirStrs[0]); reInitLogging(homeDirStrs); File solrJPath = ((options.has(solrjDir)) ? options.valueOf(solrjDir) : new File("lib-solrj")); try { if (solrJPath.isAbsolute()) { Boot.extendClasspathWithSolJJarDir(null, solrJPath); } else { Boot.extendClasspathWithSolJJarDir(homeDirStrs, solrJPath); } } catch (IndexerSpecException ise) { logger.fatal("Fatal error: Failure to load SolrJ", ise); logger.error("Exiting..."); System.exit(10); } // Now add local lib directories try { if (addnlLibDirs.value(options)!= null) { addnlLibDirStrs = addnlLibDirs.value(options).split("[,;|]"); Boot.extendClasspathWithLocalJarDirs(homeDirStrs, addnlLibDirStrs); } } catch (IndexerSpecException ise) { logger.fatal("Fatal error: Failure to load SolrJ", ise); logger.error("Exiting..."); System.exit(10); } } private static void reInitLogging(String[] homeDirs) { for (String dir : homeDirs) { File log4jProps = new File(dir, "log4j.properties"); if (log4jProps.exists()) { LogManager.resetConfiguration(); PropertyConfigurator.configure(log4jProps.getAbsolutePath()); return; } } } }