obol/testScript.java

package obol;

import java.io.*;
import java.util.*;

import obol.tools.Base64;
import obol.tools.Debug;

import obol.lang.API;
import obol.lang.Runtime;
import obol.lang.ScriptHandle;
import obol.lang.ReturnValue;
import obol.lang.ObolException;
import obol.lang.LoadedScriptInfo;

/** General script testing tool.
 * Loads and executes some script, allowing script inputs to be given on the
 * command line.
 * @version $Id: testScript.java,v 1.1 2007/03/16 16:22:07 perm Exp $
 */
public class testScript {
    private static final String __me = "obol.testScript";
    private static final String __version = "$Id: testScript.java,v 1.1 2007/03/16 16:22:07 perm Exp $";

    private static Debug __D = new Debug();

    public static String helpText =
"Usage:  java " + __me + " <args> <scriptfile> <script-params>\n" +
"    <args> are:\n" +
"        -h\tthis help text\n" +
"        -v\tbe verbose\n" +
"        -V\tprint version and exit\n" +
"        -n <name>\tname of script to execute, instead of first found\n" +
"        -r <ver>\tversion of script to execute, instead of first found\n" +
"        -D <name>=<level>  set debug level for a named debug facility\n" +
"             (can appear multiple times) See tools.Debug class docs.\n" +
"    <scriptfile> - an obol script filename\n" +
"    <script-params> - script input arguments, of the form \"key=value\".";


    // return true if the string contains any whitespace character
    private static boolean hasWhiteSpace(String data) {
	for (int _i = 0; _i < data.length(); _i++) {
	    if (Character.isWhitespace(data.charAt(_i))) {
		return true;
	    }
	}
	return false;
    }
    

    // strip enclosing double and single qoutes from the given string
    private static String strip(String data) {
	if (0 != data.length()) {
	    int _end = data.length() - 1;
	    char _dq = '"', _sq = '\'';
	    if ((_dq == data.charAt(0) && _dq == data.charAt(_end)) ||
		    (_sq == data.charAt(0) && _sq == data.charAt(_end))) {
		data = data.substring(1,_end);
	    }
	}
	return data;
    }


    // base64-decode the string, if it is surrounded by a pair of bars
    private static Object decode(String data) {
	int _end = data.length() - 1;
	if ('|' == data.charAt(0) && '|' == data.charAt(_end)) {	// Base64
	    return Base64.decode(data.substring(1, _end));
	}
	return data;
    }


    // convert an array of strings of the form "key=value" into a hashmap,
    // starting at the given index.
    private static Map mapifyArgs(String [] args, int startIndex) {
	HashMap _map = new HashMap(args.length - startIndex);
	for (int _i = startIndex; _i < args.length; _i++) {
	    String [] _sa = args[_i].split("=");
	    if (null == _sa || 2 != _sa.length) {
		throw new RuntimeException(__me + ".mapifyArgs(): " +
			"Bogus argument \"" + args[_i] + "\"!");
	    }
	    String _key = _sa[0];
	    if (hasWhiteSpace(_key)) {
		throw new RuntimeException(__me + ".mapifyArgs(): " +
			"Whitespace in key part of arg \"" + args[_i] +
			"\"!");
	    }
	    String _value = strip(_sa[1]);
	    _map.put(_key, decode(strip(_value)));
	}
	return _map;
    }


    // create a string consisting of comma-separated iterator elements
    private static String dumpIterator(Iterator it) { return dumpIterator(it, false); }
    private static String dumpIterator(Iterator it, boolean quote) {
	StringBuffer _sb = new StringBuffer();
	while(it.hasNext()) {
	    if (quote) _sb.append('"');
	    _sb.append(it.next().toString());
	    if (quote) _sb.append('"');
	    if (it.hasNext()) { _sb.append(", "); }
	}
	return _sb.toString();
    }


    // Main program (doh!)
    public static void main(String [] args) throws Exception {
	try  {
	    mainLoop(args);
	} catch (Exception e) {
	    e.printStackTrace();
	    throw e;
	}
    }

    public static void mainLoop(String [] args) throws Exception {
	// Process args
	int _i = 0;
	if (0 == args.length)  {
	    System.out.println(helpText);
	    System.exit(0);
	}
	String _scriptName = null;
	String _scriptVersion = null;
	String _debugName = null;
	String _debugLevel = null;
	boolean _argsOK = true;
	int _usedArgs = 0;
	for(; _i < args.length; _i++) {
	    String _arg = args[_i];
	    if (false == _arg.startsWith("-")) {
		break;
	    }
//	    System.err.println("processing arg " + _arg);
	    if ("-h".equals(_arg)) {
		System.out.println(helpText);
		System.exit(0);
	    } else if ("-v".equals(_arg)) {
	    } else if ("-V".equals(_arg)) {
		System.out.println(__me + " version: " + __version);
		System.exit(0);
	    } else if ("-n".equals(_arg)) {
		if (false == ((_i + 1) < args.length)) {
		    System.err.println("ERROR: Missing script name argument.");
		    _argsOK = false;
		}
		_scriptName = strip(args[++_i]);
		_usedArgs++;
	    } else if ("-r".equals(_arg)) {
		if (false == ((_i + 1) < args.length)) {
		    System.err.println("ERROR: Missing script version argument.");
		    _argsOK = false;
		}
		_scriptVersion = strip(args[++_i]);
		_usedArgs++;
	    } else if ("-D".equals(_arg)) {
		if (false == ((_i + 1) < args.length)) {
		    System.err.println("ERROR: Missing debug name facility and level argument!");
		    System.err.println("       Available facilities: " + Debug.getNames());
		    _argsOK = false;
		} else {
		    String [] _sa = args[++_i].split("=");
		    if (2 != _sa.length) {
			System.err.println("ERROR: -D option must have \"debug-name=level\" syntax!");
			_argsOK = false;
		    } else {
			_debugName = _sa[0];
			_debugLevel = _sa[1];
			// Call this here since -D can occure multiple times.
			Debug.setLevel(_debugName, _debugLevel);
		    }
		}
		_usedArgs++;
	    } else {
		_argsOK = false;
		System.err.println(__me + ": Unrecognized argument \"" + _arg +
		    "\"!");
	    }
	}
	if ((0 != _usedArgs && _usedArgs == (args.length - 1))
		|| (_i >= args.length)) {
	    System.err.println(__me + ": ERROR: Missing filename argument.");
	    _argsOK = false;
	}
	if (false == _argsOK) {
	    System.out.println(helpText);
	    System.exit(1);
	}
	String _scriptFileName = args[_i++];
	Map _args = mapifyArgs(args, _i);

	// contact Obol runtime, and load all scripts from the given file
	API _lobo = Runtime.getInstance();
	System.err.println(__me + ": Loading script(s) from file \"" +
		_scriptFileName + "\"");
	LoadedScriptInfo [] _loaded = _lobo.loadScripts(_scriptFileName);
	if (null == _loaded) {
	    System.err.println(__me + ": *** no scripts found in input file!");
	    System.exit(1);
	}
	LoadedScriptInfo _defaultInfo = _loaded[0];
	if (null == _scriptName) { 
	    _scriptName = _defaultInfo.getName();
	}
	for(Iterator _it = _lobo.getInfoIterator(); _it.hasNext(); ) {
	    // tell user what scripts were loaded from the file
	    LoadedScriptInfo _scriptInfo = (LoadedScriptInfo)_it.next();
	    System.err.println(__me + ": Runtime loaded script:\n" +
		    _scriptInfo.dumpAll());
	}

	// get instance of the script we want (either user-supplied or first
	// encountered), and tell user about it.
	ScriptHandle _script = _lobo.getScriptInstance(_scriptName, _scriptVersion);
	if (null == _script) {
	    if (null != _scriptName) {
		System.err.println(__me + ": *** no script named \"" +
			_scriptName+ "\" found in input file!");
	    }
	    if (null != _scriptVersion) {
		System.err.println(__me + ": *** no script of version " +
			_scriptVersion + " found in input file!");
	    }
	}
	System.err.println(__me + ": Selected this script: " +
		_script.getScriptInfo().dumpAll() + "\n...");

	// see if we can give the script all its input-requirements.
	if (false == _script.setMissingInputRequirements(_args)) {
	    Set _missing = _script.getMissingInputRequirements();
	    System.err.println(__me + ": *** There are " + _missing.size() +
		    " missing " + "input symbols: " +
		    dumpIterator(_missing.iterator()));
	    System.err.println(__me + ": *** Please rectify and retry.");
	    System.exit(1);
	}

	// start script
	System.err.println(__me + ": Starting script \"" + _scriptName +
		"\" with " + _args.size() + " input arguments " +
		dumpIterator(_args.keySet().iterator(), true) + " ...");
	
	_script.startExecution();

	try {
	    // main script handling event-loop
	    while (true) {
		// wait for a particular status change (available results,
		// or more input needed, as well as some defaults states,
		// such as completion or error states).
		int _status = _script.waitForStatus(
			ScriptHandle.STATUS_ARGUMENTS_REQUIRED
			| ScriptHandle.STATUS_RESULT_AVAILABLE);
		// status has changed, now see what it is
		if (0 != (_status & ScriptHandle.STATUS_ERROR_AVAILABLE)) {
		    // handle error flag
		    throw new RuntimeException(__me + ": Error status set");
		}
		if (0 != (_status & ScriptHandle.STATUS_RESULT_AVAILABLE)) {
		    // handle results availability
		    System.err.println(__me + ": Results available");
		}
		if (0 != (_status & ScriptHandle.STATUS_ARGUMENTS_REQUIRED)) {
		    // handle more missing input requirements: either supply
		    // more of user-supplied arguments, or complain and die.
		    Set _missing = _script.getMissingInputRequirements();
		    System.err.println(__me + ": Script require more input: " +
			    dumpIterator(_missing.iterator()));
		    if (false == _script.setMissingInputRequirements(_args)) {
			_missing = _script.getMissingInputRequirements();
			System.err.println(__me + ": ERROR: There are " +
				"still " + _missing.size() + " missing " +
				"input symbols: " +
				dumpIterator(_missing.iterator()));
			System.err.println("\nPlease rectify and retry.");
			System.exit(1);
		    }
		    System.err.println(__me + ": Required input provided, continuing.");
		    _script.continueExecution();
		}
		if (0 != (_status & ScriptHandle.STATUS_DONE)) {
		    // handle completion.
		    System.err.println("\n" + __me + ": Script is done.");
		    break;
		}
	    }

	    // obtain any results from the script, and tell user about these
	    Map _resultSpec = _script.getResultSpecification();
	    System.out.println(__me + ": Script \"" + _scriptName +
		    "\" returned " + _resultSpec.size() + " values: ");
	    int _count = 1;
	    for (Iterator _it = _resultSpec.keySet().iterator(); _it.hasNext();) {
		String _symName = (String)_it.next();
		ReturnValue _sym = _script.getSymbol(_symName);
		System.out.print("   " + (_count++) + " ReturnValue \"" +
			_symName + "\"");
		if (null == _sym || null == _sym.getValue()) {
		    System.out.println(" has NO value set!");
		} else {
		    System.out.println(" = " + _sym.dumpValue());
		}
	    }
	} catch (ObolException e) {
	    int [] _pos = _script.getCurrentPosition();
	    System.err.println(__me + "Caught " + e + " at " + _pos[0] + ":" + _pos[1]);
	    e.printStackTrace();
	}
	
	// we're done.
	System.err.println("\n" + __me + ": Done.");

    }
}

Generated by GNU enscript 1.6.4.