/** * $Id$ * $Date$ * */ package org.xmlsh.sh.core; import java.io.PrintWriter; import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.xmlsh.core.ICommand; import org.xmlsh.core.ThrowException; import org.xmlsh.core.UnexpectedException; import org.xmlsh.core.XValue; import org.xmlsh.sh.module.CommandFactory; import org.xmlsh.sh.module.IModule; import org.xmlsh.sh.shell.Shell; import org.xmlsh.util.Util; import org.xmlsh.xpath.ThreadLocalShell; public class SimpleCommandExpr extends CommandExpr { private static Logger mLogger = LogManager.getLogger(); private CommandPrefixExpr mPrefix; private Word mCommand; private CommandSuffixExpr mSuffix; @Override public boolean isSimple() { return true; } /* * Construct a command out of a word args and redir * both first and words might be assignments */ public SimpleCommandExpr(Word first, WordList args, IORedirectList redir) { mLogger.entry(first, args, redir); WordList cmdline = new WordList(); cmdline.add(first); cmdline.addAll(args); for(Word w : cmdline) { // not to command yet if(mCommand == null) { mCommand = w; continue; } if(mSuffix == null) mSuffix = new CommandSuffixExpr(); mSuffix.addArg(w); } if(redir != null) { for(IORedirect io : redir) mSuffix.addIO(io); } mLogger.exit(); } public SimpleCommandExpr(CommandPrefixExpr prefix, Word command, CommandSuffixExpr suffix) { mLogger.entry(prefix, command, suffix); mPrefix = prefix; mCommand = command; mSuffix = suffix; mLogger.exit(); } /* * (non-Javadoc) * * @see org.xmlsh.sh.core.Command#print(java.io.PrintStream) */ @Override public void print(PrintWriter out, boolean bExec) { if(mPrefix != null) mPrefix.print(out); if(mCommand != null) mCommand.print(out); if(mSuffix != null) { out.print(" "); mSuffix.print(out); } } /* * (non-Javadoc) * * @see org.xmlsh.sh.core.Command#exec(org.xmlsh.core.XEnvironment) */ @Override public int exec(Shell shell) throws Exception { mLogger.entry(mCommand); if(mCommand == null || mCommand.isEmpty()) return mLogger.exit(execNull(shell)); List<XValue> cmdLine = mSuffix.toCmdLine(shell, mCommand, getSourceLocation()); // Ignore empty or blank command lines if(cmdLine == null || cmdLine.isEmpty()) return mLogger.exit(0); String cmdName = cmdLine.remove(0).toString(); ICommand cmd = CommandFactory.getCommand(shell, cmdName, getSourceLocation()); if(cmd == null) { logLocation(shell); shell.printErr(mCommand + ": not found"); return mLogger.exit(1); } Shell saved_shell = null; /* * If there is a prefix then clone the shell, otherwise just clone the IO */ boolean popIO = false; if(mPrefix == null) { shell.getEnv().saveIO(); popIO = true; } else { saved_shell = shell; shell = shell.clone(); // must now close shell assert (shell != null); if(shell == null) throw mLogger .throwing(new UnexpectedException("Shell is null after close")); } int refcnt = 0; // In case we need to restore it - get it from possibly cloned shell Shell saved_context_shell = ThreadLocalShell.set(shell); try { if(mPrefix != null) mPrefix.exec(shell, getSourceLocation()); mSuffix.exec(shell, getSourceLocation()); // Push the current module if its different IModule mod = cmd.getModule(); assert (mod != null); try { shell.pushModule(mod); return cmd.run(shell, cmdName, cmdLine); } finally { mod = shell.popModule(); } } catch (ThrowException e) { throw e;// Rethrow } catch (Throwable e) { mLogger.catching(e); logLocation(shell); // Note: shell is the cloned shell .. shell.printErr("Exception running: " + cmdName + "\n" + e.toString()); /* * Save exception here ???? */ return mLogger.exit(-1); } finally { mLogger.trace("exec finally: {}", this); ThreadLocalShell.set(saved_context_shell); // TODO: should I push this back into the mdoule ? if(!popIO) { mLogger.trace("Closing cloned shell {} saved {}", shell, saved_shell); Util.safeClose(shell); } else { assert (!shell.isClosed()); if(!shell.isClosed()) { mLogger.trace("Restoring shell io {}", shell); shell.getEnv().restoreIO(); } } mLogger.exit(); } } private void logLocation(Shell shell) { shell.printLoc(mLogger, getSourceLocation()); } private int execNull(Shell shell) throws Exception { if(mPrefix != null) mPrefix.exec(shell, getSourceLocation()); if(mSuffix != null) mSuffix.exec(shell, getSourceLocation()); return shell.getStatus(); } @Override public String getName() { return mCommand == null ? "<command>" : mCommand.getSimpleName(); } } // // // Copyright (C) 2008-2014 David A. Lee. // // The contents of this file are subject to the "Simplified BSD License" (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.opensource.org/licenses/bsd-license.php // // Software distributed under the License is distributed on an "AS IS" basis, // WITHOUT WARRANTY OF ANY KIND, either express or implied. // See the License for the specific language governing rights and limitations // under the License. // // The Original Code is: all this file. // // The Initial Developer of the Original Code is David A. Lee // // Portions created by (your name) are Copyright (C) (your legal entity). All // Rights Reserved. // // Contributor(s): none. //