JudoScript: Scripting for Java and Beyond

The creator of JudoScript explains the need for and the benefits of a good scripting tool for Java.
Introduction to the JudoScript Language

JudoScript's many features can be grouped into three areas: general programming, Java scripting and application scripting.

1. General Programming Features

JudoScript supports typeless variables with typed values. Each value is an object of some class. The primitive data types include integral and floating-point numbers, string and date/time. A value also can be an instance of any user-defined class, Java object or array, function reference, or any of its built-in object types and data structures.

array

one- or multi-dimensional linear container

linkedList

same as array, but implemented as a linked list

struct

a map; is the root of all user-defined classes

orderedMap

same as struct, except the order of added keys is retained

stack

a first-in-last-out container

queue

a first-in-first-out container

tableData

a two-dimensional array with column captions and methods for retrieving rows or columns

treeNode

a convenience for building trees

Classes and functions can be declared anywhere, in any order. Classes can extend others; the root of user-defined class is either struct or orderedMap. Classes are nothing but a struct associated with a number of methods. It is possible to transpose an object from one class to another after it is instantiated.

Expressions in JudoScript are similar to those in Java or C; so are flow control statements. The parentheses for the expression in if-else, switch, while and for statements are optional. There also is an extended loop statement for enumerating array elements.

  arr = { 0, 1, 2, 3, 4 };
  for x in arr {
    switch x {
    case 0:  println 'zero'; break;
    case 1:  println 'uno';  break;
    default: println x;      break;
    }
  }
 

Functions can be referenced and stored in variables. This can be used for, say, special sorting of arrays:

  a = { '1.2', '3', '1.10', '1.2.1', '2.3' };
  a.sort( &my_comparator );
  println a;
  function my_comparator(lhs, rhs) {
   la = lhs.csv('.');
   ra = rhs.csv('.');
   for i from 0 to la.size() {
    if la[i].int() < ra[i].int() { return -1; }
    if la[i].int() > ra[i].int() { return 1; }
   }
   if la.size() == ra.size() { return 0; }
   return la.size() > ra.size();
  }
 

In this example, we want 1.10 to appear after 1.2. Had we used array's default sort() method, it would be an alphabetical sort and 1.10 would go first.

Exceptions can be thrown by the JudoScript language engine or by the executed Java code. They can be captured and handled. JudoScript also offers a "resume" statement, which is not found in Java.

  { a = 1;
    println 'a + "abc" = ',  a + "abc"; // exception
    println 'abc' @ a = ',   "abc" @ a; // concat
  catch:
    println 'EXCEPTION: ', $_.message;
    resume;
  finally:
    println 'Done.';
  }
  //The result:
  // a + "abc" = EXCEPTION: Invalid number format: abc
  // 'abc' @ a = abc1
  // Done.
 

Thread programming in JudoScript is easy: a thread is declared in the same way that a function is declared. The following example shows a multithreaded HTTP server:

  println <err> 'Port: 8088';
  docRoot = '/var/share/';
  ss = startServer(8088);
  while { start thread hndlr(acceptHttp(ss)); }
  thread hndlr req { req.serveFile(docRoot); }
  //Singled-threaded HTTP server, use these:
  // while { hndlr(acceptHttp(ss)); }
  // function hndlr req { req.serveFile(docRoot); }
 

2. Java Scripting

Java code can be used directly in JudoScript. Some people are happily surprised when they learn they can run Java without having to compile the code.

  hash = javanew java.util.Hashtable;
  hash.put( 'date',    date(2001,1,1) );
  hash.put( 'integer', 1 );
  hash.put( 'double',  10.01 );
  hash.put( 'string', 'Hello, World!' );
  keys = hash.keys();
  while keys.hasMoreElements() {
    k = keys.nextElement();
    println k, ' = ', hash.get(k);
  }
 

Java arrays can be created and used the same way as native JudoScript arrays:

  ba = javanew byte[]{ 0, 1, 2 };
  for x in ba { println x; }
  oa = javanew java.lang.Object[3];
  oa[0] = javanew java.io.File('abc');
  oa[1] = java.lang.System::out;
  oa[2] = javanew java.util.Hashtable;
  for x in oa { println x; }
 

As you have seen, static members of a Java class are accessed by the :: operator. You even can alias a Java static method to become a JudoScript function; some of the JudoScript system functions are indeed Java static methods.

  function gc for java.lang.System::gc();
  function props for java.lang.System::getProperties();
  function getProp for java.lang.System::getProperty();
 

System functions, including initialContext() and weblogicInitialContext() are designed specifically for EJB and JNDI client scripting.

  const #OrderHome = 'com.myecom.OrderHome';
  ctx = weblogicInitialContext('t3://server','user','pass');
  home = ctx.lookup(#OrderHome);
  key = javanew com.myecom.OrderKey('00134');
  order = home.findByPrimaryKey(key);
  // ...
 

JudoScript does not require long list of imports or declaration of variables with long class names. Nor does it require casting everywhere and exceptions catching. Combined with JDBC scripting, for things like querying for order keys, your scripts can do a lot of powerful work.

In cases where you truly need Java, such as a special GUI component or extension of an abstract Java class, you can write embedded Java class in JudoScript. An adapter mechanism is available that allows JudoScript to implement Java interfaces, but a Java compiler must be available for these purposes. Conversely, JudoScript can be embedded in other Java software, through its language engine interface must supports the Bean-Script-Framework (BSF).

The capability to use Java directly is significant, because this makes all Java software--what's on the market today and what's available next year--developed tomorrow, available to JudoScript.

3. JudoScript Application Features

The following is an incomplete list of JudoScript application features:

  • JDBC scripting

  • XML SAX-style scripting, DOM programming and XSLT

  • HTML/SGML scraping

  • Sendmail

  • HTTP server and client handling, including cookies

  • Scheduling

  • Execution of command lines

  • SSH and SCP (via ISNetworks' MindTerm package)

  • File operations in filesystems and in ZIP, TAR or GZIP archives

  • Copying of files and directories between combinations of file systems and ZIP or TAR archives

  • Encryption and decryption (based on JCE)

  • Java GUI scripting

Some of these features are implemented as system functions and objects, like the one in the HTTP server example above. Some use straightforward syntax, such as sendmail, files and archives.

  sendmail
  to:      'tom@tom_jerry.org, jerry@tom_jerry.org'
  cc:      'mike@tom_jerry.org'
  from:    'james@tom_jerry.org'
  subject: 'Test test'
  attach:  'data.zip, readme.txt'
  body:    [[*
           Hi Tom and Jerry,
           Attached is the data and usage. Enjoy!
           -James
           *]]
  htmlBody: [[*
           <html><body>
           <p>Hi Tom and Jerry,</p>
           <p>Attached is the data and usage.
              <b>Enjoy!</b></p>
           <p>-James</p>
           </body></html>
           *]]
  ;
 
  // copy original Java files into src.jar
  copy '*.java, *.judo' except '*/parser/*.java'
       in srcDir recursive noHidden echo
       into 'src.jar';
  // archive original Java files and docs
  jarFile = createJar('save.jar');
  copy '*.java, *.judo' except '*/parser/*.java'
       in srcDir recursive noHidden echo
       into jarFile under 'src/';
  copy '*' in docDor recursive noHidden echo
       into jarFile under 'doc/';
  jarFile.close();
 

XML SAX scripting, HTML scraping and Java GUI scripting use an event-driven model, and GUI programs generate events. For XML and HTML documents, the parser creates an "event" for each tag, which includes text, and JudoScript specifies handlers for these events.

  // print out links and text lengths in HTML
  do 'http://www.yahoo.com' as sgml {
  <a>:    println 'URL:  ", $_.href;
  <img>:  println 'URL:  ", $_.src;
  <link>: println 'URL:  ", $_.src;
  TEXT:   println 'Text: length=', $_.length();
  }
 

This HTML/SGML scripting feature has been used extensively to produce JudoScript's own documentation.

  // A Swing GUI that does nothing.
  frame = javanew javax.swing.JFrame("Hi!");
  frame.setVisible(true);
  guiEvents {
  <frame : Window : windowClosing> :  exit(0);
  }
 

The built-in variable $_ representes the current event. In the case of HTML or XML, it represents the tag itself. In GUI programs, it is the event object in respective listener methods.

A few other areas involve more complicated, special-purpose statements. This includes scheduling, command-line execution and JDBC scripting.

JDBC scripting is one of the major inspirations for this language. SQL statements can be executed easily in JudoScript, either individually, in a group or in a batch. Statements can be prepared, then executed with bound variables. Stored procedures can be executed in the same ways. The following example demonstrates creating tables, as well as inserting and querying with both prepared and direct executions. Note the JDBC driver is loaded automatically based on the URL, because JudoScript has knowledge about many JDBC drivers.

  { // try block.
  connect 'jdbc:mysql://localhost/mydb', 'user', 'pass';
  // (re-)create tables
  tables = { 'participants', 'media', 'people' };
  for x in tables { // drop tables if exist already
    if tableExists(x) {
      executeSQL: drop table (* x *);
    }
  }
  executeSQL {
    create table people
    ( personID  int primary key,
      name      varchar(20) not null,
      alias     varchar(20),
      sex       varchar(1),  // 'M', 'F'
      addTime   date
    );
    create table media
    ( folderID  varchar(255) not null,
      fileName  varchar(128) not null,
      type      varchar(1) not null,
      fileTime  date,
      bytes     int,
      addTime   date,
      constraint pathName primary key (folderID,fileName)
    );
    create table participants
    ( folderID  varchar(255),
      fileName  varchar(128),
      personID  int,
      constraint ref_media  foreign key (folderID,fileName)
                 references media (folderID,fileName),
      constraint ref_people foreign key (personID)
                 references people (personID)
    );
  } // end of executeSQL.
  // insert
  prepare mediatbl:
    insert into media
      (folderID,fileName,type,fileTime,bytes,addTime)
    values (?,?,?,?,?,now())
  ;
  executeUpdate mediatbl
    with @1 = '/2001-06', // default type is "string".
         @2 = 'DSC00001.jpg',
         @3 = 'I',
         @4:date = date(2001,6,3),
         @5:int = 45044
  ;
  println unit(mediatbl.updateCount,'row'),
          " inserted into 'media' table.";
  preparedExecuteUpdate partbl: // one-step prepare & execute.
    insert into participants (folderID,fileName,personID)
    values (?,?,?)
  ; with @1 = '/2001-06',
         @2 = 'DSC00001.jpg',
         @3:int = 1  // for alias 'bear'
  ;
  println unit(partbl.updateCount,'row'),
          " inserted into 'participants' table.";
  // query
  executeQuery q: select * from people order by alias ;
  while q.next() {
    println 'personID: ', q[1];
    println '    name: ', q[2];
    println '   alias: ', q[3];
    println '     sex: ', q.SEX;
    println ' addTime: ', q.addTime, nl, '--------';
  }
  catch:   $_.printStackTrace();
  finally: disconnect();
  } // end of try block.
 
______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Re: JudoScript: Scripting for Java and Beyond

Anonymous's picture

Congratulations for this great language!

Re: JudoScript: Scripting for Java and Beyond

Anonymous's picture

First of all, when the JudoScript language was announced on comp.lang.python.announce in late March this year, I thought it was an April Fools' Joke, especially with that "4GL" stuff (like the sendmail example).

Secondly, I don't think that the author justifies his statement that languages such as Jython "...are not good enough to use Java's rich functionality." Having actually used Jython for real-world stuff, I know I'd prefer to use a well-known, well-understood and widely-supported language such as Python whether or not it fits JudoScript's author's ideological criteria.

Re: JudoScript: Scripting for Java and Beyond

Anonymous's picture

I agree.

The effort to learn yet another new syntax for essentially doing the same job far outweights its benefits.

The JDBC stuff looks good though...

Re: JudoScript: Scripting for Java and Beyond

Anonymous's picture

<blockquote>Java is a so-called system language, with low-level, fine-granularity APIs and language constructs that enforce good software engineering. But these elements become obstacles in our situations. On a related note, coding in Java requires expertise that is at times not available or desirable.</blockquote>

As someone who has embedded JavaScript support into several Java applications, I must say that your goals while commendable would seem to tail your own notation of the failing of Java. Im not sure a language with so many solution based constructs that must be learned is going to dent that relevant expertise or ease of approachability problem. Like it or not, JavaScript is everywhere, and even the average Graphic Designer understands some fundamentails. Giving users a simple, fascade object written in Java passed through to the JavaScript interpreter seems to me to be much more effective than a whole new language to teach every designer, sysadmin and integrator in the world.

Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix