KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > util > loading > ContextClassLoaderSwitcher


1 /*
2   * JBoss, Home of Professional Open Source
3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
4   * by the @authors tag. See the copyright.txt in the distribution for a
5   * full listing of individual contributors.
6   *
7   * This is free software; you can redistribute it and/or modify it
8   * under the terms of the GNU Lesser General Public License as
9   * published by the Free Software Foundation; either version 2.1 of
10   * the License, or (at your option) any later version.
11   *
12   * This software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this software; if not, write to the Free
19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21   */

22 package org.jboss.util.loading;
23
24 import java.security.AccessController JavaDoc;
25 import java.security.PrivilegedAction JavaDoc;
26
27 /**
28  * A helper for context classloading switching.<p>
29  *
30  * When a security manager is installed, the
31  * constructor checks for the runtime permissions
32  * &quot;getClassLoader&quot; and &quot;setContextClassLoader&quot;.
33  * This allows the methods of this class to be used later without
34  * having to run in privileged blocks.
35  *
36  * There are optimized methods to perform the operations within
37  * a switch context. This avoids retrieving the current thread
38  * on every operation.
39  *
40  * @version <tt>$Revision: 1958 $</tt>
41  * @author <a HREF="mailto:adrian@jboss.org">Adrian Brock</a>
42  */

43 public class ContextClassLoaderSwitcher
44    extends ContextClassLoader
45 {
46    /**
47     * Set the context classloader permission
48     */

49    public static final RuntimePermission JavaDoc SETCONTEXTCLASSLOADER = new RuntimePermission JavaDoc("setContextClassLoader");
50
51    /**
52     * Instantiate a new context class loader switcher
53     */

54    public static final NewInstance INSTANTIATOR = new NewInstance();
55
56    /**
57     * Constructor.
58     * @throws SecurityException when not authroized to get/set the context classloader
59     */

60    private ContextClassLoaderSwitcher()
61    {
62       super();
63       SecurityManager JavaDoc manager = System.getSecurityManager();
64       if (manager != null)
65          manager.checkPermission(SETCONTEXTCLASSLOADER);
66    }
67
68    /**
69     * Set the context classloader
70     *
71     * @param the new context classloader
72     */

73    public void setContextClassLoader(final ClassLoader JavaDoc cl)
74    {
75       setContextClassLoader(Thread.currentThread(), cl);
76    }
77
78    /**
79     * Set the context classloader for the given thread
80     *
81     * @param thread the thread
82     * @param the new context classloader
83     */

84    public void setContextClassLoader(final Thread JavaDoc thread, final ClassLoader JavaDoc cl)
85    {
86       AccessController.doPrivileged(new PrivilegedAction JavaDoc()
87       {
88          public Object JavaDoc run()
89          {
90             thread.setContextClassLoader(cl);
91             return null;
92          }
93       });
94    }
95
96    /**
97     * Retrieve a switch context
98     *
99     * @return the switch context
100     */

101    public SwitchContext getSwitchContext()
102    {
103       return new SwitchContext();
104    }
105
106    /**
107     * Retrieve a switch context and set the new context classloader
108     *
109     * @param cl the new classloader
110     * @return the switch context
111     */

112    public SwitchContext getSwitchContext(final ClassLoader JavaDoc cl)
113    {
114       return new SwitchContext(cl);
115    }
116
117    /**
118     * Retrieve a switch context for the classloader of a given class
119     *
120     * @deprecated using a class to determine the classloader is a
121     * bad idea, it has the same problems as Class.forName()
122     * @param clazz the class whose classloader should be set
123     * as the context classloader
124     * @return the switch context
125     */

126    public SwitchContext getSwitchContext(final Class JavaDoc clazz)
127    {
128       return new SwitchContext(clazz.getClassLoader());
129    }
130
131    /**
132     * A helper class to remember the original classloader and
133     * avoid continually retrieveing the current thread.
134     */

135    public class SwitchContext
136    {
137       /**
138        * The original classloader
139        */

140       private ClassLoader JavaDoc origCL;
141
142       /**
143        * The current classloader
144        */

145       private ClassLoader JavaDoc currentCL;
146
147       /**
148        * The current thread
149        */

150       private Thread JavaDoc currentThread;
151
152       private SwitchContext()
153       {
154          currentThread = Thread.currentThread();
155          origCL = getContextClassLoader(currentThread);
156          currentCL = origCL;
157       }
158
159       private SwitchContext(ClassLoader JavaDoc cl)
160       {
161          this();
162          setClassLoader(cl);
163       }
164
165       /**
166        * Retrieve the current thread
167        */

168       public Thread JavaDoc getThread()
169       {
170          return currentThread;
171       }
172
173       /**
174        * Retrieve the original classloader
175        */

176       public ClassLoader JavaDoc getOriginalClassLoader()
177       {
178          return origCL;
179       }
180
181       /**
182        * Retrieve the current classloader
183        * (as set through this class).
184        */

185       public ClassLoader JavaDoc getCurrentClassLoader()
186       {
187          return currentCL;
188       }
189
190       /**
191        * Change the context classloader<p>
192        *
193        * The operation is ignored if the classloader is null
194        * or has not changed
195        *
196        * @param cl the new classloader
197        */

198       public void setClassLoader(ClassLoader JavaDoc cl)
199       {
200          if (cl != null && cl != currentCL)
201          {
202             setContextClassLoader(currentThread, cl);
203             currentCL = cl;
204          }
205       }
206
207       /**
208        * Reset back to the original classloader,
209        * only when it has changed.
210        */

211       public void reset()
212       {
213          if (currentCL != null && currentCL != origCL)
214             setContextClassLoader(currentThread, origCL);
215       }
216
217       /**
218        * Force a reset back to the original classloader,
219        * useful when somebody else might have changed
220        * the thread context classloader so we cannot optimize
221        */

222       public void forceReset()
223       {
224          setContextClassLoader(currentThread, origCL);
225       }
226    }
227
228    private static class NewInstance
229       implements PrivilegedAction JavaDoc
230    {
231       public Object JavaDoc run()
232       {
233          return new ContextClassLoaderSwitcher();
234       }
235    }
236 }
237
Popular Tags