| Jacl |

    1   /*
    2    *  Jacl.java
    3    *
    4    *  Copyright (c) 1998-2001, The University of Sheffield.
    5    *
    6    *  This file is part of GATE (see http://gate.ac.uk/), and is free
    7    *  software, licenced under the GNU Library General Public License,
    8    *  Version 2, June 1991 (in the distribution as file licence.html,
    9    *  and also available at http://gate.ac.uk/gate/licence.html).
    10   *
    11   *  Hamish Cunningham, 14/03/00
    12   *
    13   *  $Id: Jacl.java,v 1.8 2001/01/30 14:18:02 hamish Exp $
    14   */
    15
    16
    17  package gate.util;
    18
    19  import java.util.*;
    20  import tcl.lang.*;
    21
    22
    23  /**
    24    * This class provides access to the Jacl Tcl interpreter, and
    25    * caters for loading any Tcl scripts that live in the GATE source.
    26    * It also serves as examples of how Tcl can be used from Java using
    27    * the Jacl library (which is my excuse for those cases where there was
    28    * an obvious easier way!).
    29    * <P>
    30    * Note that all GATE Tcl scripts should be in the namespace "GATE".
    31    */
    32  public class Jacl
    33  {
    34    /** Debug flag */
    35    private static final boolean DEBUG = false;
    36
    37    /** The Tcl interpreter */
    38    private Interp interp;
    39
    40    /** Construction */
    41    public Jacl() { interp = new Interp(); }
    42
    43    /** Get the interpreter */
    44    public Interp getInterp() { return interp; }
    45
    46    /** Local fashion for newlines */
    47    private String nl = Strings.getNl();
    48
    49    /** Some Tcl code to get us into the gate/src directory (from gate
    50      * or a subdir).
    51      */
    52    String goToGateSrcScript =
    53      "set WD [pwd]                                                       "+nl+
    54      "if { ! [string match \"*gate*\" $WD] } {                          "+nl+
    55      "  error \"not in the gate directories\"                           "+nl+
    56      "}                                                                  "+nl+
    57      "while { [file tail $WD] != \"gate\" } { cd ..; set WD [pwd] }     "+nl+
    58      "cd src                                                             "+nl;
    59
    60    /** Some Tcl code to find all the .tcl files under a directory. */
    61    private String findTclScript =
    62      "set tclFiles [list]                                                "+nl+
    63      "                                                                   "+nl+
    64      "proc filter { dir } {                                              "+nl+
    65      "  global tclFiles                                                  "+nl+
    66      "                                                                   "+nl+
    67      "  foreach f [glob -nocomplain ${dir}/*] {                          "+nl+
    68      "    if [file isdirectory $f] { filter $f }                         "+nl+
    69      "    if [string match {*.tcl} $f] {                                 "+nl+
    70      "      lappend tclFiles [string range $f 2 end]                     "+nl+
    71      "    }                                                              "+nl+
    72      "  }                                                                "+nl+
    73      "}                                                                  "+nl+
    74      "                                                                   "+nl+
    75      "filter {.}         ;# do the search                                "+nl+
    76      "return $tclFiles   ;# return the result to the interpreter         "+nl;
    77
    78    /** Locate any files named .tcl in the directory hierarchy under .
    79      * and return a list of them.
    80      */
    81    public List findScripts()  throws TclException {
    82      return findScripts("");
    83    } // findScripts()
    84
    85    /** Locate any files named .tcl in the directory hierarchy under .
    86      * and return a list of them. The prelimScript parameter should be
    87      * a non-null string containing Tcl code that will be evaluated before
    88      * the finder script runs (so it can be used to change directory,
    89      * for e.g.).
    90      */
    91    public List findScripts(String prelimScript) throws TclException {
    92      List scriptPaths = new ArrayList();
    93
    94      String finderScript = prelimScript + findTclScript;
    95
    96      // "return" in a script evaluated from Java works by throwing an
    97      // exception with completion code of TCL.RETURN (so using "set" to
    98      // return a value is easier where possible)
    99      try {
    100       interp.eval(finderScript);
    101     } catch(TclException e) {
    102       if(e.getCompletionCode() != TCL.RETURN) // wasn't a "return" exception
    103         throw(e);
    104     }
    105
    106     TclObject resultObject = interp.getResult();
    107     TclObject pathsArray[] = TclList.getElements(interp, resultObject);
    108     for(int i = 0; i < pathsArray.length; i++)
    109       scriptPaths.add(pathsArray[i].toString());
    110
    111     return scriptPaths;
    112   } // findScripts
    113
    114   /** Copy scripts from the GATE source tree into the classes dir, so
    115     * that they will make it into gate.jar, and so that getResource
    116     * (used by Interp.evalResource) will find them.
    117     */
    118   void copyGateScripts(List scriptPaths) throws TclException {
    119     // tcl code to do the copy (move to GATE src dir first)
    120     String copyScript = goToGateSrcScript +
    121       "foreach f $scriptFilesToCopy {                                   "+nl+
    122       "  file copy -force $f ../classes/$f                              "+nl+
    123       "}                                                                "+nl;
    124
    125     // set a variable containing the list of paths to the scripts
    126     TclObject tclPathsList = TclList.newInstance();
    127     ListIterator iter = scriptPaths.listIterator();
    128     while(iter.hasNext()) {
    129       TclObject path = TclString.newInstance((String) iter.next());
    130       TclList.append(interp, tclPathsList, path);
    131     }
    132     interp.setVar("scriptFilesToCopy", tclPathsList, TCL.GLOBAL_ONLY);
    133
    134     // evaluate the copy script
    135     interp.eval(copyScript);
    136   } // copyGateScripts
    137
    138   /** Load a list of Tcl scripts. The class loader is used to find the
    139     * scripts, so they must be on the class path, preferably in the same
    140     * code base as this class. Naming: each path in the list should be
    141     * the path to the script relative to the CLASSPATH. So, for e.g., if
    142     * you have MyJar.jar on the classpath, and it contains a script housed
    143     * in package x.y called z.tcl, the name should be x/y/z.tcl. (The class
    144     * loader can then be asked to retrieve /x/y/z.tcl and will find the
    145     * file in the jar.)
    146     */
    147   public void loadScripts(List scriptPaths) throws TclException {
    148     ListIterator iter = scriptPaths.listIterator();
    149     while(iter.hasNext()) {
    150       String path = (String) iter.next();
    151       String leadingSlash = "";
    152
    153       // leading "/" on path needed by classloader
    154       if(! path.startsWith("/"))
    155         leadingSlash = "/";
    156       interp.evalResource(leadingSlash + path);
    157     }
    158   } // loadScripts(scriptPaths)
    159
    160   /** Loads all the scripts in the GATE source. So to get a Tcl interpreter
    161     * that's fully initialised with all the GATE Tcl code do:
    162     * <PRE>
    163     * Jacl jacl = new Jacl();
    164     * jacl.loadScripts();
    165     * </PRE>
    166     */
    167   public void loadScripts() throws TclException {
    168     listGateScripts();
    169     loadScripts(gateScriptsList);
    170   } // loadScripts()
    171
    172   /** Set up the gateScriptsList member. This uses the ScriptsList.tcl
    173     * script, which is built by "make tcl".
    174     */
    175   void listGateScripts() throws TclException {
    176     gateScriptsList = new ArrayList();
    177
    178     interp.evalResource("/gate/util/ScriptsList.tcl");
    179     TclObject scriptsList = interp.getResult();
    180
    181     TclObject pathsArray[] = TclList.getElements(interp, scriptsList);
    182     for(int i = 0; i < pathsArray.length; i++)
    183       gateScriptsList.add(pathsArray[i].toString());
    184   } // listGateScripts
    185
    186   /** This is a list of all the .tcl files in the GATE source, used by
    187     * the loadScripts() method.
    188     */
    189   private List gateScriptsList;
    190
    191 } // class Jacl
    192
    193
    194
    195
    196
    197
    198

| Jacl |