KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jpublish > action > jython > JythonClassLoader


1 /*--
2
3  Copyright (C) 2001-2003 Aetrion LLC.
4  All rights reserved.
5  
6  Redistribution and use in source and binary forms, with or without
7  modification, are permitted provided that the following conditions
8  are met:
9  
10  1. Redistributions of source code must retain the above copyright
11     notice, this list of conditions, and the following disclaimer.
12  
13  2. Redistributions in binary form must reproduce the above copyright
14     notice, this list of conditions, and the disclaimer that follows
15     these conditions in the documentation and/or other materials
16     provided with the distribution.
17
18  3. The name "JPublish" must not be used to endorse or promote products
19     derived from this software without prior written permission. For
20     written permission, please contact info@aetrion.com.
21  
22  4. Products derived from this software may not be called "JPublish", nor
23     may "JPublish" appear in their name, without prior written permission
24     from Aetrion LLC (info@aetrion.com).
25  
26  In addition, the authors of this software request (but do not require)
27  that you include in the end-user documentation provided with the
28  redistribution and/or in the software itself an acknowledgement equivalent
29  to the following:
30      "This product includes software developed by
31       Aetrion LLC (http://www.aetrion.com/)."
32
33  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
34  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
35  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36  DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
37  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
42  IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43  POSSIBILITY OF SUCH DAMAGE.
44
45  For more information on JPublish, please see <http://www.jpublish.org/>.
46  
47  */

48
49 package org.jpublish.action.jython;
50
51 import java.io.File JavaDoc;
52 import java.io.IOException JavaDoc;
53 import java.io.InputStream JavaDoc;
54 import java.net.MalformedURLException JavaDoc;
55 import java.net.URL JavaDoc;
56 import java.util.ArrayList JavaDoc;
57 import java.util.zip.ZipEntry JavaDoc;
58 import java.util.zip.ZipFile JavaDoc;
59
60 import com.anthonyeden.lib.util.IOUtilities;
61 import com.anthonyeden.lib.util.MessageUtilities;
62 import org.apache.commons.logging.Log;
63 import org.apache.commons.logging.LogFactory;
64 import org.jpublish.JPublishEngine;
65
66 /**
67  * Custom class loader used to load classes which are exposed to Jython.
68  *
69  * @author Anthony Eden
70  */

71
72 public class JythonClassLoader extends ClassLoader JavaDoc {
73
74     private static Log log = LogFactory.getLog(JythonClassLoader.class);
75
76     private File JavaDoc searchDirectory;
77
78     /**
79      * Construct a new JythonClassLoader which searches for classes in the given directory.
80      *
81      * @param searchDirectory The root directory where classes may be found
82      */

83
84     public JythonClassLoader(String JavaDoc searchDirectory) {
85         this(new File JavaDoc(searchDirectory));
86     }
87
88     /**
89      * Construct a new JythonClassLoader which searches for classes in the parent ClassLoader first and then in the
90      * given directory.
91      *
92      * @param searchDirectory The root directory where classes may be found
93      * @param parent The parent ClassLoader
94      */

95
96     public JythonClassLoader(String JavaDoc searchDirectory, ClassLoader JavaDoc parent) {
97         this(new File JavaDoc(searchDirectory), parent);
98     }
99
100     /**
101      * Construct a new JythonClassLoader which searches for classes in the given directory.
102      *
103      * @param searchDirectory The root directory where classes may be found
104      */

105
106     public JythonClassLoader(File JavaDoc searchDirectory) {
107         super();
108         this.searchDirectory = searchDirectory;
109     }
110
111     /**
112      * Construct a new JythonClassLoader which searches for classes in the parent ClassLoader first and then in the
113      * given directory.
114      *
115      * @param searchDirectory The root directory where classes may be found
116      * @param parent The parent ClassLoader
117      */

118
119     public JythonClassLoader(File JavaDoc searchDirectory, ClassLoader JavaDoc parent) {
120         super(parent);
121         this.searchDirectory = searchDirectory;
122     }
123
124     /**
125      * Get the directory which is searched for class files.
126      *
127      * @return The search directory
128      */

129
130     public File JavaDoc getSearchDirectory() {
131         return searchDirectory;
132     }
133
134     /**
135      * Set the directory which is searched for class files.
136      *
137      * @param searchDirectory The new search directory
138      */

139
140     public void setSearchDirectory(File JavaDoc searchDirectory) {
141         this.searchDirectory = searchDirectory;
142     }
143
144     /**
145      * Find the class with the given class name.
146      *
147      * @param name The class name
148      * @return the Class object
149      * @throws ClassNotFoundException
150      */

151
152     public Class JavaDoc findClass(String JavaDoc name) throws ClassNotFoundException JavaDoc {
153         byte[] b = loadClassData(name);
154         return defineClass(name, b, 0, b.length);
155     }
156
157     /**
158      * Find the resource URL with the given name. If the resource URL cannot be found then this method returns null.
159      *
160      * @param name The resource name
161      * @return The URL
162      */

163
164     public URL JavaDoc findResource(String JavaDoc name) {
165         File JavaDoc file = findFile(name);
166         if (file == null) {
167             return null;
168         }
169
170         try {
171             String JavaDoc urlString = "jar:" + file.toURL() + "!/" + name;
172             log.debug("URL: " + urlString);
173
174             return new URL JavaDoc(urlString);
175         } catch (MalformedURLException JavaDoc e) {
176             log.error("Malformed URL error: " + e.getMessage());
177             return null;
178         }
179     }
180
181     /**
182      * Load the class data for the given name.
183      *
184      * @param name The class name
185      * @return The class data as a byte array
186      * @throws ClassNotFoundException
187      */

188
189     private byte[] loadClassData(String JavaDoc name) throws ClassNotFoundException JavaDoc {
190         log.debug("Loading class data for " + name);
191
192         if (!name.endsWith(".class")) {
193             Object JavaDoc[] args = {name};
194             throw new ClassNotFoundException JavaDoc(MessageUtilities.getMessage(getClass(), JPublishEngine.MESSAGE_PACKAGE, "invalidClassName",
195                     args));
196         }
197
198         String JavaDoc path = name.replace('.', '/') + ".class";
199
200         byte[] data = loadData(path);
201         if (data == null) {
202             Object JavaDoc[] args = {name, path};
203             throw new ClassNotFoundException JavaDoc(MessageUtilities.getMessage(getClass(), JPublishEngine.MESSAGE_PACKAGE, "classNotFound",
204                     args));
205         }
206
207         return data;
208     }
209
210     /**
211      * Find the ZIP or JAR file which contains the given path.
212      *
213      * @param path The path
214      * @return The FIle
215      */

216
217     private File JavaDoc findFile(String JavaDoc path) {
218         File JavaDoc[] files = searchDirectory.listFiles();
219         for (int i = 0; i < files.length; i++) {
220             if (files[i].getName().endsWith(".jar") ||
221                     files[i].getName().endsWith(".zip")) {
222                 //log.debug("Looking for data in " + files[i]);
223

224                 try {
225                     ZipFile JavaDoc zipFile = new ZipFile JavaDoc(files[i]);
226                     ZipEntry JavaDoc zipEntry = zipFile.getEntry(path);
227
228                     if (zipEntry != null) {
229                         return files[i];
230                     }
231                 } catch (IOException JavaDoc e) {
232                     Object JavaDoc[] args = {files[i].getPath(), e.getMessage()};
233                     String JavaDoc msg = MessageUtilities.getMessage(getClass(),
234                             JPublishEngine.MESSAGE_PACKAGE, "findFileIOError",
235                             args);
236                     log.error(msg);
237                 }
238             }
239         }
240         return null;
241     }
242
243     /**
244      * Load the data from the given path. This method first tries to find the path in any JAR or ZIP files in the
245      * specified directory. If a JAR or ZIP file is found then the data is read from the file and returned as a byte
246      * array.
247      *
248      * @param path The path
249      * @return The byte array of data
250      */

251
252     private byte[] loadData(String JavaDoc path) {
253         File JavaDoc file = findFile(path);
254         if (file == null) {
255             return null;
256         }
257
258         InputStream JavaDoc in = null;
259         try {
260             ZipFile JavaDoc zipFile = new ZipFile JavaDoc(file);
261             ZipEntry JavaDoc zipEntry = zipFile.getEntry(path);
262
263             long dataSize = zipEntry.getSize();
264             log.debug("ZIP entry size: " + dataSize);
265
266             ArrayList JavaDoc dataList = new ArrayList JavaDoc();
267             in = zipFile.getInputStream(zipEntry);
268             int b = -1;
269             while ((b = in.read()) != -1) {
270                 dataList.add(new Byte JavaDoc((byte) b));
271             }
272
273             byte[] data = new byte[dataList.size()];
274             for (int j = 0; j < data.length; j++) {
275                 data[j] = ((Byte JavaDoc) dataList.get(j)).byteValue();
276             }
277
278             return data;
279         } catch (IOException JavaDoc e) {
280             log.error("IO error: " + e.getMessage());
281         } finally {
282             IOUtilities.close(in);
283         }
284
285         return null;
286     }
287
288 }
289
Popular Tags