EMMA Coverage Report (generated Wed Jun 28 22:15:27 PDT 2006)
[all classes][org.apache.derby.impl.services.reflect]

COVERAGE SUMMARY FOR SOURCE FILE [DatabaseClasses.java]

nameclass, %method, %block, %line, %
DatabaseClasses.java100% (1/1)77%  (10/13)49%  (126/256)50%  (39/78)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class DatabaseClasses100% (1/1)77%  (10/13)49%  (126/256)50%  (39/78)
DatabaseClasses (): void 100% (1/1)100% (3/3)100% (2/2)
WriteClassFile (String, ByteArray, Throwable): void 0%   (0/1)0%   (0/62)0%   (0/16)
boot (boolean, Properties): void 100% (1/1)100% (31/31)100% (8/8)
buildSpecificFactory (String, String): ByteArray 0%   (0/1)0%   (0/42)0%   (0/13)
getClassInspector (): ClassInspector 100% (1/1)100% (3/3)100% (1/1)
getClassLoaderVersion (): int 100% (1/1)78%  (7/9)67%  (2/3)
isApplicationClass (Class): boolean 0%   (0/1)0%   (0/4)0%   (0/1)
loadApplicationClass (ObjectStreamClass): Class 100% (1/1)100% (5/5)100% (1/1)
loadApplicationClass (String): Class 100% (1/1)94%  (49/52)88%  (15/17)
loadGeneratedClass (String, ByteArray): GeneratedClass 100% (1/1)23%  (5/22)14%  (1/7)
notifyModifyClasspath (String): void 100% (1/1)100% (8/8)100% (3/3)
notifyModifyJar (boolean): void 100% (1/1)100% (8/8)100% (3/3)
stop (): void 100% (1/1)100% (7/7)100% (3/3)

1/*
2 
3   Derby - Class org.apache.derby.impl.services.reflect.DatabaseClasses
4 
5   Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable.
6 
7   Licensed under the Apache License, Version 2.0 (the "License");
8   you may not use this file except in compliance with the License.
9   You may obtain a copy of the License at
10 
11      http://www.apache.org/licenses/LICENSE-2.0
12 
13   Unless required by applicable law or agreed to in writing, software
14   distributed under the License is distributed on an "AS IS" BASIS,
15   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   See the License for the specific language governing permissions and
17   limitations under the License.
18 
19 */
20 
21package org.apache.derby.impl.services.reflect;
22 
23import org.apache.derby.iapi.services.sanity.SanityManager;
24 
25import org.apache.derby.iapi.services.loader.ClassFactory;
26import org.apache.derby.iapi.services.loader.GeneratedClass;
27import org.apache.derby.iapi.services.loader.ClassInspector;
28 
29import org.apache.derby.iapi.services.monitor.ModuleControl;
30import org.apache.derby.iapi.services.monitor.ModuleSupportable;
31import org.apache.derby.iapi.services.monitor.Monitor;
32 
33import org.apache.derby.iapi.error.StandardException;
34import org.apache.derby.iapi.services.property.PropertyUtil;
35 
36import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
37import org.apache.derby.iapi.services.monitor.Monitor;
38 
39import org.apache.derby.iapi.services.compiler.*;
40import java.lang.reflect.Modifier;
41import org.apache.derby.iapi.sql.compile.CodeGeneration;
42 
43import org.apache.derby.iapi.util.ByteArray;
44import org.apache.derby.iapi.services.io.FileUtil;
45import org.apache.derby.iapi.services.i18n.MessageService;
46import org.apache.derby.iapi.reference.Property;
47import org.apache.derby.iapi.reference.SQLState;
48import org.apache.derby.iapi.reference.MessageId;
49import org.apache.derby.iapi.reference.ClassName;
50 
51import java.util.Properties;
52import java.util.Hashtable;
53 
54import java.io.ObjectStreamClass;
55import java.io.File;
56import java.io.FileOutputStream;
57import java.io.IOException;
58import java.io.Serializable;
59 
60/**
61 
62    An abstract implementation of the ClassFactory. This package can
63        be extended to fully implement a ClassFactory. Implementations can
64        differ in two areas, how they load a class and how they invoke methods
65        of the generated class.
66 
67    <P>
68        This class manages a hash table of loaded generated classes and
69        their GeneratedClass objects.  A loaded class may be referenced
70        multiple times -- each class has a reference count associated
71        with it.  When a load request arrives, if the class has already
72        been loaded, its ref count is incremented.  For a remove request,
73        the ref count is decremented unless it is the last reference,
74        in which case the class is removed.  This is transparent to users.
75 
76        @see org.apache.derby.iapi.services.loader.ClassFactory
77*/
78 
79abstract class DatabaseClasses
80        implements ClassFactory, ModuleControl
81{
82        /*
83        ** Fields
84        */
85 
86        private        ClassInspector        classInspector;
87        private JavaFactory                javaFactory;
88 
89        private UpdateLoader                applicationLoader;
90 
91        /*
92        ** Constructor
93        */
94 
95        DatabaseClasses() {
96        }
97 
98        /*
99        ** Public methods of ModuleControl
100        */
101 
102        public void boot(boolean create, Properties startParams)
103                throws StandardException
104        {
105 
106                classInspector = new ClassInspector(this);
107 
108                //
109                //The ClassFactory runs per service (database) mode (booted as a service module after AccessFactory).
110                //If the code that booted
111                //us needs a per-database classpath then they pass in the classpath using
112                //the runtime property BOOT_DB_CLASSPATH in startParams
113 
114 
115                String classpath = null;
116                if (startParams != null) {
117                        classpath = startParams.getProperty(Property.BOOT_DB_CLASSPATH);
118                }
119 
120                if (classpath != null) {
121                        applicationLoader = new UpdateLoader(classpath, this, true,
122                                                 true);
123                }
124 
125                javaFactory = (JavaFactory) org.apache.derby.iapi.services.monitor.Monitor.startSystemModule(org.apache.derby.iapi.reference.Module.JavaFactory);
126        }
127 
128 
129 
130        public void stop() {
131                if (applicationLoader != null)
132                        applicationLoader.close();
133        }
134 
135        /*
136        **        Public methods of ClassFactory
137        */
138 
139        /**
140                Here we load the newly added class now, rather than waiting for the
141                findGeneratedClass(). Thus we are assuming that the class is going
142                to be used sometime soon. Delaying the load would mean storing the class
143                data in a file, this wastes cycles and compilcates the cleanup.
144 
145                @see ClassFactory#loadGeneratedClass
146 
147                @exception        StandardException Class format is bad.
148        */
149        public final GeneratedClass loadGeneratedClass(String fullyQualifiedName, ByteArray classDump)
150                throws StandardException {
151 
152 
153                        try {
154 
155 
156                                return loadGeneratedClassFromData(fullyQualifiedName, classDump);
157 
158                        } catch (LinkageError le) {
159 
160                            WriteClassFile(fullyQualifiedName, classDump, le);
161 
162                                throw StandardException.newException(SQLState.GENERATED_CLASS_LINKAGE_ERROR,
163                                                        le, fullyQualifiedName);
164 
165                    } catch (VirtualMachineError vme) { // these may be beyond saving, but fwiw
166 
167                            WriteClassFile(fullyQualifiedName, classDump, vme);
168 
169                            throw vme;
170                    }
171 
172        }
173 
174    private static void WriteClassFile(String fullyQualifiedName, ByteArray bytecode, Throwable t) {
175 
176                // get the un-qualified name and add the extension
177        int lastDot = fullyQualifiedName.lastIndexOf((int)'.');
178        String filename = fullyQualifiedName.substring(lastDot+1,fullyQualifiedName.length()).concat(".class");
179 
180                Object env = Monitor.getMonitor().getEnvironment();
181                File dir = env instanceof File ? (File) env : null;
182 
183                File classFile = FileUtil.newFile(dir,filename);
184 
185                // find the error stream
186                HeaderPrintWriter errorStream = Monitor.getStream();
187 
188                try {
189                        FileOutputStream fis = new FileOutputStream(classFile);
190                        fis.write(bytecode.getArray(),
191                                bytecode.getOffset(), bytecode.getLength());
192                        fis.flush();
193                        if (t!=null) {                                
194                                errorStream.printlnWithHeader(MessageService.getTextMessage(MessageId.CM_WROTE_CLASS_FILE, fullyQualifiedName, classFile, t));
195                        }
196                        fis.close();
197                } catch (IOException e) {
198                        if (SanityManager.DEBUG)
199                                SanityManager.THROWASSERT("Unable to write .class file");
200                }
201        }
202 
203        public ClassInspector getClassInspector() {
204                return classInspector;
205        }
206 
207 
208        public final Class loadApplicationClass(String className)
209                throws ClassNotFoundException {
210        
211        if (className.startsWith("org.apache.derby.")) {
212            // Assume this is an engine class, if so
213            // try to load from this class loader,
214            // this ensures in strange class loader
215            // environments we do not get ClassCastExceptions
216            // when an engine class is loaded through a different
217            // class loader to the rest of the engine.
218            try {
219                return Class.forName(className);
220            } catch (ClassNotFoundException cnfe)
221            {
222                // fall through to the code below,
223                // could be client or tools class
224                // in a different loader.
225            }
226        }
227 
228                Throwable loadError;
229                try {
230                        try {
231                                return loadClassNotInDatabaseJar(className);
232                        } catch (ClassNotFoundException cnfe) {
233                                if (applicationLoader == null)
234                                        throw cnfe;
235                                Class c = applicationLoader.loadClass(className, true);
236                                if (c == null)
237                                        throw cnfe;
238                                return c;
239                        }
240                }
241                catch (SecurityException se)
242                {
243                        // Thrown if the class has been comprimised in some
244                        // way, e.g. modified in a signed jar.
245                        loadError = se;        
246                }
247                catch (LinkageError le)
248                {
249                        // some error linking the jar, again could
250                        // be malicious code inserted into a jar.
251                        loadError = le;        
252                }
253                throw new ClassNotFoundException(className + " : " + loadError.getMessage());
254        }
255        
256        abstract Class loadClassNotInDatabaseJar(String className)
257                throws ClassNotFoundException;
258 
259        public final Class loadApplicationClass(ObjectStreamClass classDescriptor)
260                throws ClassNotFoundException {
261                return loadApplicationClass(classDescriptor.getName());
262        }
263 
264        public boolean isApplicationClass(Class theClass) {
265 
266                return theClass.getClassLoader()
267                        instanceof JarLoader;
268        }
269 
270        public void notifyModifyJar(boolean reload) throws StandardException  {
271                if (applicationLoader != null) {
272                        applicationLoader.modifyJar(reload);
273                }
274        }
275 
276        /**
277                Notify the class manager that the classpath has been modified.
278 
279                @exception StandardException thrown on error
280        */
281        public void notifyModifyClasspath(String classpath) throws StandardException {
282 
283                if (applicationLoader != null) {
284                        applicationLoader.modifyClasspath(classpath);
285                }
286        }
287 
288 
289        public int getClassLoaderVersion() {
290                if (applicationLoader != null) {
291                        return applicationLoader.getClassLoaderVersion();
292                }
293 
294                return -1;
295        }
296 
297        public ByteArray buildSpecificFactory(String className, String factoryName)
298                throws StandardException {
299 
300                ClassBuilder cb = javaFactory.newClassBuilder(this, CodeGeneration.GENERATED_PACKAGE_PREFIX,
301                        Modifier.PUBLIC | Modifier.FINAL, factoryName, "org.apache.derby.impl.services.reflect.GCInstanceFactory");
302 
303                MethodBuilder constructor = cb.newConstructorBuilder(Modifier.PUBLIC);
304 
305                constructor.callSuper();
306                constructor.methodReturn();
307                constructor.complete();
308                constructor = null;
309 
310                MethodBuilder noArg = cb.newMethodBuilder(Modifier.PUBLIC, ClassName.GeneratedByteCode, "getNewInstance");
311                noArg.pushNewStart(className);
312                noArg.pushNewComplete(0);
313                noArg.methodReturn();
314                noArg.complete();
315                noArg = null;
316 
317                return cb.getClassBytecode();
318        }
319 
320        /*
321        ** Class specific methods
322        */
323        
324        /*
325        ** Keep track of loaded generated classes and their GeneratedClass objects.
326        */
327 
328        abstract LoadedGeneratedClass loadGeneratedClassFromData(String fullyQualifiedName, ByteArray classDump); 
329}

[all classes][org.apache.derby.impl.services.reflect]
EMMA 2.0.5312 (C) Vladimir Roubtsov