001: /*
002: * Copyright 2004,2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.bsf;
018:
019: import java.beans.PropertyChangeSupport;
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.net.URL;
023: import java.security.AccessController;
024: import java.security.PrivilegedActionException;
025: import java.security.PrivilegedExceptionAction;
026: import java.util.Enumeration;
027: import java.util.Hashtable;
028: import java.util.Iterator;
029: import java.util.MissingResourceException;
030: import java.util.NoSuchElementException;
031: import java.util.Properties;
032: import java.util.StringTokenizer;
033: import java.util.Vector;
034:
035: import org.apache.bsf.util.CodeBuffer;
036: import org.apache.bsf.util.ObjectRegistry;
037: import org.apache.commons.logging.Log;
038: import org.apache.commons.logging.LogFactory;
039:
040: /**
041: * This class is the entry point to the bean scripting framework. An
042: * application wishing to integrate scripting to a Java app would
043: * place an instance of a BSFManager in their code and use its services
044: * to register the beans they want to make available for scripting,
045: * load scripting engines, and run scripts.
046: * <p>
047: * BSFManager serves as the registry of available scripting engines
048: * as well. Loading and unloading of scripting engines is
049: * supported as well. Each BSFManager loads one engine per language.
050: * Several BSFManagers can be created per JVM.
051: *
052: * @author Sanjiva Weerawarana
053: * @author Matthew J. Duftler
054: * @author Sam Ruby
055: * @author Olivier Gruber (added original debugging support)
056: * @author Don Schwarz (added support for registering languages dynamically)
057: */
058: public class BSFManager {
059: // version string is in the form "abc.yyyymmdd" where
060: // "abc" represents a dewey decimal number (three levels, each between 0 and 9),
061: // and "yyyy" a four digit year, "mm" a two digit month, "dd" a two digit day.
062: //
063: // Example: "240.20060925" stands for: BSF version "2.4.0" as of "2006-09-25"
064: protected static String version = "240.20061006";
065:
066: // table of registered scripting engines
067: protected static Hashtable registeredEngines = new Hashtable();
068:
069: // mapping of file extensions to languages
070: protected static Hashtable extn2Lang = new Hashtable();
071:
072: // table of scripting engine instances created by this manager.
073: // only one instance of a given language engine is created by a single
074: // manager instance.
075: protected Hashtable loadedEngines = new Hashtable();
076:
077: // table of registered beans for use by scripting engines.
078: protected ObjectRegistry objectRegistry = new ObjectRegistry();
079:
080: // prop change support containing loaded engines to inform when any
081: // of my interesting properties change
082: protected PropertyChangeSupport pcs;
083:
084: // the class loader to use if a class loader is needed. Default is
085: // he who loaded me (which may be null in which case its Class.forName).
086: // protected ClassLoader classLoader = getClass().getClassLoader();
087: protected ClassLoader classLoader = Thread.currentThread()
088: .getContextClassLoader(); // rgf, 2006-01-05
089:
090: // temporary directory to use to dump temporary files into. Note that
091: // if class files are dropped here then unless this dir is in the
092: // classpath or unless the classloader knows to look here, the classes
093: // will not be found.
094: protected String tempDir = ".";
095:
096: // classpath used by those that need a classpath
097: protected String classPath;
098:
099: // stores BSFDeclaredBeans representing objects
100: // introduced by a client of BSFManager
101: protected Vector declaredBeans = new Vector();
102:
103: private Log logger = LogFactory.getLog(this .getClass().getName());
104:
105: //////////////////////////////////////////////////////////////////////
106: //
107: // pre-register engines that BSF supports off the shelf
108: //
109: //////////////////////////////////////////////////////////////////////
110:
111: static {
112: try {
113: Enumeration e = BSFManager.class
114: .getClassLoader()
115: .getResources("org/apache/bsf/Languages.properties");
116: while (e.hasMoreElements()) {
117: URL url = (URL) e.nextElement();
118: InputStream is = url.openStream();
119:
120: Properties p = new Properties();
121: p.load(is);
122:
123: for (Enumeration keys = p.propertyNames(); keys
124: .hasMoreElements();) {
125:
126: String key = (String) keys.nextElement();
127: String value = p.getProperty(key);
128: String className = value.substring(0, value
129: .indexOf(","));
130:
131: // get the extensions for this language
132: String exts = value.substring(
133: value.indexOf(",") + 1, value.length());
134: StringTokenizer st = new StringTokenizer(exts, "|");
135: String[] extensions = new String[st.countTokens()];
136: for (int i = 0; st.hasMoreTokens(); i++) {
137: extensions[i] = ((String) st.nextToken())
138: .trim();
139: }
140:
141: registerScriptingEngine(key, className, extensions);
142: }
143: }
144: } catch (IOException ex) {
145:
146: ex.printStackTrace();
147: System.err.println("Error reading Languages file " + ex);
148: } catch (NoSuchElementException nsee) {
149:
150: nsee.printStackTrace();
151: System.err
152: .println("Syntax error in Languages resource bundle");
153: } catch (MissingResourceException mre) {
154:
155: mre.printStackTrace();
156: System.err.println("Initialization error: "
157: + mre.toString());
158: }
159: }
160:
161: public BSFManager() {
162: pcs = new PropertyChangeSupport(this );
163: }
164:
165: /** Returns the version string of BSF.
166: *
167: * @return version string in the form "abc.yyyymmdd" where
168: "abc" represents a dewey decimal number (three levels, each between 0 and 9), and
169: "yyyy" a four digit year, "mm" a two digit month,
170: "dd" a two digit day.
171: *
172: <br>Example: "<code>240.20061006</code>"
173: stands for: BSF version <code>2.4.0</code> as of <code>2006-10-06</code>.
174: *
175: *
176: * @since 2006-01-17
177: */
178: public static String getVersion() {
179:
180: return version;
181: }
182:
183: /**
184: * Apply the given anonymous function of the given language to the given
185: * parameters and return the resulting value.
186: *
187: * @param lang language identifier
188: * @param source (context info) the source of this expression
189: (e.g., filename)
190: * @param lineNo (context info) the line number in source for expr
191: * @param columnNo (context info) the column number in source for expr
192: * @param funcBody the multi-line, value returning script to evaluate
193: * @param paramNames the names of the parameters above assumes
194: * @param arguments values of the above parameters
195: *
196: * @exception BSFException if anything goes wrong while running the script
197: */
198: public Object apply(String lang, String source, int lineNo,
199: int columnNo, Object funcBody, Vector paramNames,
200: Vector arguments) throws BSFException {
201: logger.debug("BSFManager:apply");
202:
203: final BSFEngine e = loadScriptingEngine(lang);
204: final String sourcef = source;
205: final int lineNof = lineNo, columnNof = columnNo;
206: final Object funcBodyf = funcBody;
207: final Vector paramNamesf = paramNames;
208: final Vector argumentsf = arguments;
209: Object result = null;
210:
211: try {
212: final Object resultf = AccessController
213: .doPrivileged(new PrivilegedExceptionAction() {
214: public Object run() throws Exception {
215: return e.apply(sourcef, lineNof, columnNof,
216: funcBodyf, paramNamesf, argumentsf);
217: }
218: });
219: result = resultf;
220: } catch (PrivilegedActionException prive) {
221:
222: logger.error("Exception: ", prive);
223: throw (BSFException) prive.getException();
224: }
225:
226: return result;
227: }
228:
229: /**
230: * Compile the application of the given anonymous function of the given
231: * language to the given parameters into the given <tt>CodeBuffer</tt>.
232: *
233: * @param lang language identifier
234: * @param source (context info) the source of this expression
235: (e.g., filename)
236: * @param lineNo (context info) the line number in source for expr
237: * @param columnNo (context info) the column number in source for expr
238: * @param funcBody the multi-line, value returning script to evaluate
239: * @param paramNames the names of the parameters above assumes
240: * @param arguments values of the above parameters
241: * @param cb code buffer to compile into
242: *
243: * @exception BSFException if anything goes wrong while running the script
244: */
245: public void compileApply(String lang, String source, int lineNo,
246: int columnNo, Object funcBody, Vector paramNames,
247: Vector arguments, CodeBuffer cb) throws BSFException {
248: logger.debug("BSFManager:compileApply");
249:
250: final BSFEngine e = loadScriptingEngine(lang);
251: final String sourcef = source;
252: final int lineNof = lineNo, columnNof = columnNo;
253: final Object funcBodyf = funcBody;
254: final Vector paramNamesf = paramNames;
255: final Vector argumentsf = arguments;
256: final CodeBuffer cbf = cb;
257:
258: try {
259: AccessController
260: .doPrivileged(new PrivilegedExceptionAction() {
261: public Object run() throws Exception {
262: e.compileApply(sourcef, lineNof, columnNof,
263: funcBodyf, paramNamesf, argumentsf,
264: cbf);
265: return null;
266: }
267: });
268: } catch (PrivilegedActionException prive) {
269:
270: logger.error("Exception :", prive);
271: throw (BSFException) prive.getException();
272: }
273: }
274:
275: /**
276: * Compile the given expression of the given language into the given
277: * <tt>CodeBuffer</tt>.
278: *
279: * @param lang language identifier
280: * @param source (context info) the source of this expression
281: (e.g., filename)
282: * @param lineNo (context info) the line number in source for expr
283: * @param columnNo (context info) the column number in source for expr
284: * @param expr the expression to compile
285: * @param cb code buffer to compile into
286: *
287: * @exception BSFException if any error while compiling the expression
288: */
289: public void compileExpr(String lang, String source, int lineNo,
290: int columnNo, Object expr, CodeBuffer cb)
291: throws BSFException {
292: logger.debug("BSFManager:compileExpr");
293:
294: final BSFEngine e = loadScriptingEngine(lang);
295: final String sourcef = source;
296: final int lineNof = lineNo, columnNof = columnNo;
297: final Object exprf = expr;
298: final CodeBuffer cbf = cb;
299:
300: try {
301: AccessController
302: .doPrivileged(new PrivilegedExceptionAction() {
303: public Object run() throws Exception {
304: e.compileExpr(sourcef, lineNof, columnNof,
305: exprf, cbf);
306: return null;
307: }
308: });
309: } catch (PrivilegedActionException prive) {
310:
311: logger.error("Exception :", prive);
312: throw (BSFException) prive.getException();
313: }
314: }
315:
316: /**
317: * Compile the given script of the given language into the given
318: * <tt>CodeBuffer</tt>.
319: *
320: * @param lang language identifier
321: * @param source (context info) the source of this script
322: (e.g., filename)
323: * @param lineNo (context info) the line number in source for script
324: * @param columnNo (context info) the column number in source for script
325: * @param script the script to compile
326: * @param cb code buffer to compile into
327: *
328: * @exception BSFException if any error while compiling the script
329: */
330: public void compileScript(String lang, String source, int lineNo,
331: int columnNo, Object script, CodeBuffer cb)
332: throws BSFException {
333: logger.debug("BSFManager:compileScript");
334:
335: final BSFEngine e = loadScriptingEngine(lang);
336: final String sourcef = source;
337: final int lineNof = lineNo, columnNof = columnNo;
338: final Object scriptf = script;
339: final CodeBuffer cbf = cb;
340:
341: try {
342: AccessController
343: .doPrivileged(new PrivilegedExceptionAction() {
344: public Object run() throws Exception {
345: e.compileScript(sourcef, lineNof,
346: columnNof, scriptf, cbf);
347: return null;
348: }
349: });
350: } catch (PrivilegedActionException prive) {
351:
352: logger.error("Exception :", prive);
353: throw (BSFException) prive.getException();
354: }
355: }
356:
357: /**
358: * Declare a bean. The difference between declaring and registering
359: * is that engines are spsed to make declared beans "pre-available"
360: * in the scripts as far as possible. That is, if a script author
361: * needs a registered bean, he needs to look it up in some way. However
362: * if he needs a declared bean, the language has the responsibility to
363: * make those beans avaialable "automatically."
364: * <p>
365: * When a bean is declared it is automatically registered as well
366: * so that any declared bean can be gotton to by looking it up as well.
367: * <p>
368: * If any of the languages that are already running in this manager
369: * says they don't like this (by throwing an exception) then this
370: * method will simply quit with that exception. That is, any engines
371: * that come after than in the engine enumeration will not even be
372: * told about this new bean.
373: * <p>
374: * So, in general its best to declare beans before the manager has
375: * been asked to load any engines because then the user can be informed
376: * when an engine rejects it. Also, its much more likely that an engine
377: * can declare a bean at start time than it can at any time.
378: *
379: * @param beanName name to declare bean as
380: * @param bean the bean that's being declared
381: * @param type the type to represent the bean as
382: *
383: * @exception BSFException if any of the languages that are already
384: * running decides to throw an exception when asked to
385: * declare this bean.
386: */
387: public void declareBean(String beanName, Object bean, Class type)
388: throws BSFException {
389: logger.debug("BSFManager:declareBean");
390:
391: registerBean(beanName, bean);
392:
393: BSFDeclaredBean tempBean = new BSFDeclaredBean(beanName, bean,
394: type);
395: declaredBeans.addElement(tempBean);
396:
397: Enumeration enginesEnum = loadedEngines.elements();
398: BSFEngine engine;
399: while (enginesEnum.hasMoreElements()) {
400: engine = (BSFEngine) enginesEnum.nextElement();
401: engine.declareBean(tempBean);
402: }
403: }
404:
405: /**
406: * Evaluate the given expression of the given language and return the
407: * resulting value.
408: *
409: * @param lang language identifier
410: * @param source (context info) the source of this expression
411: (e.g., filename)
412: * @param lineNo (context info) the line number in source for expr
413: * @param columnNo (context info) the column number in source for expr
414: * @param expr the expression to evaluate
415: *
416: * @exception BSFException if anything goes wrong while running the script
417: */
418: public Object eval(String lang, String source, int lineNo,
419: int columnNo, Object expr) throws BSFException {
420: logger.debug("BSFManager:eval");
421:
422: final BSFEngine e = loadScriptingEngine(lang);
423: final String sourcef = source;
424: final int lineNof = lineNo, columnNof = columnNo;
425: final Object exprf = expr;
426: Object result = null;
427:
428: try {
429: final Object resultf = AccessController
430: .doPrivileged(new PrivilegedExceptionAction() {
431: public Object run() throws Exception {
432: return e.eval(sourcef, lineNof, columnNof,
433: exprf);
434: }
435: });
436: result = resultf;
437: } catch (PrivilegedActionException prive) {
438:
439: logger.error("Exception: ", prive);
440: throw (BSFException) prive.getException();
441: }
442:
443: return result;
444: }
445:
446: //////////////////////////////////////////////////////////////////////
447: //
448: // Convenience functions for exec'ing and eval'ing scripts directly
449: // without loading and dealing with engines etc..
450: //
451: //////////////////////////////////////////////////////////////////////
452:
453: /**
454: * Execute the given script of the given language.
455: *
456: * @param lang language identifier
457: * @param source (context info) the source of this expression
458: (e.g., filename)
459: * @param lineNo (context info) the line number in source for expr
460: * @param columnNo (context info) the column number in source for expr
461: * @param script the script to execute
462: *
463: * @exception BSFException if anything goes wrong while running the script
464: */
465: public void exec(String lang, String source, int lineNo,
466: int columnNo, Object script) throws BSFException {
467: logger.debug("BSFManager:exec");
468:
469: final BSFEngine e = loadScriptingEngine(lang);
470: final String sourcef = source;
471: final int lineNof = lineNo, columnNof = columnNo;
472: final Object scriptf = script;
473:
474: try {
475: AccessController
476: .doPrivileged(new PrivilegedExceptionAction() {
477: public Object run() throws Exception {
478: e
479: .exec(sourcef, lineNof, columnNof,
480: scriptf);
481: return null;
482: }
483: });
484: } catch (PrivilegedActionException prive) {
485:
486: logger.error("Exception :", prive);
487: throw (BSFException) prive.getException();
488: }
489: }
490:
491: /**
492: * Execute the given script of the given language, attempting to
493: * emulate an interactive session w/ the language.
494: *
495: * @param lang language identifier
496: * @param source (context info) the source of this expression
497: * (e.g., filename)
498: * @param lineNo (context info) the line number in source for expr
499: * @param columnNo (context info) the column number in source for expr
500: * @param script the script to execute
501: *
502: * @exception BSFException if anything goes wrong while running the script
503: */
504: public void iexec(String lang, String source, int lineNo,
505: int columnNo, Object script) throws BSFException {
506: logger.debug("BSFManager:iexec");
507:
508: final BSFEngine e = loadScriptingEngine(lang);
509: final String sourcef = source;
510: final int lineNof = lineNo, columnNof = columnNo;
511: final Object scriptf = script;
512:
513: try {
514: AccessController
515: .doPrivileged(new PrivilegedExceptionAction() {
516: public Object run() throws Exception {
517: e.iexec(sourcef, lineNof, columnNof,
518: scriptf);
519: return null;
520: }
521: });
522: } catch (PrivilegedActionException prive) {
523:
524: logger.error("Exception :", prive);
525: throw (BSFException) prive.getException();
526: }
527: }
528:
529: /**
530: * Get classLoader
531: */
532: public ClassLoader getClassLoader() {
533: logger.debug("BSFManager:getClassLoader");
534: return classLoader;
535: }
536:
537: /**
538: * Get classPath
539: */
540: public String getClassPath() {
541: logger.debug("BSFManager:getClassPath");
542: if (classPath == null) {
543: try {
544: classPath = System.getProperty("java.class.path");
545: } catch (Throwable t) {
546:
547: logger.debug("Exception :", t);
548: // prolly a security exception .. so no can do
549: }
550: }
551: return classPath;
552: }
553:
554: /**
555: * Determine the language of a script file by looking at the file
556: * extension.
557: *
558: * @param fileName the name of the file
559: *
560: * @return the scripting language the file is in if the file extension
561: * is known to me (must have been registered via
562: * registerScriptingEngine).
563: *
564: * @exception BSFException if file's extension is unknown.
565: */
566: public static String getLangFromFilename(String fileName)
567: throws BSFException {
568: int dotIndex = fileName.lastIndexOf(".");
569:
570: if (dotIndex != -1) {
571: String extn = fileName.substring(dotIndex + 1);
572: String langval = (String) extn2Lang.get(extn);
573: String lang = null;
574: int index, loops = 0;
575:
576: if (langval != null) {
577: while ((index = langval.indexOf(":", 0)) != -1) {
578: // Great. Multiple language engines registered
579: // for this extension.
580: // Try to find first one that is in our classpath.
581: lang = langval.substring(0, index);
582: langval = langval.substring(index + 1);
583: loops++;
584:
585: // Test to see if in classpath
586: try {
587: String engineName = (String) registeredEngines
588: .get(lang);
589: Class.forName(engineName);
590: } catch (ClassNotFoundException cnfe) {
591:
592: // Bummer.
593: lang = langval;
594: continue;
595: }
596:
597: // Got past that? Good.
598: break;
599: }
600: if (loops == 0) {
601: lang = langval;
602: }
603: }
604:
605: if (lang != null && lang != "") {
606: return lang;
607: }
608: }
609: throw new BSFException(BSFException.REASON_OTHER_ERROR,
610: "file extension missing or unknown: "
611: + "unable to determine language for '"
612: + fileName + "'");
613: }
614:
615: /**
616: * Return the current object registry of the manager.
617: *
618: * @return the current registry.
619: */
620: public ObjectRegistry getObjectRegistry() {
621: return objectRegistry;
622: }
623:
624: /**
625: * Get tempDir
626: */
627: public String getTempDir() {
628: return tempDir;
629: }
630:
631: /**
632: * Determine whether a language is registered.
633: *
634: * @param lang string identifying a language
635: *
636: * @return true iff it is
637: */
638: public static boolean isLanguageRegistered(String lang) {
639: return (registeredEngines.get(lang) != null);
640: }
641:
642: //////////////////////////////////////////////////////////////////////
643: //
644: // Bean scripting framework services
645: //
646: //////////////////////////////////////////////////////////////////////
647:
648: /**
649: * Load a scripting engine based on the lang string identifying it.
650: *
651: * @param lang string identifying language
652: * @exception BSFException if the language is unknown (i.e., if it
653: * has not been registered) with a reason of
654: * REASON_UNKNOWN_LANGUAGE. If the language is known but
655: * if the interface can't be created for some reason, then
656: * the reason is set to REASON_OTHER_ERROR and the actual
657: * exception is passed on as well.
658: */
659: public BSFEngine loadScriptingEngine(String lang)
660: throws BSFException {
661: logger.debug("BSFManager:loadScriptingEngine");
662:
663: // if its already loaded return that
664: BSFEngine eng = (BSFEngine) loadedEngines.get(lang);
665: if (eng != null) {
666: return eng;
667: }
668:
669: // is it a registered language?
670: String engineClassName = (String) registeredEngines.get(lang);
671: if (engineClassName == null) {
672: logger.error("unsupported language: " + lang);
673: throw new BSFException(
674: BSFException.REASON_UNKNOWN_LANGUAGE,
675: "unsupported language: " + lang);
676: }
677:
678: // create the engine and initialize it. if anything goes wrong
679: // except.
680: try {
681: Class engineClass = (classLoader == null) ? Class
682: .forName(engineClassName) : classLoader
683: .loadClass(engineClassName);
684: final BSFEngine engf = (BSFEngine) engineClass
685: .newInstance();
686: final BSFManager this f = this ;
687: final String langf = lang;
688: final Vector dbf = declaredBeans;
689: AccessController
690: .doPrivileged(new PrivilegedExceptionAction() {
691: public Object run() throws Exception {
692: engf.initialize(this f, langf, dbf);
693: return null;
694: }
695: });
696: eng = engf;
697: loadedEngines.put(lang, eng);
698: pcs.addPropertyChangeListener(eng);
699: return eng;
700: } catch (PrivilegedActionException prive) {
701:
702: logger.error("Exception :", prive);
703: throw (BSFException) prive.getException();
704: } catch (Throwable t) {
705:
706: logger.error("Exception :", t);
707: throw new BSFException(BSFException.REASON_OTHER_ERROR,
708: "unable to load language: " + lang, t);
709: }
710: }
711:
712: /**
713: * return a handle to a bean registered in the bean registry by the
714: * application or a scripting engine. Returns null if bean is not found.
715: *
716: * @param beanName name of bean to look up
717: *
718: * @return the bean if its found or null
719: */
720: public Object lookupBean(String beanName) {
721: logger.debug("BSFManager:lookupBean");
722:
723: try {
724: return ((BSFDeclaredBean) objectRegistry.lookup(beanName)).bean;
725: } catch (IllegalArgumentException e) {
726:
727: logger.debug("Exception :", e);
728: return null;
729: }
730: }
731:
732: /**
733: * Registering a bean allows a scripting engine or the application to
734: * access that bean by name and to manipulate it.
735: *
736: * @param beanName name to register under
737: * @param bean the bean to register
738: */
739: public void registerBean(String beanName, Object bean) {
740: logger.debug("BSFManager:registerBean");
741:
742: BSFDeclaredBean tempBean;
743:
744: if (bean == null) {
745: tempBean = new BSFDeclaredBean(beanName, null, null);
746: } else {
747:
748: tempBean = new BSFDeclaredBean(beanName, bean, bean
749: .getClass());
750: }
751: objectRegistry.register(beanName, tempBean);
752: }
753:
754: /**
755: * Register a scripting engine in the static registry of the
756: * BSFManager.
757: *
758: * @param lang string identifying language
759: * @param engineClassName fully qualified name of the class interfacing
760: * the language to BSF.
761: * @param extensions array of file extensions that should be mapped to
762: * this language type. may be null.
763: */
764: public static void registerScriptingEngine(String lang,
765: String engineClassName, String[] extensions) {
766: registeredEngines.put(lang, engineClassName);
767: if (extensions != null) {
768: for (int i = 0; i < extensions.length; i++) {
769: String langstr = (String) extn2Lang.get(extensions[i]);
770: langstr = (langstr == null) ? lang : lang + ":"
771: + langstr;
772: extn2Lang.put(extensions[i], langstr);
773: }
774: }
775: }
776:
777: /**
778: * Set the class loader for those that need to use it. Default is he
779: * who loaded me or null (i.e., its Class.forName).
780: *
781: * @param classLoader the class loader to use.
782: */
783: public void setClassLoader(ClassLoader classLoader) {
784: logger.debug("BSFManager:setClassLoader");
785:
786: pcs.firePropertyChange("classLoader", this .classLoader,
787: classLoader);
788: this .classLoader = classLoader;
789: }
790:
791: /**
792: * Set the classpath for those that need to use it. Default is the value
793: * of the java.class.path property.
794: *
795: * @param classPath the classpath to use
796: */
797: public void setClassPath(String classPath) {
798: logger.debug("BSFManager:setClassPath");
799:
800: pcs.firePropertyChange("classPath", this .classPath, classPath);
801: this .classPath = classPath;
802: }
803:
804: /**
805: * Set the object registry used by this manager. By default a new
806: * one is created when the manager is new'ed and this overwrites
807: * that one.
808: *
809: * @param objectRegistry the registry to use
810: */
811: public void setObjectRegistry(ObjectRegistry objectRegistry) {
812: logger.debug("BSFManager:setObjectRegistry");
813:
814: this .objectRegistry = objectRegistry;
815: }
816:
817: /**
818: * Temporary directory to put stuff into (for those who need to). Note
819: * that unless this directory is in the classpath or unless the
820: * classloader knows to look in here, any classes here will not
821: * be found! BSFManager provides a service method to load a class
822: * which uses either the classLoader provided by the class loader
823: * property or, if that fails, a class loader which knows to load from
824: * the tempdir to try to load the class. Default value of tempDir
825: * is "." (current working dir).
826: *
827: * @param tempDir the temporary directory
828: */
829: public void setTempDir(String tempDir) {
830: logger.debug("BSFManager:setTempDir");
831:
832: pcs.firePropertyChange("tempDir", this .tempDir, tempDir);
833: this .tempDir = tempDir;
834: }
835:
836: /**
837: * Gracefully terminate all engines
838: */
839: public void terminate() {
840: logger.debug("BSFManager:terminate");
841:
842: Enumeration enginesEnum = loadedEngines.elements();
843: BSFEngine engine;
844: while (enginesEnum.hasMoreElements()) {
845: engine = (BSFEngine) enginesEnum.nextElement();
846: engine.terminate();
847: }
848:
849: loadedEngines = new Hashtable();
850: }
851:
852: /**
853: * Undeclare a previously declared bean. This removes the bean from
854: * the list of declared beans in the manager as well as asks every
855: * running engine to undeclared the bean. As with above, if any
856: * of the engines except when asked to undeclare, this method does
857: * not catch that exception. Quietly returns if the bean is unknown.
858: *
859: * @param beanName name of bean to undeclare
860: *
861: * @exception BSFException if any of the languages that are already
862: * running decides to throw an exception when asked to
863: * undeclare this bean.
864: */
865: public void undeclareBean(String beanName) throws BSFException {
866: logger.debug("BSFManager:undeclareBean");
867:
868: unregisterBean(beanName);
869:
870: BSFDeclaredBean tempBean = null;
871: boolean found = false;
872: for (Iterator i = declaredBeans.iterator(); i.hasNext();) {
873: tempBean = (BSFDeclaredBean) i.next();
874: if (tempBean.name.equals(beanName)) {
875: found = true;
876: break;
877: }
878: }
879:
880: if (found) {
881: declaredBeans.removeElement(tempBean);
882:
883: Enumeration enginesEnum = loadedEngines.elements();
884: while (enginesEnum.hasMoreElements()) {
885: BSFEngine engine = (BSFEngine) enginesEnum
886: .nextElement();
887: engine.undeclareBean(tempBean);
888: }
889: }
890: }
891:
892: /**
893: * Unregister a previously registered bean. Silent if name is not found.
894: *
895: * @param beanName name of bean to unregister
896: */
897: public void unregisterBean(String beanName) {
898: logger.debug("BSFManager:unregisterBean");
899:
900: objectRegistry.unregister(beanName);
901: }
902: }
|