KickJava   Java API By Example, From Geeks To Geeks.

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


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  * Free SoftwareFoundation, Inc.
23  * 59 Temple Place, Suite 330
24  * Boston, MA 02111-1307 USA
25  *
26  * @author Scott Ferguson
27  */

28
29 package com.caucho.loader;
30
31 import com.caucho.make.DependencyContainer;
32 import com.caucho.util.CharBuffer;
33 import com.caucho.vfs.Dependency;
34 import com.caucho.vfs.JarPath;
35 import com.caucho.vfs.Path;
36
37 import javax.annotation.PostConstruct;
38 import java.io.IOException JavaDoc;
39 import java.net.URL JavaDoc;
40 import java.util.ArrayList JavaDoc;
41 import java.util.HashSet JavaDoc;
42 import java.util.Vector JavaDoc;
43 import java.util.logging.Level JavaDoc;
44 import java.util.logging.Logger JavaDoc;
45
46 /**
47  * Class loader which checks for changes in class files and automatically
48  * picks up new jars.
49  */

50 public class TreeLoader extends Loader implements Dependency
51 {
52   private static final Logger JavaDoc log
53     = Logger.getLogger(TreeLoader.class.getName());
54   
55   // Directory which may have jars dynamically added
56
private Path _dir;
57
58   // When the directory was last modified
59
private long _lastModified;
60
61   private String JavaDoc []_fileNames;
62
63   // list of the jars in the directory
64
private ArrayList JavaDoc<JarEntry> _jarList;
65
66   private HashSet JavaDoc<Path> _files = new HashSet JavaDoc<Path>();
67   private HashSet JavaDoc<Path> _tempFiles = new HashSet JavaDoc<Path>();
68   
69   // list of dependencies
70
private DependencyContainer _dependencyList = new DependencyContainer();
71
72   /**
73    * Creates a new directory loader.
74    */

75   public TreeLoader()
76   {
77   }
78
79   /**
80    * Creates a new directory loader.
81    */

82   public TreeLoader(Path dir)
83   {
84     _dir = dir;
85
86     init();
87   }
88
89   /**
90    * The directory loader's path.
91    */

92   public void setPath(Path path)
93   {
94     _dir = path;
95   }
96
97   /**
98    * The directory loader's path.
99    */

100   public Path getPath()
101   {
102     return _dir;
103   }
104
105   /**
106    * Create a new class loader
107    *
108    * @param parent parent class loader
109    * @param dir directories which can handle dynamic jar addition
110    */

111   public static DynamicClassLoader create(ClassLoader JavaDoc parent, Path dir)
112   {
113     DynamicClassLoader loader = new DynamicClassLoader(parent);
114
115     TreeLoader treeLoader = new TreeLoader(dir);
116
117     loader.addLoader(treeLoader);
118
119     loader.init();
120     
121     return loader;
122   }
123
124   /**
125    * Initialize
126    */

127   @PostConstruct
128   public void init()
129   {
130     _lastModified = _dir.getLastModified();
131     
132     try {
133       _fileNames = _dir.list();
134     } catch (IOException JavaDoc e) {
135     }
136
137     _jarList = new ArrayList JavaDoc<JarEntry>();
138     _dependencyList = new DependencyContainer();
139
140     fillJars();
141   }
142   
143   /**
144    * True if any of the loaded classes have been modified. If true, the
145    * caller should drop the classpath and create a new one.
146    */

147   public boolean isModified()
148   {
149     return _dependencyList.isModified();
150   }
151
152   /**
153    * Sets the owning class loader.
154    */

155   public void setLoader(DynamicClassLoader loader)
156   {
157     super.setLoader(loader);
158
159     for (int i = 0; i < _jarList.size(); i++)
160       loader.addURL(_jarList.get(i).getJarPath());
161   }
162
163   /**
164    * Find all the jars in this directory and add them to jarList.
165    */

166   private void fillJars()
167   {
168     clearJars();
169
170     fillJars(_dir);
171   }
172   
173   /**
174    * Find all the jars in this directory and add them to jarList.
175    */

176   private void fillJars(Path dir)
177   {
178     try {
179       String JavaDoc []list = dir.list();
180
181       for (int j = 0; list != null && j < list.length; j++) {
182     Path path = dir.lookup(list[j]);
183
184     if (list[j].endsWith(".jar") || list[j].endsWith(".zip")) {
185       addJar(path);
186     }
187     else if (path.isDirectory()) {
188       fillJars(path);
189     }
190       }
191       
192     } catch (IOException JavaDoc e) {
193     }
194   }
195
196   private void addJar(Path jar)
197   {
198     JarPath jarPath = JarPath.create(jar);
199     JarEntry jarEntry = new JarEntry(jarPath);
200
201     if (_jarList.contains(jarEntry))
202       return;
203
204     _jarList.add(jarEntry);
205     _dependencyList.add(jarPath.getDepend());
206   }
207   
208   /**
209    * Adds resources to the enumeration.
210    */

211   public void getResources(Vector JavaDoc<URL JavaDoc> vector, String JavaDoc name)
212   {
213     for (int i = 0; i < _jarList.size(); i++) {
214       JarEntry jarEntry = _jarList.get(i);
215       Path path = jarEntry.getJarPath();
216
217       path = path.lookup(name);
218
219       if (path.canRead() || path.isDirectory()) {
220     try {
221       vector.add(new URL JavaDoc(path.getURL()));
222     } catch (Exception JavaDoc e) {
223       log.log(Level.WARNING, e.toString(), e);
224     }
225       }
226     }
227   }
228
229   /**
230    * Fill data for the class path. fillClassPath() will add all
231    * .jar and .zip files in the directory list.
232    */

233   protected String JavaDoc getClassPath(String JavaDoc head)
234   {
235     CharBuffer cb = new CharBuffer();
236
237     cb.append(head);
238
239     for (int i = 0; i < _jarList.size(); i++) {
240       JarEntry jarEntry = _jarList.get(i);
241       JarPath jar = jarEntry.getJarPath();
242
243       if (cb.length() > 0)
244         cb.append(Path.getPathSeparatorChar());
245       cb.append(jar.getContainer().getNativePath());
246     }
247
248     return cb.close();
249   }
250
251   /**
252    * Returns the class entry.
253    *
254    * @param name name of the class
255    */

256   protected ClassEntry getClassEntry(String JavaDoc name)
257     throws ClassNotFoundException JavaDoc
258   {
259     String JavaDoc pathName = name.replace('.', '/');
260     
261     String JavaDoc pkg = "";
262     int p = pathName.lastIndexOf('/');
263     if (p > 0)
264       pkg = pathName.substring(0, p + 1);
265          
266     pathName = pathName + ".class";
267
268     Path classPath = null;
269     
270     // Find the path corresponding to the class
271
for (int i = 0; i < _jarList.size(); i++) {
272       JarEntry jarEntry = _jarList.get(i);
273       Path path = jarEntry.getJarPath();
274
275       Path filePath = path.lookup(pathName);
276       
277       if (filePath.canRead() && filePath.getLength() > 0) {
278         ClassEntry entry = new ClassEntry(getLoader(), name, filePath,
279                                           filePath,
280                       jarEntry.getCodeSource(pathName));
281
282         ClassPackage classPackage = jarEntry.getPackage(pkg);
283
284         entry.setClassPackage(classPackage);
285
286         return entry;
287       }
288     }
289
290     return null;
291   }
292
293   /**
294    * Find a given path somewhere in the classpath
295    *
296    * @param pathName the relative resourceName
297    *
298    * @return the matching path or null
299    */

300   public Path getPath(String JavaDoc pathName)
301   {
302     for (int i = 0; i < _jarList.size(); i++) {
303       JarEntry jarEntry = _jarList.get(i);
304       Path path = jarEntry.getJarPath();
305
306       Path filePath = path.lookup(pathName);
307
308       if (filePath.canRead())
309     return filePath;
310     }
311
312     return null;
313   }
314
315   public Path getCodePath()
316   {
317     return _dir;
318   }
319
320   /**
321    * Destroys the loader, closing the jars.
322    */

323   protected void destroy()
324   {
325     clearJars();
326   }
327
328   /**
329    * Closes the jars.
330    */

331   private void clearJars()
332   {
333     ArrayList JavaDoc<JarEntry> jars = new ArrayList JavaDoc<JarEntry>(_jarList);
334     _jarList.clear();
335     
336     for (int i = 0; i < jars.size(); i++) {
337       JarEntry jarEntry = jars.get(i);
338
339       JarPath jarPath = jarEntry.getJarPath();
340
341       jarPath.closeJar();
342     }
343   }
344
345   public String JavaDoc toString()
346   {
347     return "TreeLoader[" + _dir + "]";
348   }
349 }
350
Popular Tags