com.rathravane.till.console.shell.consoleLooper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of silt Show documentation
Show all versions of silt Show documentation
A small collection of classes used in various Rathravane systems.
/*
* Copyright 2006-2016, Rathravane LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.rathravane.till.console.shell;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.TreeSet;
import java.util.Vector;
import com.rathravane.till.console.ConsoleProgram;
import com.rathravane.till.console.ConsoleLineReader;
import com.rathravane.till.console.CmdLinePrefs;
import com.rathravane.till.console.ConsoleProgram.usageException;
import com.rathravane.till.nv.rrNvReadable;
/**
* implements a looper that repeatedly prompts for a command line and handles it
* @author peter
*/
public class consoleLooper implements ConsoleProgram.looper
{
public consoleLooper ( String[] headerLines, String prompt, String secondaryPrompt, commandList cl )
{
fHeaderLines = headerLines;
fInputQueue = new LinkedList ();
fPrompt = prompt;
fSecondaryPrompt = secondaryPrompt;
fEnableHelp = true;
fWorkspace = new HashMap ();
fState = inResult.kReady;
fCommands = cl;
}
public enum inResult
{
kReady,
kSecondaryPrompt,
kQuit
};
/**
* this key is used for a boolean setting that will suppress the copyright notice
*/
public static final String kSetting_Quiet = "quiet";
@Override
public boolean setup ( rrNvReadable p, CmdLinePrefs clp )
{
boolean quiet = p.getBoolean ( kSetting_Quiet, false );
if ( clp != null )
{
final String args = clp.getFileArgumentsAsString ();
if ( args != null && args.length () > 0 )
{
queue ( args );
queue ( "quit" );
quiet = true;
}
}
if ( !quiet )
{
writeHeader ();
}
return true;
}
@Override
public void teardown ( rrNvReadable p )
{
}
@Override
public boolean loop ( rrNvReadable p )
{
boolean result = true;
try
{
final String line = getInput ();
if ( line != null )
{
fState = handleInput ( p, line, System.out );
if ( fState == null )
{
fState = inResult.kReady;
}
}
else
{
// end of input stream
result = false;
}
}
catch ( IOException x )
{
// a break in console IO, we're done
System.err.println ( x.getMessage () );
result = false;
}
return result && !fState.equals ( inResult.kQuit );
}
public synchronized void queue ( String input )
{
fInputQueue.add ( input );
}
public synchronized void queueFromCmdLine ( CmdLinePrefs clp, boolean withQuit )
{
final Vector args = clp.getFileArguments ();
if ( args.size () > 0 )
{
final StringBuffer sb = new StringBuffer ();
for ( String s : args )
{
sb.append ( s );
sb.append ( ' ' );
}
queue ( sb.toString () );
if ( withQuit ) queue ( "quit" );
}
}
protected void writeHeader ()
{
if ( fHeaderLines != null )
{
for ( String header : fHeaderLines )
{
System.out.println ( header );
}
}
}
/**
* override this to handle input before its been parsed in the usual way
* @param input
* @param outputTo
* @return true to continue, false to exit
*/
protected inResult handleInput ( rrNvReadable p, String input, PrintStream outputTo )
{
inResult result = inResult.kReady;
final String[] commandLine = splitLine ( input );
if ( commandLine.length == 0 )
{
result = handleEmptyLine ( p, outputTo );
}
else
{
result = handleCommand ( p, commandLine, outputTo );
}
return result;
}
/**
* default handling for empty lines -- just ignore them
* @return true
*/
protected inResult handleEmptyLine ( rrNvReadable p, PrintStream outputTo )
{
return inResult.kReady;
}
/**
* consoles can override this to change how command lines are processed
* @param commandLine
* @param outputTo
* @return true to continue, false to exit
*/
protected inResult handleCommand ( rrNvReadable p, String[] commandLine, PrintStream outputTo )
{
inResult result = inResult.kReady;
final command m = getHandler ( commandLine );
if ( m != null )
{
final int argsLen = commandLine.length - 1;
final String[] args = new String [ argsLen ];
System.arraycopy ( commandLine, 1, args, 0, argsLen );
try
{
result = invoke ( m, p, args, outputTo );
}
catch ( Exception x )
{
result = handleInvocationException ( commandLine, x, outputTo );
}
}
else
{
result = handleUnrecognizedCommand ( commandLine, outputTo );
}
return result;
}
protected inResult invoke ( command m, rrNvReadable p, String[] args, PrintStream outputTo )
{
try
{
m.checkArgs ( p, args );
return m.execute ( fWorkspace, outputTo );
}
catch ( usageException x )
{
outputTo.println ( m.getUsage () );
outputTo.println ( x.getMessage () );
}
return inResult.kReady;
}
/**
* default handling for unrecognized commands
* @return inResult.kReady
*/
protected inResult handleUnrecognizedCommand ( String[] commandLine, PrintStream outputTo )
{
outputTo.println ( "Unrecognized command '" + commandLine[0] + "'." );
return inResult.kReady;
}
/**
* default handling for invocation problems
* @return inResult.kReady
*/
protected inResult handleInvocationException ( String[] commandLine, Exception x, PrintStream outputTo )
{
if ( x instanceof InvocationTargetException )
{
InvocationTargetException itc = (InvocationTargetException) x;
Throwable target = itc.getTargetException ();
outputTo.println ( "ERROR: " + target.getClass ().getName () + ": " + target.getMessage () );
}
else
{
outputTo.println ( "Error running command '" + commandLine[0] + "'. " + x.getMessage() );
}
return inResult.kReady;
}
protected HashMap getWorkspace ()
{
return fWorkspace;
}
private String[] fHeaderLines;
private final LinkedList fInputQueue;
private final String fPrompt;
private final String fSecondaryPrompt;
private boolean fEnableHelp;
private inResult fState;
private final commandList fCommands;
private final HashMap fWorkspace;
public static final String kCmdPrefix = "__";
public static final int kCmdPrefixLength = kCmdPrefix.length ();
private synchronized String getInput () throws IOException
{
String input = null;
if ( fInputQueue.size () > 0 )
{
input = fInputQueue.remove ();
}
else
{
String prompt = fPrompt;
if ( fState == inResult.kReady )
{
System.out.println ();
}
else
{
prompt = fSecondaryPrompt;
}
input = ConsoleLineReader.getLine ( prompt );
}
return input;
}
/**
* split a string on its whitespace into individual tokens
* @param line
* @return split array
*/
static String[] splitLine ( final String line )
{
final LinkedList tokens = new LinkedList ();
StringBuffer current = new StringBuffer ();
boolean quoting = false;
boolean lastWasWs = true;
for ( int i=0; i 0 )
{
tokens.add ( current.toString () );
}
current = new StringBuffer ();
lastWasWs = true;
}
else if ( c == '"' )
{
if ( lastWasWs )
{
// starting quoted string. eat it, flip quote flag
quoting = true;
}
else if ( !quoting )
{
// e.g. abc"def
current.append ( c );
}
else
{
// end quoted string
// e.g. "foo" bar, but also "foo"bar
tokens.add ( current.toString () );
current = new StringBuffer ();
quoting = false;
}
lastWasWs = false;
}
else
{
current.append ( c );
lastWasWs = false;
}
}
if ( current.length () > 0 )
{
tokens.add ( current.toString () );
}
return tokens.toArray ( new String[ tokens.size () ] );
}
private command getHandler ( String[] cmdLine )
{
if ( cmdLine.length > 0 )
{
return fCommands.getCommandFor ( cmdLine[0] );
}
else
{
return null;
}
}
public void __script ( String[] args, PrintStream outTo ) throws ConsoleProgram.usageException, IOException
{
if ( args.length != 2 )
{
throw new ConsoleProgram.usageException ( "script " );
}
LinkedList lines = new LinkedList ();
final String filename = args[1];
final BufferedReader bis = new BufferedReader ( new FileReader ( filename ) );
String input;
while ( ( input = bis.readLine () ) != null )
{
lines.add ( input );
}
bis.close ();
// add to the front of the queue so that script within script runs in
// correct order.
synchronized ( this )
{
fInputQueue.addAll ( 0, lines );
}
}
public void __help ( String[] args, PrintStream outTo ) throws ConsoleProgram.usageException, IOException
{
if ( fEnableHelp )
{
TreeSet allMethods = new TreeSet ();
Class> clazz = getClass ();
while ( !clazz.equals ( Object.class ) )
{
Method[] methods = clazz.getDeclaredMethods ();
for ( Method m : methods )
{
final String methodName = m.getName ();
if ( methodName.startsWith ( kCmdPrefix ) &&
methodName.length () > kCmdPrefixLength )
{
Class>[] params = m.getParameterTypes ();
if ( params.length == 2 && params[0].equals ( String[].class ) &&
params[1].equals ( PrintStream.class ) )
{
allMethods.add ( methodName.substring ( kCmdPrefixLength ) );
}
}
}
clazz = clazz.getSuperclass ();
}
for ( String s : allMethods )
{
outTo.println ( " " + s );
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy