Package nexj.core.tools

Source Code of nexj.core.tools.GenericREPL$FlushWriter

// Copyright 2010 NexJ Systems Inc. This software is licensed under the terms of the Eclipse Public License 1.0
package nexj.core.tools;

import java.io.BufferedReader;
import java.io.FilterWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;

import nexj.core.scripting.Parser;
import nexj.core.util.GenericException;
import nexj.core.util.IOUtil;
import nexj.core.util.Logger;
import nexj.core.util.StringUtil;
import nexj.core.util.SysUtil;

/**
* Base class for Scheme REPLs
*/
public abstract class GenericREPL extends GenericTool
{
   // constants

   /**
    * Exit code if an error occurred while logging in.
    */
   public final static int EXIT_LOGIN = 11;

   // attributes

   /**
    * True to suppress prompts and result printing.
    */
   private boolean m_bQuiet;

   /**
    * The maximum result print length.
    */
   protected long m_lMaxCount;

   /**
    * The user name to use
    */
   protected String m_sUser;

   // associations

   /**
    * The standard input reader.
    */
   protected Reader m_reader;

   /**
    * The standard output writer.
    */
   protected Writer m_writer;

   /**
    * The class logger.
    */
   protected final static Logger s_logger = Logger.getLogger(GenericREPL.class);

   // operations

   /**
    * The parse to use to parse input
    *
    * @return The parser to use
    */
   protected abstract Parser getParser();

   /**
    * Evaluate a parsed expression
    *
    * @param expr Expression to evaluate
    * @return The result of the evaluation
    */
   protected abstract Object evaluate(Object expr);

   /**
    * Write the given object to the given writer
    *
    * @param writer Writer to write the object to
    * @param obj Object to write
    * @throws IOException
    */
   protected abstract void write(Writer writer, Object obj) throws IOException;

   /**
    * Get a message from the given throwable
    *
    * @param t Throwable to get message for
    * @return Localized formatted message
    */
   protected abstract String getMessage(Throwable t);

   /**
    * @see nexj.core.tools.GenericTool#begin()
    */
   protected void begin() throws Exception
   {
      super.begin();

      m_sUser = getProperty("app.user");
      m_bQuiet = StringUtil.parseBoolean(getProperty("scm.quiet", "false"));
      m_lMaxCount = Long.parseLong(getProperty("scm.limit", "0"));
      m_reader = new BufferedReader(new InputStreamReader(System.in, IOUtil.ENCODING));
      m_writer = new FlushWriter(new OutputStreamWriter(System.out, IOUtil.ENCODING));
   }

   /**
    * @see nexj.core.tools.GenericTool#execute(java.lang.String)
    */
   protected final void execute(String sCommand) throws Exception
   {
      if (sCommand != null && sCommand.equals("-"))
      {
         sCommand = null;
      }

      Reader reader = (sCommand != null) ? new StringReader(sCommand) : m_reader;
      Parser parser = getParser();
      String sStartupMessage;

      setReader(reader);

      try
      {
         sStartupMessage = startup();
      }
      catch (nexj.core.tools.GenericREPL.LoginException t)
      {
         Throwable cause = t.getCause();

         setExitCode(EXIT_LOGIN);

         if (!m_bQuiet)
         {
            m_writer.write("; Login error: " + cause.getMessage());
            m_writer.write(SysUtil.LINE_SEP);
            m_writer.flush();
         }

         s_logger.info("Login error", cause);

         return;
      }

      if (sCommand == null && !m_bQuiet)
      {
         m_writer.write("; NexJ Scheme");
         m_writer.write(SysUtil.LINE_SEP);

         if (sStartupMessage != null)
         {
            m_writer.write("; " + sStartupMessage);
            m_writer.write(SysUtil.LINE_SEP);
         }

         m_writer.flush();
      }

      for (;;)
      {
         if (sCommand == null && !m_bQuiet)
         {
            m_writer.write(SysUtil.LINE_SEP);
            m_writer.write("> ");
            m_writer.flush();
         }

         try
         {
            Object expr = parser.parse(reader, null);

            if (expr == Parser.EOF)
            {
               break;
            }

            if (sCommand != null)
            {
               setReader(m_reader);
            }

            Object result;

            try
            {
               result = evaluate(expr);
            }
            finally
            {
               if (sCommand != null)
               {
                  setReader(reader);
               }
            }

            if (!m_bQuiet)
            {
               m_writer.write(SysUtil.LINE_SEP);
               m_writer.write("; ");
               write(m_writer, result);
               m_writer.write(SysUtil.LINE_SEP);
               m_writer.flush();
            }
         }
         catch (Throwable e)
         {
            s_logger.debug("Error", e);

            if (!m_bQuiet)
            {
               m_writer.write(SysUtil.LINE_SEP);
               m_writer.write(";Error: ");

               for (Throwable t = e; t != null; t = t.getCause())
               {
                  if (t != e)
                  {
                     m_writer.write(SysUtil.LINE_SEP);
                     m_writer.write(";Cause: ");
                  }

                  m_writer.write(getMessage(t));

                  StringWriter sw = new StringWriter();

                  t.printStackTrace(new PrintWriter(sw));

                  String s = sw.toString();
                  int i = s.indexOf(SysUtil.LINE_SEP);

                  if (i >= 0 && i < s.length())
                  {
                     m_writer.write(SysUtil.LINE_SEP);
                     m_writer.write(s.substring(i + SysUtil.LINE_SEP.length()));
                  }
               }

               m_writer.flush();
            }

            if (sCommand != null)
            {
               System.exit(1);
            }
         }
      }
   }

   /**
    * Set the reader we are using. Optionally override to handle this.
    *
    * @param reader Reader we are using to parse user input
    */
   protected void setReader(Reader reader)
   {
   }

   /**
    * Called after fully initialized. May return a single line message to print
    * before accepting input. By default returns null.
    *
    * @return A startup message or null for none.
    */
   protected String startup()
   {
      return null;
   }

   /**
    * @see nexj.core.tools.GenericTool#getCommandUsage()
    */
   protected String[] getCommandUsage()
   {
      return new String[]
      {
         "<script> - executes the script",
         "- - interactive mode"
      };
   }

   /**
    * @see nexj.core.tools.GenericTool#getOptionUsage()
    */
   protected String[] getOptionUsage()
   {
      return new String[]
      {
         "-Dapp.user=<user name>",
         "-Dscm.quiet=<true/false>",
         "-Dscm.limit=<#max result chars>"
      };
   }

   /**
    * @see nexj.core.tools.GenericTool#isCommandRequired()
    */
   protected boolean isCommandRequired()
   {
      return false;
   }

   /**
    * Notify the user of a change in status
    *
    * @param sMessage Status message to be printed
    */
   protected final void status(String sMessage)
   {
      if (m_bQuiet)
      {
         return;
      }

      try
      {
         m_writer.write("; " + sMessage);
         m_writer.write(SysUtil.LINE_SEP);
         m_writer.flush();
      }
      catch (IOException e)
      {
         s_logger.warn("Exception writing to output", e);
      }

   }

   // inner classes

   private static class FlushWriter extends FilterWriter
   {
      protected FlushWriter(Writer out)
      {
         super(out);
      }

      /**
       * @see java.io.Writer#write(char[], int, int)
       */
      public void write(char[] cbuf, int off, int len) throws IOException
      {
         super.write(cbuf, off, len);
         flush();
      }

      /**
       * @see java.io.Writer#write(int)
       */
      public void write(int c) throws IOException
      {
         super.write(c);
         flush();
      }

      /**
       * @see java.io.Writer#write(java.lang.String, int, int)
       */
      public void write(String str, int off, int len) throws IOException
      {
         super.write(str, off, len);
         flush();
      }
   }

   /**
    * An exception indicating an error occurred while logging in
    */
   protected class LoginException extends GenericException
   {
      private static final long serialVersionUID = 1480781571552138131L;

      public LoginException(Throwable cause)
      {
         super("err.repl.login", null, cause);
      }
   }
}
TOP

Related Classes of nexj.core.tools.GenericREPL$FlushWriter

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.