Package henplus.commands

Source Code of henplus.commands.LoadCommand

/*
* This is free software, licensed under the Gnu Public License (GPL) get a copy from <http://www.gnu.org/licenses/gpl.html>
*
* author: Henner Zeller <H.Zeller@acm.org>
*/
package henplus.commands;

import henplus.AbstractCommand;
import henplus.CommandDispatcher;
import henplus.HenPlus;
import henplus.Interruptable;
import henplus.SQLSession;
import henplus.SigIntHandler;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Stack;
import java.util.StringTokenizer;

/**
* The Load command loads scripts; it implemnts the commands 'load', 'start', '@' and '@@'.
*/
public class LoadCommand extends AbstractCommand implements Interruptable {

    /**
     * to determine recursively loaded files, we remember all open files.
     */
    private final Set<File> _openFiles;

    /**
     * current working directory stack - to always open files relative to the currently open file.
     */
    private final Stack<File> _cwdStack;

    private volatile boolean _running;

    /**
     * returns the command-strings this command can handle.
     */
    @Override
    public String[] getCommandList() {
        return new String[] { "load", "start", "@", "@@" };
    }

    public LoadCommand() {
        _openFiles = new HashSet<File>();
        _cwdStack = new Stack<File>();
        try {
            final File cwd = new File(".");
            _cwdStack.push(cwd.getCanonicalFile());
        } catch (final IOException e) {
            HenPlus.msg().println("cannot determine current working directory: " + e);
        }
    }

    /**
     * filename completion by default.
     */
    @Override
    public Iterator<String> complete(final CommandDispatcher disp, final String partialCommand, final String lastWord) {
        return new FileCompletionIterator(partialCommand, lastWord);
    }

    /**
     * open a file. If this is a relative filename, then open according to current working directory.
     *
     * @param filename
     *            the filename to open
     * @return a file that represents the correct file name.
     */
    File openFile(final String filename) {
        File f = new File(filename);
        if (!f.isAbsolute()) {
            f = new File(_cwdStack.peek(), filename);
        }
        return f;
    }

    /**
     * execute the command given.
     */
    @Override
    public int execute(final SQLSession session, final String cmd, final String param) {
        final StringTokenizer st = new StringTokenizer(param);
        final int argc = st.countTokens();
        if (argc < 1) {
            return SYNTAX_ERROR;
        }
        final HenPlus henplus = HenPlus.getInstance();
        while (st.hasMoreElements()) {
            int commandCount = 0;
            final String filename = (String) st.nextElement();
            final long startTime = System.currentTimeMillis();
            File currentFile = null;
            try {
                henplus.pushBuffer();
                henplus.getDispatcher().startBatch();
                File f = openFile(filename);
                f = f.getCanonicalFile();
                if (_openFiles.contains(f)) {
                    throw new IOException("recursive inclusion alert: skipping file " + f.getName());
                }
                HenPlus.msg().println(f.getName());
                currentFile = f;
                _openFiles.add(currentFile);
                _cwdStack.push(currentFile.getParentFile());
                final String encoding = System.getProperty("file.encoding"); //"UTF-8"
                final FileInputStream is = new FileInputStream(currentFile);
                final BufferedReader reader = new BufferedReader(new InputStreamReader(is, encoding));
                _running = true;
                SigIntHandler.getInstance().pushInterruptable(this);
                String line;
                while (_running && (line = reader.readLine()) != null) {
                    final byte execResult = henplus.executeLine(line);
                    if (execResult == HenPlus.LINE_EXECUTED) {
                        ++commandCount;
                    }
                }
            } catch (final Exception e) {
                // e.printStackTrace();
                HenPlus.msg().println(e.getMessage());
                if (st.hasMoreElements()) {
                    HenPlus.msg().println("..skipping to next file.");
                    continue;
                }
                return EXEC_FAILED;
            } finally {
                henplus.popBuffer(); // no open state ..
                if (!_running) {
                    HenPlus.msg().println("cancel file loading " + currentFile);
                }
                henplus.getDispatcher().endBatch();
                if (currentFile != null) {
                    _openFiles.remove(currentFile);
                    _cwdStack.pop();
                }
                SigIntHandler.getInstance().popInterruptable();

            }
            final long execTime = System.currentTimeMillis() - startTime;
            HenPlus.msg().print(commandCount + " commands in ");
            TimeRenderer.printTime(execTime, HenPlus.msg());
            if (commandCount != 0) {
                HenPlus.msg().print("; avg. time ");
                TimeRenderer.printFraction(execTime, commandCount, HenPlus.msg());
            }
            if (execTime != 0 && commandCount > 0) {
                HenPlus.msg().print("; " + 1000 * commandCount / execTime + " per second");
            }
            HenPlus.msg().println(" (" + filename + ")");
        }
        return SUCCESS;
    }

    @Override
    public void interrupt() {
        _running = false;
    }

    @Override
    public boolean requiresValidSession(final String cmd) {
        return false;
    }

    /**
     * return a descriptive string.
     */
    @Override
    public String getShortDescription() {
        return "load file and execute commands";
    }

    @Override
    public String getSynopsis(final String cmd) {
        return cmd + " <filename> [<filename> ..]";
    }

    @Override
    public String getLongDescription(final String cmd) {
        return "\tOpens one file or a sequence of files and reads the\n"
                + "\tcontained sql-commands line by line. If the path of the\n"
                + "\tfilename is not absolute, it is interpreted relative to\n"
                + "\tthe current working directory. If the load command itself\n"
                + "\tis executed in some loaded file, then the current working\n"
                + "\tdirectory is the directory that file is in.\n" + "\tThe commands 'load' and 'start' do exactly the same;\n"
                + "\t'start', '@' and '@@' are provided for compatibility \n"
                + "\twith oracle SQLPLUS scripts. However, there is no\n"
                + "\tdistinction between '@' and '@@' as in SQLPLUS; henplus\n"
                + "\talways reads subfiles relative to the contained file.\n";
    }
}

/*
* Local variables: c-basic-offset: 4 compile-command:
* "ant -emacs -find build.xml" End:
*/ 
TOP

Related Classes of henplus.commands.LoadCommand

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.