KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > services > bytecode > BCClass


1 /*
2
3    Derby - Class org.apache.derby.impl.services.bytecode.BCClass
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.bytecode;
23
24 import org.apache.derby.iapi.services.compiler.ClassBuilder;
25 import org.apache.derby.iapi.services.compiler.MethodBuilder;
26 import org.apache.derby.iapi.services.compiler.LocalField;
27
28 import org.apache.derby.iapi.services.classfile.ClassHolder;
29 import org.apache.derby.iapi.services.classfile.ClassMember;
30 import org.apache.derby.iapi.services.classfile.ClassFormatOutput;
31 import org.apache.derby.iapi.services.loader.ClassFactory;
32
33 import org.apache.derby.iapi.services.monitor.Monitor;
34
35 import org.apache.derby.iapi.error.StandardException;
36 import org.apache.derby.iapi.reference.Property;
37 import org.apache.derby.iapi.reference.SQLState;
38
39 import org.apache.derby.iapi.util.ByteArray;
40 import org.apache.derby.iapi.services.classfile.VMOpcode;
41
42 import java.lang.reflect.Modifier JavaDoc;
43
44 import org.apache.derby.iapi.services.sanity.SanityManager;
45 import org.apache.derby.iapi.services.classfile.VMDescriptor;
46
47 import org.apache.derby.impl.services.bytecode.GClass;
48
49 import java.io.IOException JavaDoc;
50
51 /**
52  * ClassBuilder is used to construct a java class's byte array
53  * representation.
54  *
55  * Limitations:
56  * No checking for language use violations such as invalid modifiers
57  * or duplicate field names.
58  * All classes must have a superclass; java.lang.Object must be
59  * supplied if there is no superclass.
60  *
61  * <p>
62  * When a class is first created, it has:
63  * <ul>
64  * <li> a superclass
65  * <li> modifiers
66  * <li> a name
67  * <li> a package
68  * <li> no superinterfaces, methods, fields, or constructors
69  * <li> an empty static initializer
70  * <li> an empty initializer
71  * </ul>
72  * <p>
73  * MethodBuilder implementations are required to supply a way for
74  * Generators to give them code. Most typically, they may have
75  * a stream to which the Generator writes the code that is of
76  * the type to satisfy what the Generator is writing.
77  * <p>
78  * BCClass is a ClassBuilder implementation for generating java bytecode
79  * directly.
80  *
81  */

82 class BCClass extends GClass {
83     
84     /**
85      * Simple text indicating any limits execeeded while generating
86      * the class file.
87      */

88     String JavaDoc limitMsg;
89     
90     //
91
// ClassBuilder interface
92
//
93
/**
94      * add a field to this class. Fields cannot
95      * be initialized here, they must be initialized
96      * in the static initializer code (static fields)
97      * or in the constructors.
98      * <p>
99      * static fields also added to this list,
100      * with the modifier set appropriately.
101      */

102     public LocalField addField(String JavaDoc javaType, String JavaDoc name, int modifiers) {
103
104         Type type = factory.type(javaType);
105         // put it into the class holder right away.
106
ClassMember field = classHold.addMember(name, type.vmName(), modifiers);
107         int cpi = classHold.addFieldReference(field);
108
109         return new BCLocalField(type, cpi);
110     }
111
112     /**
113      * At the time the class is completed and bytecode
114      * generated, if there are no constructors then
115      * the default no-arg constructor will be defined.
116      */

117     public ByteArray getClassBytecode() throws StandardException {
118
119         // return if already done
120
if (bytecode != null) return bytecode;
121         
122         try {
123
124             if (SanityManager.DEBUG) {
125                 if (SanityManager.DEBUG_ON("ClassLineNumbers")) {
126
127                     ClassFormatOutput sout = new ClassFormatOutput(2);
128
129                     int cpiUTF = classHold.addUtf8("GC.java");
130
131                     sout.putU2(cpiUTF);
132
133                     classHold.addAttribute("SourceFile", sout);
134                 }
135             }
136
137             // the class is now complete, get its bytecode.
138
bytecode = classHold.getFileFormat();
139             
140         } catch (IOException JavaDoc ioe) {
141             throw StandardException.newException(
142                     SQLState.GENERATED_CLASS_LINKAGE_ERROR, ioe, getFullName());
143         }
144
145         // release resources, we have the code now.
146
// name is not released, it may still be accessed.
147
classHold = null;
148
149         if (SanityManager.DEBUG) {
150             if (SanityManager.DEBUG_ON("DumpClassFile")) {
151                 /* Dump the file in derby.system.home */
152                 String JavaDoc systemHome = System.getProperty(Property.SYSTEM_HOME_PROPERTY,".");
153                 writeClassFile(systemHome,false,null);
154             }
155         }
156
157         if (SanityManager.DEBUG) {
158           if (SanityManager.DEBUG_ON("ByteCodeGenInstr")) {
159             SanityManager.DEBUG("ByteCodeGenInstr",
160                 "GEN complete for class "+name);
161           }
162         }
163         
164         if (limitMsg != null)
165             throw StandardException.newException(
166                     SQLState.GENERATED_CLASS_LIMIT_EXCEEDED, getFullName(), limitMsg);
167         return bytecode;
168     }
169
170
171     /**
172      * the class's unqualified name
173      */

174     public String JavaDoc getName() {
175         return name;
176     }
177  
178     /**
179      * a method. Once it is created, thrown
180      * exceptions, statements, and local variable declarations
181      * must be added to it. It is put into its defining class
182      * when it is created.
183      * <verbatim>
184        Java: #modifiers #returnType #methodName() {}
185             // modifiers is the | of the JVM constants for
186             // the modifiers such as static, public, etc.
187        </verbatim>
188      * <p>
189      * This is used to start a constructor as well; pass in
190      * null for the returnType when used in that manner.
191      *
192      * See java.lang.reflect.Modifiers
193      * @param modifiers the | of the Modifiers
194      * constants representing the visibility and control of this
195      * method.
196      * @param returnType the return type of the method as its
197      * Java language type name.
198      * @param methodName the name of the method.
199      *
200      * @return the method builder.
201      */

202     public MethodBuilder newMethodBuilder(int modifiers, String JavaDoc returnType,
203         String JavaDoc methodName) {
204
205         return newMethodBuilder(modifiers, returnType,
206             methodName, (String JavaDoc[]) null);
207
208     }
209
210
211     /**
212      * a method with parameters. Once it is created, thrown
213      * exceptions, statements, and local variable declarations
214      * must be added to it. It is put into its defining class
215      * when it is created.
216      * <verbatim>
217        Java: #modifiers #returnType #methodName() {}
218             // modifiers is the | of the JVM constants for
219             // the modifiers such as static, public, etc.
220        </verbatim>
221      * <p>
222      * This is used to start a constructor as well; pass in
223      * null for the returnType when used in that manner.
224      *
225      * See java.lang.reflect.Modifiers
226      * @param modifiers the | of the Modifiers
227      * constants representing the visibility and control of this
228      * method.
229      * @param returnType the return type of the method as its
230      * Java language type name.
231      * @param methodName the name of the method.
232      * @param parms an array of ParameterDeclarations representing the
233      * method's parameters
234      *
235      * @return the method builder.
236      */

237     public MethodBuilder newMethodBuilder(int modifiers, String JavaDoc returnType,
238         String JavaDoc methodName, String JavaDoc[] parms) {
239
240         if (SanityManager.DEBUG) {
241             SanityManager.ASSERT(returnType!=null);
242         }
243
244         BCMethod m = new BCMethod(this,
245                                     returnType,
246                                     methodName,
247                                     modifiers,
248                                     parms,
249                                     factory);
250
251         return m;
252         
253     }
254
255
256     /**
257      * a constructor. Once it is created, thrown
258      * exceptions, statements, and local variable declarations
259      * must be added to it. It is put into its defining class
260      * when it is created.
261      * <verbatim>
262        Java: #modifiers #className() {}
263             // modifiers is the | of the JVM constants for
264             // the modifiers such as static, public, etc.
265             // className is taken from definingClass.getName()
266        </verbatim>
267      * <p>
268      * This is used to start a constructor as well; pass in
269      * null for the returnType when used in that manner.
270      *
271      * See Modifiers
272      * @param modifiers the | of the Modifiers
273      * constants representing the visibility and control of this
274      * method.
275      *
276      * @return the method builder for the constructor.
277      */

278     public MethodBuilder newConstructorBuilder(int modifiers) {
279
280         BCMethod m = new BCMethod(this, "void", "<init>",
281                                     modifiers,
282                                     (String JavaDoc []) null,
283                                     factory);
284
285         return m;
286     }
287     //
288
// class interface
289
//
290

291     String JavaDoc getSuperClassName() {
292         return superClassName;
293     }
294
295     /**
296      * Let those that need to get to the
297      * classModify tool to alter the class definition.
298      */

299     ClassHolder modify() {
300         return classHold;
301     }
302
303     /*
304     ** Method descriptor caching
305     */

306
307     BCClass(ClassFactory cf, String JavaDoc packageName, int classModifiers,
308             String JavaDoc className, String JavaDoc superClassName,
309             BCJava factory) {
310
311         super(cf, packageName.concat(className));
312
313         if (SanityManager.DEBUG) {
314           if (SanityManager.DEBUG_ON("ByteCodeGenInstr")) {
315             SanityManager.DEBUG("ByteCodeGenInstr",
316                 "GEN starting for class "+className);
317           }
318         }
319
320         // by the time the constructor is done, we have:
321
//
322
// package #packageName;
323
// #classModifiers class #className extends #superClassName
324
// { }
325
//
326

327         name = className;
328         if (superClassName == null)
329             superClassName = "java.lang.Object";
330         this.superClassName = superClassName;
331
332         classType = factory.type(getFullName());
333
334         classHold = new ClassHolder(qualifiedName, factory.type(superClassName).vmNameSimple, classModifiers);
335
336         this.factory = factory;
337     }
338
339     protected ClassHolder classHold;
340
341     protected String JavaDoc superClassName;
342     protected String JavaDoc name;
343
344     BCJava factory;
345     final Type classType;
346
347     ClassFactory getClassFactory() {
348         return cf;
349     }
350
351     public void newFieldWithAccessors(String JavaDoc getter, String JavaDoc setter,
352         int methodModifers,
353         boolean staticField, String JavaDoc type) {
354
355         String JavaDoc vmType = factory.type(type).vmName();
356         methodModifers |= Modifier.FINAL;
357
358
359         // add a field, field has same name as get method
360
int fieldModifiers = Modifier.PRIVATE;
361         if (staticField)
362             fieldModifiers |= Modifier.STATIC;
363
364         ClassMember field = classHold.addMember(getter, vmType, fieldModifiers);
365         int cpi = classHold.addFieldReference(field);
366
367         /*
368         ** add the get method
369         */

370
371         String JavaDoc sig = BCMethodDescriptor.get(BCMethodDescriptor.EMPTY, vmType, factory);
372
373         ClassMember method = classHold.addMember(getter, sig, methodModifers);
374
375         CodeChunk chunk = new CodeChunk(this);
376
377         // load 'this' if required
378
if (!staticField)
379             chunk.addInstr(VMOpcode.ALOAD_0); // this
380

381         // get the field value
382
chunk.addInstrU2((staticField ? VMOpcode.GETSTATIC : VMOpcode.GETFIELD), cpi);
383
384         // and return it
385
short vmTypeId = BCJava.vmTypeId(vmType);
386
387         chunk.addInstr(CodeChunk.RETURN_OPCODE[vmTypeId]);
388
389         int typeWidth = Type.width(vmTypeId);
390         chunk.complete(null, classHold, method, typeWidth, 1);
391
392         /*
393         ** add the set method
394         */

395         String JavaDoc[] pda = new String JavaDoc[1];
396         pda[0] = vmType;
397         sig = new BCMethodDescriptor(pda, VMDescriptor.VOID, factory).toString();
398         method = classHold.addMember(setter, sig, methodModifers);
399         chunk = new CodeChunk(this);
400
401         // load 'this' if required
402
if (!staticField)
403             chunk.addInstr(VMOpcode.ALOAD_0); // this
404
// push the only parameter
405
chunk.addInstr((short) (CodeChunk.LOAD_VARIABLE_FAST[vmTypeId] + 1));
406         
407         // and set the field
408
chunk.addInstrU2((staticField ? VMOpcode.PUTSTATIC : VMOpcode.PUTFIELD), cpi);
409
410         chunk.addInstr(VMOpcode.RETURN);
411
412         chunk.complete(null, classHold, method, typeWidth + (staticField ? 0 : 1), 1 + typeWidth);
413     }
414     
415     /**
416      * Add the fact that some class limit was exceeded while generating
417      * the class. We create a set of them and report at the end, this
418      * allows the generated class file to still be dumped.
419      * @param mb
420      * @param limitName
421      * @param limit
422      * @param value
423      */

424     void addLimitExceeded(BCMethod mb, String JavaDoc limitName, int limit, int value)
425     {
426         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
427         if (limitMsg != null)
428         {
429             sb.append(limitMsg);
430             sb.append(", ");
431         }
432         
433         sb.append("method:");
434         sb.append(mb.getName());
435         sb.append(" ");
436         sb.append(limitName);
437         sb.append(" (");
438         sb.append(value);
439         sb.append(" > ");
440         sb.append(limit);
441         sb.append(")");
442         
443         limitMsg = sb.toString();
444     }
445     
446     /**
447      * Add the fact that some class limit was exceeded while generating
448      * the class. Text is the simple string passed in.
449      * @param rawText Text to be reported.
450      *
451      * @see BCClass#addLimitExceeded(BCMethod, String, int, int)
452      */

453     void addLimitExceeded(String JavaDoc rawText)
454     {
455         if (limitMsg != null)
456         {
457             limitMsg = limitMsg + ", " + rawText;
458        }
459         else
460         {
461             limitMsg = rawText;
462         }
463     }
464
465 }
466
Popular Tags