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