|
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 |
|