KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > loader > EnvironmentClassLoader


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.loader;
31
32 import com.caucho.jca.UserTransactionProxy;
33 import com.caucho.jmx.Jmx;
34 import com.caucho.log.EnvironmentStream;
35 import com.caucho.management.j2ee.J2EEManagedObject;
36 import com.caucho.management.j2ee.JTAResource;
37 import com.caucho.naming.Jndi;
38 import com.caucho.security.PolicyImpl;
39 import com.caucho.transaction.TransactionManagerImpl;
40 import com.caucho.util.ResinThreadPoolExecutor;
41 import com.caucho.vfs.Vfs;
42
43 import javax.management.MBeanServerFactory JavaDoc;
44 import java.lang.reflect.Method JavaDoc;
45 import java.util.ArrayList JavaDoc;
46 import java.util.Hashtable JavaDoc;
47 import java.util.Properties JavaDoc;
48 import java.util.logging.Level JavaDoc;
49
50 /**
51  * Class loader which checks for changes in class files and automatically
52  * picks up new jars.
53  *
54  * <p>DynamicClassLoaders can be chained creating one virtual class loader.
55  * From the perspective of the JDK, it's all one classloader. Internally,
56  * the class loader chain searches like a classpath.
57  */

58 public class EnvironmentClassLoader extends DynamicClassLoader {
59   private static boolean _isStaticInit;
60
61   // listeners invoked at the start of any child environment
62
private static EnvironmentLocal<ArrayList JavaDoc<EnvironmentListener>> _childListeners
63     = new EnvironmentLocal<ArrayList JavaDoc<EnvironmentListener>>();
64
65   // The owning bean
66
private EnvironmentBean _owner;
67
68   // Class loader specific attributes
69
private Hashtable JavaDoc<String JavaDoc,Object JavaDoc> _attributes =
70     new Hashtable JavaDoc<String JavaDoc,Object JavaDoc>(8);
71
72   // Array of listeners
73
// XXX: this used to be a weak reference list, but that caused problems
74
// server/306i - can't be weak reference, instead create WeakStopListener
75
private ArrayList JavaDoc<EnvironmentListener> _listeners;
76   private WeakStopListener _stopListener;
77
78   // Returns true once the environment has started
79
private volatile boolean _isStarted;
80
81   // Returns true if the environment is active
82
private volatile boolean _isActive;
83
84   // Returns true if the environment is stopped
85
private volatile boolean _isStopped;
86
87   private Throwable JavaDoc _configException;
88
89   /**
90    * Creates a new environment class loader.
91    */

92   public EnvironmentClassLoader()
93   {
94     super(Thread.currentThread().getContextClassLoader());
95
96     // initializeEnvironment();
97

98     initListeners();
99   }
100
101   /**
102    * Creates a new environment class loader.
103    */

104   public EnvironmentClassLoader(ClassLoader JavaDoc parent)
105   {
106     super(parent);
107
108     // initializeEnvironment();
109

110     initListeners();
111   }
112
113   /**
114    * Returns the environment's owner.
115    */

116   public EnvironmentBean getOwner()
117   {
118     return _owner;
119   }
120
121   /**
122    * Sets the environment's owner.
123    */

124   public void setOwner(EnvironmentBean owner)
125   {
126     _owner = owner;
127   }
128
129   /**
130    * Sets the config exception.
131    */

132   public void setConfigException(Throwable JavaDoc e)
133   {
134     if (_configException == null)
135       _configException = e;
136   }
137
138   /**
139    * Gets the config exception.
140    */

141   public Throwable JavaDoc getConfigException()
142   {
143     return _configException;
144   }
145
146   /**
147    * Returns true if the environment is active
148    */

149   public boolean isActive()
150   {
151     return _isActive;
152   }
153
154   /**
155    * Initialize the environment.
156    */

157   public void init()
158   {
159     initializeEnvironment();
160
161     super.init();
162   }
163
164   /**
165    * Returns the named attributes
166    */

167   public Object JavaDoc getAttribute(String JavaDoc name)
168   {
169     if (_attributes != null)
170       return _attributes.get(name);
171     else
172       return null;
173   }
174
175   /**
176    * Sets the named attributes
177    */

178   public Object JavaDoc setAttribute(String JavaDoc name, Object JavaDoc obj)
179   {
180     if (obj == null) {
181       if (_attributes == null)
182         return null;
183       else
184         return _attributes.remove(name);
185     }
186
187     if (_attributes == null)
188       _attributes = new Hashtable JavaDoc<String JavaDoc,Object JavaDoc>(8);
189
190     return _attributes.put(name, obj);
191   }
192
193   /**
194    * Removes the named attributes
195    */

196   public Object JavaDoc removeAttribute(String JavaDoc name)
197   {
198     if (_attributes == null)
199       return null;
200     else
201       return _attributes.remove(name);
202   }
203
204   /**
205    * Adds a listener to detect environment lifecycle changes.
206    */

207   public void addListener(EnvironmentListener listener)
208   {
209     synchronized (this) {
210       if (_listeners == null) {
211         _listeners = new ArrayList JavaDoc<EnvironmentListener>();
212
213         initListeners();
214       }
215     }
216
217     synchronized (_listeners) {
218       for (int i = _listeners.size() - 1; i >= 0; i--) {
219         EnvironmentListener oldListener = _listeners.get(i);
220
221         if (listener == oldListener) {
222           return;
223         }
224         else if (oldListener == null)
225           _listeners.remove(i);
226       }
227
228       _listeners.add(listener);
229     }
230
231     if (_isStarted) {
232       try {
233         listener.environmentStart(this);
234       } catch (RuntimeException JavaDoc e) {
235         throw e;
236       } catch (Throwable JavaDoc e) {
237         throw new StartRuntimeException(e);
238       }
239     }
240   }
241
242   /**
243    * Adds self as a listener.
244    */

245   private void initListeners()
246   {
247     ClassLoader JavaDoc parent = getParent();
248
249     for (; parent != null; parent = parent.getParent()) {
250       if (parent instanceof EnvironmentClassLoader) {
251         EnvironmentClassLoader loader = (EnvironmentClassLoader) parent;
252
253         if (_stopListener == null)
254           _stopListener = new WeakStopListener(this);
255
256         loader.addListener(_stopListener);
257
258         return;
259       }
260     }
261   }
262
263   /**
264    * Adds a listener to detect environment lifecycle changes.
265    */

266   public void removeListener(EnvironmentListener listener)
267   {
268     if (_listeners == null)
269       return;
270
271     synchronized (_listeners) {
272       for (int i = _listeners.size() - 1; i >= 0; i--) {
273         EnvironmentListener oldListener = _listeners.get(i);
274
275         if (listener == oldListener) {
276           _listeners.remove(i);
277           return;
278         }
279         else if (oldListener == null)
280           _listeners.remove(i);
281       }
282     }
283   }
284
285   /**
286    * Adds a child listener.
287    */

288   void addChildListener(EnvironmentListener listener)
289   {
290     synchronized (_childListeners) {
291       ArrayList JavaDoc<EnvironmentListener> listeners
292         = _childListeners.getLevel(this);
293
294       if (listeners == null) {
295         listeners = new ArrayList JavaDoc<EnvironmentListener>();
296
297         _childListeners.set(listeners, this);
298       }
299
300       listeners.add(listener);
301     }
302
303     if (_lifecycle.isStarting()) {
304       try {
305         listener.environmentStart(this);
306       } catch (Throwable JavaDoc e) {
307         log().log(Level.WARNING, e.toString(), e);
308       }
309     }
310   }
311
312   /**
313    * Removes a child listener.
314    */

315   void removeChildListener(EnvironmentListener listener)
316   {
317     synchronized (_childListeners) {
318       ArrayList JavaDoc<EnvironmentListener> listeners
319         = _childListeners.getLevel(this);
320
321       if (listeners != null)
322         listeners.remove(listener);
323     }
324   }
325
326   /**
327    * Returns the listeners.
328    */

329   protected ArrayList JavaDoc<EnvironmentListener> getEnvironmentListeners()
330   {
331     ArrayList JavaDoc<EnvironmentListener> listeners;
332     listeners = new ArrayList JavaDoc<EnvironmentListener>();
333
334     // add the descendent listeners
335
synchronized (_childListeners) {
336       ClassLoader JavaDoc loader;
337
338       for (loader = this; loader != null; loader = loader.getParent()) {
339         if (loader instanceof EnvironmentClassLoader) {
340           ArrayList JavaDoc<EnvironmentListener> childListeners;
341           childListeners = _childListeners.getLevel(loader);
342
343           if (childListeners != null)
344             listeners.addAll(childListeners);
345         }
346       }
347     }
348
349     if (_listeners == null)
350       return listeners;
351
352     synchronized (_listeners) {
353       for (int i = 0; i < _listeners.size(); i++) {
354         EnvironmentListener listener = _listeners.get(i);
355
356         if (listener != null)
357           listeners.add(listener);
358         else {
359           _listeners.remove(i);
360           i--;
361         }
362       }
363     }
364
365     return listeners;
366   }
367
368   /**
369    * Marks the environment of the class loader as started. The
370    * class loader itself doesn't use this, but a callback might.
371    */

372   public void start()
373   {
374     synchronized (this) {
375       if (_isStarted)
376         return;
377
378       _isStarted = true;
379     }
380
381     try {
382       ArrayList JavaDoc<EnvironmentListener> listeners = getEnvironmentListeners();
383
384       int size = listeners.size();
385       for (int i = 0; listeners != null && i < size; i++) {
386         EnvironmentListener listener = listeners.get(i);
387
388         listener.environmentStart(this);
389       }
390     } catch (RuntimeException JavaDoc e) {
391       throw e;
392     } catch (Error JavaDoc e) {
393       throw e;
394     } catch (Throwable JavaDoc e) {
395       throw new StartRuntimeException(e);
396     } finally {
397       _isActive = true;
398     }
399   }
400
401   /**
402    * Stops the environment, closing down any resources.
403    *
404    * The resources are closed in the reverse order that they're started
405    */

406   public void stop()
407   {
408     synchronized (this) {
409       if (_isStopped)
410         return;
411
412       _isStopped = true;
413       _isActive = false;
414     }
415
416     ArrayList JavaDoc<EnvironmentListener> listeners = getEnvironmentListeners();
417
418     Thread JavaDoc thread = Thread.currentThread();
419     ClassLoader JavaDoc oldLoader = thread.getContextClassLoader();
420     thread.setContextClassLoader(this);
421
422     try {
423       // closing down in reverse
424
if (listeners != null) {
425         for (int i = listeners.size() - 1; i >= 0; i--) {
426           EnvironmentListener listener = listeners.get(i);
427
428           try {
429             listener.environmentStop(this);
430           } catch (Throwable JavaDoc e) {
431             e.printStackTrace();
432             log().log(Level.WARNING, e.toString(), e);
433           }
434         }
435       }
436     } finally {
437       thread.setContextClassLoader(oldLoader);
438
439       // drain the thread pool for GC
440
ResinThreadPoolExecutor.getThreadPool().stopEnvironment(this);
441     }
442   }
443
444   /**
445    * Copies the loader.
446    */

447   protected void replace(EnvironmentClassLoader source)
448   {
449     super.replace(source);
450
451     // XXX: might need separate class
452
_owner = source._owner;
453     _attributes = source._attributes;
454     if (source._listeners != null) {
455       if (_listeners == null)
456         _listeners = new ArrayList JavaDoc<EnvironmentListener>();
457       _listeners.addAll(source._listeners);
458       source._listeners.clear();
459     }
460
461     _isStarted = source._isStarted;
462     _isActive = source._isActive;
463     _isStopped = source._isStopped;
464   }
465
466   /**
467    * Destroys the class loader.
468    */

469   public void destroy()
470   {
471     try {
472       WeakStopListener stopListener = _stopListener;
473       _stopListener = null;
474
475       // make sure it's stopped first
476
stop();
477
478       super.destroy();
479
480       ClassLoader JavaDoc parent = getParent();
481       for (; parent != null; parent = parent.getParent()) {
482         if (parent instanceof EnvironmentClassLoader) {
483           EnvironmentClassLoader loader = (EnvironmentClassLoader) parent;
484
485           loader.removeListener(stopListener);
486         }
487       }
488     } finally {
489       _owner = null;
490       _attributes = null;
491       _listeners = null;
492     }
493   }
494
495   public String JavaDoc toString()
496   {
497     if (getId() != null)
498       return "EnvironmentClassLoader$" + System.identityHashCode(this) + "[" + getId() + "]";
499     else {
500       // return "EnvironmentClassLoader$" + System.identityHashCode(this) + getLoaders();
501
return "EnvironmentClassLoader$" + System.identityHashCode(this) + "[]";
502     }
503   }
504
505   /**
506    * Initializes the environment
507    */

508   public static synchronized void initializeEnvironment()
509   {
510     if (_isStaticInit)
511       return;
512
513     _isStaticInit = true;
514
515     Thread JavaDoc thread = Thread.currentThread();
516     ClassLoader JavaDoc oldLoader = thread.getContextClassLoader();
517     try {
518       thread.setContextClassLoader(ClassLoader.getSystemClassLoader());
519
520       ClassLoader JavaDoc loader = thread.getContextClassLoader();
521
522       PolicyImpl.init();
523
524       EnvironmentStream.setStdout(System.out);
525       EnvironmentStream.setStderr(System.err);
526
527       try {
528         Vfs.initJNI();
529       } catch (Throwable JavaDoc e) {
530       }
531
532       if (System.getProperty("org.xml.sax.driver") == null)
533         System.setProperty("org.xml.sax.driver", "com.caucho.xml.Xml");
534
535       Properties JavaDoc props = System.getProperties();
536
537       if (props.get("java.util.logging.manager") == null) {
538         props.put("java.util.logging.manager",
539                   "com.caucho.log.LogManagerImpl");
540       }
541
542       if (props.get("java.naming.factory.initial") == null) {
543         props.put("java.naming.factory.initial",
544                   "com.caucho.naming.InitialContextFactoryImpl");
545       }
546
547       props.put("java.naming.factory.url.pkgs", "com.caucho.naming");
548
549       EnvironmentProperties.enableEnvironmentSystemProperties(true);
550
551       TransactionManagerImpl tm = TransactionManagerImpl.getInstance();
552       // TransactionManagerImpl.setLocal(tm);
553
Jndi.bindDeep("java:comp/TransactionManager", tm);
554
555       UserTransactionProxy ut = UserTransactionProxy.getInstance();
556       Jndi.bindDeep("java:comp/UserTransaction", ut);
557       
558       Jndi.bindDeep("java:comp/ThreadPool",
559             ResinThreadPoolExecutor.getThreadPool());
560
561       String JavaDoc oldBuilder = props.getProperty("javax.management.builder.initial");
562       if (oldBuilder == null)
563         oldBuilder = "com.caucho.jmx.MBeanServerBuilderImpl";
564
565       /*
566       props.put("javax.management.builder.initial",
567         "com.caucho.jmx.EnvironmentMBeanServerBuilder");
568       */

569
570       props.put("javax.management.builder.initial", oldBuilder);
571
572       if (MBeanServerFactory.findMBeanServer(null).size() == 0)
573         MBeanServerFactory.createMBeanServer("Resin");
574
575       try {
576         Class JavaDoc cl = Class.forName("java.lang.management.ManagementFactory");
577         Method JavaDoc method = cl.getMethod("getPlatformMBeanServer", new Class JavaDoc[0]);
578         method.invoke(null, new Object JavaDoc[0]);
579       } catch (Throwable JavaDoc e) {
580       }
581
582       Jndi.bindDeep("java:comp/env/jmx/MBeanServer",
583                     Jmx.getContextMBeanServer());
584       Jndi.bindDeep("java:comp/env/jmx/GlobalMBeanServer",
585                     Jmx.getGlobalMBeanServer());
586
587       J2EEManagedObject.register(new JTAResource(tm));
588
589     } catch (Throwable JavaDoc e) {
590       e.printStackTrace();
591     } finally {
592       thread.setContextClassLoader(oldLoader);
593     }
594   }
595 }
596
Popular Tags