Source Code Cross Referenced for ClassManagerImpl.java in  » Scripting » beanshell » bsh » classpath » 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.classpath 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*****************************************************************************
002:         *                                                                           *
003:         *  This file is part of the BeanShell Java Scripting distribution.          *
004:         *  Documentation and updates may be found at http://www.beanshell.org/      *
005:         *                                                                           *
006:         *  Sun Public License Notice:                                               *
007:         *                                                                           *
008:         *  The contents of this file are subject to the Sun Public License Version  *
009:         *  1.0 (the "License"); you may not use this file except in compliance with *
010:         *  the License. A copy of the License is available at http://www.sun.com    * 
011:         *                                                                           *
012:         *  The Original Code is BeanShell. The Initial Developer of the Original    *
013:         *  Code is Pat Niemeyer. Portions created by Pat Niemeyer are Copyright     *
014:         *  (C) 2000.  All Rights Reserved.                                          *
015:         *                                                                           *
016:         *  GNU Public License Notice:                                               *
017:         *                                                                           *
018:         *  Alternatively, the contents of this file may be used under the terms of  *
019:         *  the GNU Lesser General Public License (the "LGPL"), in which case the    *
020:         *  provisions of LGPL are applicable instead of those above. If you wish to *
021:         *  allow use of your version of this file only under the  terms of the LGPL *
022:         *  and not to allow others to use your version of this file under the SPL,  *
023:         *  indicate your decision by deleting the provisions above and replace      *
024:         *  them with the notice and other provisions required by the LGPL.  If you  *
025:         *  do not delete the provisions above, a recipient may use your version of  *
026:         *  this file under either the SPL or the LGPL.                              *
027:         *                                                                           *
028:         *  Patrick Niemeyer (pat@pat.net)                                           *
029:         *  Author of Learning Java, O'Reilly & Associates                           *
030:         *  http://www.pat.net/~pat/                                                 *
031:         *                                                                           *
032:         *****************************************************************************/package bsh.classpath;
033:
034:        import java.net.*;
035:        import java.util.*;
036:        import java.lang.ref.*;
037:        import java.io.IOException;
038:        import java.io.*;
039:        import bsh.classpath.BshClassPath.ClassSource;
040:        import bsh.classpath.BshClassPath.JarClassSource;
041:        import bsh.classpath.BshClassPath.GeneratedClassSource;
042:        import bsh.BshClassManager;
043:        import bsh.ClassPathException;
044:        import bsh.Interpreter; // for debug()
045:        import bsh.UtilEvalError;
046:
047:        /**
048:         <pre>
049:         Manage all classloading in BeanShell.
050:         Allows classpath extension and class file reloading.
051:
052:         This class holds the implementation of the BshClassManager so that it
053:         can be separated from the core package.
054:
055:         This class currently relies on 1.2 for BshClassLoader and weak references.
056:         Is there a workaround for weak refs?  If so we could make this work
057:         with 1.1 by supplying our own classloader code...
058:
059:         See "http://www.beanshell.org/manual/classloading.html" for details
060:         on the bsh classloader architecture.
061:
062:         Bsh has a multi-tiered class loading architecture.  No class loader is
063:         created unless/until a class is generated, the classpath is modified, 
064:         or a class is reloaded.
065:
066:         Note: we may need some synchronization in here
067:
068:         Note on jdk1.2 dependency:
069:
070:         We are forced to use weak references here to accomodate all of the 
071:         fleeting namespace listeners.  (NameSpaces must be informed if the class 
072:         space changes so that they can un-cache names).  I had the interesting 
073:         thought that a way around this would be to implement BeanShell's own 
074:         garbage collector...  Then I came to my senses and said - screw it, 
075:         class re-loading will require 1.2.
076:
077:         ---------------------
078:
079:         Classloading precedence:
080:
081:         in-script evaluated class (scripted class)
082:         in-script added / modified classpath
083:
084:         optionally, external classloader
085:         optionally, thread context classloader
086:
087:         plain Class.forName()
088:         source class (.java file in classpath)
089:
090:         </pre>
091:
092:         */
093:        public class ClassManagerImpl extends BshClassManager {
094:            static final String BSH_PACKAGE = "bsh";
095:            /**
096:            	The classpath of the base loader.  Initially and upon reset() this is
097:            	an empty instance of BshClassPath.  It grows as paths are added or is
098:            	reset when the classpath is explicitly set.  This could also be called
099:            	the "extension" class path, but is not strictly confined to added path
100:            	(could be set arbitrarily by setClassPath())
101:             */
102:            private BshClassPath baseClassPath;
103:            private boolean super Import;
104:
105:            /**
106:            	This is the full blown classpath including baseClassPath (extensions),
107:            	user path, and java bootstrap path (rt.jar)
108:
109:            	This is lazily constructed and further (and more importantly) lazily
110:            	intialized in components because mapping the full path could be
111:            	expensive.
112:
113:            	The full class path is a composite of:
114:            		baseClassPath (user extension) : userClassPath : bootClassPath
115:            	in that order.
116:             */
117:            private BshClassPath fullClassPath;
118:
119:            // ClassPath Change listeners
120:            private Vector listeners = new Vector();
121:            private ReferenceQueue refQueue = new ReferenceQueue();
122:
123:            /**
124:            	This handles extension / modification of the base classpath
125:            	The loader to use where no mapping of reloaded classes exists.
126:
127:            	The baseLoader is initially null meaning no class loader is used.
128:             */
129:            private BshClassLoader baseLoader;
130:
131:            /**
132:            	Map by classname of loaders to use for reloaded classes
133:             */
134:            private Map loaderMap;
135:
136:            /**
137:            	Used by BshClassManager singleton constructor
138:             */
139:            public ClassManagerImpl() {
140:                reset();
141:            }
142:
143:            /**
144:            	@return the class or null
145:             */
146:            public Class classForName(String name) {
147:                // check positive cache
148:                Class c = (Class) absoluteClassCache.get(name);
149:                if (c != null)
150:                    return c;
151:
152:                // check negative cache
153:                if (absoluteNonClasses.get(name) != null) {
154:                    if (Interpreter.DEBUG)
155:                        Interpreter.debug("absoluteNonClass list hit: " + name);
156:                    return null;
157:                }
158:
159:                if (Interpreter.DEBUG)
160:                    Interpreter.debug("Trying to load class: " + name);
161:
162:                // Check explicitly mapped (reloaded) class...
163:                ClassLoader overlayLoader = getLoaderForClass(name);
164:                if (overlayLoader != null) {
165:                    try {
166:                        c = overlayLoader.loadClass(name);
167:                    } catch (Exception e) {
168:                        // used to squeltch this... changed for 1.3
169:                        // see BshClassManager
170:                    } catch (NoClassDefFoundError e2) {
171:                        throw noClassDefFound(name, e2);
172:                    }
173:
174:                    // Should be there since it was explicitly mapped
175:                    // throw an error?
176:                }
177:
178:                // insure that core classes are loaded from the same loader
179:                if (c == null) {
180:                    if (name.startsWith(BSH_PACKAGE))
181:                        try {
182:                            c = Interpreter.class.getClassLoader().loadClass(
183:                                    name);
184:                        } catch (ClassNotFoundException e) {
185:                        }
186:                }
187:
188:                // Check classpath extension / reloaded classes
189:                if (c == null) {
190:                    if (baseLoader != null)
191:                        try {
192:                            c = baseLoader.loadClass(name);
193:                        } catch (ClassNotFoundException e) {
194:                        }
195:                }
196:
197:                // Optionally try external classloader
198:                if (c == null) {
199:                    if (externalClassLoader != null)
200:                        try {
201:                            c = externalClassLoader.loadClass(name);
202:                        } catch (ClassNotFoundException e) {
203:                        }
204:                }
205:
206:                // Optionally try context classloader
207:                // Note that this might be a security violation
208:                // is catching the SecurityException sufficient for all environments?
209:                // or do we need a way to turn this off completely?
210:                if (c == null) {
211:                    try {
212:                        ClassLoader contextClassLoader = Thread.currentThread()
213:                                .getContextClassLoader();
214:                        if (contextClassLoader != null)
215:                            c = Class.forName(name, true, contextClassLoader);
216:                    } catch (ClassNotFoundException e) { // fall through
217:                    } catch (SecurityException e) {
218:                    } // fall through
219:                }
220:
221:                // try plain class forName()
222:                if (c == null)
223:                    try {
224:                        c = plainClassForName(name);
225:                    } catch (ClassNotFoundException e) {
226:                    }
227:
228:                // Try .java source file
229:                if (c == null)
230:                    c = loadSourceClass(name);
231:
232:                // Cache result (or null for not found)
233:                // Note: plainClassForName already caches, so it will be redundant
234:                // in that case, however this process only happens once
235:                cacheClassInfo(name, c);
236:
237:                return c;
238:            }
239:
240:            /**
241:            	Get a resource URL using the BeanShell classpath
242:            	@param path should be an absolute path
243:             */
244:            public URL getResource(String path) {
245:                URL url = null;
246:                if (baseLoader != null)
247:                    // classloader wants no leading slash
248:                    url = baseLoader.getResource(path.substring(1));
249:                if (url == null)
250:                    url = super .getResource(path);
251:                return url;
252:            }
253:
254:            /**
255:            	Get a resource stream using the BeanShell classpath
256:            	@param path should be an absolute path
257:             */
258:            public InputStream getResourceAsStream(String path) {
259:                InputStream in = null;
260:                if (baseLoader != null) {
261:                    // classloader wants no leading slash
262:                    in = baseLoader.getResourceAsStream(path.substring(1));
263:                }
264:                if (in == null) {
265:                    in = super .getResourceAsStream(path);
266:                }
267:                return in;
268:            }
269:
270:            ClassLoader getLoaderForClass(String name) {
271:                return (ClassLoader) loaderMap.get(name);
272:            }
273:
274:            // Classpath mutators
275:
276:            /**
277:             */
278:            public void addClassPath(URL path) throws IOException {
279:                if (baseLoader == null)
280:                    setClassPath(new URL[] { path });
281:                else {
282:                    // opportunity here for listener in classpath
283:                    baseLoader.addURL(path);
284:                    baseClassPath.add(path);
285:                    classLoaderChanged();
286:                }
287:            }
288:
289:            /**
290:            	Clear all classloading behavior and class caches and reset to 
291:            	initial state.
292:             */
293:            public void reset() {
294:                baseClassPath = new BshClassPath("baseClassPath");
295:                baseLoader = null;
296:                loaderMap = new HashMap();
297:                classLoaderChanged(); // calls clearCaches() for us.
298:            }
299:
300:            /**
301:            	Set a new base classpath and create a new base classloader.
302:            	This means all types change. 
303:             */
304:            public void setClassPath(URL[] cp) {
305:                baseClassPath.setPath(cp);
306:                initBaseLoader();
307:                loaderMap = new HashMap();
308:                classLoaderChanged();
309:            }
310:
311:            /**
312:            	Overlay the entire path with a new class loader.
313:            	Set the base path to the user path + base path.
314:
315:            	No point in including the boot class path (can't reload thos).
316:             */
317:            public void reloadAllClasses() throws ClassPathException {
318:                BshClassPath bcp = new BshClassPath("temp");
319:                bcp.addComponent(baseClassPath);
320:                bcp.addComponent(BshClassPath.getUserClassPath());
321:                setClassPath(bcp.getPathComponents());
322:            }
323:
324:            /**
325:            	init the baseLoader from the baseClassPath
326:             */
327:            private void initBaseLoader() {
328:                baseLoader = new BshClassLoader(this , baseClassPath);
329:            }
330:
331:            // class reloading
332:
333:            /**
334:            	Reloading classes means creating a new classloader and using it
335:            	whenever we are asked for classes in the appropriate space.
336:            	For this we use a DiscreteFilesClassLoader
337:             */
338:            public void reloadClasses(String[] classNames)
339:                    throws ClassPathException {
340:                // validate that it is a class here?
341:
342:                // init base class loader if there is none...
343:                if (baseLoader == null)
344:                    initBaseLoader();
345:
346:                DiscreteFilesClassLoader.ClassSourceMap map = new DiscreteFilesClassLoader.ClassSourceMap();
347:
348:                for (int i = 0; i < classNames.length; i++) {
349:                    String name = classNames[i];
350:
351:                    // look in baseLoader class path 
352:                    ClassSource classSource = baseClassPath
353:                            .getClassSource(name);
354:
355:                    // look in user class path 
356:                    if (classSource == null) {
357:                        BshClassPath.getUserClassPath().insureInitialized();
358:                        classSource = BshClassPath.getUserClassPath()
359:                                .getClassSource(name);
360:                    }
361:
362:                    // No point in checking boot class path, can't reload those.
363:                    // else we could have used fullClassPath above.
364:
365:                    if (classSource == null)
366:                        throw new ClassPathException(
367:                                "Nothing known about class: " + name);
368:
369:                    // JarClassSource is not working... just need to implement it's
370:                    // getCode() method or, if we decide to, allow the BshClassManager
371:                    // to handle it... since it is a URLClassLoader and can handle JARs
372:                    if (classSource instanceof  JarClassSource)
373:                        throw new ClassPathException("Cannot reload class: "
374:                                + name + " from source: " + classSource);
375:
376:                    map.put(name, classSource);
377:                }
378:
379:                // Create classloader for the set of classes
380:                ClassLoader cl = new DiscreteFilesClassLoader(this , map);
381:
382:                // map those classes the loader in the overlay map
383:                Iterator it = map.keySet().iterator();
384:                while (it.hasNext())
385:                    loaderMap.put((String) it.next(), cl);
386:
387:                classLoaderChanged();
388:            }
389:
390:            /**
391:            	Reload all classes in the specified package: e.g. "com.sun.tools"
392:
393:            	The special package name "<unpackaged>" can be used to refer 
394:            	to unpackaged classes.
395:             */
396:            public void reloadPackage(String pack) throws ClassPathException {
397:                Collection classes = baseClassPath.getClassesForPackage(pack);
398:
399:                if (classes == null)
400:                    classes = BshClassPath.getUserClassPath()
401:                            .getClassesForPackage(pack);
402:
403:                // no point in checking boot class path, can't reload those
404:
405:                if (classes == null)
406:                    throw new ClassPathException(
407:                            "No classes found for package: " + pack);
408:
409:                reloadClasses((String[]) classes.toArray(new String[0]));
410:            }
411:
412:            /**
413:            	Unimplemented
414:            	For this we'd have to store a map by location as well as name...
415:
416:            public void reloadPathComponent( URL pc ) throws ClassPathException {
417:            	throw new ClassPathException("Unimplemented!");
418:            }
419:             */
420:
421:            // end reloading
422:            /**
423:            	Get the full blown classpath.
424:             */
425:            public BshClassPath getClassPath() throws ClassPathException {
426:                if (fullClassPath != null)
427:                    return fullClassPath;
428:
429:                fullClassPath = new BshClassPath("BeanShell Full Class Path");
430:                fullClassPath.addComponent(BshClassPath.getUserClassPath());
431:                try {
432:                    fullClassPath.addComponent(BshClassPath.getBootClassPath());
433:                } catch (ClassPathException e) {
434:                    System.err.println("Warning: can't get boot class path");
435:                }
436:                fullClassPath.addComponent(baseClassPath);
437:
438:                return fullClassPath;
439:            }
440:
441:            /**
442:            	Support for "import *;"
443:            	Hide details in here as opposed to NameSpace.
444:             */
445:            public void doSuperImport() throws UtilEvalError {
446:                // Should we prevent it from happening twice?
447:
448:                try {
449:                    getClassPath().insureInitialized();
450:                    // prime the lookup table
451:                    getClassNameByUnqName("");
452:
453:                    // always true now
454:                    //getClassPath().setNameCompletionIncludeUnqNames(true);
455:
456:                } catch (ClassPathException e) {
457:                    throw new UtilEvalError("Error importing classpath " + e);
458:                }
459:
460:                super Import = true;
461:            }
462:
463:            protected boolean hasSuperImport() {
464:                return super Import;
465:            }
466:
467:            /**
468:            	Return the name or null if none is found,
469:            	Throw an ClassPathException containing detail if name is ambigous.
470:             */
471:            public String getClassNameByUnqName(String name)
472:                    throws ClassPathException {
473:                return getClassPath().getClassNameByUnqName(name);
474:            }
475:
476:            public void addListener(Listener l) {
477:                listeners.addElement(new WeakReference(l, refQueue));
478:
479:                // clean up old listeners
480:                Reference deadref;
481:                while ((deadref = refQueue.poll()) != null) {
482:                    boolean ok = listeners.removeElement(deadref);
483:                    if (ok) {
484:                        //System.err.println("cleaned up weak ref: "+deadref);
485:                    } else {
486:                        if (Interpreter.DEBUG)
487:                            Interpreter
488:                                    .debug("tried to remove non-existent weak ref: "
489:                                            + deadref);
490:                    }
491:                }
492:            }
493:
494:            public void removeListener(Listener l) {
495:                throw new Error("unimplemented");
496:            }
497:
498:            public ClassLoader getBaseLoader() {
499:                return baseLoader;
500:            }
501:
502:            /**
503:            	Get the BeanShell classloader.
504:            public ClassLoader getClassLoader() {
505:            }
506:             */
507:
508:            /*
509:            	Impl Notes:
510:            	We add the bytecode source and the "reload" the class, which causes the
511:            	BshClassLoader to be initialized and create a DiscreteFilesClassLoader
512:            	for the bytecode.
513:
514:            	@exception ClassPathException can be thrown by reloadClasses
515:             */
516:            public Class defineClass(String name, byte[] code) {
517:                //System.out.println( "defineClass: "+name );
518:                baseClassPath.setClassSource(name, new GeneratedClassSource(
519:                        code));
520:                try {
521:                    reloadClasses(new String[] { name });
522:                } catch (ClassPathException e) {
523:                    throw new bsh.InterpreterError("defineClass: " + e);
524:                }
525:                return classForName(name);
526:            }
527:
528:            /**
529:            	Clear global class cache and notify namespaces to clear their 
530:            	class caches.
531:
532:            	The listener list is implemented with weak references so that we 
533:            	will not keep every namespace in existence forever.
534:             */
535:            protected void classLoaderChanged() {
536:                // clear the static caches in BshClassManager
537:                clearCaches();
538:
539:                Vector toRemove = new Vector(); // safely remove
540:                for (Enumeration e = listeners.elements(); e.hasMoreElements();) {
541:                    WeakReference wr = (WeakReference) e.nextElement();
542:                    Listener l = (Listener) wr.get();
543:                    if (l == null) // garbage collected
544:                        toRemove.add(wr);
545:                    else
546:                        l.classLoaderChanged();
547:                }
548:                for (Enumeration e = toRemove.elements(); e.hasMoreElements();)
549:                    listeners.removeElement(e.nextElement());
550:            }
551:
552:            public void dump(PrintWriter i) {
553:                i.println("Bsh Class Manager Dump: ");
554:                i.println("----------------------- ");
555:                i.println("baseLoader = " + baseLoader);
556:                i.println("loaderMap= " + loaderMap);
557:                i.println("----------------------- ");
558:                i.println("baseClassPath = " + baseClassPath);
559:            }
560:
561:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.