/*******************************************************************************
*                                                                              *
*  File:        Rhino_11a.java                          Revision:  1.0         *
*                                                                              *
*  Purpose:     creates JavaScript objects with "Prototype" and "Parent" from  *
*               within Java and tests them under JavaScript                    *
*                                                                              *
*  Creation:    01.11.2001                     Last Modification:  01.11.2001  *
*                                                                              *
*  Platform:    IBM-compatible PC running Windows 98SE                         *
*                                                                              *
*  Environment: Java 1.3                                                       *
*                                                                              *
*  Author:      Andreas Rozek           Phone:  ++49 (711) 6770682             *
*               Kirschblütenweg 15      Fax:    -                              *
*             D-70569 Stuttgart         EMail:  Andreas.Rozek@T-Online.De      *
*               Germany                                                        *
*                                                                              *
*  URL:         http://www.Andreas-Rozek.de/                                   *
*                                                                              *
*  Copyright:   this software is published under the  "GNU Lesser General Pub- *
*               lic  License"  (see  "http://www.fsf.org/copyleft/lesser.html" *
*               for additional information)                                    *
*                                                                              *
*  Comments:    (none)                                                         *
*                                                                              *
*******************************************************************************/

import java.io.*;                            // Java file handling and stream IO
import org.mozilla.javascript.*;                   // Rhino distribution classes

public class Rhino_11a extends ScriptableObject {

/*******************************************************************************
*                                                                              *
*                          Non-Public Class Variables                          *
*                                                                              *
*******************************************************************************/

  static Rhino_11a Global;           // refers to the JavaScript "Global" object
  static Object    undefined;     // shortcut referring to the "undefined" value

/*******************************************************************************
*                                                                              *
*                             Public Class Methods                             *
*                                                                              *
*******************************************************************************/

/*******************************************************************************
*                                                                              *
* evaluateFile          evaluates the contents of a given (script source) file *
*                                                                              *
*******************************************************************************/

  public static void evaluateFile (Context actualContext, String FileName) {
    FileReader InStream = null;
    try {
      InStream = new FileReader(FileName);
      actualContext.evaluateReader(Global, InStream, FileName, 1, null);
    } catch (FileNotFoundException Signal) {
      Context.reportError(
        "unable to open file \"" + FileName + "\" (reason: \"" + Signal.getMessage() + "\")"
      );
    } catch (WrappedException Signal) {
      Context.reportError(
        "WrappedException while evaluating file \"" + FileName +
        "\" (reason: \"" + Signal.getMessage() + "\")"
      );
    } catch (EvaluatorException Signal) {
      Context.reportError(
        "EvaluatorException while evaluating file \"" + FileName +
        "\" (reason: \"" + Signal.getMessage() + "\")"
      );
    } catch (JavaScriptException Signal) {
      Context.reportError(
        "JavaScriptException while evaluating file \"" + FileName +
        "\" (reason: \"" + Signal.getMessage() + "\")"
      );
    } catch (IOException Signal) {
      Context.reportError(
        "error while reading file \"" + FileName + "\" (reason: \"" + Signal.getMessage() + "\")"
      );
    } finally {
      try {
        if (InStream != null) InStream.close();
      } catch (Exception Signal) {
        /* nop */
      };
    };
  };

/*******************************************************************************
*                                                                              *
* evaluateString               evaluates the contents of a given script source *
*                                                                              *
*******************************************************************************/

  public static void evaluateString (Context actualContext, String SourceText) {
    try {
      actualContext.evaluateString(Global, SourceText, "Rhino_11a", 1, null);
    } catch (WrappedException Signal) {
      Context.reportError(
        "WrappedException while evaluating the internal script source " +
        "(reason: \"" + Signal.getMessage() + "\")"
      );
    } catch (EvaluatorException Signal) {
      Context.reportError(
        "EvaluatorException while evaluating the internal script source " +
        "(reason: \"" + Signal.getMessage() + "\")"
      );
    } catch (JavaScriptException Signal) {
      Context.reportError(
        "JavaScriptException while evaluating the internal script source " +
        "(reason: \"" + Signal.getMessage() + "\")"
      );
    };
  };

/*******************************************************************************
*                                                                              *
* exit                             leaves the shell with the given return code *
*                                                                              *
*******************************************************************************/

  public static void exit (
    Context actualContext, Scriptable actualObject, Object[] ArgList, Function FunctionContext
  ) {
    if        (ArgList.length == 0) {
      java.lang.System.exit(0);
    } else if (ArgList.length != 1) {
      throw new IllegalArgumentException("exit(code) called with more than one argument");
    } else if (ArgList[0] == undefined) {
      throw new IllegalArgumentException("exit(code) called with an undefined argument");
    } else {
      double ReturnCode = Context.toNumber(ArgList[0]);
      if (Double.isNaN(ReturnCode)) {
        throw new IllegalArgumentException("exit(code) called with non-numeric argument");
      } else if (Double.isInfinite(ReturnCode) || (ReturnCode < Integer.MIN_VALUE) || (ReturnCode > Integer.MAX_VALUE)) {
        throw new IllegalArgumentException("exit(code) called with infinite numeric argument");
      } else {
        java.lang.System.exit((int) ReturnCode);
      };
    };
  };

/*******************************************************************************
*                                                                              *
* main                                                            main program *
*                                                                              *
*******************************************************************************/

  public static void main (String ArgList[]) {
    if (ArgList.length != 0) {
      complainln("Warning: any given command line arguments will be ignored");
    };

  /**** prepare Rhino execution environment ****/

    Global = new Rhino_11a();      // let "Rhino_11a" become the "Global" object

    Context ScriptContext = Context.enter();
      Scriptable ScriptScope = ScriptContext.initStandardObjects(Global);

      undefined = ScriptContext.getUndefinedValue();

    /**** register internal functions ****/

      String[] NameList = {"exit", "print", "println"};
      try {
        Global.defineFunctionProperties(NameList, Rhino_11a.class, ScriptableObject.DONTENUM);
      } catch (PropertyException Signal) {
        complainln("unable to register global shell functions");
        exit(-1);
      };

    /**** now create various JavaScript objects ****/

      Scriptable Container = null;
      try {
        Container = ScriptContext.newObject(Global);
          Container.put("Background",  Container, "lightgrey");
        Global.put("Container", Global, Container);
      } catch (Exception Signal) {
        complainln("error while creating a \"Container\"");
        complainln("(reason: \"" + Signal.getMessage() + "\")");
        exit(-1);
      };

      Scriptable ControlProto = null;
      try {
        ControlProto = ScriptContext.newObject(Global);
          ControlProto.put("Foreground",  ControlProto, "black");
          ControlProto.put("Text",        ControlProto, "");
        Global.put("ControlProto", Global, ControlProto);
      } catch (Exception Signal) {
        complainln("error while creating a \"ControlProto\"");
        complainln("(reason: \"" + Signal.getMessage() + "\")");
        exit(-1);
      };

      Scriptable Control = null;
      try {
        Control = ScriptContext.newObject(Global);
          Control.setPrototype(ControlProto);
          Control.setParentScope(Container);

          Control.put("Text", Control, "(anything)");
        Global.put("Control", Global, Control);
      } catch (Exception Signal) {
        complainln("error while creating a \"Control\"");
        complainln("(reason: \"" + Signal.getMessage() + "\")");
        exit(-1);
      };

    /**** and test their appearance under JavaScript ****/

      evaluateFile(ScriptContext,"Rhino_11a.js");
    ScriptContext.exit();

  /**** that's it! ****/

    exit(0);
  };

/*******************************************************************************
*                                                                              *
* print, println                       print the given arguments onto "stdout" *
*                                                                              *
*******************************************************************************/

  public static void print (
    Context actualContext, Scriptable actualObject, Object[] ArgList, Function FunctionContext
  ) {
    for (int i = 0; i < ArgList.length; i++) { // don't worry about "undefined" arguments
      java.lang.System.out.print(Context.toString(ArgList[i]));
    };
  };


  public static void println (
    Context actualContext, Scriptable actualObject, Object[] ArgList, Function FunctionContext
  ) {
    print(actualContext,actualObject,ArgList,FunctionContext);
    java.lang.System.out.println();
  };

/*******************************************************************************
*                                                                              *
*                           Non-Public Class Methods                           *
*                                                                              *
*******************************************************************************/

/*******************************************************************************
*                                                                              *
* complain, complainln                   print the given message onto "stderr" *
*                                                                              *
*******************************************************************************/

  static void complain (String Message) {
    java.lang.System.out.print(Message);
  };

  static void complainln () {
    java.lang.System.out.println();
  };

  static void complainln (String Message) {
    java.lang.System.out.println(Message);
  };

/*******************************************************************************
*                                                                              *
* exit                           leaves the program with the given return code *
*                                                                              *
*******************************************************************************/

  static void exit (int ReturnCode) {
    java.lang.System.exit(ReturnCode);
  };

/*******************************************************************************
*                                                                              *
* print, println                         print the given message onto "stdout" *
*                                                                              *
*******************************************************************************/

  static void print (String Message) {
    java.lang.System.out.print(Message);
  };

  static void println () {
    java.lang.System.out.println();
  };

  static void println (String Message) {
    java.lang.System.out.println(Message);
  };

/*******************************************************************************
*                                                                              *
*                           Public Instance Methods                            *
*                                                                              *
*******************************************************************************/

/*******************************************************************************
*                                                                              *
* getClassName                yields the (Rhino-internal) name of this "class" *
*                                                                              *
*******************************************************************************/

  public String getClassName () {
   return "global";
  };
};

