KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.services.reflect.UpdateLoader
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.iapi.services.context.ContextService;
25 import org.apache.derby.iapi.services.monitor.Monitor;
26 import org.apache.derby.iapi.services.monitor.Monitor;
27 import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
28 import org.apache.derby.iapi.util.IdUtil;
29 import org.apache.derby.iapi.error.StandardException;
30 import org.apache.derby.iapi.services.locks.ShExLockable;
31 import org.apache.derby.iapi.services.locks.ShExQual;
32 import org.apache.derby.iapi.services.locks.LockFactory;
33 import org.apache.derby.iapi.services.locks.Latch;
34 import org.apache.derby.iapi.services.locks.C_LockFactory;
35 import org.apache.derby.iapi.services.loader.ClassFactoryContext;
36 import org.apache.derby.iapi.services.loader.JarReader;
37 import org.apache.derby.iapi.services.property.PersistentSet;
38
39 import org.apache.derby.iapi.services.property.PropertyUtil;
40 import org.apache.derby.iapi.reference.Property;
41
42 import java.io.InputStream JavaDoc;
43
44 import org.apache.derby.iapi.reference.MessageId;
45 import org.apache.derby.iapi.reference.Module;
46 import org.apache.derby.iapi.services.i18n.MessageService;
47
48 public class UpdateLoader {
49
50     private JarLoader[] jarList;
51     private HeaderPrintWriter vs;
52     private final ClassLoader JavaDoc myLoader;
53     private boolean initDone;
54     private String JavaDoc thisClasspath;
55     private final LockFactory lf;
56     private final ShExLockable classLoaderLock;
57     private int version;
58     private boolean normalizeToUpper;
59     private DatabaseClasses parent;
60
61     private boolean needReload;
62     private JarReader jarReader;
63
64     public UpdateLoader(String JavaDoc classpath, DatabaseClasses parent, boolean verbose, boolean normalizeToUpper)
65         throws StandardException {
66
67         this.normalizeToUpper = normalizeToUpper;
68         this.parent = parent;
69         lf = (LockFactory) Monitor.getServiceModule(parent, Module.LockFactory);
70
71         if (verbose) {
72             vs = Monitor.getStream();
73         }
74         
75         myLoader = getClass().getClassLoader();
76
77         this.classLoaderLock = new ClassLoaderLock(this);
78
79         initializeFromClassPath(classpath);
80     }
81
82     private void initializeFromClassPath(String JavaDoc classpath) throws StandardException {
83
84         String JavaDoc[][] elements = IdUtil.parseDbClassPath(classpath, normalizeToUpper);
85         
86         int jarCount = elements.length;
87         jarList = new JarLoader[jarCount];
88             
89         for (int i = 0; i < jarCount; i++) {
90             jarList[i] = new JarLoader(this, elements[i], vs);
91         }
92
93         if (vs != null) {
94             vs.println(MessageService.getTextMessage(MessageId.CM_CLASS_LOADER_START, classpath));
95         }
96         
97         thisClasspath = classpath;
98         initDone = false;
99     }
100
101     /**
102         Load the class from the class path.
103
104         @exception ClassNotFoundException Class can not be found
105     */

106     public Class JavaDoc loadClass(String JavaDoc className, boolean resolve)
107         throws ClassNotFoundException JavaDoc {
108
109
110         JarLoader jl = null;
111
112         boolean unlockLoader = false;
113         try {
114             unlockLoader = lockClassLoader(ShExQual.SH);
115
116             synchronized (this) {
117
118                 if (needReload) {
119                     reload();
120                 }
121             
122                 Class JavaDoc clazz = checkLoaded(className, resolve);
123                 if (clazz != null)
124                     return clazz;
125
126                 String JavaDoc jvmClassName = className.replace('.', '/').concat(".class");
127
128                 if (!initDone)
129                     initLoaders();
130
131                 for (int i = 0; i < jarList.length; i++) {
132
133                     jl = jarList[i];
134
135                     Class JavaDoc c = jl.loadClassData(className, jvmClassName, resolve);
136                     if (c != null) {
137                         if (vs != null)
138                             vs.println(MessageService.getTextMessage(MessageId.CM_CLASS_LOAD, className, jl.getJarName()));
139
140                         return c;
141                     }
142                 }
143             }
144
145             return null;
146
147
148         } catch (StandardException se) {
149             throw new ClassNotFoundException JavaDoc(MessageService.getTextMessage(MessageId.CM_CLASS_LOAD_EXCEPTION, className, jl == null ? null : jl.getJarName(), se));
150         } finally {
151             if (unlockLoader) {
152                 lf.unlock(this, this, classLoaderLock, ShExQual.SH);
153             }
154         }
155     }
156
157     public InputStream JavaDoc getResourceAsStream(String JavaDoc name) {
158
159         InputStream JavaDoc is = (myLoader == null) ?
160             ClassLoader.getSystemResourceAsStream(name) :
161             myLoader.getResourceAsStream(name);
162
163         if (is != null)
164             return is;
165
166         // match behaviour of standard class loaders.
167
if (name.endsWith(".class"))
168             return null;
169
170         boolean unlockLoader = false;
171         try {
172             unlockLoader = lockClassLoader(ShExQual.SH);
173
174             synchronized (this) {
175
176                 if (needReload) {
177                     reload();
178                 }
179
180                 if (!initDone)
181                     initLoaders();
182
183                 for (int i = 0; i < jarList.length; i++) {
184
185                     JarLoader jl = jarList[i];
186
187                     is = jl.getStream(name);
188                     if (is != null) {
189                         return is;
190                     }
191                 }
192             }
193             return null;
194
195         } catch (StandardException se) {
196             return null;
197         } finally {
198             if (unlockLoader) {
199                 lf.unlock(this, this, classLoaderLock, ShExQual.SH);
200             }
201         }
202     }
203
204     public synchronized void modifyClasspath(String JavaDoc classpath)
205         throws StandardException {
206
207         // lock transaction classloader exclusively
208
lockClassLoader(ShExQual.EX);
209         version++;
210
211
212         modifyJar(false);
213         initializeFromClassPath(classpath);
214     }
215
216
217     public synchronized void modifyJar(boolean reload) throws StandardException {
218
219         // lock transaction classloader exclusively
220
lockClassLoader(ShExQual.EX);
221         version++;
222
223         if (!initDone)
224             return;
225
226         if (reload) {
227             //first close the existing jar file opens
228
close();
229             initializeFromClassPath(thisClasspath);
230             return;
231         }
232
233         // first thing to do is to remove all Class entries
234
// and then get a complete set of loaders ...
235
synchronized (this) {
236
237             for (int i = 0; i < jarList.length; i++) {
238
239                 JarLoader jl = jarList[i];
240
241                 JarFile newJarFile = jl.setInvalid(reload);
242             }
243         }
244     }
245
246     private boolean lockClassLoader(ShExQual qualifier)
247         throws StandardException {
248
249         if (lf == null)
250             return false;
251
252         ClassFactoryContext cfc = (ClassFactoryContext) ContextService.getContextOrNull(ClassFactoryContext.CONTEXT_ID);
253
254         // This method can be called from outside of the database
255
// engine, in which case tc will be null. In that case
256
// we lock the class loader only for the duration of
257
// the loadClass().
258
Object JavaDoc lockSpace = null;
259         
260         if (cfc != null) {
261             lockSpace = cfc.getLockSpace();
262         }
263         if (lockSpace == null)
264             lockSpace = this;
265
266         lf.lockObject(lockSpace, lockSpace, classLoaderLock, qualifier, C_LockFactory.TIMED_WAIT);
267
268         return (lockSpace == this);
269     }
270
271     Class JavaDoc checkLoaded(String JavaDoc className, boolean resolve) {
272
273         for (int i = 0; i < jarList.length; i++) {
274             Class JavaDoc c = jarList[i].checkLoaded(className, resolve);
275             if (c != null)
276                 return c;
277         }
278         return null;
279     }
280
281     public void close() {
282
283         for (int i = 0; i < jarList.length; i++) {
284             jarList[i].setInvalid(false);
285         }
286
287     }
288
289     private void initLoaders() {
290
291         if (initDone)
292             return;
293
294         for (int i = 0; i < jarList.length; i++) {
295             jarList[i].initialize();
296         }
297         initDone = true;
298     }
299
300     public int getClassLoaderVersion() {
301         return version;
302     }
303
304     synchronized void needReload() {
305         version++;
306         needReload = true;
307     }
308
309     private void reload() throws StandardException {
310         thisClasspath = getClasspath();
311         // first close the existing jar file opens
312
close();
313         initializeFromClassPath(thisClasspath);
314         needReload = false;
315     }
316
317
318     private String JavaDoc getClasspath()
319         throws StandardException {
320
321         ClassFactoryContext cfc = (ClassFactoryContext) ContextService.getContextOrNull(ClassFactoryContext.CONTEXT_ID);
322
323         PersistentSet ps = cfc.getPersistentSet();
324         
325         String JavaDoc classpath = PropertyUtil.getServiceProperty(ps, Property.DATABASE_CLASSPATH);
326
327         //
328
//In per database mode we must always have a classpath. If we do not
329
//yet have one we make one up.
330
if (classpath==null)
331             classpath="";
332
333
334         return classpath;
335     }
336
337     JarReader getJarReader() {
338         if (jarReader == null) {
339
340             ClassFactoryContext cfc = (ClassFactoryContext) ContextService.getContextOrNull(ClassFactoryContext.CONTEXT_ID);
341
342             jarReader = cfc.getJarReader();
343         }
344         return jarReader;
345     }
346 }
347
348
349 class ClassLoaderLock extends ShExLockable {
350
351     private UpdateLoader myLoader;
352
353     ClassLoaderLock(UpdateLoader myLoader) {
354         this.myLoader = myLoader;
355     }
356
357     public void unlockEvent(Latch lockInfo)
358     {
359         super.unlockEvent(lockInfo);
360
361         if (lockInfo.getQualifier().equals(ShExQual.EX)) {
362             // how do we tell if we are reverting or not
363
myLoader.needReload();
364         }
365     }
366 }
367
Popular Tags