Source Code Cross Referenced for NameSpace.java in  » Scripting » beanshell » bsh » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » beanshell » bsh 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*****************************************************************************
0002:         *                                                                           *
0003:         *  This file is part of the BeanShell Java Scripting distribution.          *
0004:         *  Documentation and updates may be found at http://www.beanshell.org/      *
0005:         *                                                                           *
0006:         *  Sun Public License Notice:                                               *
0007:         *                                                                           *
0008:         *  The contents of this file are subject to the Sun Public License Version  *
0009:         *  1.0 (the "License"); you may not use this file except in compliance with *
0010:         *  the License. A copy of the License is available at http://www.sun.com    * 
0011:         *                                                                           *
0012:         *  The Original Code is BeanShell. The Initial Developer of the Original    *
0013:         *  Code is Pat Niemeyer. Portions created by Pat Niemeyer are Copyright     *
0014:         *  (C) 2000.  All Rights Reserved.                                          *
0015:         *                                                                           *
0016:         *  GNU Public License Notice:                                               *
0017:         *                                                                           *
0018:         *  Alternatively, the contents of this file may be used under the terms of  *
0019:         *  the GNU Lesser General Public License (the "LGPL"), in which case the    *
0020:         *  provisions of LGPL are applicable instead of those above. If you wish to *
0021:         *  allow use of your version of this file only under the  terms of the LGPL *
0022:         *  and not to allow others to use your version of this file under the SPL,  *
0023:         *  indicate your decision by deleting the provisions above and replace      *
0024:         *  them with the notice and other provisions required by the LGPL.  If you  *
0025:         *  do not delete the provisions above, a recipient may use your version of  *
0026:         *  this file under either the SPL or the LGPL.                              *
0027:         *                                                                           *
0028:         *  Patrick Niemeyer (pat@pat.net)                                           *
0029:         *  Author of Learning Java, O'Reilly & Associates                           *
0030:         *  http://www.pat.net/~pat/                                                 *
0031:         *                                                                           *
0032:         *****************************************************************************/package bsh;
0033:
0034:        import java.util.*;
0035:
0036:        import java.io.InputStream;
0037:        import java.io.BufferedReader;
0038:        import java.io.InputStreamReader;
0039:        import java.io.IOException;
0040:
0041:        import java.lang.reflect.Method;
0042:        import java.lang.reflect.Field;
0043:
0044:        /**
0045:         A namespace	in which methods, variables, and imports (class names) live.  
0046:         This is package public because it is used in the implementation of some 
0047:         bsh commands.  However for normal use you should be using methods on 
0048:         bsh.Interpreter to interact with your scripts.
0049:         <p>
0050:
0051:         A bsh.This object is a thin layer over a NameSpace that associates it with
0052:         an Interpreter instance.  Together they comprise a Bsh scripted object 
0053:         context.
0054:         <p>
0055:
0056:         Note: I'd really like to use collections here, but we have to keep this
0057:         compatible with JDK1.1 
0058:         */
0059:        /*
0060:         Thanks to Slava Pestov (of jEdit fame) for import caching enhancements.
0061:         Note: This class has gotten too big.  It should be broken down a bit.
0062:         */
0063:        public class NameSpace implements  java.io.Serializable,
0064:                BshClassManager.Listener, NameSource {
0065:            public static final NameSpace JAVACODE = new NameSpace(
0066:                    (BshClassManager) null, "Called from compiled Java code.");
0067:            static {
0068:                JAVACODE.isMethod = true;
0069:            }
0070:
0071:            // Begin instance data
0072:            // Note: if we add something here we should reset it in the clear() method.
0073:
0074:            /**
0075:            	The name of this namespace.  If the namespace is a method body
0076:            	namespace then this is the name of the method.  If it's a class or
0077:            	class instance then it's the name of the class.
0078:             */
0079:            private String nsName;
0080:            private NameSpace parent;
0081:            private Hashtable variables;
0082:            private Hashtable methods;
0083:
0084:            protected Hashtable importedClasses;
0085:            private Vector importedPackages;
0086:            private Vector importedCommands;
0087:            private Vector importedObjects;
0088:            private Vector importedStatic;
0089:            private String packageName;
0090:
0091:            transient private BshClassManager classManager;
0092:
0093:            // See notes in getThis()
0094:            private This this Reference;
0095:
0096:            /** Name resolver objects */
0097:            private Hashtable names;
0098:
0099:            /** The node associated with the creation of this namespace.
0100:            	This is used support getInvocationLine() and getInvocationText(). */
0101:            SimpleNode callerInfoNode;
0102:
0103:            /** 
0104:            	Note that the namespace is a method body namespace.  This is used for
0105:            	printing stack traces in exceptions.  
0106:             */
0107:            boolean isMethod;
0108:
0109:            /**
0110:            	Note that the namespace is a class body or class instance namespace.  
0111:            	This is used for controlling static/object import precedence, etc.
0112:             */
0113:            /*
0114:            	Note: We can move this class related behavior out to a subclass of 
0115:            	NameSpace, but we'll start here.
0116:             */
0117:            boolean isClass;
0118:            Class classStatic;
0119:            Object classInstance;
0120:
0121:            void setClassStatic(Class clas) {
0122:                this .classStatic = clas;
0123:                importStatic(clas);
0124:            }
0125:
0126:            void setClassInstance(Object instance) {
0127:                this .classInstance = instance;
0128:                importObject(instance);
0129:            }
0130:
0131:            Object getClassInstance() throws UtilEvalError {
0132:                if (classInstance != null)
0133:                    return classInstance;
0134:
0135:                if (classStatic != null
0136:                //|| ( getParent()!=null && getParent().classStatic != null ) 
0137:                )
0138:                    throw new UtilEvalError(
0139:                            "Can't refer to class instance from static context.");
0140:                else
0141:                    throw new InterpreterError(
0142:                            "Can't resolve class instance 'this' in: " + this );
0143:            }
0144:
0145:            /**
0146:            	Local class cache for classes resolved through this namespace using 
0147:            	getClass() (taking into account imports).  Only unqualified class names
0148:            	are cached here (those which might be imported).  Qualified names are 
0149:            	always absolute and are cached by BshClassManager.
0150:             */
0151:            transient private Hashtable classCache;
0152:
0153:            // End instance data
0154:
0155:            // Begin constructors
0156:
0157:            /**
0158:            	@parent the parent namespace of this namespace.  Child namespaces
0159:            	inherit all variables and methods of their parent and can (of course)
0160:            	override / shadow them.
0161:             */
0162:            public NameSpace(NameSpace parent, String name) {
0163:                // Note: in this case parent must have a class manager.
0164:                this (parent, null, name);
0165:            }
0166:
0167:            public NameSpace(BshClassManager classManager, String name) {
0168:                this (null, classManager, name);
0169:            }
0170:
0171:            public NameSpace(NameSpace parent, BshClassManager classManager,
0172:                    String name) {
0173:                // We might want to do this here rather than explicitly in Interpreter
0174:                // for global (see also prune())
0175:                //if ( classManager == null && (parent == null ) )
0176:                // create our own class manager?
0177:
0178:                setName(name);
0179:                setParent(parent);
0180:                setClassManager(classManager);
0181:
0182:                // Register for notification of classloader change
0183:                if (classManager != null)
0184:                    classManager.addListener(this );
0185:            }
0186:
0187:            // End constructors
0188:
0189:            public void setName(String name) {
0190:                this .nsName = name;
0191:            }
0192:
0193:            /**
0194:            	The name of this namespace.  If the namespace is a method body
0195:            	namespace then this is the name of the method.  If it's a class or
0196:            	class instance then it's the name of the class.
0197:             */
0198:            public String getName() {
0199:                return this .nsName;
0200:            }
0201:
0202:            /**
0203:            	Set the node associated with the creation of this namespace.
0204:            	This is used in debugging and to support the getInvocationLine()
0205:            	and getInvocationText() methods.
0206:             */
0207:            void setNode(SimpleNode node) {
0208:                callerInfoNode = node;
0209:            }
0210:
0211:            /**
0212:             */
0213:            SimpleNode getNode() {
0214:                if (callerInfoNode != null)
0215:                    return callerInfoNode;
0216:                if (parent != null)
0217:                    return parent.getNode();
0218:                else
0219:                    return null;
0220:            }
0221:
0222:            /**
0223:            	Resolve name to an object through this namespace.
0224:             */
0225:            public Object get(String name, Interpreter interpreter)
0226:                    throws UtilEvalError {
0227:                CallStack callstack = new CallStack(this );
0228:                return getNameResolver(name).toObject(callstack, interpreter);
0229:            }
0230:
0231:            /**
0232:            	Set the variable through this namespace.
0233:            	This method obeys the LOCALSCOPING property to determine how variables
0234:            	are set.
0235:            	<p>
0236:            	Note: this method is primarily intended for use internally.  If you use
0237:            	this method outside of the bsh package and wish to set variables with
0238:            	primitive values you will have to wrap them using bsh.Primitive.
0239:            	@see bsh.Primitive
0240:            	<p>
0241:            	Setting a new variable (which didn't exist before) or removing
0242:            	a variable causes a namespace change.
0243:
0244:            	@param strictJava specifies whether strict java rules are applied.
0245:             */
0246:            public void setVariable(String name, Object value,
0247:                    boolean strictJava) throws UtilEvalError {
0248:                // if localscoping switch follow strictJava, else recurse
0249:                boolean recurse = Interpreter.LOCALSCOPING ? strictJava : true;
0250:                setVariable(name, value, strictJava, recurse);
0251:            }
0252:
0253:            /**
0254:            	Set a variable explicitly in the local scope.
0255:             */
0256:            void setLocalVariable(String name, Object value, boolean strictJava)
0257:                    throws UtilEvalError {
0258:                setVariable(name, value, strictJava, false/*recurse*/);
0259:            }
0260:
0261:            /**
0262:            	Set the value of a the variable 'name' through this namespace.
0263:            	The variable may be an existing or non-existing variable.
0264:            	It may live in this namespace or in a parent namespace if recurse is 
0265:            	true.
0266:            	<p>
0267:            	Note: This method is not public and does *not* know about LOCALSCOPING.
0268:            	Its caller methods must set recurse intelligently in all situations 
0269:            	(perhaps based on LOCALSCOPING).
0270:
0271:            	<p>
0272:            	Note: this method is primarily intended for use internally.  If you use
0273:            	this method outside of the bsh package and wish to set variables with
0274:            	primitive values you will have to wrap them using bsh.Primitive.
0275:            	@see bsh.Primitive
0276:            	<p>
0277:            	Setting a new variable (which didn't exist before) or removing
0278:            	a variable causes a namespace change.
0279:
0280:            	@param strictJava specifies whether strict java rules are applied.
0281:            	@param recurse determines whether we will search for the variable in
0282:            	  our parent's scope before assigning locally.
0283:             */
0284:            void setVariable(String name, Object value, boolean strictJava,
0285:                    boolean recurse) throws UtilEvalError {
0286:                if (variables == null)
0287:                    variables = new Hashtable();
0288:
0289:                // primitives should have been wrapped
0290:                if (value == null)
0291:                    throw new InterpreterError("null variable value");
0292:
0293:                // Locate the variable definition if it exists.
0294:                Variable existing = getVariableImpl(name, recurse);
0295:
0296:                // Found an existing variable here (or above if recurse allowed)
0297:                if (existing != null) {
0298:                    try {
0299:                        existing.setValue(value, Variable.ASSIGNMENT);
0300:                    } catch (UtilEvalError e) {
0301:                        throw new UtilEvalError("Variable assignment: " + name
0302:                                + ": " + e.getMessage());
0303:                    }
0304:                } else
0305:                // No previous variable definition found here (or above if recurse)
0306:                {
0307:                    if (strictJava)
0308:                        throw new UtilEvalError(
0309:                                "(Strict Java mode) Assignment to undeclared variable: "
0310:                                        + name);
0311:
0312:                    // If recurse, set global untyped var, else set it here.	
0313:                    //NameSpace varScope = recurse ? getGlobal() : this;
0314:                    // This modification makes default allocation local
0315:                    NameSpace varScope = this ;
0316:
0317:                    varScope.variables.put(name, createVariable(name, value,
0318:                            null/*modifiers*/));
0319:
0320:                    // nameSpaceChanged() on new variable addition
0321:                    nameSpaceChanged();
0322:                }
0323:            }
0324:
0325:            ////////////////////////////////////////////////////////////////////////////
0326:
0327:            /**
0328:            	<p>
0329:            	Sets a variable or property.  See "setVariable" for rules regarding
0330:            	scoping.
0331:            	</p>
0332:            	
0333:            	<p>
0334:            	We first check for the existence of the variable.  If it exists, we set 
0335:            	it.
0336:            	If the variable does not exist we look for a property.  If the  property
0337:            	exists and is writable we set it.
0338:            	Finally, if neither the variable or the property exist, we create a new
0339:            	variable.
0340:            	</p>
0341:            
0342:            	@param strictJava specifies whether strict java rules are applied.
0343:             */
0344:            public void setVariableOrProperty(String name, Object value,
0345:                    boolean strictJava) throws UtilEvalError {
0346:                // if localscoping switch follow strictJava, else recurse
0347:                boolean recurse = Interpreter.LOCALSCOPING ? strictJava : true;
0348:                setVariableOrProperty(name, value, strictJava, recurse);
0349:            }
0350:
0351:            /**
0352:            	Set a variable or property explicitly in the local scope.
0353:            	
0354:            	<p>
0355:            	Sets a variable or property.  See "setLocalVariable" for rules regarding
0356:            	scoping.
0357:            	</p>
0358:            	
0359:            	<p>
0360:            	We first check for the existence of the variable.  If it exists, we set 
0361:            	it.
0362:            	If the variable does not exist we look for a property.  If the  property
0363:            	exists and is writable we set it.
0364:            	Finally, if neither the variable or the property exist, we create a new
0365:            	variable.
0366:            	</p>		
0367:             */
0368:            void setLocalVariableOrProperty(String name, Object value,
0369:                    boolean strictJava) throws UtilEvalError {
0370:                setVariableOrProperty(name, value, strictJava, false/*recurse*/);
0371:            }
0372:
0373:            /**
0374:            	Set the value of a the variable or property 'name' through this
0375:            	namespace.
0376:            
0377:            	<p>
0378:            	Sets a variable or property.  See "setVariableOrProperty" for rules 
0379:            	regarding scope.
0380:            	</p>
0381:            	
0382:            	<p>
0383:            	We first check for the existence of the variable.  If it exists, we set 
0384:            	it.
0385:            	If the variable does not exist we look for a property.  If the  property
0386:            	exists and is writable we set it.
0387:            	Finally, if neither the variable or the property exist, we create a new
0388:            	variable.
0389:            	</p>	
0390:            
0391:            	@param strictJava specifies whether strict java rules are applied.
0392:            	@param recurse determines whether we will search for the variable in
0393:            	  our parent's scope before assigning locally.
0394:             */
0395:            void setVariableOrProperty(String name, Object value,
0396:                    boolean strictJava, boolean recurse) throws UtilEvalError {
0397:                if (variables == null)
0398:                    variables = new Hashtable();
0399:
0400:                // primitives should have been wrapped
0401:                if (value == null)
0402:                    throw new InterpreterError("null variable value");
0403:
0404:                // Locate the variable definition if it exists.
0405:                Variable existing = getVariableImpl(name, recurse);
0406:
0407:                // Found an existing variable here (or above if recurse allowed)
0408:                if (existing != null) {
0409:                    try {
0410:                        existing.setValue(value, Variable.ASSIGNMENT);
0411:                    } catch (UtilEvalError e) {
0412:                        throw new UtilEvalError("Variable assignment: " + name
0413:                                + ": " + e.getMessage());
0414:                    }
0415:                } else
0416:                // No previous variable definition found here (or above if recurse)
0417:                {
0418:                    if (strictJava)
0419:                        throw new UtilEvalError(
0420:                                "(Strict Java mode) Assignment to undeclared variable: "
0421:                                        + name);
0422:
0423:                    boolean setProp = attemptSetPropertyValue(name, value, null);
0424:                    if (setProp)
0425:                        return;
0426:
0427:                    // If recurse, set global untyped var, else set it here.	
0428:                    //NameSpace varScope = recurse ? getGlobal() : this;
0429:                    // This modification makes default allocation local
0430:                    NameSpace varScope = this ;
0431:
0432:                    varScope.variables.put(name, createVariable(name, value,
0433:                            null/*modifiers*/));
0434:
0435:                    // nameSpaceChanged() on new variable addition
0436:                    nameSpaceChanged();
0437:                }
0438:            }
0439:
0440:            protected Variable createVariable(String name, Object value,
0441:                    Modifiers mods) throws UtilEvalError {
0442:                return createVariable(name, null/*type*/, value, mods);
0443:            }
0444:
0445:            protected Variable createVariable(String name, Class type,
0446:                    Object value, Modifiers mods) throws UtilEvalError {
0447:                return new Variable(name, type, value, mods);
0448:            }
0449:
0450:            protected Variable createVariable(String name, Class type, LHS lhs)
0451:                    throws UtilEvalError {
0452:                return new Variable(name, type, lhs);
0453:            }
0454:
0455:            /**
0456:            	Remove the variable from the namespace.
0457:             */
0458:            public void unsetVariable(String name) {
0459:                if (variables != null) {
0460:                    variables.remove(name);
0461:                    nameSpaceChanged();
0462:                }
0463:            }
0464:
0465:            /**
0466:            	Get the names of variables defined in this namespace.
0467:            	(This does not show variables in parent namespaces).
0468:             */
0469:            public String[] getVariableNames() {
0470:                if (variables == null)
0471:                    return new String[0];
0472:                else
0473:                    return enumerationToStringArray(variables.keys());
0474:            }
0475:
0476:            /**
0477:            	Get the names of methods declared in this namespace.
0478:            	(This does not include methods in parent namespaces).
0479:             */
0480:            public String[] getMethodNames() {
0481:                if (methods == null)
0482:                    return new String[0];
0483:                else
0484:                    return enumerationToStringArray(methods.keys());
0485:            }
0486:
0487:            /**
0488:            	Get the methods defined in this namespace.
0489:            	(This does not show methods in parent namespaces).
0490:            	Note: This will probably be renamed getDeclaredMethods()
0491:             */
0492:            public BshMethod[] getMethods() {
0493:                if (methods == null)
0494:                    return new BshMethod[0];
0495:                else
0496:                    return flattenMethodCollection(methods.elements());
0497:            }
0498:
0499:            private String[] enumerationToStringArray(Enumeration e) {
0500:                Vector v = new Vector();
0501:                while (e.hasMoreElements())
0502:                    v.addElement(e.nextElement());
0503:                String[] sa = new String[v.size()];
0504:                v.copyInto(sa);
0505:                return sa;
0506:            }
0507:
0508:            /**
0509:            	Flatten the vectors of overloaded methods to a single array.
0510:            	@see #getMethods()
0511:             */
0512:            private BshMethod[] flattenMethodCollection(Enumeration e) {
0513:                Vector v = new Vector();
0514:                while (e.hasMoreElements()) {
0515:                    Object o = e.nextElement();
0516:                    if (o instanceof  BshMethod)
0517:                        v.addElement(o);
0518:                    else {
0519:                        Vector ov = (Vector) o;
0520:                        for (int i = 0; i < ov.size(); i++)
0521:                            v.addElement(ov.elementAt(i));
0522:                    }
0523:                }
0524:                BshMethod[] bma = new BshMethod[v.size()];
0525:                v.copyInto(bma);
0526:                return bma;
0527:            }
0528:
0529:            /**
0530:            	Get the parent namespace.
0531:            	Note: this isn't quite the same as getSuper().
0532:            	getSuper() returns 'this' if we are at the root namespace.
0533:             */
0534:            public NameSpace getParent() {
0535:                return parent;
0536:            }
0537:
0538:            /**
0539:            	Get the parent namespace' This reference or this namespace' This
0540:            	reference if we are the top.
0541:             */
0542:            public This getSuper(Interpreter declaringInterpreter) {
0543:                if (parent != null)
0544:                    return parent.getThis(declaringInterpreter);
0545:                else
0546:                    return getThis(declaringInterpreter);
0547:            }
0548:
0549:            /**
0550:            	Get the top level namespace or this namespace if we are the top.
0551:            	Note: this method should probably return type bsh.This to be consistent
0552:            	with getThis();
0553:             */
0554:            public This getGlobal(Interpreter declaringInterpreter) {
0555:                if (parent != null)
0556:                    return parent.getGlobal(declaringInterpreter);
0557:                else
0558:                    return getThis(declaringInterpreter);
0559:            }
0560:
0561:            /**
0562:            	A This object is a thin layer over a namespace, comprising a bsh object
0563:            	context.  It handles things like the interface types the bsh object
0564:            	supports and aspects of method invocation on it.  
0565:            	<p>
0566:
0567:            	The declaringInterpreter is here to support callbacks from Java through
0568:            	generated proxies.  The scripted object "remembers" who created it for
0569:            	things like printing messages and other per-interpreter phenomenon
0570:            	when called externally from Java.
0571:             */
0572:            /*
0573:            	Note: we need a singleton here so that things like 'this == this' work
0574:            	(and probably a good idea for speed).
0575:
0576:            	Caching a single instance here seems technically incorrect,
0577:            	considering the declaringInterpreter could be different under some
0578:            	circumstances.  (Case: a child interpreter running a source() / eval() 
0579:            	command ).  However the effect is just that the main interpreter that
0580:            	executes your script should be the one involved in call-backs from Java.
0581:
0582:            	I do not know if there are corner cases where a child interpreter would
0583:            	be the first to use a This reference in a namespace or if that would
0584:            	even cause any problems if it did...  We could do some experiments
0585:            	to find out... and if necessary we could cache on a per interpreter
0586:            	basis if we had weak references...  We might also look at skipping 
0587:            	over child interpreters and going to the parent for the declaring 
0588:            	interpreter, so we'd be sure to get the top interpreter.
0589:             */
0590:            public This getThis(Interpreter declaringInterpreter) {
0591:                if (this Reference == null)
0592:                    this Reference = This.getThis(this , declaringInterpreter);
0593:
0594:                return this Reference;
0595:            }
0596:
0597:            public BshClassManager getClassManager() {
0598:                if (classManager != null)
0599:                    return classManager;
0600:                if (parent != null && parent != JAVACODE)
0601:                    return parent.getClassManager();
0602:
0603:                //System.out.println("experiment: creating class manager");
0604:                classManager = BshClassManager
0605:                        .createClassManager(null/*interp*/);
0606:
0607:                //Interpreter.debug("No class manager namespace:" +this);
0608:                return classManager;
0609:            }
0610:
0611:            void setClassManager(BshClassManager classManager) {
0612:                this .classManager = classManager;
0613:            }
0614:
0615:            /**
0616:            	Used for serialization
0617:             */
0618:            public void prune() {
0619:                // Cut off from parent, we must have our own class manager.
0620:                // Can't do this in the run() command (needs to resolve stuff)
0621:                // Should we do it by default when we create a namespace will no
0622:                // parent of class manager?
0623:
0624:                if (this .classManager == null)
0625:                    // XXX if we keep the createClassManager in getClassManager then we can axe
0626:                    // this?
0627:                    setClassManager(BshClassManager
0628:                            .createClassManager(null/*interp*/));
0629:
0630:                setParent(null);
0631:            }
0632:
0633:            public void setParent(NameSpace parent) {
0634:                this .parent = parent;
0635:
0636:                // If we are disconnected from root we need to handle the def imports
0637:                if (parent == null)
0638:                    loadDefaultImports();
0639:            }
0640:
0641:            /**
0642:            	<p>
0643:            	Get the specified variable or property in this namespace or a parent
0644:            	namespace.
0645:            	</p>
0646:            
0647:            	<p>
0648:            	We first search for a variable name, and then a property.
0649:            	</p>
0650:            
0651:            	@return The variable or property value or Primitive.VOID if neither is
0652:            		defined.
0653:             */
0654:            public Object getVariableOrProperty(String name, Interpreter interp)
0655:                    throws UtilEvalError {
0656:                Object val = getVariable(name, true);
0657:                return (val == Primitive.VOID) ? getPropertyValue(name, interp)
0658:                        : val;
0659:            }
0660:
0661:            /**
0662:            	Get the specified variable in this namespace or a parent namespace.
0663:            	<p>
0664:            	Note: this method is primarily intended for use internally.  If you use
0665:            	this method outside of the bsh package you will have to use 
0666:            	Primitive.unwrap() to get primitive values.
0667:            	@see Primitive#unwrap( Object )
0668:
0669:            	@return The variable value or Primitive.VOID if it is not defined.
0670:             */
0671:            public Object getVariable(String name) throws UtilEvalError {
0672:                return getVariable(name, true);
0673:            }
0674:
0675:            /**
0676:            	Get the specified variable in this namespace.
0677:            	@param recurse If recurse is true then we recursively search through 
0678:            	parent namespaces for the variable.
0679:            	<p>
0680:            	Note: this method is primarily intended for use internally.  If you use
0681:            	this method outside of the bsh package you will have to use 
0682:            	Primitive.unwrap() to get primitive values.
0683:            	@see Primitive#unwrap( Object )
0684:
0685:            	@return The variable value or Primitive.VOID if it is not defined.
0686:             */
0687:            public Object getVariable(String name, boolean recurse)
0688:                    throws UtilEvalError {
0689:                Variable var = getVariableImpl(name, recurse);
0690:                return unwrapVariable(var);
0691:            }
0692:
0693:            /**
0694:            	Locate a variable and return the Variable object with optional 
0695:            	recursion through parent name spaces.
0696:            	<p/>
0697:            	If this namespace is static, return only static variables.
0698:
0699:            	@return the Variable value or null if it is not defined
0700:             */
0701:            protected Variable getVariableImpl(String name, boolean recurse)
0702:                    throws UtilEvalError {
0703:                Variable var = null;
0704:
0705:                // Change import precedence if we are a class body/instance
0706:                // Get imported first.
0707:                if (var == null && isClass)
0708:                    var = getImportedVar(name);
0709:
0710:                if (var == null && variables != null)
0711:                    var = (Variable) variables.get(name);
0712:
0713:                // Change import precedence if we are a class body/instance
0714:                if (var == null && !isClass)
0715:                    var = getImportedVar(name);
0716:
0717:                // try parent
0718:                if (recurse && (var == null) && (parent != null))
0719:                    var = parent.getVariableImpl(name, recurse);
0720:
0721:                return var;
0722:            }
0723:
0724:            /*
0725:            	Get variables declared in this namespace.
0726:             */
0727:            public Variable[] getDeclaredVariables() {
0728:                if (variables == null)
0729:                    return new Variable[0];
0730:                Variable[] vars = new Variable[variables.size()];
0731:                int i = 0;
0732:                for (Enumeration e = variables.elements(); e.hasMoreElements();)
0733:                    vars[i++] = (Variable) e.nextElement();
0734:                return vars;
0735:            }
0736:
0737:            /**
0738:            	Unwrap a variable to its value.
0739:            	@return return the variable value.  A null var is mapped to 
0740:            		Primitive.VOID
0741:             */
0742:            protected Object unwrapVariable(Variable var) throws UtilEvalError {
0743:                return (var == null) ? Primitive.VOID : var.getValue();
0744:            }
0745:
0746:            /**
0747:            	@deprecated See #setTypedVariable( String, Class, Object, Modifiers )
0748:             */
0749:            public void setTypedVariable(String name, Class type, Object value,
0750:                    boolean isFinal) throws UtilEvalError {
0751:                Modifiers modifiers = new Modifiers();
0752:                if (isFinal)
0753:                    modifiers.addModifier(Modifiers.FIELD, "final");
0754:                setTypedVariable(name, type, value, modifiers);
0755:            }
0756:
0757:            /**
0758:            	Declare a variable in the local scope and set its initial value.
0759:            	Value may be null to indicate that we would like the default value 
0760:            	for the variable type. (e.g.  0 for integer types, null for object 
0761:            	types).  An existing typed variable may only be set to the same type.
0762:            	If an untyped variable of the same name exists it will be overridden 
0763:            	with the new typed var.
0764:            	The set will perform a Types.getAssignableForm() on the value if 
0765:            	necessary.
0766:
0767:            	<p>
0768:            	Note: this method is primarily intended for use internally.  If you use
0769:            	this method outside of the bsh package and wish to set variables with
0770:            	primitive values you will have to wrap them using bsh.Primitive.
0771:            	@see bsh.Primitive
0772:
0773:            	@param value If value is null, you'll get the default value for the type
0774:            	@param modifiers may be null
0775:             */
0776:            public void setTypedVariable(String name, Class type, Object value,
0777:                    Modifiers modifiers) throws UtilEvalError {
0778:                //checkVariableModifiers( name, modifiers );
0779:
0780:                if (variables == null)
0781:                    variables = new Hashtable();
0782:
0783:                // Setting a typed variable is always a local operation.
0784:                Variable existing = getVariableImpl(name, false/*recurse*/);
0785:
0786:                // Null value is just a declaration
0787:                // Note: we might want to keep any existing value here instead of reset
0788:
0789:                // does the variable already exist?
0790:                if (existing != null) {
0791:                    // Is it typed?
0792:                    if (existing.getType() != null) {
0793:                        // If it had a different type throw error.
0794:                        // This allows declaring the same var again, but not with
0795:                        // a different (even if assignable) type.
0796:                        if (existing.getType() != type) {
0797:                            throw new UtilEvalError("Typed variable: " + name
0798:                                    + " was previously declared with type: "
0799:                                    + existing.getType());
0800:                        } else {
0801:                            // else set it and return
0802:                            existing.setValue(value, Variable.DECLARATION);
0803:                            return;
0804:                        }
0805:                    }
0806:                    // Careful here:
0807:                    // else fall through to override and install the new typed version
0808:                }
0809:
0810:                // Add the new typed var
0811:                variables.put(name,
0812:                        createVariable(name, type, value, modifiers));
0813:            }
0814:
0815:            /**
0816:            	Dissallow static vars outside of a class
0817:            	@param name is here just to allow the error message to use it
0818:            protected void checkVariableModifiers( String name, Modifiers modifiers )
0819:            	throws UtilEvalError
0820:            {
0821:            	if ( modifiers!=null && modifiers.hasModifier("static") )
0822:            		throw new UtilEvalError(
0823:            			"Can't declare static variable outside of class: "+name );
0824:            }
0825:             */
0826:
0827:            /**
0828:            	Note: this is primarily for internal use.
0829:            	@see Interpreter#source( String )
0830:            	@see Interpreter#eval( String )
0831:             */
0832:            public void setMethod(String name, BshMethod method)
0833:                    throws UtilEvalError {
0834:                //checkMethodModifiers( method );
0835:
0836:                if (methods == null)
0837:                    methods = new Hashtable();
0838:
0839:                Object m = methods.get(name);
0840:
0841:                if (m == null)
0842:                    methods.put(name, method);
0843:                else if (m instanceof  BshMethod) {
0844:                    Vector v = new Vector();
0845:                    v.addElement(m);
0846:                    v.addElement(method);
0847:                    methods.put(name, v);
0848:                } else
0849:                    // Vector
0850:                    ((Vector) m).addElement(method);
0851:            }
0852:
0853:            /**
0854:            	@see #getMethod( String, Class [], boolean )
0855:            	@see #getMethod( String, Class [] )
0856:             */
0857:            public BshMethod getMethod(String name, Class[] sig)
0858:                    throws UtilEvalError {
0859:                return getMethod(name, sig, false/*declaredOnly*/);
0860:            }
0861:
0862:            /**
0863:            	Get the bsh method matching the specified signature declared in 
0864:            	this name space or a parent.
0865:            	<p>
0866:            	Note: this method is primarily intended for use internally.  If you use
0867:            	this method outside of the bsh package you will have to be familiar
0868:            	with BeanShell's use of the Primitive wrapper class.
0869:            	@see bsh.Primitive
0870:            	@return the BshMethod or null if not found
0871:            	@param declaredOnly if true then only methods declared directly in this
0872:            		namespace will be found and no inherited or imported methods will
0873:            		be visible.
0874:             */
0875:            public BshMethod getMethod(String name, Class[] sig,
0876:                    boolean declaredOnly) throws UtilEvalError {
0877:                BshMethod method = null;
0878:
0879:                // Change import precedence if we are a class body/instance
0880:                // Get import first.
0881:                if (method == null && isClass && !declaredOnly)
0882:                    method = getImportedMethod(name, sig);
0883:
0884:                Object m = null;
0885:                if (method == null && methods != null) {
0886:                    m = methods.get(name);
0887:
0888:                    // m contains either BshMethod or Vector of BshMethod
0889:                    if (m != null) {
0890:                        // unwrap 
0891:                        BshMethod[] ma;
0892:                        if (m instanceof  Vector) {
0893:                            Vector vm = (Vector) m;
0894:                            ma = new BshMethod[vm.size()];
0895:                            vm.copyInto(ma);
0896:                        } else
0897:                            ma = new BshMethod[] { (BshMethod) m };
0898:
0899:                        // Apply most specific signature matching
0900:                        Class[][] candidates = new Class[ma.length][];
0901:                        for (int i = 0; i < ma.length; i++)
0902:                            candidates[i] = ma[i].getParameterTypes();
0903:
0904:                        int match = Reflect.findMostSpecificSignature(sig,
0905:                                candidates);
0906:                        if (match != -1)
0907:                            method = ma[match];
0908:                    }
0909:                }
0910:
0911:                if (method == null && !isClass && !declaredOnly)
0912:                    method = getImportedMethod(name, sig);
0913:
0914:                // try parent
0915:                if (!declaredOnly && (method == null) && (parent != null))
0916:                    return parent.getMethod(name, sig);
0917:
0918:                return method;
0919:            }
0920:
0921:            /**
0922:            	Import a class name.
0923:            	Subsequent imports override earlier ones
0924:             */
0925:            public void importClass(String name) {
0926:                if (importedClasses == null)
0927:                    importedClasses = new Hashtable();
0928:
0929:                importedClasses.put(Name.suffix(name, 1), name);
0930:                nameSpaceChanged();
0931:            }
0932:
0933:            /**
0934:            	subsequent imports override earlier ones
0935:             */
0936:            public void importPackage(String name) {
0937:                if (importedPackages == null)
0938:                    importedPackages = new Vector();
0939:
0940:                // If it exists, remove it and add it at the end (avoid memory leak)
0941:                if (importedPackages.contains(name))
0942:                    importedPackages.remove(name);
0943:
0944:                importedPackages.addElement(name);
0945:                nameSpaceChanged();
0946:            }
0947:
0948:            /**
0949:            	Import scripted or compiled BeanShell commands in the following package
0950:            	in the classpath.  You may use either "/" path or "." package notation.
0951:            	e.g. importCommands("/bsh/commands") or importCommands("bsh.commands")
0952:            	are equivalent.  If a relative path style specifier is used then it is
0953:            	made into an absolute path by prepending "/".
0954:             */
0955:            public void importCommands(String name) {
0956:                if (importedCommands == null)
0957:                    importedCommands = new Vector();
0958:
0959:                // dots to slashes
0960:                name = name.replace('.', '/');
0961:                // absolute
0962:                if (!name.startsWith("/"))
0963:                    name = "/" + name;
0964:                // remove trailing (but preserve case of simple "/")
0965:                if (name.length() > 1 && name.endsWith("/"))
0966:                    name = name.substring(0, name.length() - 1);
0967:
0968:                // If it exists, remove it and add it at the end (avoid memory leak)
0969:                if (importedCommands.contains(name))
0970:                    importedCommands.remove(name);
0971:
0972:                importedCommands.addElement(name);
0973:                nameSpaceChanged();
0974:            }
0975:
0976:            /**
0977:            	A command is a scripted method or compiled command class implementing a 
0978:            	specified method signature.  Commands are loaded from the classpath
0979:            	and may be imported using the importCommands() method.
0980:            	<p/>
0981:
0982:            	This method searches the imported commands packages for a script or
0983:            	command object corresponding to the name of the method.  If it is a
0984:            	script the script is sourced into this namespace and the BshMethod for
0985:            	the requested signature is returned.  If it is a compiled class the
0986:            	class is returned.  (Compiled command classes implement static invoke()
0987:            	methods).
0988:            	<p/>
0989:
0990:            	The imported packages are searched in reverse order, so that later
0991:            	imports take priority.
0992:            	Currently only the first object (script or class) with the appropriate
0993:            	name is checked.  If another, overloaded form, is located in another
0994:            	package it will not currently be found.  This could be fixed.
0995:            	<p/>
0996:
0997:            	@return a BshMethod, Class, or null if no such command is found.
0998:            	@param name is the name of the desired command method
0999:            	@param argTypes is the signature of the desired command method.
1000:            	@throws UtilEvalError if loadScriptedCommand throws UtilEvalError
1001:            		i.e. on errors loading a script that was found
1002:             */
1003:            public Object getCommand(String name, Class[] argTypes,
1004:                    Interpreter interpreter) throws UtilEvalError {
1005:                if (Interpreter.DEBUG)
1006:                    Interpreter.debug("getCommand: " + name);
1007:                BshClassManager bcm = interpreter.getClassManager();
1008:
1009:                if (importedCommands != null) {
1010:                    // loop backwards for precedence
1011:                    for (int i = importedCommands.size() - 1; i >= 0; i--) {
1012:                        String path = (String) importedCommands.elementAt(i);
1013:
1014:                        String scriptPath;
1015:                        if (path.equals("/"))
1016:                            scriptPath = path + name + ".bsh";
1017:                        else
1018:                            scriptPath = path + "/" + name + ".bsh";
1019:
1020:                        Interpreter
1021:                                .debug("searching for script: " + scriptPath);
1022:
1023:                        InputStream in = bcm.getResourceAsStream(scriptPath);
1024:
1025:                        if (in != null)
1026:                            return loadScriptedCommand(in, name, argTypes,
1027:                                    scriptPath, interpreter);
1028:
1029:                        // Chop leading "/" and change "/" to "."
1030:                        String className;
1031:                        if (path.equals("/"))
1032:                            className = name;
1033:                        else
1034:                            className = path.substring(1).replace('/', '.')
1035:                                    + "." + name;
1036:
1037:                        Interpreter.debug("searching for class: " + className);
1038:                        Class clas = bcm.classForName(className);
1039:                        if (clas != null)
1040:                            return clas;
1041:                    }
1042:                }
1043:
1044:                if (parent != null)
1045:                    return parent.getCommand(name, argTypes, interpreter);
1046:                else
1047:                    return null;
1048:            }
1049:
1050:            protected BshMethod getImportedMethod(String name, Class[] sig)
1051:                    throws UtilEvalError {
1052:                // Try object imports
1053:                if (importedObjects != null)
1054:                    for (int i = 0; i < importedObjects.size(); i++) {
1055:                        Object object = importedObjects.elementAt(i);
1056:                        Class clas = object.getClass();
1057:                        Method method = Reflect
1058:                                .resolveJavaMethod(getClassManager(), clas,
1059:                                        name, sig, false/*onlyStatic*/);
1060:                        if (method != null)
1061:                            return new BshMethod(method, object);
1062:                    }
1063:
1064:                // Try static imports
1065:                if (importedStatic != null)
1066:                    for (int i = 0; i < importedStatic.size(); i++) {
1067:                        Class clas = (Class) importedStatic.elementAt(i);
1068:                        Method method = Reflect
1069:                                .resolveJavaMethod(getClassManager(), clas,
1070:                                        name, sig, true/*onlyStatic*/);
1071:                        if (method != null)
1072:                            return new BshMethod(method, null/*object*/);
1073:                    }
1074:
1075:                return null;
1076:            }
1077:
1078:            protected Variable getImportedVar(String name) throws UtilEvalError {
1079:                // Try object imports
1080:                if (importedObjects != null)
1081:                    for (int i = 0; i < importedObjects.size(); i++) {
1082:                        Object object = importedObjects.elementAt(i);
1083:                        Class clas = object.getClass();
1084:                        Field field = Reflect.resolveJavaField(clas, name,
1085:                                false/*onlyStatic*/);
1086:                        if (field != null)
1087:                            return createVariable(name, field.getType(),
1088:                                    new LHS(object, field));
1089:                    }
1090:
1091:                // Try static imports
1092:                if (importedStatic != null)
1093:                    for (int i = 0; i < importedStatic.size(); i++) {
1094:                        Class clas = (Class) importedStatic.elementAt(i);
1095:                        Field field = Reflect
1096:                                .resolveJavaField(clas, name, true/*onlyStatic*/);
1097:                        if (field != null)
1098:                            return createVariable(name, field.getType(),
1099:                                    new LHS(field));
1100:                    }
1101:
1102:                return null;
1103:            }
1104:
1105:            /**
1106:            	Load a command script from the input stream and find the BshMethod in
1107:            	the target namespace.
1108:            	@throws UtilEvalError on error in parsing the script or if the the
1109:            		method is not found after parsing the script.
1110:             */
1111:            /*
1112:            	If we want to support multiple commands in the command path we need to
1113:            	change this to not throw the exception.
1114:             */
1115:            private BshMethod loadScriptedCommand(InputStream in, String name,
1116:                    Class[] argTypes, String resourcePath,
1117:                    Interpreter interpreter) throws UtilEvalError {
1118:                try {
1119:                    interpreter.eval(new InputStreamReader(in), this ,
1120:                            resourcePath);
1121:                } catch (EvalError e) {
1122:                    /* 
1123:                    	Here we catch any EvalError from the interpreter because we are
1124:                    	using it as a tool to load the command, not as part of the
1125:                    	execution path.
1126:                     */
1127:                    Interpreter.debug(e.toString());
1128:                    throw new UtilEvalError("Error loading script: "
1129:                            + e.getMessage());
1130:                }
1131:
1132:                // Look for the loaded command 
1133:                BshMethod meth = getMethod(name, argTypes);
1134:                /*
1135:                if ( meth == null )
1136:                	throw new UtilEvalError("Loaded resource: " + resourcePath +
1137:                		"had an error or did not contain the correct method" );
1138:                 */
1139:
1140:                return meth;
1141:            }
1142:
1143:            /**
1144:            	Helper that caches class.
1145:             */
1146:            void cacheClass(String name, Class c) {
1147:                if (classCache == null) {
1148:                    classCache = new Hashtable();
1149:                    //cacheCount++; // debug
1150:                }
1151:
1152:                classCache.put(name, c);
1153:            }
1154:
1155:            /**
1156:            	Load a class through this namespace taking into account imports.
1157:            	The class search will proceed through the parent namespaces if
1158:            	necessary.
1159:
1160:            	@return null if not found.
1161:             */
1162:            public Class getClass(String name) throws UtilEvalError {
1163:                Class c = getClassImpl(name);
1164:                if (c != null)
1165:                    return c;
1166:                else
1167:                // implement the recursion for getClassImpl()
1168:                if (parent != null)
1169:                    return parent.getClass(name);
1170:                else
1171:                    return null;
1172:            }
1173:
1174:            /**
1175:            	Implementation of getClass() 
1176:
1177:            	Load a class through this namespace taking into account imports.
1178:            	<p>
1179:
1180:            	Check the cache first.  If an unqualified name look for imported 
1181:            	class or package.  Else try to load absolute name.
1182:            	<p>
1183:
1184:            	This method implements caching of unqualified names (normally imports).
1185:            	Qualified names are cached by the BshClassManager.
1186:            	Unqualified absolute class names (e.g. unpackaged Foo) are cached too
1187:            	so that we don't go searching through the imports for them each time.
1188:
1189:            	@return null if not found.
1190:             */
1191:            private Class getClassImpl(String name) throws UtilEvalError {
1192:                Class c = null;
1193:
1194:                // Check the cache
1195:                if (classCache != null) {
1196:                    c = (Class) classCache.get(name);
1197:
1198:                    if (c != null)
1199:                        return c;
1200:                }
1201:
1202:                // Unqualified (simple, non-compound) name
1203:                boolean unqualifiedName = !Name.isCompound(name);
1204:
1205:                // Unqualified name check imported
1206:                if (unqualifiedName) {
1207:                    // Try imported class
1208:                    if (c == null)
1209:                        c = getImportedClassImpl(name);
1210:
1211:                    // if found as imported also cache it
1212:                    if (c != null) {
1213:                        cacheClass(name, c);
1214:                        return c;
1215:                    }
1216:                }
1217:
1218:                // Try absolute
1219:                c = classForName(name);
1220:                if (c != null) {
1221:                    // Cache unqualified names to prevent import check again
1222:                    if (unqualifiedName)
1223:                        cacheClass(name, c);
1224:                    return c;
1225:                }
1226:
1227:                // Not found
1228:                if (Interpreter.DEBUG)
1229:                    Interpreter.debug("getClass(): " + name + " not	found in "
1230:                            + this );
1231:                return null;
1232:            }
1233:
1234:            /**
1235:            	Try to make the name into an imported class.
1236:            	This method takes into account only imports (class or package)
1237:            	found directly in this NameSpace (no parent chain).
1238:             */
1239:            private Class getImportedClassImpl(String name)
1240:                    throws UtilEvalError {
1241:                // Try explicitly imported class, e.g. import foo.Bar;
1242:                String fullname = null;
1243:                if (importedClasses != null)
1244:                    fullname = (String) importedClasses.get(name);
1245:
1246:                // not sure if we should really recurse here for explicitly imported
1247:                // class in parent...  
1248:
1249:                if (fullname != null) {
1250:                    /*
1251:                    	Found the full name in imported classes.
1252:                     */
1253:                    // Try to make the full imported name
1254:                    Class clas = classForName(fullname);
1255:
1256:                    // Handle imported inner class case
1257:                    if (clas == null) {
1258:                        // Imported full name wasn't found as an absolute class
1259:                        // If it is compound, try to resolve to an inner class.  
1260:                        // (maybe this should happen in the BshClassManager?)
1261:
1262:                        if (Name.isCompound(fullname))
1263:                            try {
1264:                                clas = getNameResolver(fullname).toClass();
1265:                            } catch (ClassNotFoundException e) { /* not a class */
1266:                            }
1267:                        else if (Interpreter.DEBUG)
1268:                            Interpreter
1269:                                    .debug("imported unpackaged name not found:"
1270:                                            + fullname);
1271:
1272:                        // If found cache the full name in the BshClassManager
1273:                        if (clas != null) {
1274:                            // (should we cache info in not a class case too?)
1275:                            getClassManager().cacheClassInfo(fullname, clas);
1276:                            return clas;
1277:                        }
1278:                    } else
1279:                        return clas;
1280:
1281:                    // It was explicitly imported, but we don't know what it is.
1282:                    // should we throw an error here??
1283:                    return null;
1284:                }
1285:
1286:                /*
1287:                	Try imported packages, e.g. "import foo.bar.*;"
1288:                	in reverse order of import...
1289:                	(give later imports precedence...)
1290:                 */
1291:                if (importedPackages != null)
1292:                    for (int i = importedPackages.size() - 1; i >= 0; i--) {
1293:                        String s = ((String) importedPackages.elementAt(i))
1294:                                + "." + name;
1295:                        Class c = classForName(s);
1296:                        if (c != null)
1297:                            return c;
1298:                    }
1299:
1300:                BshClassManager bcm = getClassManager();
1301:                /*
1302:                	Try super import if available
1303:                	Note: we do this last to allow explicitly imported classes
1304:                	and packages to take priority.  This method will also throw an
1305:                	error indicating ambiguity if it exists...
1306:                 */
1307:                if (bcm.hasSuperImport()) {
1308:                    String s = bcm.getClassNameByUnqName(name);
1309:                    if (s != null)
1310:                        return classForName(s);
1311:                }
1312:
1313:                return null;
1314:            }
1315:
1316:            private Class classForName(String name) {
1317:                return getClassManager().classForName(name);
1318:            }
1319:
1320:            /**
1321:            	Implements NameSource
1322:            	@return all variable and method names in this and all parent
1323:            	namespaces
1324:             */
1325:            public String[] getAllNames() {
1326:                Vector vec = new Vector();
1327:                getAllNamesAux(vec);
1328:                String[] names = new String[vec.size()];
1329:                vec.copyInto(names);
1330:                return names;
1331:            }
1332:
1333:            /**
1334:            	Helper for implementing NameSource
1335:             */
1336:            protected void getAllNamesAux(Vector vec) {
1337:                Enumeration varNames = variables.keys();
1338:                while (varNames.hasMoreElements())
1339:                    vec.addElement(varNames.nextElement());
1340:
1341:                Enumeration methodNames = methods.keys();
1342:                while (methodNames.hasMoreElements())
1343:                    vec.addElement(methodNames.nextElement());
1344:
1345:                if (parent != null)
1346:                    parent.getAllNamesAux(vec);
1347:            }
1348:
1349:            Vector nameSourceListeners;
1350:
1351:            /**
1352:            	Implements NameSource
1353:            	Add a listener who is notified upon changes to names in this space.
1354:             */
1355:            public void addNameSourceListener(NameSource.Listener listener) {
1356:                if (nameSourceListeners == null)
1357:                    nameSourceListeners = new Vector();
1358:                nameSourceListeners.addElement(listener);
1359:            }
1360:
1361:            /**
1362:            	Perform "import *;" causing the entire classpath to be mapped.
1363:            	This can take a while.
1364:             */
1365:            public void doSuperImport() throws UtilEvalError {
1366:                getClassManager().doSuperImport();
1367:            }
1368:
1369:            public String toString() {
1370:                return "NameSpace: "
1371:                        + (nsName == null ? super .toString() : nsName + " ("
1372:                                + super .toString() + ")")
1373:                        + (isClass ? " (isClass) " : "")
1374:                        + (isMethod ? " (method) " : "")
1375:                        + (classStatic != null ? " (class static) " : "")
1376:                        + (classInstance != null ? " (class instance) " : "");
1377:            }
1378:
1379:            /*
1380:            	For serialization.
1381:            	Don't serialize non-serializable objects.
1382:             */
1383:            private synchronized void writeObject(java.io.ObjectOutputStream s)
1384:                    throws IOException {
1385:                // clear name resolvers... don't know if this is necessary.
1386:                names = null;
1387:
1388:                s.defaultWriteObject();
1389:            }
1390:
1391:            /**
1392:            	Invoke a method in this namespace with the specified args and
1393:            	interpreter reference.  No caller information or call stack is
1394:            	required.  The method will appear as if called externally from Java.
1395:            	<p>
1396:
1397:            	@see bsh.This.invokeMethod( 
1398:            		String methodName, Object [] args, Interpreter interpreter, 
1399:            		CallStack callstack, SimpleNode callerInfo, boolean )
1400:             */
1401:            public Object invokeMethod(String methodName, Object[] args,
1402:                    Interpreter interpreter) throws EvalError {
1403:                return invokeMethod(methodName, args, interpreter, null, null);
1404:            }
1405:
1406:            /**
1407:            	This method simply delegates to This.invokeMethod();
1408:            	<p>
1409:            	@see bsh.This.invokeMethod( 
1410:            		String methodName, Object [] args, Interpreter interpreter, 
1411:            		CallStack callstack, SimpleNode callerInfo )
1412:             */
1413:            public Object invokeMethod(String methodName, Object[] args,
1414:                    Interpreter interpreter, CallStack callstack,
1415:                    SimpleNode callerInfo) throws EvalError {
1416:                return getThis(interpreter)
1417:                        .invokeMethod(methodName, args, interpreter, callstack,
1418:                                callerInfo, false/*declaredOnly*/);
1419:            }
1420:
1421:            /**
1422:            	Clear all cached classes and names
1423:             */
1424:            public void classLoaderChanged() {
1425:                nameSpaceChanged();
1426:            }
1427:
1428:            /**
1429:            	Clear all cached classes and names
1430:             */
1431:            public void nameSpaceChanged() {
1432:                classCache = null;
1433:                names = null;
1434:            }
1435:
1436:            /**
1437:            	Import standard packages.  Currently:
1438:            	<pre>
1439:            		importClass("bsh.EvalError");
1440:            		importClass("bsh.Interpreter");
1441:            		importPackage("javax.swing.event");
1442:            		importPackage("javax.swing");
1443:            		importPackage("java.awt.event");
1444:            		importPackage("java.awt");
1445:            		importPackage("java.net");
1446:            		importPackage("java.util");
1447:            		importPackage("java.io");
1448:            		importPackage("java.lang");
1449:            		importCommands("/bsh/commands");
1450:            	</pre>
1451:             */
1452:            public void loadDefaultImports() {
1453:                /**
1454:                	Note: the resolver looks through these in reverse order, per
1455:                	precedence rules...  so for max efficiency put the most common
1456:                	ones later.
1457:                 */
1458:                importClass("bsh.EvalError");
1459:                importClass("bsh.Interpreter");
1460:                importPackage("javax.swing.event");
1461:                importPackage("javax.swing");
1462:                importPackage("java.awt.event");
1463:                importPackage("java.awt");
1464:                importPackage("java.net");
1465:                importPackage("java.util");
1466:                importPackage("java.io");
1467:                importPackage("java.lang");
1468:                importCommands("/bsh/commands");
1469:            }
1470:
1471:            /**
1472:            	This is the factory for Name objects which resolve names within
1473:            	this namespace (e.g. toObject(), toClass(), toLHS()).
1474:            	<p>
1475:
1476:            	This was intended to support name resolver caching, allowing 
1477:            	Name objects to cache info about the resolution of names for 
1478:            	performance reasons.  However this not proven useful yet.  
1479:            	<p>
1480:
1481:            	We'll leave the caching as it will at least minimize Name object
1482:            	creation.
1483:            	<p>
1484:
1485:            	(This method would be called getName() if it weren't already used for 
1486:            	the simple name of the NameSpace)
1487:            	<p>
1488:
1489:            	This method was public for a time, which was a mistake.  
1490:            	Use get() instead.
1491:             */
1492:            Name getNameResolver(String ambigname) {
1493:                if (names == null)
1494:                    names = new Hashtable();
1495:
1496:                Name name = (Name) names.get(ambigname);
1497:
1498:                if (name == null) {
1499:                    name = new Name(this , ambigname);
1500:                    names.put(ambigname, name);
1501:                }
1502:
1503:                return name;
1504:            }
1505:
1506:            public int getInvocationLine() {
1507:                SimpleNode node = getNode();
1508:                if (node != null)
1509:                    return node.getLineNumber();
1510:                else
1511:                    return -1;
1512:            }
1513:
1514:            public String getInvocationText() {
1515:                SimpleNode node = getNode();
1516:                if (node != null)
1517:                    return node.getText();
1518:                else
1519:                    return "<invoked from Java code>";
1520:            }
1521:
1522:            /**
1523:            	This is a helper method for working inside of bsh scripts and commands.
1524:            	In that context it is impossible to see a ClassIdentifier object
1525:            	for what it is.  Attempting to access a method on a ClassIdentifier
1526:            	will look like a static method invocation.  
1527:            	
1528:            	This method is in NameSpace for convenience (you don't have to import
1529:            	bsh.ClassIdentifier to use it );
1530:             */
1531:            public static Class identifierToClass(ClassIdentifier ci) {
1532:                return ci.getTargetClass();
1533:            }
1534:
1535:            /**
1536:            	Clear all variables, methods, and imports from this namespace.
1537:            	If this namespace is the root, it will be reset to the default 
1538:            	imports.
1539:            	@see #loadDefaultImports()
1540:             */
1541:            public void clear() {
1542:                variables = null;
1543:                methods = null;
1544:                importedClasses = null;
1545:                importedPackages = null;
1546:                importedCommands = null;
1547:                importedObjects = null;
1548:                if (parent == null)
1549:                    loadDefaultImports();
1550:                classCache = null;
1551:                names = null;
1552:            }
1553:
1554:            /**
1555:            	Import a compiled Java object's methods and variables into this 
1556:            	namespace.  When no scripted method / command or variable is found
1557:            	locally in this namespace method / fields of the object will be
1558:            	checked.  Objects are checked in the order of import with later imports
1559:            	taking precedence.
1560:            	<p/>
1561:             */
1562:            /*
1563:            	Note: this impor pattern is becoming common... could factor it out into
1564:            	an importedObject Vector class.
1565:             */
1566:            public void importObject(Object obj) {
1567:                if (importedObjects == null)
1568:                    importedObjects = new Vector();
1569:
1570:                // If it exists, remove it and add it at the end (avoid memory leak)
1571:                if (importedObjects.contains(obj))
1572:                    importedObjects.remove(obj);
1573:
1574:                importedObjects.addElement(obj);
1575:                nameSpaceChanged();
1576:
1577:            }
1578:
1579:            /**
1580:             */
1581:            public void importStatic(Class clas) {
1582:                if (importedStatic == null)
1583:                    importedStatic = new Vector();
1584:
1585:                // If it exists, remove it and add it at the end (avoid memory leak)
1586:                if (importedStatic.contains(clas))
1587:                    importedStatic.remove(clas);
1588:
1589:                importedStatic.addElement(clas);
1590:                nameSpaceChanged();
1591:            }
1592:
1593:            /**
1594:            	Set the package name for classes defined in this namespace.
1595:            	Subsequent sets override the package.
1596:             */
1597:            void setPackage(String packageName) {
1598:                this .packageName = packageName;
1599:            }
1600:
1601:            String getPackage() {
1602:                if (packageName != null)
1603:                    return packageName;
1604:
1605:                if (parent != null)
1606:                    return parent.getPackage();
1607:
1608:                return null;
1609:            }
1610:
1611:            /**
1612:             * If a writable property exists for the given name, set it and return true,
1613:             * otherwise do nothing and return false.
1614:             */
1615:            boolean attemptSetPropertyValue(String propName, Object value,
1616:                    Interpreter interp) throws UtilEvalError {
1617:
1618:                String accessorName = Reflect.accessorName("set", propName);
1619:
1620:                Class[] classArray = new Class[] { value == null ? null : value
1621:                        .getClass() };
1622:
1623:                BshMethod m = getMethod(accessorName, classArray);
1624:
1625:                if (m != null) {
1626:                    try {
1627:                        invokeMethod(accessorName, new Object[] { value },
1628:                                interp);
1629:                        // m.invoke(new Object[] {value}, interp);
1630:                        return true;
1631:                    } catch (EvalError ee) {
1632:                        throw new UtilEvalError(
1633:                                "'This' property accessor threw exception: "
1634:                                        + ee.getMessage());
1635:                    }
1636:                }
1637:
1638:                return false;
1639:            }
1640:
1641:            /**
1642:             * Get a property from a scripted object or Primitive.VOID if no such
1643:             * property exists.
1644:             * @throws UtilEvalError 
1645:             * @throws UtilEvalError 
1646:             */
1647:            Object getPropertyValue(String propName, Interpreter interp)
1648:                    throws UtilEvalError {
1649:
1650:                String accessorName = Reflect.accessorName("get", propName);
1651:                Class[] classArray = new Class[0];
1652:
1653:                BshMethod m = getMethod(accessorName, classArray);
1654:
1655:                try {
1656:                    if (m != null)
1657:                        return m.invoke((Object[]) null, interp);
1658:
1659:                    accessorName = Reflect.accessorName("is", propName);
1660:                    m = getMethod(accessorName, classArray);
1661:                    if (m != null)
1662:                        return m.invoke((Object[]) null, interp);
1663:
1664:                    return Primitive.VOID;
1665:                } catch (EvalError ee) {
1666:                    throw new UtilEvalError(
1667:                            "'This' property accessor threw exception: "
1668:                                    + ee.getMessage());
1669:                }
1670:            }
1671:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.