/* * Extension.java -- * * Copyright (c) 1997 Cornell University. * Copyright (c) 1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and * redistribution of this file, and for a DISCLAIMER OF ALL * WARRANTIES. * * Included in SQLite3 port to C# for use in testharness only; 2008 Noah B Hart * * RCS @(#) $Id: Extension.java,v 1.2 1999/05/09 21:18:54 dejong Exp $ * */ using System; namespace tcl.lang { /// Base class for all Tcl Extensions. A Tcl Extension defines a set of /// commands that can be loaded into an Interp as a single unit. /// /// When a Tcl Extension is loaded into an Interp, either statically /// (using the "new" operator inside Java code) or dynamically (using /// the java::load command in Tcl scripts), it usually creates a set of /// commands inside the interpreter. Occasionally, loading an Extension /// may lead to additional side effects. For example, a communications /// Extension may open network connections when it's loaded. Please /// refer to the documentation of the specific Extension for details. /// abstract public class Extension { /// Default constructor. Does nothing. The purpose of this /// constructor is to make sure instances of this Extension can be /// loaded dynamically using the "java::load" command, which calls /// Class.newInstance(). /// public Extension() { } /// Initialize the Extension to run in a normal (unsafe) /// interpreter. This usually means creating all the commands /// provided by this class. A particular implementation can arrange /// the commands to be loaded on-demand using the loadOnDemand() /// function. /// /// /// current interpreter. /// abstract public void init( Interp interp ); /// Initialize the Extension to run in a safe interpreter. This /// method should be written carefully, so that it initializes the /// safe interpreter only with partial functionality provided by /// the Extension that is safe for use by untrusted code. /// /// The default implementation always throws a TclException, so that /// a subclass of Extension cannot be loaded into a safe interpreter /// unless it has overridden the safeInit() method. /// /// /// the safe interpreter in which the Extension should /// be initialized. /// public void safeInit( Interp safeInterp ) { throw new TclException( safeInterp, "Extension \"" + GetType().ToString() + "\" cannot be loaded into a safe interpreter" ); } /// Create a stub command which autoloads the real command the first time /// the stub command is invoked. Register the stub command in the /// interpreter. /// /// /// current interp. /// /// name of the command, e.g., "after". /// /// name of the Java class that implements this command, /// e.g. "tcl.lang.AfterCmd" /// public static void loadOnDemand( Interp interp, string cmdName, string clsName ) { interp.createCommand( cmdName, new AutoloadStub( clsName ) ); } } /// The purpose of AutoloadStub is to load-on-demand the classes that /// implement Tcl commands. This reduces Jacl start up time and, when /// running Jacl off a web page, reduces download time significantly. /// class AutoloadStub : Command { internal string className; /// Create a stub command which autoloads the real command the first time /// the stub command is invoked. /// /// /// name of the Java class that implements this command, /// e.g. "tcl.lang.AfterCmd" /// internal AutoloadStub( string clsName ) { className = clsName; } /// Load the class that implements the given command and execute it. /// /// /// the current interpreter. /// /// command arguments. /// /// TclException if error happens inside the real command proc. /// public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv ) { Type cmdClass = null; Command cmd; try { cmdClass = System.Type.GetType( className, true ); } catch ( System.Exception e ) { throw new TclException( interp, "ClassNotFoundException for class \"" + className + "\"" ); } try { cmd = (Command)SupportClass.CreateNewInstance( cmdClass ); } catch ( System.UnauthorizedAccessException e1 ) { throw new TclException( interp, "IllegalAccessException for class \"" + cmdClass.FullName + "\"" ); } catch ( System.InvalidCastException e3 ) { throw new TclException( interp, "ClassCastException for class \"" + cmdClass.FullName + "\"" ); } catch ( System.Exception e2 ) { throw new TclException( interp, "InstantiationException for class \"" + cmdClass.FullName + "\"" ); } interp.createCommand( argv[0].ToString(), cmd ); TCL.CompletionCode rc = cmd.cmdProc( interp, argv ); return rc == TCL.CompletionCode.EXIT ? TCL.CompletionCode.EXIT : TCL.CompletionCode.RETURN; } } }