lcsim/src/org/lcsim/job
diff -u -r1.49 -r1.50
--- JobControlManager.java 31 Mar 2011 01:36:38 -0000 1.49
+++ JobControlManager.java 31 Mar 2011 23:19:28 -0000 1.50
@@ -27,6 +27,7 @@
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
@@ -40,6 +41,8 @@
import org.jdom.Element;
import org.jdom.Text;
import org.jdom.input.SAXBuilder;
+import org.jdom.output.Format;
+import org.jdom.output.XMLOutputter;
import org.lcsim.LCSimVersion;
import org.lcsim.units.Constants;
import org.lcsim.util.Driver;
@@ -62,56 +65,87 @@
* substituted into the XML file. An unlimited number of command-line variable
* definitions are allowed.
*
- * In the XML file, variables have the format <code>${var}</code>. No nested variable
- * definitions are allowed (e.g. no variables within variables).
+ * The <code>v</code> option turns on verbose mode.
+ *
+ * In the XML file, variables have the format <code>${[varname]}</code>. No nested variable
+ * definitions are allowed (e.g. no variables within variables).
+ *
+ * Command-line parameters that can be defined using switches are overridden by the
+ * corresponding settings in the job XML file, if they are present. This means that
+ * if these parameters are to be taken from the CL, the matching settings should be
+ * left out of the XML job file.
+ *
+ * A single <code>JobControlManager</code> should be used to execute one job, after
+ * which it should be discarded. If the {@link #run()} method is called twice on
+ * the same manager, a fatal exception will be thrown.
*
- * @version $Id: JobControlManager.java,v 1.49 2011/03/31 01:36:38 jeremy Exp $
+ * @version $Id: JobControlManager.java,v 1.50 2011/03/31 23:19:28 jeremy Exp $
* @author Jeremy McCormick
*/
public class JobControlManager
{
- private LCSimLoop loop;
+ // The LCIO record loop.
+ private LCSimLoop loop = new LCSimLoop();
- private Map<String, Driver> driverMap;
- private List<Driver> driverExec;
+ // Driver management.
+ private Map<String, Driver> driverMap = new LinkedHashMap<String, Driver>();
+ private List<Driver> driverExec = new ArrayList<Driver>();
private Map<String, String> availableDrivers = new HashMap<String, String>();
- private List<File> inputFiles;
- private Map<String,String> variableMap;
- private Map<String,Double> constants = new HashMap<String,Double>();
-
+ // Run parameters.
+ private List<File> inputFiles = new ArrayList<File>();
private int maxEvents = -1;
private int skipEvents = -1;
+ private File rewriteFile;
- private File cacheDirectory;
- private FileCache fileCache; // Start with default dir.
-
- private ClassLoader loader;
-
+ // Variables and constants.
+ private Map<String, String> variableMap = new HashMap<String, String>();
+ private Map<String, Double> constantsMap = new HashMap<String, Double>();
+
// Boolean job options.
- private boolean printInputFiles;
- private boolean printDriverStatistics;
- private boolean printSystemProperties;
- private boolean printUserClassPath;
- private boolean printDriversDetailed;
- private boolean printVersion;
- private boolean verbose;
- private boolean wasSetup;
- private boolean dryRun;
+ private boolean performDryRun;
+ private boolean rewrite;
+
+ // Settings effecting logging verbosity.
+ private boolean printInputFiles;
+ private boolean printDriverStatistics;
+ private boolean printSystemProperties;
+ private boolean printUserClassPath;
+ private boolean printDriversDetailed;
+ private boolean printVersion;
+ private boolean verbose;
+
+ // File caching.
+ private File cacheDirectory;
+ private FileCache fileCache; // Start with default dir.
+
+ // True once job parameters are setup from CL and XML.
+ private boolean wasSetup;
+
+ // Flag so that only one job is run by the manager.
+ private boolean ranJob;
+
+ // The manager's class loader.
+ private ClassLoader loader;
- // The log stream.
- private PrintStream logStream = System.out;
+ // The log stream for messages.
+ PrintStream logStream = System.out;
- private Element root;
+ // Root node of XML job file.
+ private Element root;
- private JDOMExpressionFactory factory;
+ // XML utils.
+ private JDOMExpressionFactory factory = new JDOMExpressionFactory();
+ private ParameterConverters paramConverter = new ParameterConverters(factory);
- private static ParameterConverters paramConverter;
+ // Command line options.
+ private static final Options options = createCommandLineOptions();
- private Options options;
+ // Reg exp to extract variables from a string with the form "${varName}".
+ private static final Pattern varPattern = Pattern.compile("[$][{][a-zA-Z_-]*[}]");
/**
- * This is the default no-argument constructor.
+ * The default constructor.
*/
public JobControlManager()
{
@@ -122,10 +156,7 @@
catch (IOException x)
{
throw new RuntimeException(x);
- }
-
- // Create Options object to represent command-line args.
- this.options = createCommandLineOptions();
+ }
}
/**
@@ -134,47 +165,65 @@
*/
public static void main(String args[])
{
- // FIXME Manual usage printout bypassing CLI.
- if (args.length == 0)
- {
- System.out.println("Usage: -pPropFile.prop -Dvar=value steeringFile.xml");
- return;
- }
JobControlManager mgr = new JobControlManager();
+ if (args.length == 0)
+ {
+ mgr.logStream.println("java -jar lcsim-bin.jar [options] steeringFile.xml");
+ HelpFormatter help = new HelpFormatter();
+ help.printHelp(" ", options);
+ System.exit(1);
+ }
mgr.parseCommandLineOptions(args);
mgr.run();
}
-
+
/**
* Create the command line options.
- * @return The command line options.
+ * @return The command line options for the manager.
*/
- private Options createCommandLineOptions()
+ private static Options createCommandLineOptions()
{
Options options = new Options();
- Option propOpt = new Option("p", true, "Properties file with variable definitions.");
- Option defOpt = new Option("D", true, "Variable definition.");
+ Option propOpt = new Option("p", true, "Load a properties file containing variable definitions");
+ Option defOpt = new Option("D", true, "Define a variable with form [name]=[value]");
+ Option rewriteOpt = new Option("w", true, "Rewrite the XML file with variables resolved");
+ Option verbOpt = new Option("v", false, "Turn on verbose mode");
+ Option skipOpt = new Option("s", true, "Set the number of events to skip.");
+ Option evtOpt = new Option("n", true, "Set the max number of events to process.");
+ Option dryOpt = new Option("x", false, "Perform a dry run which does not process events");
+ Option quietOpt = new Option("q", false, "Turn on quiet mode.");
options.addOption(propOpt);
options.addOption(defOpt);
+ options.addOption(rewriteOpt);
+ options.addOption(verbOpt);
+ options.addOption(skipOpt);
+ options.addOption(evtOpt);
+ options.addOption(dryOpt);
+ options.addOption(quietOpt);
return options;
}
/**
- * Parse command-line options and setup internal state from them. This method
- * calls {@link #setup(File)} to load the steering paramters from the XML file
- * after processing other command line options.
+ * Parse command-line options and setup job state from them. This method
+ * calls {@link #setup(File)} to load the steering paramters from an XML file,
+ * after processing other command line options. This method is private so that
+ * callers must all use the {@link #main(String[])} routine as the primary
+ * entry point.
*
* @param args The command line arguments.
*/
private void parseCommandLineOptions(String args[])
{
- CommandLineParser parser = new PosixParser();
+ // Setup parser.
+ CommandLineParser parser = new PosixParser();
+
+ // CommandLine to be loaded.
CommandLine cl = null;
- // Parse arguments.
+ // Parse CL arguments.
try
{
cl = parser.parse(options, args);
@@ -183,11 +232,19 @@
{
throw new RuntimeException(x);
}
+
+ // Turn on verbose mode. This setting may be overridden by control section from XML.
+ if (cl.hasOption("v"))
+ {
+ setVerbose(true);
+ }
+ // Turn on quiet mode. If "-v" is also specified, this will have no effect.
+ else if (cl.hasOption("q"))
+ {
+ setVerbose(false);
+ }
- // Init variable map.
- variableMap = new HashMap<String, String>();
-
- // Load properties file.
+ // Load properties file containing variable definitions.
if (cl.hasOption("p"))
{
String[] propValues = cl.getOptionValues("p");
@@ -220,7 +277,7 @@
}
}
- // Variable definitions.
+ // Process user variable definitions.
if (cl.hasOption("D"))
{
String[] defValues = cl.getOptionValues("D");
@@ -237,7 +294,37 @@
}
}
- // Extra argument is name of XML steering file.
+ // Rewrite XML file with variables resolved.
+ if (cl.hasOption("w"))
+ {
+ this.rewrite = true;
+ String rewritePath = cl.getOptionValue("w");
+ this.rewriteFile = new File(rewritePath);
+ if (this.rewriteFile.exists())
+ {
+ throw new RuntimeException("Rewrite file already exists: " + rewritePath);
+ }
+ }
+
+ // Set max number of events to run.
+ if (cl.hasOption("n"))
+ {
+ this.maxEvents = Integer.valueOf(cl.getOptionValue("n"));
+ }
+
+ // Set number of events to skip.
+ if (cl.hasOption("s"))
+ {
+ this.skipEvents = Integer.valueOf(cl.getOptionValue("s"));
+ }
+
+ // Perform a dry run, not processing any events but doing job setup.
+ if (cl.hasOption("x"))
+ {
+ this.performDryRun = true;
+ }
+
+ // The path to the XML steering file, which has no command switch.
if (cl.getArgList().size() == 0)
{
throw new RuntimeException("Missing LCSim XML file argument.");
@@ -245,25 +332,30 @@
else if (cl.getArgList().size() > 1)
{
throw new RuntimeException("Too many extra arguments.");
- }
+ }
- // Setup steering file and check for existence.
+ // Setup the XML steering file and check for its existence.
File xmlRunControlFile = new File((String) cl.getArgList().get(0));
if (!xmlRunControlFile.exists())
- throw new RuntimeException("The steering file " + args[0] + " does not exist!");
+ {
+ throw new RuntimeException("The steering file " + args[0] + " does not exist!");
+ }
- // Setup from XML.
+ // Setup job parameters from XML now that CL options are all processed.
setup(xmlRunControlFile);
}
/**
- * Add a variable definition to be substituted into the XML steering file.
+ * Add a variable definition to be substituted into the job's XML file.
* @param key The variable name.
* @param value The variable's value.
*/
private void addVariableDefinition(String key, String value)
{
- //logStream.println(key + " = " + value);
+ if (verbose)
+ {
+ logStream.println(key + " = " + value);
+ }
if (!this.variableMap.containsKey(key))
{
variableMap.put(key, value);
@@ -275,12 +367,23 @@
}
/**
- * Execute a job using the current steering state.
+ * Execute a job using the current parameters. This is publically accessible
+ * in case the CL interface isn't being used and {@link #setup(File)} was called
+ * manually.
*/
public void run()
{
+ // Only one job can be run with the manager, after which a new one should be created.
+ if (this.ranJob)
+ {
+ throw new RuntimeException("Cannot run multiple jobs! Create another JobManager.");
+ }
+
+ // If setup was not called first, then abort the job.
if (!wasSetup)
- throw new RuntimeException("Aborting job! The setup() method was never called.");
+ {
+ throw new RuntimeException("Aborting job! The method JobManager.setup(File) was never called.");
+ }
if (printVersion)
{
@@ -299,12 +402,15 @@
// Add the LCIO files to the loop.
loop.setLCIORecordSource(new LCIOEventSource("test", inputFiles));
- PrintStream statsStream = null;
-
+ // Driver statistics printout.
+ PrintStream statsStream = null;
if (printDriverStatistics)
+ {
statsStream = logStream;
+ }
- if (!dryRun)
+ // Execute job if not a dry run.
+ if (!performDryRun)
{
if (verbose)
{
@@ -315,7 +421,9 @@
if (skipEvents > 0)
{
if (verbose)
+ {
logStream.println("Skipping " + skipEvents + " events.");
+ }
loop.skip(skipEvents);
}
@@ -328,22 +436,30 @@
logStream.println("End time: " + (new Date()));
}
}
+ // A dry run does not process any events.
else
{
+ // Always print this info msg.
logStream.println("Executed dry run. No events processed!");
}
}
- // Record source exhausted before number of events was hit.
+ // Record source was exhausted before max events was hit. This is probably fine,
+ // but print message in case more were expected.
catch (LoopSourceExhaustedException x)
{
logStream.println(x.getMessage());
}
- // Other exceptions.
- catch (Exception x)
+ // Catch other fatal exceptions thrown from the loop.
+ catch (Exception e)
{
- throw new RuntimeException(x);
+ throw new RuntimeException(e);
}
+
+ // Cleanup.
loop.dispose();
+
+ // Set flag so that manager is NOT reused for another job.
+ this.ranJob = true;
}
/**
@@ -356,27 +472,18 @@
}
/**
- * Return a list of Drivers to be executed. This could be used to call them
- * from an external framework like JAS3. The list will be empty unless the
- * <code>setup()</code> method has been called.
+ * Return a list of Drivers to be executed. This can be used from an external
+ * framework like JAS3. The list will be empty unless the <code>setup()</code>
+ * method has been called.
* @return A <code>List</code> of <code>Drivers</code>.
*/
public List<Driver> getDriverExecList()
{
return this.driverExec;
}
-
- /**
- * Setup method which uses an embedded resource as the steering file.
- * @param resource
- */
- public void setup(String resource)
- {
- setup(JobControlManager.class.getResourceAsStream(resource));
- }
-
+
/**
- * Setup method which uses a File.
+ * Setup method from a <code>File</code>.
* @param file
*/
public void setup(File file)
@@ -392,7 +499,8 @@
}
/**
- * Setup method which uses a <code>InputStream</code> for steering.
+ * Setup job parameters from an <code>InputStream</code> with XML text.
+ * This could easily be used to load from a resource stream in a jar file.
* @param in The XML input stream.
*/
public void setup(InputStream in)
@@ -405,10 +513,7 @@
builder.setValidation(true);
builder.setFeature("http://apache.org/xml/features/validation/schema", true);
- // Setup expression resolution.
- factory = new JDOMExpressionFactory();
- if (paramConverter == null)
- paramConverter = new ParameterConverters(factory);
+ // Setup expression resolution.
builder.setFactory(factory);
// Build the document.
@@ -425,26 +530,74 @@
// Setup the JobControlManager from the XML file.
setup(doc);
}
-
+
+ /**
+ * The primary setup method. The other setup methods,
+ * {@link #setup(InputStream)} and {@link #setup(File)} both call
+ * this.
+ * @param doc The lcsim recon XML document describing the job.
+ */
+ private void setup(Document doc)
+ {
+ // Set the root element.
+ root = doc.getRootElement();
+
+ // Do variable substitutions.
+ substituteVariables(doc);
+
+ // Rewrite XML after variable substitution. Correctness of values,
+ // such as existence of input file paths, is NOT checked.
+ if (this.rewrite)
+ {
+ rewriteXMLSteering(doc);
+ }
+
+ // Setup the job control parameters.
+ setupJobControlParameters();
+
+ // Print system properties.
+ if (printSystemProperties)
+ {
+ printSystemProperties(logStream);
+ }
+
+ // Setup the class loader.
+ setupClassLoader();
+
+ // Setup units.
+ setupUnits();
+
+ // Process the variable definitions.
+ processConstants();
+
+ // Setup drivers with parameters and execution order.
+ setupDrivers();
+
+ // Setup the file cache.
+ setupFileCache();
+
+ // Setup the input files.
+ setupInputFiles();
+
+ // Flag JobManager as setup.
+ wasSetup = true;
+ }
+
/**
- * Perform variable substitution for an entire document.
+ * Perform variable substitution within all text data in a entire document.
* @param doc The XML document.
*/
private void substituteVariables(Document doc)
{
substituteVariables(doc.getRootElement());
}
-
- // Pattern to extract variables from text of the form "${varName}". Underscores
- // and dashes are accepted in variable names, as well as the usual letters and numbers.
- static private final Pattern varPattern = Pattern.compile("[$][{][a-zA-Z_-]*[}]");
-
+
/**
- * Substitute values from the previously filled internal <code>variableMap</code>
- * into an XML element and all its children, recursively.
+ * Substitute values from the <code>variableMap</code> into an XML element
+ * and all its children, recursively.
*
* @param element The XML element.
- * @throw RuntimeException If variable does not exist in the <code>variableMap</code>.
+ * @throw RuntimeException If a variable does not exist in the <code>variableMap</code>.
*/
private void substituteVariables(Element element)
{
@@ -454,11 +607,11 @@
// Create a new matcher.
Matcher match = varPattern.matcher(text);
- // No variables were used so return.
+ // No variables were used.
if (!match.find())
return;
- // New text from current to contain resolved variable values.
+ // Text data on which to perform substitutions.
String newText = new String(text);
// Reset the matcher.
@@ -473,10 +626,10 @@
// The name of the variable for lookup.
String varName = var.substring(2, var.length() - 1);
- // Get the value of the variable.
+ // The value of the variable.
String varValue = variableMap.get(varName);
- // If a variable is not defined, then the application will immediately exit here.
+ // If a variable was not defined, then the application will immediately exit here.
if (varValue == null)
{
throw new RuntimeException("Variable not defined: " + varName);
@@ -486,95 +639,238 @@
newText = newText.replace(var, varValue);
}
- // Set the element's new text with the substituted values.
+ // Set this element's new text value.
element.setText(newText);
}
- // Recursively process all child elements.
+ // Recursively process all child elements of this one.
for (Iterator it = element.getChildren().iterator(); it.hasNext(); )
{
substituteVariables((Element)it.next());
}
}
-
+
/**
- * The primary setup method. Public setup methods all end up here.
- * @param doc The lcsim recon XML document describing the job.
+ * Rewrite the XML steering file after resolving variables (done externally).
+ * The output path is set by command line argument to "-w".
+ * @param doc The XML steering doc with variables substituted.
*/
- private void setup(Document doc)
- {
- // Clear and/or setup data structures for the next run.
- clear();
-
- // Set the root element.
- root = doc.getRootElement();
-
- // Do variable substitutions.
- substituteVariables(doc);
-
- // Setup the job control parameters.
- setupJobControlParameters();
-
- // Print system properties.
- if (printSystemProperties)
- printSystemProperties(logStream);
-
- // Setup the class loader.
- setupClassLoader();
+ private void rewriteXMLSteering(Document doc)
+ {
+ if (verbose)
+ {
+ logStream.println("Rewriting XML to " + this.rewriteFile + " ...");
+ }
+ XMLOutputter outputter = new XMLOutputter();
+ outputter.setFormat(Format.getPrettyFormat());
+ try
+ {
+ FileOutputStream out = new FileOutputStream(this.rewriteFile);
+ outputter.output(doc, out);
+ out.close();
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
- // Setup units.
- setupUnits();
-
- // Process the variable definitions.
- processConstants();
-
- // Setup drivers with parameters and execution order.
- setupDrivers();
+ /**
+ * Setup the drivers from the XML job file,
+ * adding them to the JobManager's <code>driverMap</code> .
+ */
+ private void setupDrivers()
+ {
+ if (printDriversDetailed)
+ {
+ logStream.println("--- Drivers ---");
+ }
+
+ // Loop over the list of driver elements.
+ List<Element> drivers = root.getChild("drivers").getChildren("driver");
+ for (Element driver : drivers)
+ {
+ // Get the name of the Driver.
+ String name = driver.getAttributeValue("name");
- // Setup the file cache.
- setupFileCache();
+ // Get the fully qualified type of the Driver. ([packageName].[className])
+ String type = driver.getAttributeValue("type");
- // Setup the input files.
- setupInputFiles();
+ // Translate from a short name (optional).
+ if (availableDrivers.get(type) != null)
+ {
+ type = availableDrivers.get(type);
+ }
- // Flag JobManager as setup.
- wasSetup = true;
- }
-
- /**
- * Get the map of numerical constants to values.
- * @return The map of numerical constants.
- */
- public Map<String,Double> getConstants()
- {
- return this.constants;
- }
+ //
+ // Get Class, BeanInfo, and Constructor, and setup the new Driver instance.
+ //
+
+ // Class of the Driver.
+ Class driverClass;
+ try
+ {
+ driverClass = loader.loadClass(type);
+ }
+ catch (ClassNotFoundException x)
+ {
+ throw new RuntimeException("The Driver class " + type + " was not found.", x);
+ }
+
+ if (printDriversDetailed)
+ logStream.println(driverClass.getCanonicalName());
+
+ // The Driver instance.
+ Driver newDriver;
+ try
+ {
+ newDriver = (Driver) driverClass.newInstance();
+ }
+ catch (InstantiationException x)
+ {
+ throw new RuntimeException("Failed to create a Driver of class " + type + ". " +
+ "This class might be missing a public constructor with no arguments.",x);
+ }
+ catch (IllegalAccessException x)
+ {
+ throw new RuntimeException("Cannot access Driver type " + type + ". " +
+ "You may need to make this class or its constructor public.",x);
+ }
- /**
- * Reset private variables before next execution.
- */
- private void clear()
- {
- inputFiles = new ArrayList<File>();
- driverExec = new ArrayList<Driver>();
- driverMap = new LinkedHashMap<String, Driver>();
- maxEvents = -1;
- cacheDirectory = null;
- fileCache = null;
- loader = null;
- printDriverStatistics = false;
- printSystemProperties = false;
- printUserClassPath = false;
- printDriversDetailed = false;
- printInputFiles = true; // Defaults to true.
- printVersion = false;
- verbose = false;
- wasSetup = false;
- dryRun = false;
- logStream = System.out;
- loop = new LCSimLoop();
- root = null;
- }
+ // Get a list of Driver parameters.
+ List<Element> parameters = driver.getChildren();
+
+ // Process the parameters.
+ for (Element parameterElement : parameters)
+ {
+ // The parameter's setter method that we will find.
+ Method setter = null;
+
+ // The parameter's type that will be inferred from the method or is given by a type string in
+ // the case of an overloaded method.
+ Class propertyType = null;
+
+ // Get the parameter name.
+ String pname = parameterElement.getName();
+
+ // Find setter methods that look like good matches for this parameter.
+ List<Method> methods = getSetterMethods(driverClass);
+ List<Method> methodCandidates = new ArrayList<Method>();
+ for (Method method : methods)
+ {
+ String propHack = method.getName().replace("set", "");
+ propHack = propHack.substring(0, 1).toLowerCase() + propHack.substring(1);
+ if (propHack.equals(pname))
+ {
+ methodCandidates.add(method);
+ }
+ }
+
+ // Found the single setter method.
+ if (methodCandidates.size() == 1)
+ {
+ setter = methodCandidates.get(0);
+ if (setter.getParameterTypes().length > 1)
+ {
+ throw new RuntimeException("The set method has too many arguments for parameter: " + pname);
+ }
+ propertyType = setter.getParameterTypes()[0];
+ }
+ // Found several, overloaded methods. Try to disambiguate them.
+ else if (methodCandidates.size() > 1)
+ {
+ if (parameterElement.getAttribute("type") == null)
+ throw new RuntimeException("Parameter " + pname + " in Driver " + driverClass.getCanonicalName()
+ + " is overloaded, but a type field is missing from the parameter's XML element.");
+ try
+ {
+ // Try a primitive type first.
+ propertyType = getPrimitiveType(parameterElement.getAttribute("type").getValue());
+
+ // If type is null, then parameter is an Object and not a primitive, or it is not a valid type.
+ if (propertyType == null)
+ propertyType = Class.forName(parameterElement.getAttribute("type").getValue());
+ }
+ catch (ClassNotFoundException x)
+ {
+ throw new RuntimeException("Bad user type: " + parameterElement.getAttribute("type").getValue() + " for parameter " + pname + ".");
+ }
+ // Find a method that matches the user type.
+ for (Method candidateMethod : methodCandidates)
+ {
+ if (candidateMethod.getParameterTypes().length == 1 &&
+ candidateMethod.getParameterTypes()[0].equals(propertyType))
+ {
+ setter = candidateMethod;
+ break;
+ }
+ }
+ }
+ // No method found. The parameter name is probably invalid.
+ else if (methodCandidates.size() == 0)
+ {
+ throw new RuntimeException("No set method found for parameter: " + pname);
+ }
+
+ // No setter method found.
+ if (setter == null)
+ {
+ throw new RuntimeException("Unable to find set method for parameter: " + pname);
+ }
+
+ // Convert the parameter to the appropriate type.
+ IParameterConverter converter = paramConverter.getConverterForType(propertyType);
+ if (converter == null)
+ {
+ throw new RuntimeException(
+ "No converter found for parameter " + parameterElement.getName() +
+ " with type " + propertyType.getName() + ".");
+ }
+ Object nextParameter = converter.convert(factory, parameterElement);
+
+ // Call the setter with the parameter as argument.
+ Object pargs[] = new Object[1];
+ pargs[0] = nextParameter;
+ try
+ {
+ // This invokes the setter method of the driver.
+ setter.invoke(newDriver, pargs);
+
+ // Print parameters and values as they are set.
+ if (printDriversDetailed)
+ logStream.println(" " + pname + " = " + parameterElement.getText().trim());
+ }
+ catch (Exception x)
+ {
+ throw new RuntimeException("Problem processing parameter " + parameterElement.getName() + ".", x);
+ }
+ } // parameter loop
+
+ // Add a driver to the manager.
+ addDriver(name, newDriver);
+ } // driver loop
+
+ if (printDriversDetailed)
+ {
+ logStream.println("--- End Drivers ---");
+ }
+
+ // Make a list of Drivers to be executed.
+ List<Element> exec = root.getChild("execute").getChildren("driver");
+ for (Element execDriver : exec)
+ {
+ String driverName = execDriver.getAttributeValue("name");
+ Driver driverFind = driverMap.get(driverName);
+ if (driverFind != null)
+ {
+ driverExec.add(driverFind);
+ }
+ else
+ {
+ throw new RuntimeException("A Driver called " + driverName + " was not found.");
+ }
+ }
+ }
/**
* Add a Driver to the Driver map.
@@ -585,7 +881,7 @@
{
if (driverMap.containsKey(name))
{
- throw new RuntimeException("ERROR: duplicate driver name: " + name);
+ throw new RuntimeException("Duplicate driver name: " + name);
}
driverMap.put(name, driver);
}
@@ -601,6 +897,12 @@
logStream.println();
}
+ /**
+ * Cleaup file text and add to file list.
+ * @param fileText The file's raw text path from XML file.
+ * @param fileList The list files to which new file will be appended.
+ * @return The file that was created from the text.
+ */
private File processFileText(String fileText, List<File> fileList)
{
Element fileElement = new Element("file");
@@ -658,7 +960,7 @@
}
/**
- * Setup the input files to be processed using the XML steering document.
+ * Setup the list of input files to be processed from the XML job file.
*/
@SuppressWarnings("unchecked")
private void setupInputFiles()
@@ -699,7 +1001,7 @@
}
}
- // Read fileSets.
+ // Process <fileSet> elements.
List<Element> fileSets = (List<Element>)root.getChild("inputFiles").getChildren("fileSet");
for (Element fileSet : fileSets)
{
@@ -717,7 +1019,7 @@
}
}
- // Read fileRegExps, which may only reference local files.
+ // Read <fileRegExp> elements, which may only reference local files, not URLs.
List<Element> fileRegExps = (List<Element>)root.getChild("inputFiles").getChildren("fileRegExp");
for (Element fileRegExp : fileRegExps)
{
@@ -728,7 +1030,9 @@
throw new RuntimeException(basedir + " is not a valid directory!");
String dirlist[] = dir.list();
if (verbose)
+ {
logStream.println();
+ }
for (String file : dirlist)
{
if (file.endsWith(".slcio"))
@@ -738,28 +1042,32 @@
{
processFileText(basedir + File.separator + file, inputFiles);
if (verbose)
- logStream.println("Matched file <" + file.toString() + "> to pattern <" + pattern.toString() + ">");
+ {
+ logStream.println("Matched file <" + file.toString() + "> to pattern <" + pattern.toString() + ">");
+ }
}
else
{
if (verbose)
+ {
logStream.println("Did NOT match file <" + file.toString() + "> to pattern <" + pattern.toString() + ">");
+ }
}
}
}
}
- // Check that all files exist.
+ // Check that all the files exist.
for (File file : inputFiles)
{
if (!file.exists())
{
- logStream.println("The file " + file.getAbsolutePath() + " does not exist!");
- throw new RuntimeException("The file " + file.getAbsolutePath() + " does not exist!");
+ logStream.println("The input file " + file.getAbsolutePath() + " does not exist!");
[truncated at 1000 lines; 313 more skipped]