Andreas Rozek      

A Runtime Environment for LuaJava Scripts

This page describes the author's own runtime environment for Lua [1] scripts. It is based on LuaJava's [2] built-in "Console" class, but contains additional environment methods.

The author's "Acquainting" series for LuaJava assumes that you are using his environment to run the scripts. If you don't plan to do so, you should consider to prepend these scripts with an alternative header which defines any otherwise missing function.

Please, also consider my "Hints for Reading" and the "List of Recent Changes"!
(Problems displaying this page? Ugly graphics? Please, click here)

LuaJava - a simple Runtime Environment

Initially, the idea behind the author's LuaJava class was just to understand how to run Lua scripts from within Java. Soon, however, it became necessary to customize the environment for Lua and to include additional or replace existing functions without having to start any Lua script with a (rather specific and probably continously changing) header. Today, this class defines an environment which is considerably different from the original Lua/LuaJava set-up and contains numerous additional objects and functions.

Please note, that the author's LuaJava class is not (yet) an interactive shell (you will have to stick to the original "Console" class if you need shell functionality). Instead, it only runs the given Lua script passing any additional command line arguments to that script.

Compilation

The source code of the LuaJava class is publically available and may be compiled using
 

  javac LuaJava.java

Please note, that the class imports the luajava package which must therefore be available somewhere whithin the compiler's search path for additional classes and libraries.

Installation

The resulting class file(s) should be stored in a directory where the Java runtime environment (JRE) will be able to find it - you may, for example, exploit the Java extension mechanism for that purpose (which will prevent you from having to modify the classpath when invoking Java).

Please, don't forget that the LuaJava class belongs to the author's luna package and should therefore be placed within a subdirectory of that name! (Under Windows, the directory "c:\Program Files\Java\jre\classes\luna\" could be an example for a place where to store the class files)

The associated initialization "profile" script (called LuaJava.lua) should be copied to the same directory as LuaJava.class. Java will then be able to locate that script as a "resource" using its built-in "class loader".

Invocation

Invoking LuaJava follows the pattern given below:
 

  java luna.LuaJava script-file [arguments]

where

java

stands for the command to invoke the Java runtime environment (JRE) - including any possibly required options (such as a specific classpath setting), if necessary;

script-file

represents the access path of the Lua script file which is to be executed;

arguments

stands for an (optional) list of command line arguments which will be passed to the given Lua script;

You may try to run, e.g., LuaJava_00.lua (the first script of the "Acquainting" series) to see if the environment works properly.

Internal Functions

The LuaJava environment itself defines the following additional functions:

complain ([...])

converts the given objects into strings and writes them (without interjacent blanks) onto stderr;

complainln ([...])

converts the given objects into strings, writes them (without interjacent blanks) onto stderr and finishes that series with a line-feed ("\n");

cry ([...])

acts as a synonym for complain (all synonyms in this list are defined for historical reasons only and stem from a time when the author was a REXX programmer);

cryln ([...])

acts as a synonym for complainln;

exit ([code])

terminates both the actual Lua script and the underlying Java environment returning the (optionally) given exit code to the operating system (default for code is 0);

print ([...])

converts the given objects into strings and writes them (without interjacent blanks) onto stdout;

println ([...])

converts the given objects into strings, writes them (without interjacent blanks) onto stdout and finishes that series with a line-feed ("\n");

require (PackageName)

replaces the built-in Lua function of the same name which loops endlessly if one tries to load the same script recursively (which may very well happen if several script files with complex inter-dependencies have to be loaded);

say ([...])

acts as a synonym for print;

sayln ([...])

acts as a synonym for println;

io.getFolderSeparator ()

returns the (Platform-specific) character which is used to separate folder names in file specifications;

string._trim (Argument)

returns a copy of the given string after removing any leading and trailing white space;

Further definitions will be loaded through the initialization profile (LuaJava.lua) and related script files.

Customization

As mentioned before, the LuaJava environment looks for an associated (optional) initialization script (called LuaJava.lua) which - if found - is loaded and executed after the initial definition of any environment objects and functions - but before executing the Lua script given on the command line.

For the time being, this "Profile" defines the three functions

  • io.getFolderSeparator ()
  • require (scriptfile)
  • string._trim (Argument)

(see above for a description of these functions) and then loads the author's Luna library.

If desired, the user may modify this script and, e.g., add his/her own definitions which are then loaded upon every invocation of LuaJava. The recommended approach, however, is to place any modifications in external script files and to "require" them from within the profile (as it is already done at the end of LuaJava.lua).

Alternative Header for "Acquainting" Scripts

If you don't plan to use the author's LuaJava class to run the scripts from the "Acquainting" series, you should, at least, prepend these scripts with the following code (which is also available for download):

--------------------------------------------------------------------------------
-- complain[ln]                          writes the given objects onto stderr --
--------------------------------------------------------------------------------

  function complain (...)
    for i = 1,arg.n do
      io.stderr:write(tostring(arg[i]));
    end;
  end;

  function complainln (...)
    for i = 1,arg.n do
      io.stderr:write(tostring(arg[i]));
    end;
    io.stderr:write("\n");
  end;

--------------------------------------------------------------------------------
-- cry[ln]                 synonyms for complain[ln] (for historical reasons) --
--------------------------------------------------------------------------------

  cry   = complain;
  cryln = complainln;

--------------------------------------------------------------------------------
-- exit                         leaves the script and it's (Java) environment --
--------------------------------------------------------------------------------

  local SystemClass = luajava.bindClass("java.lang.System");

  function exit (ExitCode)
    if (ExitCode == nil) then SystemClass:exit(0); end;

    local realExitCode = tonumber(ExitCode);
    if (realExitCode == nil) then
      error("non-numeric \"ExitCode\" given: \""..ExitCode.."\""); -- not fool-proof!
    else
      SystemClass:exit(realExitCode);
    end;
  end;

--------------------------------------------------------------------------------
-- print[ln]                             writes the given objects onto stdout --
--------------------------------------------------------------------------------

  function print (...)
    for i = 1,arg.n do
      io.stdout:write(tostring(arg[i]));
    end;
  end;

  function println (...)
    for i = 1,arg.n do
      io.stdout:write(tostring(arg[i]));
    end;
    io.stdout:write("\n");
  end;

--------------------------------------------------------------------------------
-- require             an updated version of the intrinsic "require" function --
--------------------------------------------------------------------------------

  local _require = require;                    -- preserve the original function

  function require (PackageName)                      -- and define a better one
    if (PackageName == nil) then
      error("missingArgument: no \"PackageName\" given");
    end;

    if (type(PackageName) ~= "string") then
      error("illegalArgument: given \"PackageName\" is not of type \"string\"");
    end;

    PackageName = string._trim(PackageName); -- normalize the package name a bit
    if (PackageName == "") then
      error("emptyArgument: given \"PackageName\" is empty");
    end;

    if (io.FolderSeparator ~= "/") then
      PackageName = string.gsub(PackageName, "/", io.FolderSeparator);
    end;

--**** check if that package is currently being loaded ****

    if (_LOADING ~= nil) and (type(_LOADING) == "table") and _LOADING[PackageName]
    then
      return true;           -- avoid recursive loading of the requested package
    else
      if (_LOADING == nil) or (type(_LOADING) ~= "table") then
        _LOADING = {[PackageName] = true};       -- mark package as being loaded
      else
        _LOADING[PackageName] = true;
      end;

      _require(PackageName);

      if (_LOADING ~= nil) and (type(_LOADING) == "table") then
        _LOADING[PackageName] = nil;                           -- unmark package
      end;
    end;
  end;

--------------------------------------------------------------------------------
-- say[ln]                    synonyms for print[ln] (for historical reasons) --
--------------------------------------------------------------------------------

  say   = print;
  sayln = println;

--------------------------------------------------------------------------------
-- io.getFolderSeparator determines the platform-specific separator character --
--------------------------------------------------------------------------------

  local FileClass = luajava.bindClass("java.io.File");

  function io.getFolderSeparator ()
    return FileClass.separator;
  end;

  io.FolderSeparator = io.getFolderSeparator();    -- shortcut for direct access

--------------------------------------------------------------------------------
-- string._trim   yields a copy of "Argument" without leading/trailing blanks --
--------------------------------------------------------------------------------

  function string._trim (Argument)
    return string.gsub(string.gsub(Argument, "^%s+", ""), "%s+$", "");
  end;

See above for a description of the functions found in this code.

Source Code

The source code of any Java class or Lua script described above is publically available:

References

[1]

The Programming Language Lua
(see http://www.lua.org)
The given address is the primary starting point for any kind of (not just literature) search related to Lua: from here you are directed to Lua distributions, documentation, additional libraries or tools - and you may get in contact with other Lua users;

[2]

Thiago Ponte
LuaJava - A Script Tool for Java
(see http://www.keplerproject.org/luajava/)
LuaJava provides a "bridge" between Lua and Java: it allows Java classes, objects and methods to be accessed from within Lua , Java interfaces to be implemented by Lua objects (and their functions) or Lua to be extended unsing Java. Visit the given address for the actual LuaJava distribution, some documentation and two examples;

[3] Java Technology
(see http://java.sun.com/)
Visit the given address to learn more about Java or to download the actual distribution for your platform;

Disclaimer

Please, also consider the author's Disclaimer!


http://www.Andreas-Rozek.de/LuaJava/Acquainting/LuaJava_en.html   (last Modification: 14.11.2004)