KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > beanutils > ContextClassLoaderLocal


1 /*
2  * Copyright 2001-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.commons.beanutils;
18
19 import java.util.Map JavaDoc;
20 import java.util.WeakHashMap JavaDoc;
21
22 /**
23  * A value that is provided per (thread) context classloader.
24  * Patterned after ThreadLocal.
25  * There is a separate value used when Thread.getContextClassLoader() is null.
26  * This mechanism provides isolation for web apps deployed in the same container.
27  * <strong>Note:</strong> A WeakHashMap bug in several 1.3 JVMs results in a memory leak
28  * for those JVMs.
29  *
30  * @see java.lang.Thread#getContextClassLoader
31  * @author Eric Pabst
32  */

33 public class ContextClassLoaderLocal {
34     private Map JavaDoc valueByClassLoader = new WeakHashMap JavaDoc();
35     private boolean globalValueInitialized = false;
36     private Object JavaDoc globalValue;
37
38     public ContextClassLoaderLocal() {
39         super();
40     }
41
42     /**
43      * Returns the initial value for this ContextClassLoaderLocal
44      * variable. This method will be called once per Context ClassLoader for
45      * each ContextClassLoaderLocal, the first time it is accessed
46      * with get or set. If the programmer desires ContextClassLoaderLocal variables
47      * to be initialized to some value other than null, ContextClassLoaderLocal must
48      * be subclassed, and this method overridden. Typically, an anonymous
49      * inner class will be used. Typical implementations of initialValue
50      * will call an appropriate constructor and return the newly constructed
51      * object.
52      *
53      * @return a new Object to be used as an initial value for this ContextClassLoaderLocal
54      */

55     protected Object JavaDoc initialValue() {
56         return null;
57     }
58
59     /**
60      * Gets the instance which provides the functionality for {@link BeanUtils}.
61      * This is a pseudo-singleton - an single instance is provided per (thread) context classloader.
62      * This mechanism provides isolation for web apps deployed in the same container.
63      * @return the object currently associated with the
64      */

65     public synchronized Object JavaDoc get() {
66         // synchronizing the whole method is a bit slower
67
// but guarentees no subtle threading problems, and there's no
68
// need to synchronize valueByClassLoader
69

70         // make sure that the map is given a change to purge itself
71
valueByClassLoader.isEmpty();
72         try {
73             
74             ClassLoader JavaDoc contextClassLoader = Thread.currentThread().getContextClassLoader();
75             if (contextClassLoader != null) {
76                 
77                 Object JavaDoc value = valueByClassLoader.get(contextClassLoader);
78                 if ((value == null)
79                 && !valueByClassLoader.containsKey(contextClassLoader)) {
80                     value = initialValue();
81                     valueByClassLoader.put(contextClassLoader, value);
82                 }
83                 return value;
84                 
85             }
86             
87         } catch (SecurityException JavaDoc e) { /* SWALLOW - should we log this? */ }
88         
89         // if none or exception, return the globalValue
90
if (!globalValueInitialized) {
91             globalValue = initialValue();
92             globalValueInitialized = true;
93         }//else already set
94
return globalValue;
95     }
96
97     /**
98      * Sets the value - a value is provided per (thread) context classloader.
99      * This mechanism provides isolation for web apps deployed in the same container.
100      *
101      * @param value the object to be associated with the entrant thread's context classloader
102      */

103     public synchronized void set(Object JavaDoc value) {
104         // synchronizing the whole method is a bit slower
105
// but guarentees no subtle threading problems
106

107         // make sure that the map is given a change to purge itself
108
valueByClassLoader.isEmpty();
109         try {
110             
111             ClassLoader JavaDoc contextClassLoader = Thread.currentThread().getContextClassLoader();
112             if (contextClassLoader != null) {
113                 valueByClassLoader.put(contextClassLoader, value);
114                 return;
115             }
116             
117         } catch (SecurityException JavaDoc e) { /* SWALLOW - should we log this? */ }
118         
119         // if in doubt, set the global value
120
globalValue = value;
121         globalValueInitialized = true;
122     }
123     
124     /**
125      * Unsets the value associated with the current thread's context classloader
126      */

127     public synchronized void unset() {
128         try {
129         
130             ClassLoader JavaDoc contextClassLoader = Thread.currentThread().getContextClassLoader();
131             unset(contextClassLoader);
132             
133         } catch (SecurityException JavaDoc e) { /* SWALLOW - should we log this? */ }
134     }
135     
136     /**
137      * Unsets the value associated with the given classloader
138      */

139     public synchronized void unset(ClassLoader JavaDoc classLoader) {
140         valueByClassLoader.remove(classLoader);
141     }
142 }
Popular Tags