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

COVERAGE SUMMARY FOR SOURCE FILE [BCClass.java]

nameclass, %method, %block, %line, %
BCClass.java100% (1/1)82%  (9/11)79%  (274/347)79%  (55.8/71)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class BCClass100% (1/1)82%  (9/11)79%  (274/347)79%  (55.8/71)
BCClass (ClassFactory, String, int, String, String, BCJava): void 100% (1/1)76%  (39/51)82%  (9/11)
addField (String, String, int): LocalField 100% (1/1)100% (24/24)100% (4/4)
getClassBytecode (): ByteArray 100% (1/1)38%  (27/72)47%  (8/17)
getClassFactory (): ClassFactory 0%   (0/1)0%   (0/3)0%   (0/1)
getName (): String 0%   (0/1)0%   (0/3)0%   (0/1)
getSuperClassName (): String 100% (1/1)100% (3/3)100% (1/1)
modify (): ClassHolder 100% (1/1)100% (3/3)100% (1/1)
newConstructorBuilder (int): MethodBuilder 100% (1/1)100% (14/14)100% (2/2)
newFieldWithAccessors (String, String, int, boolean, String): void 100% (1/1)94%  (138/147)93%  (26.9/29)
newMethodBuilder (int, String, String): MethodBuilder 100% (1/1)100% (8/8)100% (1/1)
newMethodBuilder (int, String, String, String []): MethodBuilder 100% (1/1)95%  (18/19)98%  (2.9/3)

1/*
2 
3   Derby - Class org.apache.derby.impl.services.bytecode.BCClass
4 
5   Copyright 1997, 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.bytecode;
22 
23import org.apache.derby.iapi.services.compiler.ClassBuilder;
24import org.apache.derby.iapi.services.compiler.MethodBuilder;
25import org.apache.derby.iapi.services.compiler.LocalField;
26 
27import org.apache.derby.iapi.services.classfile.ClassHolder;
28import org.apache.derby.iapi.services.classfile.ClassMember;
29import org.apache.derby.iapi.services.classfile.ClassFormatOutput;
30import org.apache.derby.iapi.services.loader.ClassFactory;
31 
32import org.apache.derby.iapi.services.monitor.Monitor;
33 
34import org.apache.derby.iapi.error.StandardException;
35import org.apache.derby.iapi.reference.Property;
36import org.apache.derby.iapi.reference.SQLState;
37 
38import org.apache.derby.iapi.util.ByteArray;
39import org.apache.derby.iapi.services.classfile.VMOpcode;
40 
41import java.lang.reflect.Modifier;
42 
43import org.apache.derby.iapi.services.sanity.SanityManager;
44import org.apache.derby.iapi.services.classfile.VMDescriptor;
45 
46import org.apache.derby.impl.services.bytecode.GClass;
47 
48import java.io.IOException;
49 
50/**
51 * ClassBuilder is used to construct a java class's byte array
52 * representation.
53 *
54 * Limitations:
55 *   No checking for language use violations such as invalid modifiers
56 *        or duplicate field names.
57 *   All classes must have a superclass; java.lang.Object must be
58 *      supplied if there is no superclass.
59 *
60 * <p>
61 * When a class is first created, it has:
62 * <ul>
63 * <li> a superclass
64 * <li> modifiers
65 * <li> a name
66 * <li> a package
67 * <li> no superinterfaces, methods, fields, or constructors
68 * <li> an empty static initializer
69 * <li> an empty initializer
70 * </ul>
71 * <p>
72 * MethodBuilder implementations are required to supply a way for
73 * Generators to give them code.  Most typically, they may have
74 * a stream to which the Generator writes the code that is of
75 * the type to satisfy what the Generator is writing.
76 * <p>
77 * BCClass is a ClassBuilder implementation for generating java bytecode
78 * directly.
79 *
80 */
81class BCClass extends GClass {
82        
83        /**
84         * Simple text indicating any limits execeeded while generating
85         * the class file.
86         */
87        String limitMsg;
88        
89        //
90        // ClassBuilder interface
91        //
92        /**
93         * add a field to this class. Fields cannot
94         * be initialized here, they must be initialized
95         * in the static initializer code (static fields)
96         * or in the constructors.
97         * <p>
98         * static fields also added to this list,
99         * with the modifier set appropriately.
100         */
101        public LocalField addField(String javaType, String name, int modifiers) {
102 
103                Type type = factory.type(javaType);
104                // put it into the class holder right away.
105                ClassMember field = classHold.addMember(name, type.vmName(), modifiers);
106                int cpi = classHold.addFieldReference(field);
107 
108                return new BCLocalField(type, cpi);
109        }
110 
111        /**
112         * At the time the class is completed and bytecode
113         * generated, if there are no constructors then
114         * the default no-arg constructor will be defined.
115         */
116        public ByteArray getClassBytecode() throws StandardException {
117 
118                // return if already done
119                if (bytecode != null) return bytecode;
120                
121                try {
122 
123                        if (SanityManager.DEBUG) {
124                                if (SanityManager.DEBUG_ON("ClassLineNumbers")) {
125 
126                                        ClassFormatOutput sout = new ClassFormatOutput(2);
127 
128                                        int cpiUTF = classHold.addUtf8("GC.java");
129 
130                                        sout.putU2(cpiUTF);
131 
132                                        classHold.addAttribute("SourceFile", sout);
133                                }
134                        }
135 
136                        // the class is now complete, get its bytecode.
137                        bytecode = classHold.getFileFormat();
138                        
139                } catch (IOException ioe) {
140                        throw StandardException.newException(
141                                        SQLState.GENERATED_CLASS_LINKAGE_ERROR, ioe, getFullName());
142                }
143 
144                // release resources, we have the code now.
145                // name is not released, it may still be accessed.
146                classHold = null;
147 
148                if (SanityManager.DEBUG) {
149                        if (SanityManager.DEBUG_ON("DumpClassFile")) {
150                                /* Dump the file in derby.system.home */
151                                String systemHome = System.getProperty(Property.SYSTEM_HOME_PROPERTY,".");
152                                writeClassFile(systemHome,false,null);
153                        }
154                }
155 
156                if (SanityManager.DEBUG) {
157                  if (SanityManager.DEBUG_ON("ByteCodeGenInstr")) {
158                        SanityManager.DEBUG("ByteCodeGenInstr",
159                                "GEN complete for class "+name);
160                  }
161                }
162                
163                if (limitMsg != null)
164                        throw StandardException.newException(
165                                        SQLState.GENERATED_CLASS_LIMIT_EXCEEDED, getFullName(), limitMsg);
166                return bytecode;
167        }
168 
169 
170        /**
171         * the class's unqualified name
172         */
173        public String getName() {
174                return name;
175        }
176 
177        /**
178         * a method. Once it is created, thrown
179         * exceptions, statements, and local variable declarations
180         * must be added to it. It is put into its defining class
181         * when it is created.
182         * <verbatim>
183           Java: #modifiers #returnType #methodName() {}
184                          // modifiers is the | of the JVM constants for
185                          // the modifiers such as static, public, etc.
186           </verbatim>
187         * <p>
188         * This is used to start a constructor as well; pass in
189         * null for the returnType when used in that manner.
190         *
191         * See java.lang.reflect.Modifiers
192         * @param modifiers the | of the Modifiers
193         *        constants representing the visibility and control of this
194         *        method.
195         * @param returnType the return type of the method as its
196         *        Java language type name.
197         * @param methodName the name of the method.
198         *
199         * @return the method builder.
200         */
201        public MethodBuilder newMethodBuilder(int modifiers, String returnType,
202                String methodName) {
203 
204                return newMethodBuilder(modifiers, returnType,
205                        methodName, (String[]) null);
206 
207        }
208 
209 
210        /**
211         * a method with parameters. Once it is created, thrown
212         * exceptions, statements, and local variable declarations
213         * must be added to it. It is put into its defining class
214         * when it is created.
215         * <verbatim>
216           Java: #modifiers #returnType #methodName() {}
217                          // modifiers is the | of the JVM constants for
218                          // the modifiers such as static, public, etc.
219           </verbatim>
220         * <p>
221         * This is used to start a constructor as well; pass in
222         * null for the returnType when used in that manner.
223         *
224         * See java.lang.reflect.Modifiers
225         * @param modifiers the | of the Modifiers
226         *        constants representing the visibility and control of this
227         *        method.
228         * @param returnType the return type of the method as its
229         *        Java language type name.
230         * @param methodName the name of the method.
231         * @param parms an array of ParameterDeclarations representing the
232         *                                method's parameters
233         *
234         * @return the method builder.
235         */
236        public MethodBuilder newMethodBuilder(int modifiers, String returnType,
237                String methodName, String[] parms) {
238 
239                if (SanityManager.DEBUG) {
240                        SanityManager.ASSERT(returnType!=null);
241                }
242 
243                BCMethod m = new BCMethod(this,
244                                                                        returnType,
245                                                                        methodName,
246                                                                        modifiers,
247                                                                        parms,
248                                                                        factory);
249 
250                return m;
251                
252        }
253 
254 
255        /**
256         * a constructor. Once it is created, thrown
257         * exceptions, statements, and local variable declarations
258         * must be added to it. It is put into its defining class
259         * when it is created.
260         * <verbatim>
261           Java: #modifiers #className() {}
262                          // modifiers is the | of the JVM constants for
263                          // the modifiers such as static, public, etc.
264                          // className is taken from definingClass.getName()
265           </verbatim>
266         * <p>
267         * This is used to start a constructor as well; pass in
268         * null for the returnType when used in that manner.
269         *
270         * See Modifiers
271         * @param modifiers the | of the Modifiers
272         *        constants representing the visibility and control of this
273         *        method.
274         *
275         * @return the method builder for the constructor.
276         */
277        public MethodBuilder newConstructorBuilder(int modifiers) {
278 
279                BCMethod m = new BCMethod(this, "void", "<init>", 
280                                                                        modifiers,
281                                                                        (String []) null,
282                                                                        factory);
283 
284                return m;
285        }
286          //
287        // class interface
288        //
289 
290        String getSuperClassName() {
291                return superClassName;
292        }
293 
294        /**
295         * Let those that need to get to the
296         * classModify tool to alter the class definition.
297         */
298        ClassHolder modify() {
299                return classHold;
300        }
301 
302        /*
303        ** Method descriptor caching
304        */
305 
306        BCClass(ClassFactory cf, String packageName, int classModifiers,
307                        String className, String superClassName,
308                        BCJava factory) {
309 
310                super(cf, packageName.concat(className));
311 
312                if (SanityManager.DEBUG) {
313                  if (SanityManager.DEBUG_ON("ByteCodeGenInstr")) {
314                        SanityManager.DEBUG("ByteCodeGenInstr",
315                                "GEN starting for class "+className);
316                  }
317                }
318 
319                // by the time the constructor is done, we have:
320                //
321                // package #packageName;
322                // #classModifiers class #className extends #superClassName
323                // { }
324                //
325 
326                name = className;
327                if (superClassName == null)
328                        superClassName = "java.lang.Object";
329                this.superClassName = superClassName;
330 
331                classType = factory.type(getFullName());
332 
333                classHold = new ClassHolder(qualifiedName, factory.type(superClassName).vmNameSimple, classModifiers);
334 
335                this.factory = factory;
336        }
337 
338        protected ClassHolder classHold;
339 
340        protected String superClassName;
341        protected String name;
342 
343        BCJava factory;
344        final Type classType;
345 
346        ClassFactory getClassFactory() {
347                return cf;
348        }
349 
350        public void newFieldWithAccessors(String getter, String setter,
351                int methodModifers,
352                boolean staticField, String type) {
353 
354                String vmType = factory.type(type).vmName();
355                methodModifers |= Modifier.FINAL;
356 
357 
358                // add a field, field has same name as get method
359                int fieldModifiers = Modifier.PRIVATE;
360                if (staticField)
361                        fieldModifiers |= Modifier.STATIC;
362 
363                ClassMember field = classHold.addMember(getter, vmType, fieldModifiers);
364                int cpi = classHold.addFieldReference(field);
365 
366                /*
367                ** add the get method
368                */
369 
370                String sig = BCMethodDescriptor.get(BCMethodDescriptor.EMPTY, vmType, factory);
371 
372                ClassMember method = classHold.addMember(getter, sig, methodModifers);
373 
374                CodeChunk chunk = new CodeChunk();
375 
376                // load 'this' if required
377                if (!staticField)
378                        chunk.addInstr(VMOpcode.ALOAD_0); // this
379                
380                // get the field value
381                chunk.addInstrU2((staticField ? VMOpcode.GETSTATIC : VMOpcode.GETFIELD), cpi);
382 
383                // and return it
384                short vmTypeId = BCJava.vmTypeId(vmType);
385 
386                chunk.addInstr(CodeChunk.RETURN_OPCODE[vmTypeId]);
387 
388                int typeWidth = Type.width(vmTypeId);
389                chunk.complete(null, classHold, method, typeWidth, 1);
390 
391                /*
392                ** add the set method
393                */
394                String[] pda = new String[1];
395                pda[0] = vmType;
396                sig = new BCMethodDescriptor(pda, VMDescriptor.VOID, factory).toString();
397                method = classHold.addMember(setter, sig, methodModifers);
398                chunk = new CodeChunk();
399 
400                // load 'this' if required
401                if (!staticField)
402                        chunk.addInstr(VMOpcode.ALOAD_0); // this
403                // push the only parameter
404                chunk.addInstr((short) (CodeChunk.LOAD_VARIABLE_FAST[vmTypeId] + 1));
405                
406                // and set the field
407                chunk.addInstrU2((staticField ? VMOpcode.PUTSTATIC : VMOpcode.PUTFIELD), cpi);
408 
409                chunk.addInstr(VMOpcode.RETURN);
410 
411                chunk.complete(null, classHold, method, typeWidth + (staticField ? 0 : 1), 1 + typeWidth);
412        }
413        
414        /**
415         * Add the fact that some class limit was exceeded while generating
416         * the class. We create a set ofg them and report at the end, this
417         * allows the generated class file to still be dumped.
418         * @param mb
419         * @param limitName
420         * @param limit
421         * @param value
422         */
423        void addLimitExceeded(BCMethod mb, String limitName, int limit, int value)
424        {
425                StringBuffer sb = new StringBuffer();
426                if (limitMsg != null)
427                {
428                        sb.append(limitMsg);
429                        sb.append(", ");
430                }
431                
432                sb.append("method:");
433                sb.append(mb.getName());
434                sb.append(" ");
435                sb.append(limitName);
436                sb.append(" (");
437                sb.append(value);
438                sb.append(" > ");
439                sb.append(limit);
440                sb.append(")");
441                
442                limitMsg = sb.toString();
443        }
444 
445}

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