PageRenderTime 426ms CodeModel.GetById 52ms app.highlight 370ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-0-pre3/bsh/This.java

#
Java | 224 lines | 82 code | 26 blank | 116 comment | 4 complexity | 657c7cdcbda18667df37937ac50264f7 MD5 | raw file
  1/*****************************************************************************
  2 *                                                                           *
  3 *  This file is part of the BeanShell Java Scripting distribution.          *
  4 *  Documentation and updates may be found at http://www.beanshell.org/      *
  5 *                                                                           *
  6 *  Sun Public License Notice:                                               *
  7 *                                                                           *
  8 *  The contents of this file are subject to the Sun Public License Version  *
  9 *  1.0 (the "License"); you may not use this file except in compliance with *
 10 *  the License. A copy of the License is available at http://www.sun.com    * 
 11 *                                                                           *
 12 *  The Original Code is BeanShell. The Initial Developer of the Original    *
 13 *  Code is Pat Niemeyer. Portions created by Pat Niemeyer are Copyright     *
 14 *  (C) 2000.  All Rights Reserved.                                          *
 15 *                                                                           *
 16 *  GNU Public License Notice:                                               *
 17 *                                                                           *
 18 *  Alternatively, the contents of this file may be used under the terms of  *
 19 *  the GNU Lesser General Public License (the "LGPL"), in which case the    *
 20 *  provisions of LGPL are applicable instead of those above. If you wish to *
 21 *  allow use of your version of this file only under the  terms of the LGPL *
 22 *  and not to allow others to use your version of this file under the SPL,  *
 23 *  indicate your decision by deleting the provisions above and replace      *
 24 *  them with the notice and other provisions required by the LGPL.  If you  *
 25 *  do not delete the provisions above, a recipient may use your version of  *
 26 *  this file under either the SPL or the LGPL.                              *
 27 *                                                                           *
 28 *  Patrick Niemeyer (pat@pat.net)                                           *
 29 *  Author of Learning Java, O'Reilly & Associates                           *
 30 *  http://www.pat.net/~pat/                                                 *
 31 *                                                                           *
 32 *****************************************************************************/
 33
 34
 35package bsh;
 36
 37import java.io.IOException;
 38
 39/**
 40	'This' is the type of bsh scripted objects.
 41	A 'This' object is a bsh scripted object context.  It holds a namespace 
 42	reference and implements event listeners and various other interfaces.
 43
 44	This holds a reference to the declaring interpreter for callbacks from
 45	outside of bsh.
 46*/
 47public class This implements java.io.Serializable, Runnable {
 48	/**
 49		The namespace that this This reference wraps.
 50	*/
 51	NameSpace namespace;
 52
 53	/**
 54		This is the interpreter running when the This ref was created.
 55		It's used as a default interpreter for callback through the This
 56		where there is no current interpreter instance 
 57		e.g. interface proxy or event call backs from outside of bsh.
 58	*/
 59	transient Interpreter declaringInterpreter;
 60
 61	/**
 62		invokeMethod() here is generally used by outside code to callback
 63		into the bsh interpreter. e.g. when we are acting as an interface
 64		for a scripted listener, etc.  In this case there is no real call stack
 65		so we make a default one starting with the special JAVACODE namespace
 66		and our namespace as the next.
 67	*/
 68	transient CallStack callstack;
 69
 70	/**
 71		getThis() is a factory for bsh.This type references.  The capabilities
 72		of ".this" references in bsh are version dependent up until jdk1.3.
 73		The version dependence was to support different default interface
 74		implementations.  i.e. different sets of listener interfaces which
 75		scripted objects were capable of implementing.  In jdk1.3 the 
 76		reflection proxy mechanism was introduced which allowed us to 
 77		implement arbitrary interfaces.  This is fantastic.
 78
 79		A This object is a thin layer over a namespace, comprising a bsh object
 80		context.  We create it here only if needed for the namespace.
 81
 82		Note: this method could be considered slow because of the way it 
 83		dynamically factories objects.  However I've also done tests where 
 84		I hard-code the factory to return JThis and see no change in the 
 85		rough test suite time.  This references are also cached in NameSpace.  
 86	*/
 87    static This getThis( 
 88		NameSpace namespace, Interpreter declaringInterpreter ) 
 89	{
 90		try {
 91			if ( Capabilities.canGenerateInterfaces() )
 92				return (This)Reflect.constructObject( "bsh.XThis",
 93					new Object [] { namespace, declaringInterpreter } );
 94			else if ( Capabilities.haveSwing() )
 95				return (This)Reflect.constructObject( "bsh.JThis",
 96					new Object [] { namespace, declaringInterpreter } );
 97			else
 98				return new This( namespace, declaringInterpreter );
 99
100		} catch ( Exception e ) {
101			throw new InterpreterError("internal error 1 in This: "+e);
102		} 
103    }
104
105	/**
106		Get a version of the interface.
107		If this type of This implements it directly return this,
108		else try complain that we don't have the proxy mechanism.
109	*/
110	public Object getInterface( Class clas ) 
111		throws EvalError
112	{
113		if ( clas.isInstance( this ) )
114			return this;
115		else
116			throw new EvalError( "Dynamic proxy mechanism not available. "
117			+ "Cannot construct interface type: "+clas );
118	}
119
120	/*
121		I wish protected access were limited to children and not also 
122		package scope... I want this to be a singleton implemented by various
123		children.  
124	*/
125	protected This( NameSpace namespace, Interpreter declaringInterpreter ) { 
126		this.namespace = namespace; 
127		this.declaringInterpreter = declaringInterpreter;
128		initCallStack( namespace );
129	}
130
131	public NameSpace getNameSpace() {
132		return namespace;
133	}
134
135	public String toString() {
136		return "'this' reference to Bsh object: " + namespace.name;
137	}
138
139	public void run() {
140		try {
141			invokeMethod( "run", new Object[0] );
142		} catch( EvalError e ) {
143			declaringInterpreter.error(
144				"Exception in runnable:" + e );
145		}
146	}
147
148	/**
149		Invoke specified method from outside java code, using the declaring 
150		interpreter and current namespace.
151
152		The call stack will appear as if the method is being invoked from
153		outside of bsh in native java code.
154	*/
155	public Object invokeMethod( String name, Object [] args ) 
156		throws EvalError
157	{
158		// null callstack, one will be created for us in namespace.invokMethod
159		// null callerInfo is legal
160		return invokeMethod( name, args, declaringInterpreter, null, null );
161	}
162
163	/**
164		Invoke specified method with specified interpreter.
165		This is simply a convenience method.
166	*/
167	public Object invokeMethod( 
168		String name, Object [] args, Interpreter interpreter, 
169			CallStack callstack, SimpleNode callerInfo  ) 
170		throws EvalError
171	{
172		return namespace.invokeMethod( 
173			name, args, interpreter, callstack, callerInfo );
174	}
175
176
177	/**
178		Bind a This reference to a parent's namespace with the specified
179		declaring interpreter.  Also re-init the callstack.  It's necessary 
180		to bind a This reference before it can be used after deserialization.
181		<p>
182
183		This is a static utility method because it's used by a bsh command
184		bind() and the interpreter doesn't currently allow access to direct 
185		methods of This objects (small hack)
186	*/
187	public static void bind( 
188		This ths, NameSpace namespace, Interpreter declaringInterpreter ) 
189	{ 
190		ths.namespace.setParent( namespace ); 
191		ths.declaringInterpreter = declaringInterpreter;
192		ths.initCallStack( namespace );
193	}
194
195
196	/**
197		For serialization.
198	*/
199    private synchronized void writeObject(java.io.ObjectOutputStream s)
200        throws IOException {
201
202		// Temporarily prune the namespace.
203
204		NameSpace parent = namespace.getParent();
205		// Bind would set the interpreter, but it's possible that the parent
206		// is null (it's the root).  So save it...
207
208		//?Interpreter interpreter = declaringInterpreter;
209
210		namespace.prune();
211		s.defaultWriteObject();
212		// put it back
213		namespace.setParent( parent );
214
215		//?declaringInterpreter = interpreter;
216		//?initCallStack( namespace );
217	}
218
219	private final void initCallStack( NameSpace namespace ) {
220		callstack = new CallStack();
221		callstack.push( namespace );
222	}
223}
224