KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > services > reflect > JarLoader


1 /*
2
3    Derby - Class org.apache.derby.impl.services.reflect.JarLoader
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.impl.services.reflect;
23
24 import org.apache.derby.impl.sql.execute.JarUtil;
25 import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
26 import org.apache.derby.iapi.error.StandardException;
27
28 import java.io.File JavaDoc;
29 import java.io.InputStream JavaDoc;
30 import java.io.IOException JavaDoc;
31
32 import java.util.zip.ZipFile JavaDoc;
33 import java.util.zip.ZipInputStream JavaDoc;
34 import java.util.zip.ZipEntry JavaDoc;
35
36
37 import org.apache.derby.iapi.services.io.LimitInputStream;
38 import org.apache.derby.iapi.util.IdUtil;
39
40 import org.apache.derby.iapi.reference.MessageId;
41 import org.apache.derby.iapi.services.i18n.MessageService;
42
43
44 public class JarLoader extends ClassLoader JavaDoc {
45
46     private static final JarFile jarFileFactory;
47
48     static {
49
50         //
51
jarFileFactory = new JarFileJava2();
52     }
53
54     private UpdateLoader updateLoader;
55     private JarFile jf;
56     private HeaderPrintWriter vs;
57
58     JarLoader(UpdateLoader updateLoader, String JavaDoc[] name, HeaderPrintWriter vs) {
59
60         this.updateLoader = updateLoader;
61         this.jf = jarFileFactory.newJarFile(name);
62         this.vs = vs;
63     }
64
65     // Initialize the class loader so it knows if it
66
// is loading from a ZipFile or an InputStream
67
void initialize() {
68
69         Object JavaDoc zipData = load();
70
71         try {
72
73             if (zipData instanceof File JavaDoc) {
74                 jf.initialize((File JavaDoc) zipData);
75                 return;
76             }
77
78             if (zipData instanceof InputStream JavaDoc) {
79                 jf.isStream = true;
80                 try {
81                     ((InputStream JavaDoc) zipData).close();
82                 } catch (IOException JavaDoc ioe) {
83                 }
84                 return;
85             }
86         } catch (IOException JavaDoc ioe) {
87             if (vs != null)
88                 vs.println(MessageService.getTextMessage(MessageId.CM_LOAD_JAR_EXCEPTION, getJarName(), ioe));
89         }
90
91         // No such zip.
92
setInvalid(false);
93     }
94
95     /**
96         Handle all requests to the top-level loader.
97
98         @exception ClassNotFoundException Class can not be found
99     */

100     public Class JavaDoc loadClass(String JavaDoc className, boolean resolve)
101         throws ClassNotFoundException JavaDoc {
102
103         // we attempt the system class load even if we
104
// are stale because otherwise we will fail
105
// to load java.* classes which confuses some VMs
106
try {
107             return Class.forName(className);
108         } catch (ClassNotFoundException JavaDoc cnfe) {
109
110             if (updateLoader == null)
111                 throw new ClassNotFoundException JavaDoc(MessageService.getTextMessage(MessageId.CM_STALE_LOADER, className));
112
113             Class JavaDoc c = updateLoader.loadClass(className, resolve);
114             if (c == null)
115                 throw cnfe;
116             return c;
117         }
118     }
119
120     /**
121         
122     */

123     public InputStream JavaDoc getResourceAsStream(String JavaDoc name) {
124         if (updateLoader == null)
125             return null;
126         return updateLoader.getResourceAsStream(name);
127     }
128
129     /*
130     ** Package level api
131     */

132     final String JavaDoc getJarName() {
133         return jf.getJarName();
134     }
135
136     Class JavaDoc loadClassData(String JavaDoc className, String JavaDoc jvmClassName, boolean resolve) {
137
138         if (updateLoader == null)
139             return null;
140
141         try {
142             if (jf.isZip())
143                 return loadClassDataFromJar(className, jvmClassName, resolve);
144
145             if (jf.isStream) {
146                 // have to use a new stream each time
147
return loadClassData((InputStream JavaDoc) load(),
148                         className, jvmClassName, resolve);
149             }
150
151             return null;
152         } catch (IOException JavaDoc ioe) {
153             if (vs != null)
154                 vs.println(MessageService.getTextMessage(MessageId.CM_CLASS_LOAD_EXCEPTION, className, getJarName(), ioe));
155             return null;
156         }
157     }
158
159     /**
160         Get an InputStream for the given resource.
161     */

162     InputStream JavaDoc getStream(String JavaDoc name) {
163
164         if (updateLoader == null)
165             return null;
166
167         if (jf.isZip())
168             return getRawStream(jf.getZip(), name);
169
170         if (jf.isStream) {
171             return getRawStream((InputStream JavaDoc) load(), name);
172         }
173         return null;
174     }
175
176
177     /*
178     ** Private api
179     */

180
181
182     private Class JavaDoc loadClassDataFromJar(String JavaDoc className, String JavaDoc jvmClassName, boolean resolve)
183         throws IOException JavaDoc {
184
185         ZipEntry JavaDoc ze = jf.getEntry(jvmClassName);
186         if (ze == null)
187             return null;
188
189         InputStream JavaDoc in = jf.getZip().getInputStream(ze);
190
191         try {
192             return loadClassData(ze, in, className, resolve);
193         } finally {
194             in.close();
195         }
196     }
197
198     private Class JavaDoc loadClassData(
199         InputStream JavaDoc in, String JavaDoc className, String JavaDoc jvmClassName, boolean resolve)
200         throws IOException JavaDoc {
201
202         ZipInputStream JavaDoc zipIn = jf.getZipOnStream(in);
203
204         for (;;) {
205
206             ZipEntry JavaDoc ze = jf.getNextEntry(zipIn);
207             if (ze == null) {
208                 zipIn.close();
209                 return null;
210             }
211
212             if (ze.getName().equals(jvmClassName)) {
213                 Class JavaDoc c = loadClassData(ze, zipIn, className, resolve);
214                 zipIn.close();
215                 return c;
216             }
217         }
218         
219     }
220
221     private Class JavaDoc loadClassData(ZipEntry JavaDoc ze, InputStream JavaDoc in,
222         String JavaDoc className, boolean resolve) throws IOException JavaDoc {
223
224         byte[] data = jf.readData(ze, in, className);
225
226         Object JavaDoc[] signers = jf.getSigners(className, ze);
227
228         synchronized (updateLoader) {
229             // see if someone else loaded it while we
230
// were getting the bytes ...
231
Class JavaDoc c = updateLoader.checkLoaded(className, resolve);
232             if (c == null) {
233                 c = defineClass(className, data, 0, data.length);
234                 if (signers != null) {
235                     setSigners(c, signers);
236                 }
237                 if (resolve)
238                     resolveClass(c);
239             }
240             return c;
241
242         }
243     }
244
245     Class JavaDoc checkLoaded(String JavaDoc className, boolean resolve) {
246         if (updateLoader == null)
247             return null;
248
249         Class JavaDoc c = findLoadedClass(className);
250         if ((c != null) && resolve)
251             resolveClass(c);
252         return c;
253     }
254
255     private Object JavaDoc load() {
256
257         String JavaDoc[] dbJarName = jf.name;
258
259         String JavaDoc schemaName = dbJarName[IdUtil.DBCP_SCHEMA_NAME];
260         String JavaDoc sqlName = dbJarName[IdUtil.DBCP_SQL_JAR_NAME];
261
262         // don't need a connection, just call the code directly
263
try {
264             return updateLoader.getJarReader().readJarFile(schemaName, sqlName);
265         } catch (StandardException se) {
266             if (vs != null)
267                 vs.println(MessageService.getTextMessage(MessageId.CM_LOAD_JAR_EXCEPTION, jf.getJarName(), se));
268             return null;
269         }
270
271     }
272
273     JarFile setInvalid(boolean newJarFile) {
274
275         jf.setInvalid();
276         updateLoader = null;
277         return newJarFile ? jarFileFactory.newJarFile(jf.name) : null;
278     }
279
280     /*
281     ** Routines to get an InputStream for a namedResource
282     */

283
284     /**
285         Get a stream directly from a ZipFile.
286         In this case we can safely return the stream directly.
287         It's a new stream set up by the zip code to read just
288         the contents of this entry.
289     */

290     private InputStream JavaDoc getRawStream(ZipFile JavaDoc zip, String JavaDoc name) {
291
292         try {
293             ZipEntry JavaDoc ze = zip.getEntry(name);
294             if (ze == null)
295                 return null;
296
297             return zip.getInputStream(ze);
298         } catch (IOException JavaDoc ioe) {
299             return null;
300         }
301     }
302
303     /**
304         Get a stream from a zip file that is itself a stream.
305         Here we need to get the size of the zip entry and
306         put a limiting stream around it. Otherwise the
307         caller would end up reading the entire zip file!
308     */

309     private InputStream JavaDoc getRawStream(InputStream JavaDoc in, String JavaDoc name) {
310
311         ZipInputStream JavaDoc zipIn = null;
312         try {
313             zipIn = new ZipInputStream JavaDoc(in);
314
315             ZipEntry JavaDoc ze;
316             while ((ze = jf.getNextEntry(zipIn)) != null) {
317
318                 if (ze.getName().equals(name)) {
319                     LimitInputStream lis = new LimitInputStream(zipIn);
320                     lis.setLimit((int) ze.getSize());
321                     return lis;
322                 }
323             }
324
325             zipIn.close();
326
327         } catch (IOException JavaDoc ioe) {
328             if (zipIn != null) {
329                 try {
330                     zipIn.close();
331                 } catch (IOException JavaDoc ioe2) {
332                 }
333             }
334         }
335         return null;
336     }
337 }
338
Popular Tags