package edu.sc.seis.sod.tools; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringReader; import java.util.Iterator; import java.util.Properties; import org.apache.log4j.PropertyConfigurator; import org.apache.velocity.VelocityContext; import org.xml.sax.InputSource; import com.martiansoftware.jsap.FlaggedOption; import com.martiansoftware.jsap.JSAP; import com.martiansoftware.jsap.JSAPException; import com.martiansoftware.jsap.Option; import com.martiansoftware.jsap.Switch; import edu.sc.seis.fissuresUtil.simple.Initializer; import edu.sc.seis.seisFile.client.AbstractClient; import edu.sc.seis.seisFile.fdsnws.AbstractFDSNClient; import edu.sc.seis.sod.Args; import edu.sc.seis.sod.Start; import edu.sc.seis.sod.UserConfigurationException; import edu.sc.seis.sod.Version; import edu.sc.seis.sod.velocity.SimpleVelocitizer; public class CommandLineTool extends AbstractClient { public CommandLineTool(String[] args) throws JSAPException { super(args); } protected void addParams() throws JSAPException { super.addParams(); add(new Switch("recipe", 'r', "recipe", "Print the created recipe to stdout instead of running it")); add(new FlaggedOption("server", JSAP.STRING_PARSER, null, false, 'S', "server", "The server to use, default is 'service.iris.edu'")); } public VelocityContext getContext() { VelocityContext vc = new VelocityContext(); Iterator it = params.iterator(); while(it.hasNext()) { Object cur = it.next(); if(cur instanceof Switch) { Switch sw = (Switch)cur; if(result.getBoolean(sw.getID())) { vc.put(sw.getID(), Boolean.TRUE); } } else { Option param = (Option)cur; if(param.isList()) { Object[] paramResult = result.getObjectArray(param.getID()); if(paramResult.length > 0) { vc.put(param.getID(), paramResult); } } else if (result.getObject(param.getID()) != null) { vc.put(param.getID(), result.getObject(param.getID())); } } } return vc; } public boolean shouldPrintRecipe() { return result.getBoolean("recipe"); } public InputStream getTemplate() throws IOException { String className = getClass().getName().replace('.', '/'); return Start.createInputStream("jar:" + className + ".vm"); } protected boolean requiresStdin = false; public static void run(CommandLineTool ls) throws Exception { Start.checkGCJ(); if(ls.shouldPrintRecipe()) { /* * Sad, sad, sad, sad, sad hack to get piping system.in to work in * java. * * Print something out immediately so downstream CommandLineTools * starting at the same time will get something from * System.in.available() and read in the data. If we don't use * System.in.available() there's no way to tell if there's something * in the pipe and we block forever on System.in.read() */ System.out.println("<sod>"); System.out.flush(); } Start.setCommandName(ls.commandName); // get some defaults Properties props = System.getProperties(); Initializer.loadProps(Start.createInputStream("jar:edu/sc/seis/sod/tools/simple.props"), props); Initializer.loadProperties(ls.getArgs(), props, false); PropertyConfigurator.configure(props); if(ls.shouldPrintHelp()) { System.err.println(Args.makeHelp(ls.commandName, ls.params)); System.exit(0); } if(ls.shouldPrintVersion()) { System.err.println(ls.commandName + " " + Version.current().getVersion()); System.exit(0); } if(!ls.isSuccess()) { Start.exit(Args.makeError(ls.commandName, ls.params, ls.result)); } VelocityContext ctx = ls.getContext(); SimpleVelocitizer sv = new SimpleVelocitizer(); // Wait two seconds before checking for input on system in to allow // sluggardly pipers to do their work try { Thread.sleep(2000); } catch(InterruptedException ie) { // What do you want me to do? } if(System.in.available() > 0) { StringBuffer buff = new StringBuffer(); InputStreamReader isr = new InputStreamReader(System.in); BufferedReader r = new BufferedReader(isr); String line; boolean inSod = false; while((line = r.readLine()) != null) { if(!inSod && line.indexOf("<sod>") != -1) { inSod = true; } else if(inSod) { if(line.indexOf("</sod>") != -1) { inSod = false; } else { buff.append(line); buff.append('\n'); } } } if(buff.length() == 0) { if(!inSod) { System.err.println("There was input on sysin, but it doesn't look like it was a recipe file"); } System.exit(1); } ctx.put("additionalArms", buff.toString()); } else if(ls.requiresStdin) { Start.exit("This tool requires that a recipe be piped into it."); } else { ctx.put("additionalArms", ""); } final String result = sv.evaluate(ls.getTemplate(), ctx); if(ls.shouldPrintRecipe()) { System.out.println(result); System.exit(0); } try { Start s = new Start(new Args(new String[] {"-f", "<stream>"}), new Start.InputSourceCreator() { public InputSource create() { return new InputSource(new StringReader("<sod>\n" + result)); } }, props, true); s.start(); } catch(UserConfigurationException e) { Start.exit(e.getMessage() + " SOD will quit now and continue to cowardly quit until this is corrected."); } } }