KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.services.reflect.DatabaseClasses
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.sanity.SanityManager;
25
26 import org.apache.derby.iapi.services.loader.ClassFactory;
27 import org.apache.derby.iapi.services.loader.GeneratedClass;
28 import org.apache.derby.iapi.services.loader.ClassInspector;
29
30 import org.apache.derby.iapi.services.monitor.ModuleControl;
31 import org.apache.derby.iapi.services.monitor.ModuleSupportable;
32 import org.apache.derby.iapi.services.monitor.Monitor;
33
34 import org.apache.derby.iapi.error.StandardException;
35 import org.apache.derby.iapi.services.property.PropertyUtil;
36
37 import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
38 import org.apache.derby.iapi.services.monitor.Monitor;
39
40 import org.apache.derby.iapi.services.compiler.*;
41 import java.lang.reflect.Modifier JavaDoc;
42 import org.apache.derby.iapi.sql.compile.CodeGeneration;
43
44 import org.apache.derby.iapi.util.ByteArray;
45 import org.apache.derby.iapi.services.io.FileUtil;
46 import org.apache.derby.iapi.services.i18n.MessageService;
47 import org.apache.derby.iapi.reference.Property;
48 import org.apache.derby.iapi.reference.SQLState;
49 import org.apache.derby.iapi.reference.MessageId;
50 import org.apache.derby.iapi.reference.ClassName;
51
52 import java.util.Properties JavaDoc;
53 import java.util.Hashtable JavaDoc;
54
55 import java.io.ObjectStreamClass JavaDoc;
56 import java.io.File JavaDoc;
57 import java.io.FileOutputStream JavaDoc;
58 import java.io.IOException JavaDoc;
59 import java.io.Serializable JavaDoc;
60
61 /**
62
63     An abstract implementation of the ClassFactory. This package can
64     be extended to fully implement a ClassFactory. Implementations can
65     differ in two areas, how they load a class and how they invoke methods
66     of the generated class.
67
68     <P>
69     This class manages a hash table of loaded generated classes and
70     their GeneratedClass objects. A loaded class may be referenced
71     multiple times -- each class has a reference count associated
72     with it. When a load request arrives, if the class has already
73     been loaded, its ref count is incremented. For a remove request,
74     the ref count is decremented unless it is the last reference,
75     in which case the class is removed. This is transparent to users.
76
77     @see org.apache.derby.iapi.services.loader.ClassFactory
78 */

79
80 abstract class DatabaseClasses
81     implements ClassFactory, ModuleControl
82 {
83     /*
84     ** Fields
85     */

86
87     private ClassInspector classInspector;
88     private JavaFactory javaFactory;
89
90     private UpdateLoader applicationLoader;
91
92     /*
93     ** Constructor
94     */

95
96     DatabaseClasses() {
97     }
98
99     /*
100     ** Public methods of ModuleControl
101     */

102
103     public void boot(boolean create, Properties JavaDoc startParams)
104         throws StandardException
105     {
106
107         classInspector = new ClassInspector(this);
108
109         //
110
//The ClassFactory runs per service (database) mode (booted as a service module after AccessFactory).
111
//If the code that booted
112
//us needs a per-database classpath then they pass in the classpath using
113
//the runtime property BOOT_DB_CLASSPATH in startParams
114

115
116         String JavaDoc classpath = null;
117         if (startParams != null) {
118             classpath = startParams.getProperty(Property.BOOT_DB_CLASSPATH);
119         }
120
121         if (classpath != null) {
122             applicationLoader = new UpdateLoader(classpath, this, true,
123                                                  true);
124         }
125
126         javaFactory = (JavaFactory) org.apache.derby.iapi.services.monitor.Monitor.startSystemModule(org.apache.derby.iapi.reference.Module.JavaFactory);
127     }
128
129
130
131     public void stop() {
132         if (applicationLoader != null)
133             applicationLoader.close();
134     }
135
136     /*
137     ** Public methods of ClassFactory
138     */

139
140     /**
141         Here we load the newly added class now, rather than waiting for the
142         findGeneratedClass(). Thus we are assuming that the class is going
143         to be used sometime soon. Delaying the load would mean storing the class
144         data in a file, this wastes cycles and compilcates the cleanup.
145
146         @see ClassFactory#loadGeneratedClass
147
148         @exception StandardException Class format is bad.
149     */

150     public final GeneratedClass loadGeneratedClass(String JavaDoc fullyQualifiedName, ByteArray classDump)
151         throws StandardException {
152
153
154             try {
155
156
157                 return loadGeneratedClassFromData(fullyQualifiedName, classDump);
158
159             } catch (LinkageError JavaDoc le) {
160
161                 WriteClassFile(fullyQualifiedName, classDump, le);
162
163                 throw StandardException.newException(SQLState.GENERATED_CLASS_LINKAGE_ERROR,
164                             le, fullyQualifiedName);
165
166             } catch (VirtualMachineError JavaDoc vme) { // these may be beyond saving, but fwiw
167

168                 WriteClassFile(fullyQualifiedName, classDump, vme);
169
170                 throw vme;
171             }
172
173     }
174
175     private static void WriteClassFile(String JavaDoc fullyQualifiedName, ByteArray bytecode, Throwable JavaDoc t) {
176
177         // get the un-qualified name and add the extension
178
int lastDot = fullyQualifiedName.lastIndexOf((int)'.');
179         String JavaDoc filename = fullyQualifiedName.substring(lastDot+1,fullyQualifiedName.length()).concat(".class");
180
181         Object JavaDoc env = Monitor.getMonitor().getEnvironment();
182         File JavaDoc dir = env instanceof File JavaDoc ? (File JavaDoc) env : null;
183
184         File JavaDoc classFile = FileUtil.newFile(dir,filename);
185
186         // find the error stream
187
HeaderPrintWriter errorStream = Monitor.getStream();
188
189         try {
190             FileOutputStream JavaDoc fis = new FileOutputStream JavaDoc(classFile);
191             fis.write(bytecode.getArray(),
192                 bytecode.getOffset(), bytecode.getLength());
193             fis.flush();
194             if (t!=null) {
195                 errorStream.printlnWithHeader(MessageService.getTextMessage(MessageId.CM_WROTE_CLASS_FILE, fullyQualifiedName, classFile, t));
196             }
197             fis.close();
198         } catch (IOException JavaDoc e) {
199             if (SanityManager.DEBUG)
200                 SanityManager.THROWASSERT("Unable to write .class file");
201         }
202     }
203
204     public ClassInspector getClassInspector() {
205         return classInspector;
206     }
207
208
209     public final Class JavaDoc loadApplicationClass(String JavaDoc className)
210         throws ClassNotFoundException JavaDoc {
211         
212         if (className.startsWith("org.apache.derby.")) {
213             // Assume this is an engine class, if so
214
// try to load from this class loader,
215
// this ensures in strange class loader
216
// environments we do not get ClassCastExceptions
217
// when an engine class is loaded through a different
218
// class loader to the rest of the engine.
219
try {
220                 return Class.forName(className);
221             } catch (ClassNotFoundException JavaDoc cnfe)
222             {
223                 // fall through to the code below,
224
// could be client or tools class
225
// in a different loader.
226
}
227         }
228  
229         Throwable JavaDoc loadError;
230         try {
231             try {
232                 return loadClassNotInDatabaseJar(className);
233             } catch (ClassNotFoundException JavaDoc cnfe) {
234                 if (applicationLoader == null)
235                     throw cnfe;
236                 Class JavaDoc c = applicationLoader.loadClass(className, true);
237                 if (c == null)
238                     throw cnfe;
239                 return c;
240             }
241         }
242         catch (SecurityException JavaDoc se)
243         {
244             // Thrown if the class has been comprimised in some
245
// way, e.g. modified in a signed jar.
246
loadError = se;
247         }
248         catch (LinkageError JavaDoc le)
249         {
250             // some error linking the jar, again could
251
// be malicious code inserted into a jar.
252
loadError = le;
253         }
254         throw new ClassNotFoundException JavaDoc(className + " : " + loadError.getMessage());
255     }
256     
257     abstract Class JavaDoc loadClassNotInDatabaseJar(String JavaDoc className)
258         throws ClassNotFoundException JavaDoc;
259
260     public final Class JavaDoc loadApplicationClass(ObjectStreamClass JavaDoc classDescriptor)
261         throws ClassNotFoundException JavaDoc {
262         return loadApplicationClass(classDescriptor.getName());
263     }
264
265     public boolean isApplicationClass(Class JavaDoc theClass) {
266
267         return theClass.getClassLoader()
268             instanceof JarLoader;
269     }
270
271     public void notifyModifyJar(boolean reload) throws StandardException {
272         if (applicationLoader != null) {
273             applicationLoader.modifyJar(reload);
274         }
275     }
276
277     /**
278         Notify the class manager that the classpath has been modified.
279
280         @exception StandardException thrown on error
281     */

282     public void notifyModifyClasspath(String JavaDoc classpath) throws StandardException {
283
284         if (applicationLoader != null) {
285             applicationLoader.modifyClasspath(classpath);
286         }
287     }
288
289
290     public int getClassLoaderVersion() {
291         if (applicationLoader != null) {
292             return applicationLoader.getClassLoaderVersion();
293         }
294
295         return -1;
296     }
297
298     public ByteArray buildSpecificFactory(String JavaDoc className, String JavaDoc factoryName)
299         throws StandardException {
300
301         ClassBuilder cb = javaFactory.newClassBuilder(this, CodeGeneration.GENERATED_PACKAGE_PREFIX,
302             Modifier.PUBLIC | Modifier.FINAL, factoryName, "org.apache.derby.impl.services.reflect.GCInstanceFactory");
303
304         MethodBuilder constructor = cb.newConstructorBuilder(Modifier.PUBLIC);
305
306         constructor.callSuper();
307         constructor.methodReturn();
308         constructor.complete();
309         constructor = null;
310
311         MethodBuilder noArg = cb.newMethodBuilder(Modifier.PUBLIC, ClassName.GeneratedByteCode, "getNewInstance");
312         noArg.pushNewStart(className);
313         noArg.pushNewComplete(0);
314         noArg.methodReturn();
315         noArg.complete();
316         noArg = null;
317
318         return cb.getClassBytecode();
319     }
320
321     /*
322     ** Class specific methods
323     */

324     
325     /*
326     ** Keep track of loaded generated classes and their GeneratedClass objects.
327     */

328
329     abstract LoadedGeneratedClass loadGeneratedClassFromData(String JavaDoc fullyQualifiedName, ByteArray classDump);
330 }
331
Popular Tags