Judoscript

Judoscript is a general purpose programming language designed primarily for scripting tasks on the Java platform. It was conceived and developed by James Jianbo Huang (simplified Chinese: 黄剑波; traditional Chinese: 黃劍波; pinyin: Huáng Jiànbō), starting in late 2001. Judoscript was one of the first so-called Java scripting languages; but its most striking characteristics is its audacious multi-domain support philosophy and practice.

Judoscript
Paradigmprocedural, object-oriented, scripting
Designed byJames Jianbo Huang
DeveloperJames Jianbo Huang
First appearedNovember 2001
Stable release
v0.9 / Nov. 2005
Typing disciplinedynamic, static, strong
PlatformJVM
LicenseLGPL
Websitejudoscript.com
Influenced by
SQR, Perl, JavaScript, Java

By the end of 2005, Judoscript has completed all the designated application features. The situation with Java scripting languages swiftly changed when JavaSoft announced to create its own in 2003. Judoscript's development was stopped when JavaSoft's own Groovy language was close to be released.

History

Huang has worked on a commercial report writer, SQR, which is used extensively in PeopleSoft. Technically, SQR is an archane, general purpose scripting language with embedded SQL and reporting directives for producing character-based reports and data manipulation. Written in C, it is ported to almost all flavors of major operating systems, and works with all major RDBMS databases. With the advent of Java and JDBC, Huang quickly realized that a single version of such software would eliminate the whole array of different ports of SQR. This was the seed of the Judoscript idea.

Even back in the late 1990s, embedded SQL was not a new idea; for instance, Oracle's Pro*C did just that. Remarkably, embedded SQL is indeed a domain-specific (RDBMS) feature built into a general purpose language. Regular expression in Perl is another good example, in the domain of text handling. The vision of Judoscript started to take shape, to be a general purpose scripting language with declarative expressiveness for many popular programming domains in a coherent way. At the turn of the millennium, the Internet started to permeate our lives, and a growing number of key technologies were becoming widely adopted, therefore, choosing specific domains to support in Judoscript was not too hard a thing. In a way, this vision came about at the right time. The domain-specific features that were embodied in Judoscript's lifetime included JDBC scripting, SAX-style SGML and XML programming, WSDL scripting, Ant scripting, unified file system and archive scripting, Microsoft COM scripting, running native OS executables, send mail, HTTP and SCP scripting, and last but not least, Java scripting. Had Judoscript continued to grow, it would foreseeably contain more and more domain-specific support as new technologies become prevalent, such as NoSQL, AI, etc.

Being a JVM-based scripting language, Judoscript has Java scripting as a first-class citizen. Judoscript has pioneered native Ant support, allowing users to tap into the vast pool of utilities in the Ant ecosystem. With native scripting capabilities with Java, Ant, WSDL, HTTP, and Microsoft's COM, Judoscript users can readily utilize resources from heterogeneous sources. The base language of Judoscript is very much JavaScript plus static class declaration. Like any scripting languages, Judoscript has various syntactic sugars, multi-line string literals, XML and regular expression literals, a versatile print statement, etc. However, while these aspects dominate the design of most other languages, general programmability is less significant a talking point compared to the language's key, unique characteristics.

The initial outlook of Judoscript crystallized and development commenced in late 2001; the first version was released in November. Judoscript became one of the first general purpose scripting languages designed specifically for use with the Java platform, along with Rhino, BeanShell, Jython, and a few others.

In 2004, Judoscript approached version 0.9. Development continued through 2005, where most of the final features were implemented. A key feature missing is the generation of Java bytecode either offline or at runtime, which was considered essential for such a language to reach version 1.0. For this matter, Huang has invented a Java macro assembly language, Jamaica. But this work for Judoscript was never achieved.

In JavaOne 2003, in June, JavaSoft announced its intention to create a wholly-owned scripting language for the Java platform. This monopolous move has stifled the lives of most of its competitors. The result was the Groovy language, whose name is apparently a phonetic morphing from "jruby", with its first version released in 2007. Its built-in Ant support is suspiciously connected to Judoscript's Ant scripting feature, chronologically speaking. When Groovy was about to be unleashed, Judoscript has lost impetus of moving forward. By the end of 2005, after a mere four years, Judoscript's development was stopped.

Even so, Judoscript has remained dear to language designers and aficionados, and occupies a place in the programming language history, being the first and possibly the only general purpose language with so many native domain-specific features built-in. The reason for this will be delved further later.

Language design

The design of the Judoscript language blends two distinct flavors. First and foremost, it is a general purpose scripting language like any modern programming languages, using dynamic typing and dot notation for accessing object members. Supporting both procedural and object-oriented paradigms, it sports static class declaration and inheritance. Various syntactic sugars and a versatile print statement typify its scripting language nature.

Judoscript is fully capable of scripting Java resources. Its static typing feature was introduced primarily for invoking overloaded Java methods.

The second flavor, which distances Judoscript from the rest of the crowd, is its embodiment of a number of native domain-specific statements, each carrying a very different look. Some return a value, others not. Most of these special statements can be used as regular statements anywhere in the program.[1]

Expressions can be embedded in the domain-specific statements wherever appropriate. Expressions can also be embedded in textual literals like strings and XML values, effectively making them textual templates.

Language features I: a potent scripting language

The Base language

The Judoscript base language is almost identical to JavaScript for variable and constant declarations, flow control statements, and dot notation for accessing object members. In addition to the two C++-style comments, it has a third form, /? ?/, useful to disable a chunk of code. Function parameters can have default values, and invocation can take named parameter values. Like in JavaScript, functions are also objects and can be passed as values. Dynamic programming is available via the eval and evalExternal commands. [2][3][4]

Object oriented programming

Unlike JavaScript, user-defined classes are declared statically, but the data members are dynamic. Multiple inheritance is supported, and programmers should handle potential diamond inheritance issues. Class instances can be transposed to another type.[5]

class Node
{
  constructor {
    assert(name != null);  // mandates that 'name' must be initialized
    children = [];
  }
  function addChild child { children.add(child); }
  function toString { return name; }
}

Code organization

Judoscript has a !include directive to include other scriptlets. This is the only mechanism to share code written in Judoscript.

The lack of support for Java-like package or module in other languages is intentional, in order to discourage creating libraries written in Judoscript. Reusable libraries are encouraged to be written in Java, and let Judoscript (or any Java scripting languages) to use.

Language features II: Java scripting

Java scripting is a first-class citizen in Judoscript. Listed here are some of the most important Java scripting features. Refer to the documentation to see all the uses and examples.[6]

Scripting Java Objects

a = new java::java.util.HashMap;
a.put('date',      Date(2001,1,1));
a.put('integer',   1);
a.put('double',    10.01);
a.put('string',    'Hello, World!');
a.put('Dimension', new java::java.awt.Dimension(10,20));
for k in a.keys() {
  println k:>10, ' = ', a.get(k);
}

props = new java::Properties(
          a.b.c.d.e.f.g = 'a thru g',
          h.i.j.k.l.m.n = 'h thru n'
        );
println props;

Aliasing Java static methods

The capability to alias Java static methods as Judoscript functions is an important mechanism, responsible for many built-in functions.

function prop for java::System.getProperty();
function now  for java::System.currentTimeMillis();
function rt   for java::Runtime.getRuntime();

println now(), nl;
println prop('java.class.path'), nl;
rt().gc();

Using Java classes as values

Java classes are also object values, and can be assigned to variables or constants.

const #Types = java::java.sql.Types;
fields = [ 'BIT', 'TINYINT', 'SMALLINT', 'INTEGER', 'BIGINT', 'FLOAT', 'REAL',
  'DOUBLE', 'NUMERIC', 'DECIMAL', 'CHAR', 'VARCHAR', 'LONGVARCHAR', 'DATE',
  'TIME', 'TIMESTAMP', 'BINARY', 'VARBINARY', 'LONGVARBINARY', 'NULL', 'OTHER',
  'JAVA_OBJECT', 'DISTINCT', 'STRUCT', 'ARRAY', 'BLOB', 'CLOB', 'REF'
];

println 'JDBC types in Java ', sysProperty('java.version'), ':';
for fld in fields {
  println fld:<13, ': ', #Types.(fld);
}

Extending Java classes and implementing Java interfaces

It is possible to define Judoscript classes that extend Java classes or implement Java interfaces.

class MyHashMap extends java::HashMap
{
  // Test overriding an existing method
  int hashCode() { return super.hashCode() ^ 1; }

  // A new method.
  String[] getKeys() {
    arr = [];
    for x in this { arr.add(x); }
    return arr.toStringArray();
  }

  // A new method.
  Object[] getValues() {
    arr = [];
    for x in values() { arr.add(x); }
    return arr.toObjectArray();
  }
}

Anonymous Java interface adapters can be created and used.

import java.awt.Frame;
import java.awt.event.*;

f = new java::Frame;
f.addWindowListener(
  new java::WindowListener {
    void windowClosing(WindowEvent e) { exit 0; }
  }
);
f.setVisible(true);

Language features III: special domain supports

This part of the language is what makes Judoscript unique. Each major domain support will be touched on briefly, usually with examples.

JDBC scripting

JDBC scripting is a central feature of Judoscript, as well as a key motivation for the language itself. It makes database operations intuitive and convenient.[7]

Below is an example that connects to database and runs some SQL statements.

db::connect to 'jdbc:oracle:thin:@dbsvr:1521:dbname', 'user', 'pass';
if tableExists('EMP') {
  db::sql: DROP TABLE emp;
}
db::sql {
  CREATE TABLE emp(emp_no     INTEGER PRIMARY KEY,
                   first_name VARCHAR(100),   // First Name
                   last_name  VARCHAR(100),   // Last Name
                   birth_date DATE,           -- Birth Date
                   salary     NUMBER);        -- Salary

  CREATE INDEX emp_fname ON emp(first_name);
  CREATE INDEX emp_lname ON emp(last_name);

  INSERT INTO emp(emp_no,first_name,last_name,birth_date,salary)
  VALUES( 100, 'Jim', 'Malone', to_date('1-3-1954','dd-mm-yyyy'), 86500.0);
}
println 'db::sql result: ', $_;
disconnect();

Using stored procedures is through the db:any statement.

db::any [[*
  CREATE PROCEDURE test_proc(
    param_io IN OUT NUMBER,
    param_i  IN     VARCHAR,
    param_o  OUT    VARCHAR)
  AS BEGIN
    param_o := param_i;
    IF param_io IS NOT NULL THEN
      param_io := param_io + 1;
    ELSE
      param_io := -1000;
    END IF;
  END;
*]];

The more interesting usage is the parameterized queries and updates. Queries and updates can be run directly or preparedly.

db::prepare ins:
  INSERT INTO emp( emp_no, first_name, last_name, birth_date, salary  )
           VALUES( :empNo, :firstName, :lastName, :birthDate, :salary )
;

for row in rows {
  db::sql ins with @empNo:Integer  = id++,
                   @firstName      = row[0],
                   @lastName       = row[1],
                   @birthDate:Date = row[2],
                   @salary:Number  = row[3];
}

Below is a query example.

db::query qry:
  SELECT emp_no, first_name, last_name, birth_date, salary
  FROM emp
;

println 'ID   First-Name  Last-Name    Salary    Birth-Date', nl,
        '---  ----------  -----------  --------  ----------';
while qry.next() {
  println qry[1].int()   :<5,
          qry.first_name :<12,
          qry.last_name  :<12,
          qry.salary     :*7.1, '  ',
          qry.birth_date.fmtDate('yyyy-MM-dd');
}

SGML and XML document processing

SGML is the generic hypertext format that includes HTML and XML. There are two APIs for processing XML documents: Simple API for XML (or SAX), and Document Object Model (or DOM). SAX processing scans the whole text as a stream, and fires events for each encountered tag or text segment. Judoscript has a cute little statement that makes use of this feature effectively for XML and SGML data.[8][9]

The next example shows the essence of HTML scraping. With this, writing a web site crawler is not far from reality!

do 'http://www.judoscript.org' as sgml {
    <a>:  if $_.href != null { println 'Found a hyperlink:', $_.href; }
    <p>:  println 'Found a paragraph tag.';
    TEXT: println 'Found some text:', $_.length();
}

The following example processes the XML data that is appended at the end of the script.

do $local as xml
{
<book>:       println ($_.hardcover=='true')?"Hard":"Soft", '-cover Book ------------';
<date>TEXT:   println '  Date: ', $_, ' (', $_.type, ')';
<title>TEXT:  println ' Title: ', $_;
<author>TEXT: println 'Author: ', $_;
<isbn>TEXT:   println '  ISBN: ', $_;
}
EndScript -------------------------------------------------------
<booklist>
 <book>
  <title> UNIX in a Nutshell </title>
  <author> Daniel Gilly </author>
  <publisher> O&apos;Reilly &amp; Associates, Inc. </publisher>
  <isbn> 1-56592-001-5 </isbn>
  <date type="first edition"> 1986-12 </date>
  <date type="second edition"> 1992-06 </date>
 </book>
 <book hardcover="true">
  <title> Advanced Programming in the UNIX Environment </title>
  <author> Richard Stevens </author>
  <publisher> Addison-Wesley </publisher>
  <isbn> 0-201-56317-7 </isbn>
  <date type="copyright"> 1993 </date>
  <date type="twelfth printing"> 1996-12 </date>
 </book>
</booklist>

Judoscript also supports DOM and XSLT processing of XML documents.

Apache Ant scripting

Apache Ant has been the build system for Java for a long time; companies and developers have been creating many extensions called Tasks, in Ant parlance, and the Ant ecosystem becomes a treasure trove of all kinds of utilities, either general purpose or proprietary. Judoscript has included a mechanism to directly invoke any Ant tasks. Below is an example.[10]

a = 'ants';
anttask::<echo message="Hello, ${a}!"/>
anttask::<echo>Hello, more ${a}!</echo>

There are ways to run native executables in Judoscript, but you can also resort to Ant scripting, as shown below.

src = '.';
anttask::<exec dir="${src}" executable="cmd.exe" os="Windows 2000" output="dir.txt">
  <arg line="/c dir"/>
</exec>

Unified file system and archive scripting

File manipulation is one of the most common tasks for information workers. Judoscript strives to provide a consistent experience dealing with files in both file systems and archives such as ZIP files and TAR balls.[11]

The following examples inspects files in a ZIP archive.

listFiles '*' in 'awebapp.zip' dirOnly;
for x in $_ {
  // get status for each directory
  listFiles '*.java, *.jj' in x recursive size compressedSize;
  println $_[0]:>8, '  ', $_[1]:>8, '  ', x;
}

The next example copies files into a ZIP archive. By slightly changing the expressions, you can copy files to another location in the file system.

copy '*.java, *.properties' in 'C:/temp/classes/' recursive
     into 'judo.jar' store manifest
[[*
  Manifest-Version: 1.0
  Main-Class: judo
  Created-By: James Jianbo Huang (c) 2001-(* #year *)
*]]
;

Another example for ZIP with finer control.

zf = createZip('~/archives/work-'+Date().fmtDate('yyyyMMdd')+'.zip');

copy '*' in 'c:/judo/src/' except '*/alfa*, */beta*, */save/*'
  recursive noHidden echo
  into zf under 'src/';

copy '*' in 'c:/judo/docs/' except '*/alfa*, */beta*, */save/*'
  recursive noHidden echo
  into zf under 'docs/';

copy '*' in 'c:/judo/examples/' except '*/alfa*, */beta*, */save/*'
  recursive noHidden echo
  into zf under 'examples/';

zf.close();

And you can copy internet resources to file systems or archives, shown below.

tar = createTar('yahoo_comp.tar.gz');
zip = createZip('yahoo_comp.zip');
urls = [
  'http://dir.yahoo.com/Computers_and_Internet/index.html',
  'http://dir.yahoo.com/Computers_and_Internet/Internet/index.html',
  'http://dir.yahoo.com/Computers_and_Internet/Internet/WAIS/index.html'
];
for u in urls {
  copy u into tar keepDirs;
  copy u into zip keepDirs;
}
tar.close();
zip.close();

SOAP web service scripting

In the times of Judoscript, the SOAP web service was the industry standard for remote invocations before the RESTful API emerged. Judoscript makes it easy to consume SOAP web services.[12]

svc = wsdl::'http://coldrooster.com/dhtmldude/mathservice.asmx?WSDL';
println '3 + 2 = ', svc.Add(3, 2);
println '3 - 2 = ', svc.Subtract(3, 2);
println '3 * 2 = ', svc.Multiply(3, 2);
println '3 / 2 = ', svc.Divide(3, 2);

Other application features

Judoscript has all kinds of programming goodies to cover most of the everyday tasks for information workers, such as executing OS native executables, sending E-mails, running scheduled jobs, accessing internet resources via HTTP, SSH, SCP, launching your own HTTP server, etc.[13]

The Microsoft COM scripting capability opens door to the Microsoft Office documents, using their DOM to access and manipulate data therein, and integrate with other data stores and sources.[14]

Implementation

The Judoscript language grammar and its parser are done with the JavaCC tool. Many a complicated domain-specific statement constitutes a sub-language of its own that warrants an embedded sub-parser. Other such statements and some syntactic sugars require native methods in the JavaCC grammar file. Because of these complexities, the parser directly produces the internal representation of the program, readily executable by the language engine.

There are many supporting libraries included in the language runtime; some are from third parties, others are developed internally.

See also

References

This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.