001: /*
002: * ------------------------------------------------------------------------
003: * PACKAGE: [incr Tcl]
004: * DESCRIPTION: Object-Oriented Extensions to Tcl
005: *
006: * [incr Tcl] provides object-oriented extensions to Tcl, much as
007: * C++ provides object-oriented extensions to C. It provides a means
008: * of encapsulating related procedures together with their shared data
009: * in a local namespace that is hidden from the outside world. It
010: * promotes code re-use through inheritance. More than anything else,
011: * it encourages better organization of Tcl applications through the
012: * object-oriented paradigm, leading to code that is easier to
013: * understand and maintain.
014: *
015: * This part adds a mechanism for integrating C procedures into
016: * [incr Tcl] classes as methods and procs. Each C procedure must
017: * either be declared via Itcl_RegisterC() or dynamically loaded.
018: *
019: * ========================================================================
020: * AUTHOR: Michael J. McLennan
021: * Bell Labs Innovations for Lucent Technologies
022: * mmclennan@lucent.com
023: * http://www.tcltk.com/itcl
024: *
025: * RCS: $Id: Linkage.java,v 1.1 2005/09/11 20:56:57 mdejong Exp $
026: * ========================================================================
027: * Copyright (c) 1993-1998 Lucent Technologies, Inc.
028: * ------------------------------------------------------------------------
029: * See the file "license.itcl" for information on usage and redistribution
030: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
031: */
032:
033: package itcl.lang;
034:
035: import java.util.Hashtable;
036: import java.util.Enumeration;
037:
038: import tcl.lang.*;
039:
040: // These records store the refs for the RegisterObjC function.
041:
042: class ItclJavafunc {
043: Command objCmdProc; // Java objv command handler
044: }
045:
046: // This record is stored in the interp assoc data
047:
048: class AssocHashtable extends Hashtable implements AssocData {
049:
050: public void disposeAssocData(Interp interp) {
051: Linkage.FreeC(this , interp);
052: }
053: }
054:
055: class Linkage {
056:
057: // Note: Itcl_RegisterC not supported
058:
059: /*
060: * ------------------------------------------------------------------------
061: * Itcl_RegisterObjC -> Linkage.RegisterObjC
062: *
063: * Used to associate a symbolic name with a Java procedure
064: * that handles a Tcl command. Procedures that are registered in this
065: * manner can be referenced in the body of an [incr Tcl] class
066: * definition to specify Java procedures to acting as methods/procs.
067: * Usually invoked in an initialization routine for an extension,
068: * called out in Tcl_AppInit() at the start of an application.
069: *
070: * Each symbolic procedure can have an arbitrary client data value
071: * associated with it. This value is passed into the command
072: * handler whenever it is invoked.
073: *
074: * Will raise a TclException to indicate failure.
075: * ------------------------------------------------------------------------
076: */
077:
078: static void RegisterObjC(Interp interp, // interpreter handling this registration
079: String name, // symbolic name for procedure
080: Command proc) // procedure handling Tcl command
081: throws TclException {
082: // Maps String to ItclJavafunc
083: Hashtable procTable;
084: ItclJavafunc jfunc;
085:
086: // Make sure that a proc was specified.
087:
088: if (proc == null) {
089: throw new TclException(interp,
090: "initialization error: null pointer for "
091: + "Java procedure \"" + name + "\"");
092: }
093:
094: // Add a new entry for the given procedure. If an entry with
095: // this name already exists, then make sure that it was defined
096: // with the same proc.
097:
098: procTable = Linkage.GetRegisteredProcs(interp);
099:
100: jfunc = (ItclJavafunc) procTable.get(name);
101:
102: if (jfunc != null) {
103: if (jfunc.objCmdProc != null && jfunc.objCmdProc != proc) {
104: throw new TclException(interp,
105: "initialization error: Java procedure "
106: + "with name \"" + name
107: + "\" already defined");
108: }
109: if (jfunc.objCmdProc instanceof CommandWithDispose) {
110: ((CommandWithDispose) jfunc.objCmdProc).disposeCmd();
111: }
112: } else {
113: jfunc = new ItclJavafunc();
114: }
115:
116: jfunc.objCmdProc = proc;
117: procTable.put(name, jfunc);
118: }
119:
120: /*
121: * ------------------------------------------------------------------------
122: * Itcl_FindC -> Linkage.FindC
123: *
124: * Used to query a Java procedure via its symbolic name. Looks at the
125: * list of procedures registered previously by RegisterObjC and
126: * returns the ItclJavafunc record if found; returns null otherwise.
127: * ------------------------------------------------------------------------
128: */
129:
130: static ItclJavafunc FindC(Interp interp, // interpreter handling this registration
131: String name) // symbolic name for procedure
132: {
133: boolean found = false;
134: Hashtable procTable;
135: ItclJavafunc jfunc = null;
136:
137: if (interp != null) {
138: procTable = (Hashtable) interp.getAssocData("itcl_RegC");
139:
140: if (procTable != null) {
141: jfunc = (ItclJavafunc) procTable.get(name);
142: if (jfunc != null) {
143: found = true;
144: }
145: }
146: }
147:
148: if (!found) {
149: return null;
150: } else {
151: return jfunc;
152: }
153: }
154:
155: /*
156: * ------------------------------------------------------------------------
157: * ItclGetRegisteredProcs -> Linkage.GetRegisteredProcs
158: *
159: * Returns a pointer to a hash table containing the list of registered
160: * procs in the specified interpreter. If the hash table does not
161: * already exist, it is created.
162: * ------------------------------------------------------------------------
163: */
164:
165: static Hashtable GetRegisteredProcs(Interp interp) // interpreter handling this registration
166: {
167: AssocHashtable procTable;
168:
169: // If the registration table does not yet exist, then create it.
170: procTable = (AssocHashtable) interp.getAssocData("itcl_RegC");
171:
172: if (procTable == null) {
173: procTable = new AssocHashtable();
174: interp.setAssocData("itcl_RegC", procTable);
175: }
176:
177: return procTable;
178: }
179:
180: /*
181: * ------------------------------------------------------------------------
182: * ItclFreeC -> FreeC
183: *
184: * When an interpreter is deleted, this procedure is called to
185: * free up the associated data created by RegisterObjC.
186: * ------------------------------------------------------------------------
187: */
188:
189: static void FreeC(Hashtable table, // associated data
190: Interp interp) // intepreter being deleted
191: {
192: for (Enumeration e = table.keys(); e.hasMoreElements();) {
193: String key = (String) e.nextElement();
194: ItclJavafunc jfunc = (ItclJavafunc) table.get(key);
195:
196: if (jfunc.objCmdProc instanceof CommandWithDispose) {
197: ((CommandWithDispose) jfunc.objCmdProc).disposeCmd();
198: }
199: }
200: table.clear();
201: }
202:
203: } // end class Linkage
|