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