KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > web > tomcat > tc6 > WebCtxLoader


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.web.tomcat.tc6;
23
24 import java.beans.PropertyChangeListener JavaDoc;
25 import java.io.File JavaDoc;
26 import java.lang.reflect.Method JavaDoc;
27 import java.net.MalformedURLException JavaDoc;
28 import java.net.URL JavaDoc;
29 import java.net.URLClassLoader JavaDoc;
30 import java.util.ArrayList JavaDoc;
31 import java.util.List JavaDoc;
32
33 import javax.servlet.ServletContext JavaDoc;
34
35 import org.apache.catalina.Container;
36 import org.apache.catalina.Context;
37 import org.apache.catalina.Globals;
38 import org.apache.catalina.Lifecycle;
39 import org.apache.catalina.LifecycleException;
40 import org.apache.catalina.LifecycleListener;
41 import org.apache.catalina.Loader;
42 import org.apache.naming.resources.DirContextURLStreamHandler;
43 import org.jboss.mx.loading.RepositoryClassLoader;
44 import org.jboss.logging.Logger;
45
46 /**
47  * Initial version of a JBoss implementation of the Tomcat Loader.
48  *
49  * @author Scott.Stark@jboss.org
50  * @version $Revision: 58290 $
51  */

52 public class WebCtxLoader
53    implements Lifecycle, Loader JavaDoc
54 {
55    private static final Logger log = Logger.getLogger(WebCtxLoader.class);
56    /**
57     * The ClassLoader used to scope the ENC
58     */

59    protected ClassLoader JavaDoc encLoader;
60    /**
61     * The ClassLoader returned from getClassLoader
62     */

63    protected ENCLoader ctxLoader;
64    /**
65     * The war UCL used to load the war classes
66     */

67    protected RepositoryClassLoader delegate;
68    protected Container webContainer;
69    protected URL JavaDoc warURL;
70    protected TomcatInjectionContainer injectionContainer;
71
72    /**
73     * The set of repositories associated with this class loader.
74     */

75    private ArrayList JavaDoc repositories = new ArrayList JavaDoc();
76
77    /**
78     * Create a WebCtxLoader given the ENC scoping class loader.
79     *
80     * @param encLoader
81     */

82    public WebCtxLoader(ClassLoader JavaDoc encLoader)
83    {
84       this(encLoader, null);
85    }
86    public WebCtxLoader(ClassLoader JavaDoc encLoader, TomcatInjectionContainer container)
87    {
88       this.encLoader = encLoader;
89       this.ctxLoader = new ENCLoader(encLoader);
90       ClassLoader JavaDoc parent = encLoader;
91       while ((parent instanceof RepositoryClassLoader) == false && parent != null)
92          parent = parent.getParent();
93       this.delegate = (RepositoryClassLoader) parent;
94       injectionContainer = container;
95    }
96
97    /**
98     * Use an explicit classpath
99     *
100     * @param classpath
101     */

102    public void setClasspath(List JavaDoc<URL JavaDoc> classpath)
103    {
104       for(URL JavaDoc path : classpath)
105       {
106          delegate.addURL(path);
107          ctxLoader.addURLInternal(path);
108       }
109    }
110
111    /**
112     * Build the classpath from the war url WEB-INF/{classes,lib}.
113     *
114     * @param warURL
115     * @throws MalformedURLException
116     */

117    public void setWarURL(URL JavaDoc warURL) throws MalformedURLException JavaDoc
118    {
119       this.warURL = warURL;
120       String JavaDoc path = warURL.getFile();
121       File JavaDoc classesDir = new File JavaDoc(path, "WEB-INF/classes");
122       if (classesDir.exists())
123       {
124          delegate.addURL(classesDir.toURL());
125          ctxLoader.addURLInternal(classesDir.toURL());
126       }
127       File JavaDoc libDir = new File JavaDoc(path, "WEB-INF/lib");
128       if (libDir.exists())
129       {
130          File JavaDoc[] jars = libDir.listFiles();
131          int length = jars != null ? jars.length : 0;
132          for (int j = 0; j < length; j++)
133          {
134             File JavaDoc jar = jars[j];
135             if(jar.getAbsolutePath().endsWith(".jar"))
136             {
137                delegate.addURL(jar.toURL());
138                ctxLoader.addURLInternal(jar.toURL());
139             }
140          }
141       }
142    }
143
144    public void addLifecycleListener(LifecycleListener listener)
145    {
146    }
147
148    public LifecycleListener[] findLifecycleListeners()
149    {
150       return new LifecycleListener[0];
151    }
152
153    public void removeLifecycleListener(LifecycleListener listener)
154    {
155    }
156
157    public void start() throws LifecycleException
158    {
159       // ctxLoader is set upon construction and nullified during stop
160
if (this.ctxLoader == null)
161          throw new LifecycleException("WebCtxLoader cannot be restarted");
162
163       setClassPath();
164       if (injectionContainer != null)
165       {
166          log.debug("injectionContainer enabled and processing beginning with JBoss WebCtxLoader");
167          // we need to do this because the classloader is initialize by the web container and
168
// the injection container needs the classloader so that it can build up Injectors and ENC populators
169
injectionContainer.setClassLoader(getClassLoader());
170          injectionContainer.processMetadata();
171       }
172       ServletContext JavaDoc servletContext = ((Context JavaDoc) webContainer).getServletContext();
173       if (servletContext == null)
174          return;
175    }
176
177    public void stop() throws LifecycleException
178    {
179       // Remove the ctxLoader mapping kept by the DirContextURLStreamHandler
180
DirContextURLStreamHandler.unbind(ctxLoader);
181       org.apache.commons.logging.LogFactory.release(ctxLoader);
182       org.apache.commons.logging.LogFactory.release(encLoader);
183       this.encLoader = null;
184       this.ctxLoader = null;
185       this.delegate = null;
186       this.repositories.clear();
187       this.warURL = null;
188       this.webContainer = null;
189    }
190
191    public void backgroundProcess()
192    {
193       //To change body of implemented methods use File | Settings | File Templates.
194
}
195
196    /**
197     * We must pass the wrapped encLoader as tomcat needs to see a unique
198     * class loader that is distinct from the thread context class loader seen
199     * to be in effect when the web app is started. This is due to how it
200     * binds contexts using the DirContextURLStreamHandler class.
201     *
202     * @return The ENC scoping class loader
203     * @see org.apache.naming.resources.DirContextURLStreamHandler
204     */

205    public ClassLoader JavaDoc getClassLoader()
206    {
207       return ctxLoader;
208    }
209
210    public Container getContainer()
211    {
212       return webContainer;
213    }
214
215    public void setContainer(Container container)
216    {
217       webContainer = container;
218
219    }
220
221    public boolean getDelegate()
222    {
223       return false;
224    }
225
226    public void setDelegate(boolean delegate)
227    {
228    }
229
230    public String JavaDoc getInfo()
231    {
232       return null;
233    }
234
235    public boolean getReloadable()
236    {
237       return false;
238    }
239
240    public void setReloadable(boolean reloadable)
241    {
242    }
243
244    public void addPropertyChangeListener(PropertyChangeListener JavaDoc listener)
245    {
246    }
247
248    public void addRepository(String JavaDoc repository)
249    {
250       if (repositories.contains(repository) == true)
251          return;
252       repositories.add(repository);
253       setClassPath();
254    }
255
256    public String JavaDoc[] findRepositories()
257    {
258       String JavaDoc[] tmp = new String JavaDoc[repositories.size()];
259       repositories.toArray(tmp);
260       return tmp;
261    }
262
263    public boolean modified()
264    {
265       return false;
266    }
267
268    public void removePropertyChangeListener(PropertyChangeListener JavaDoc listener)
269    {
270    }
271
272    /**
273     * Set the appropriate context attribute for our class path. This
274     * is required only because Jasper depends on it.
275     */

276    private void setClassPath()
277    {
278       // Validate our current state information
279
if (!(webContainer instanceof Context JavaDoc))
280          return;
281       ServletContext JavaDoc servletContext = ((Context JavaDoc) webContainer).getServletContext();
282       if (servletContext == null)
283          return;
284
285       try
286       {
287          Method JavaDoc method =
288             webContainer.getClass().getMethod("getCompilerClasspath", null);
289          Object JavaDoc baseClasspath = method.invoke(webContainer, null);
290          if (baseClasspath != null)
291          {
292             servletContext.setAttribute(Globals.CLASS_PATH_ATTR,
293                baseClasspath.toString());
294             return;
295          }
296       }
297       catch (Exception JavaDoc e)
298       {
299          // Ignore
300
e.printStackTrace();
301       }
302
303       StringBuffer JavaDoc classpath = new StringBuffer JavaDoc();
304
305       // Assemble the class path information from our repositories
306
for (int i = 0; i < repositories.size(); i++)
307       {
308          String JavaDoc repository = repositories.get(i).toString();
309          if (repository.startsWith("file://"))
310             repository = repository.substring(7);
311          else if (repository.startsWith("file:"))
312             repository = repository.substring(5);
313          else if (repository.startsWith("jndi:"))
314             repository = servletContext.getRealPath(repository.substring(5));
315          else
316             continue;
317          if (repository == null)
318             continue;
319          if (i > 0)
320             classpath.append(File.pathSeparator);
321          classpath.append(repository);
322       }
323
324       // Store the assembled class path as a servlet context attribute
325
servletContext.setAttribute(Globals.CLASS_PATH_ATTR,
326          classpath.toString());
327
328    }
329
330    /**
331     * A trival extension of URLClassLoader that uses an empty URL[] as its
332     * classpath so that all work is delegated to its parent.
333     */

334    static class ENCLoader extends URLClassLoader JavaDoc
335    {
336       private URL JavaDoc[] urllist = new URL JavaDoc[0];
337
338       ENCLoader(ClassLoader JavaDoc parent)
339       {
340          super(new URL JavaDoc[0], parent);
341       }
342
343       void addURLInternal(URL JavaDoc url)
344       {
345          URL JavaDoc[] result = new URL JavaDoc[urllist.length + 1];
346          for (int i = 0; i < urllist.length; i++)
347             result[i] = urllist[i];
348          result[urllist.length] = url;
349          urllist = result;
350       }
351
352       public URL JavaDoc[] getURLs()
353       {
354          return urllist;
355       }
356    }
357 }
358
Popular Tags