KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > mdr > handlers > gen > HandlerGenerator


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.mdr.handlers.gen;
20
21 import org.netbeans.lib.jmi.util.ClassFileGenerator;
22 import org.netbeans.mdr.storagemodel.*;
23 import org.netbeans.mdr.util.DebugException;
24 import org.netbeans.mdr.util.Logger;
25 import org.netbeans.mdr.util.MOFConstants;
26 import javax.jmi.model.MultiplicityType;
27 import java.io.ByteArrayOutputStream JavaDoc;
28 import java.io.DataOutputStream JavaDoc;
29 import java.io.IOException JavaDoc;
30 import java.lang.reflect.Method JavaDoc;
31 import java.lang.reflect.Modifier JavaDoc;
32 import java.util.*;
33
34 /**
35  * Abstract base class for handler generators.
36  * @author Martin Matula, Dusan Balek
37  * @version 0.1
38  */

39 public abstract class HandlerGenerator extends ClassFileGenerator {
40
41     /* -------------------------------------------------------------------- */
42     /* -- Private static constants ---------------------------------------- */
43     /* -------------------------------------------------------------------- */
44     
45     private static final String JavaDoc PRE_TYPE = "Ljava/lang/Object;"; //NOI18N
46
private static final String JavaDoc POST_DESCRIPTOR = "Ljava/lang/Object;Z)V"; //NOI18N
47
private static final String JavaDoc POST_VOID_DESCRIPTOR = "(Ljava/lang/Object;Z)V"; //NOI18N
48

49     /* -------------------------------------------------------------------- */
50     /* -- Protected static constants ---------------------------------------- */
51     /* -------------------------------------------------------------------- */
52
53     protected static final String JavaDoc DT_MULTIVALUED = "java.util.Collection"; //NOI18N
54
protected static final String JavaDoc DT_ORDERED = "java.util.List"; //NOI18N
55
protected static final String JavaDoc PRE_PREFIX = "_pre"; //NOI18N
56
protected static final String JavaDoc POST_PREFIX = "_post"; //NOI18N
57
protected static final String JavaDoc HANDLE_PREFIX = "_handle"; //NOI18N
58
protected static final String JavaDoc CUSTOM_PREFIX = "super_"; //NOI18N
59

60     private static final int PROXY_DEF_LENGTH = 3200;
61     private static final int INSTANCE_DEF_LENGTH = 32000;
62     
63     /* -------------------------------------------------------------------- */
64     /* -- Static methods (public) ----------------------------------------- */
65     /* -------------------------------------------------------------------- */
66     
67     /**
68      * Generate a handler class given a name, interface and storable object to
69      * be wrapped by a handler object.
70      */

71     public static byte[] generateHandler(final String JavaDoc name, Class JavaDoc ifc, StorableBaseObject storable) {
72         HandlerGenerator gen;
73         int def_length;
74         try {
75             if (storable instanceof StorableAssociation) {
76                 gen = new AssociationGenerator(name, ifc, ((StorableAssociation)storable).getAssociationSuperclass(), (StorableAssociation)storable, ((StorableAssociation)storable).getAssociationCustomImpl());
77                 def_length = PROXY_DEF_LENGTH;
78             } else if (storable instanceof StorableClass) {
79                 gen = new ClassGenerator(name, ifc, ((StorableClass) storable).getClassSuperclass(), (StorableClass)storable, ((StorableClass) storable).getClassCustomImpl());
80                 def_length = PROXY_DEF_LENGTH;
81             } else if (storable instanceof StorablePackage) {
82                 gen = new PackageGenerator(name, ifc, ((StorablePackage) storable).getPackageSuperclass(), (StorablePackage)storable, ((StorablePackage) storable).getPackageCustomImpl());
83                 def_length = INSTANCE_DEF_LENGTH;
84             } else if (storable instanceof StorableObject) {
85                 StorableClass proxy = ((StorableObject) storable).getClassProxy();
86                 gen = new InstanceGenerator(name, ifc, proxy.getInstanceSuperclass(), (StorableObject)storable, proxy.getInstanceCustomImpl());
87                 def_length = INSTANCE_DEF_LENGTH;
88             } else {
89                 throw new InternalError JavaDoc("Unknow dispatcher type."); //NOI18N
90
}
91         } catch (Exception JavaDoc e) {
92             throw (DebugException) Logger.getDefault().annotate(new DebugException(), e);
93         }
94         
95         ByteArrayOutputStream JavaDoc bout = new ByteArrayOutputStream JavaDoc(def_length);
96         gen.generateClassFile(bout);
97         return bout.toByteArray();
98     }
99     
100     public static boolean customImplContainsMethod(Class JavaDoc customImpl, String JavaDoc name, String JavaDoc descriptor) {
101         if (customImpl == null)
102             return false;
103         synchronized (customImplInfos) {
104             HashSet methods = (HashSet)customImplInfos.get(customImpl);
105             if (methods == null) {
106                 methods = new HashSet();
107                 Method JavaDoc[] m = customImpl.getMethods();
108                 for (int i = 0; i < m.length; i++) {
109                     if (Modifier.isAbstract(m[i].getModifiers()))
110                         continue;
111                     ArrayList params = new ArrayList();
112                     Class JavaDoc[] p = m[i].getParameterTypes();
113                     for(int j = 0; j < p.length; j++)
114                         params.add(p[j].getName());
115                     methods.add(m[i].getName() + getMethodDescriptor((String JavaDoc [])params.toArray(new String JavaDoc[params.size()]), m[i].getReturnType().getName()));
116                 }
117                 customImplInfos.put(customImpl, methods);
118             }
119             return methods.contains(name + descriptor);
120         }
121     }
122
123     /* -------------------------------------------------------------------- */
124     /* -- Static attributes ----------------------------------------------- */
125     /* -------------------------------------------------------------------- */
126
127     private static Map customImplInfos = new LinkedHashMap(10, .5f, true) {
128         private static final int MAX_SIZE = 5;
129         
130         protected boolean removeEldestEntry(Map.Entry entry) {
131             return size() > MAX_SIZE;
132         }
133     };
134
135     /* -------------------------------------------------------------------- */
136     /* -- Attributes ------------------------------------------------------ */
137     /* -------------------------------------------------------------------- */
138
139     protected final StorableBaseObject obj;
140     protected final Class JavaDoc customImpl;
141     protected final HashMap dispatchMethods = new HashMap();
142     
143     /* -------------------------------------------------------------------- */
144     /* -- Constructor ----------------------------------------------------- */
145     /* -------------------------------------------------------------------- */
146
147     /**
148      * Construct a HandlerGenerator to generate a handler class with the
149      * specified name and for the given interfaces.
150      */

151     protected HandlerGenerator(String JavaDoc className, Class JavaDoc ifc, Class JavaDoc handler, StorableBaseObject storable, Class JavaDoc custom) {
152         super(className, new String JavaDoc[] {ifc.getName()}, handler.getName(), ACC_PUBLIC | ACC_FINAL | ACC_SUPER);
153         obj = storable;
154         customImpl = custom;
155     }
156     
157
158     
159     protected FieldInfo[] generateFields() throws IOException JavaDoc {
160         return new FieldInfo[0];
161     }
162
163     /**
164      * Generate the constructor method for the proxy class.
165      */

166     protected MethodInfo generateConstructor() throws IOException JavaDoc {
167         MethodInfo minfo = new MethodInfo(
168         "<init>", getConstructorDescriptor(), //NOI18N
169
ACC_PUBLIC);
170         
171         DataOutputStream JavaDoc out = new DataOutputStream JavaDoc(minfo.getCodeStream());
172         
173         code_aload(0, out);
174         code_aload(1, out);
175         
176         // just call super.<init>(String);
177
out.writeByte(opc_invokespecial);
178         out.writeShort(cp.getMethodRef(dotToSlash(superclassName), "<init>", getConstructorDescriptor())); //NOI18N
179

180         out.writeByte(opc_return);
181         
182         minfo.setMaxStack((short)2);
183         minfo.setMaxLocals((short)2);
184         return minfo;
185     }
186     
187     protected abstract String JavaDoc getConstructorDescriptor();
188     
189     protected short getHandlerIndex(String JavaDoc methodName, String JavaDoc methodDescriptor, String JavaDoc methodType) {
190         return cp.getMethodRef(dotToSlash(superclassName), HANDLE_PREFIX + methodName, methodDescriptor + methodType);
191     }
192     
193     protected short getPreIndex(String JavaDoc methodName, String JavaDoc methodDescriptor) {
194         return cp.getMethodRef(dotToSlash(superclassName), PRE_PREFIX + methodName, methodDescriptor + PRE_TYPE);
195     }
196     
197     protected short getPostIndex(String JavaDoc methodName, String JavaDoc methodType) {
198         return cp.getMethodRef(dotToSlash(superclassName), POST_PREFIX + methodName, (methodType.equals("V") ? POST_VOID_DESCRIPTOR : ("(" + methodType + POST_DESCRIPTOR))); //NOI18N
199
}
200     
201     protected Collection getHandlerMethod(String JavaDoc methodName, String JavaDoc[] parameterTypes, String JavaDoc returnType, String JavaDoc handlerName, String JavaDoc handlerDescriptor, String JavaDoc handlerType, String JavaDoc featureName) throws IOException JavaDoc {
202         short delegateMethod = getHandlerIndex(handlerName, handlerDescriptor, handlerType);
203         short preMethod = getPreIndex(handlerName, handlerDescriptor);
204         short postMethod = getPostIndex(handlerName, handlerType);
205         String JavaDoc methodDescriptor = getMethodDescriptor(parameterTypes, returnType);
206         boolean isCustom = customImplContainsMethod(customImpl, methodName, methodDescriptor);
207
208         int[] parameterSlot = new int[parameterTypes.length];
209         int nextSlot = 1;
210         for (int i = 0; i < parameterSlot.length; i++) {
211             parameterSlot[i] = nextSlot;
212             nextSlot += getWordsPerType(parameterTypes[i]);
213         }
214         int localSlot0 = nextSlot;
215         
216         short fail = (short) localSlot0;
217         short extraInfo = (short) (localSlot0 + 1);
218         short result = (short) (localSlot0 + 2);
219         short addr = (short) (localSlot0 + 3);
220         short exception = (short) (localSlot0 + 4);
221         short customResult = (short) (localSlot0 + 5);
222         
223         MethodInfo minfo = new MethodInfo(methodName, methodDescriptor, ACC_PUBLIC | ACC_FINAL);
224         DataOutputStream JavaDoc out = new DataOutputStream JavaDoc(minfo.getCodeStream());
225         MethodInfo cminfo = null;
226         DataOutputStream JavaDoc cout = null;
227         if (isCustom) {
228             cminfo = new MethodInfo(CUSTOM_PREFIX + methodName, methodDescriptor, ACC_PUBLIC | ACC_FINAL);
229             cout = new DataOutputStream JavaDoc(cminfo.getCodeStream());
230         }
231         
232         // store "true" in the fail variable
233
out.writeByte(opc_iconst_1);
234         code_istore(fail, out);
235         // store "null" in the extraInfo variable
236
out.writeByte(opc_aconst_null);
237         out.writeByte(opc_dup);
238         code_astore(extraInfo, out);
239         // store "null" in result variable
240
code_astore(result, out);
241
242         // I'll pass this instance as the first parameter
243
code_aload(0, out);
244         
245         if (featureName != null)
246             // feature name as the second parameter
247
code_ldc(cp.getString(featureName), out);
248         
249         // The rest of parameters follows
250
for (int i = 0; i < parameterTypes.length; i++) {
251             codeWrapArgument(parameterTypes[i], parameterSlot[i], out);
252         }
253         
254         // call the _pre method
255
out.writeByte(opc_invokespecial);
256         out.writeShort(preMethod);
257
258         // start of the try block
259
short tryStart = (short) out.size();
260
261         // store the returned object in a local variable
262
code_astore(extraInfo, out);
263         
264         if (isCustom) {
265             // I'll pass this instance as the first parameter
266
code_aload(0, out);
267
268             // The rest of parameters follows
269
for (int i = 0; i < parameterTypes.length; i++) {
270                 codeLoad(parameterSlot[i], parameterTypes[i], out);
271             }
272
273             // call the custom method
274
out.writeByte(opc_invokespecial);
275             out.writeShort(cp.getMethodRef(dotToSlash(superclassName), methodName, methodDescriptor));
276
277             if (!returnType.equals("void")) { //NOI18N
278
if (PrimitiveTypeInfo.get(returnType) == null)
279                     code_astore(result, out);
280                 else {
281                     codeStore(customResult, returnType, out);
282                     codeWrapArgument(returnType, customResult, out);
283                     code_astore(result, out);
284                 }
285             }
286             
287             // I'll pass this instance as the first parameter
288
code_aload(0, cout);
289
290             if (featureName != null)
291                 // feature name as the second parameter
292
code_ldc(cp.getString(featureName), cout);
293
294             // The rest of parameters follows
295
for (int i = 0; i < parameterTypes.length; i++) {
296                 codeWrapArgument(parameterTypes[i], parameterSlot[i], cout);
297             }
298
299             // call the delegate method
300
cout.writeByte(opc_invokespecial);
301             cout.writeShort(delegateMethod);
302
303             if (returnType.equals("void")) //NOI18N
304
cout.writeByte(opc_return);
305             else
306                 codeUnwrapReturnValue(returnType, cout);
307         }
308         else {
309             // I'll pass this instance as the first parameter
310
code_aload(0, out);
311
312             if (featureName != null)
313                 // feature name as the second parameter
314
code_ldc(cp.getString(featureName), out);
315
316             // The rest of parameters follows
317
for (int i = 0; i < parameterTypes.length; i++) {
318                 codeWrapArgument(parameterTypes[i], parameterSlot[i], out);
319             }
320
321             // call the delegate method
322
out.writeByte(opc_invokespecial);
323             out.writeShort(delegateMethod);
324
325             if (!returnType.equals("void")) { //NOI18N
326
code_astore(result, out);
327             }
328         }
329         // change value of fail to "false"
330
out.writeByte(opc_iconst_0);
331         code_istore(fail, out);
332         
333         // call the finally block and return
334
out.writeByte(opc_jsr);
335         if (returnType.equals("void")) { //NOI18N
336
out.writeShort(3 + 1 + 2*getBytesForLoadOrStore(exception) + 4);
337             out.writeByte(opc_return);
338         } else {
339             if (isCustom) {
340                 if (PrimitiveTypeInfo.get(returnType) != null) {
341                     out.writeShort(3 + getBytesForLoadOrStore(customResult) + 1 + 2*getBytesForLoadOrStore(exception) + 4);
342                     codeLoad(customResult, returnType, out);
343                     if (returnType.equals("int") || returnType.equals("boolean") || returnType.equals("byte") || returnType.equals("char") || returnType.equals("short")) //NOI18N
344
out.writeByte(opc_ireturn);
345                     else if (returnType.equals("long")) //NOI18N
346
out.writeByte(opc_lreturn);
347                     else if (returnType.equals("float")) //NOI18N
348
out.writeByte(opc_freturn);
349                     else if (returnType.equals("double")) //NOI18N
350
out.writeByte(opc_dreturn);
351                     else
352                         _assert(false);
353                 } else {
354                     out.writeShort(3 + getBytesForLoadOrStore(result) + 1 + 2*getBytesForLoadOrStore(exception) + 4);
355                     code_aload(result, out);
356                     out.writeByte(opc_areturn);
357                 }
358             }
359             else {
360                 out.writeShort(3 + getBytesForLoadOrStore(result) + getBytesForUnwrapReturn(returnType) + 2*getBytesForLoadOrStore(exception) + 4);
361                 // load the returned value
362
code_aload(result, out);
363                 // convert it to the result type
364
codeUnwrapReturnValue(returnType, out);
365             }
366         }
367         // start of catch block
368
short catchStart = (short) out.size();
369         
370         // store exception
371
code_astore(exception, out);
372         
373         // call finally
374
out.writeByte(opc_jsr);
375         out.writeShort(3 + getBytesForLoadOrStore(exception) + 1);
376         
377         // load exception
378
code_aload(exception, out);
379         
380         // rethrow exception
381
out.writeByte(opc_athrow);
382         
383         // start of finally block
384
// store the return address
385
code_astore(addr, out);
386         
387         // load parameters
388
code_aload(0, out);
389         if (!returnType.equals("void")) { //NOI18N
390
code_aload(result, out);
391         }
392         code_aload(extraInfo, out);
393         code_iload(fail, out);
394         
395         // call the _post method
396
out.writeByte(opc_invokespecial);
397         out.writeShort(postMethod);
398         
399         // return from finally
400
out.writeByte(opc_ret);
401         out.writeByte(addr);
402         
403         minfo.getExceptionTable().add(new ExceptionTableEntry(tryStart, catchStart, catchStart, (short) 0));
404         
405         minfo.setMaxStack((short)15);
406         minfo.setMaxLocals((short)(localSlot0 + 6));
407         
408         if (isCustom) {
409             cminfo.setMaxStack((short)15);
410             cminfo.setMaxLocals((short)(localSlot0 + 5));
411         }
412         
413         ArrayList ret = new ArrayList();
414         ret.add(minfo);
415         if (isCustom)
416             ret.add(cminfo);
417         return ret;
418     }
419     
420     protected void codeStore(int index, String JavaDoc type, DataOutputStream JavaDoc out) throws IOException JavaDoc {
421         if (type.equals("int") || type.equals("boolean") || type.equals("byte") || type.equals("char") || type.equals("short")) //NOI18N
422
code_istore(index, out);
423         else if (type.equals("long")) //NOI18N
424
code_lstore(index, out);
425         else if (type.equals("float")) //NOI18N
426
code_fstore(index, out);
427         else if (type.equals("double")) //NOI18N
428
code_dstore(index, out);
429         else
430             code_astore(index, out);
431     }
432     
433     protected void codeLoad(int index, String JavaDoc type, DataOutputStream JavaDoc out) throws IOException JavaDoc {
434         if (type.equals("int") || type.equals("boolean") || type.equals("byte") || type.equals("char") || type.equals("short")) //NOI18N
435
code_iload(index, out);
436         else if (type.equals("long")) //NOI18N
437
code_lload(index, out);
438         else if (type.equals("float")) //NOI18N
439
code_fload(index, out);
440         else if (type.equals("double")) //NOI18N
441
code_dload(index, out);
442         else
443             code_aload(index, out);
444     }
445     
446     protected int getBytesForLoadOrStore(int idx) {
447         if (idx <= 3)
448             return 1;
449         if (idx <= 0xFF)
450             return 2;
451         return 4;
452     }
453     
454     protected void codeWrapArgument(String JavaDoc typeName, int slot, DataOutputStream JavaDoc out) throws IOException JavaDoc {
455         PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(typeName);
456         if (prim != null) {
457             if (typeName.equals("boolean")) {
458                 code_iload(slot, out);
459                 out.writeByte(opc_invokestatic);
460                 out.writeShort(cp.getMethodRef("java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;"));
461             } else {
462                 out.writeByte(opc_new);
463                 out.writeShort(cp.getClass(prim.wrapperClassName));
464
465                 out.writeByte(opc_dup);
466
467                 if (typeName.equals("int") || typeName.equals("byte") || typeName.equals("char") || typeName.equals("short")) { //NOI18N
468
code_iload(slot, out);
469                 } else if (typeName.equals("long")) { //NOI18N
470
code_lload(slot, out);
471                 } else if (typeName.equals("float")) { //NOI18N
472
code_fload(slot, out);
473                 } else if (typeName.equals("double")) { //NOI18N
474
code_dload(slot, out);
475                 } else {
476                     _assert(false);
477                 }
478
479                 out.writeByte(opc_invokespecial);
480                 out.writeShort(cp.getMethodRef(prim.wrapperClassName, "<init>", prim.wrapperConstructorDesc)); //NOI18N
481
}
482         } else {
483             code_aload(slot, out);
484         }
485     }
486     
487     protected void codeUnwrapReturnValue(String JavaDoc typeName, DataOutputStream JavaDoc out) throws IOException JavaDoc {
488         PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(typeName);
489         if (prim != null) {
490             out.writeByte(opc_dup);
491             out.writeByte(opc_ifnull);
492             out.writeShort(10);
493             
494             out.writeByte(opc_checkcast);
495             out.writeShort(cp.getClass(prim.wrapperClassName));
496             
497             out.writeByte(opc_invokevirtual);
498             out.writeShort(cp.getMethodRef(prim.wrapperClassName, prim.unwrapMethodName, prim.unwrapMethodDesc));
499             
500             if (typeName.equals("int") || typeName.equals("boolean") || typeName.equals("byte") || typeName.equals("char") || typeName.equals("short")) { //NOI18N
501
out.writeByte(opc_ireturn);
502                 out.writeByte(opc_iconst_0);
503                 out.writeByte(opc_ireturn);
504             } else if (typeName.equals("long")) { //NOI18N
505
out.writeByte(opc_lreturn);
506                 out.writeByte(opc_lconst_0);
507                 out.writeByte(opc_lreturn);
508             } else if (typeName.equals("float")) { //NOI18N
509
out.writeByte(opc_freturn);
510                 out.writeByte(opc_fconst_0);
511                 out.writeByte(opc_freturn);
512             } else if (typeName.equals("double")) { //NOI18N
513
out.writeByte(opc_dreturn);
514                 out.writeByte(opc_dconst_0);
515                 out.writeByte(opc_dreturn);
516             } else {
517                 _assert(false);
518             }
519             
520         } else {
521             out.writeByte(opc_checkcast);
522             out.writeShort(cp.getClass(dotToSlash(typeName)));
523             
524             out.writeByte(opc_areturn);
525         }
526     }
527     
528     protected int getBytesForUnwrapReturn(String JavaDoc typeName) {
529         if (PrimitiveTypeInfo.get(typeName) != null) {
530             return 13;
531         } else {
532             return 4;
533         }
534     }
535     
536     protected StorableObject getAttrType(StorableObject attr) {
537         try {
538             StorableObject curType = (StorableObject) attr.getReference(MOFConstants.SH_MODEL_TYPED_ELEMENT_TYPE);
539             String JavaDoc typeName = (String JavaDoc) curType.getMetaObject().getAttribute(MOFConstants.SH_MODEL_MODEL_ELEMENT_NAME);
540             if (typeName.equals(MOFConstants.SH_MODEL_ALIAS_TYPE))
541                 curType = getAttrType(curType);
542             return curType;
543         } catch (Exception JavaDoc e) {
544             throw (DebugException) Logger.getDefault().annotate(new DebugException(), e);
545         }
546     }
547     
548     // returns correct type name for attribute (depending on the multiplicity type)
549
protected String JavaDoc getAttrTypeName(StorableObject attr) {
550         try {
551             MultiplicityType mp = (MultiplicityType) attr.getAttribute(MOFConstants.SH_MODEL_STRUCTURAL_FEATURE_MULTIPLICITY);
552             
553             if (mp.getUpper() > 1 || mp.getUpper() == -1) {
554                 return (mp.isOrdered() ? DT_ORDERED : DT_MULTIVALUED);
555             } else if (mp.getLower() < 1) {
556                 return TagSupport.getDataTypeName(getAttrType(attr));
557             } else {
558                 return getTypeName2(attr);
559             }
560         } catch (Exception JavaDoc e) {
561             throw (DebugException) Logger.getDefault().annotate(new DebugException(), e);
562         }
563     }
564     
565     protected String JavaDoc getTypeName2(StorableObject te) {
566         return getPrimitiveName(TagSupport.getDataTypeName(getAttrType(te)));
567     }
568     
569     // converts object type name to primitive type name
570
protected String JavaDoc getPrimitiveName(String JavaDoc typeName) {
571         String JavaDoc name = (String JavaDoc) objectToPrimitive.get(typeName);
572         return name == null ? typeName : name;
573     }
574     
575     // conversion table between object type names and primitive type names
576
protected static final HashMap objectToPrimitive = new HashMap(7);
577     static {
578         objectToPrimitive.put("java.lang.Short", "short"); //NOI18N
579
objectToPrimitive.put("java.lang.Integer", "int"); //NOI18N
580
objectToPrimitive.put("java.lang.Float", "float"); //NOI18N
581
objectToPrimitive.put("java.lang.Double", "double"); //NOI18N
582
objectToPrimitive.put("java.lang.Boolean", "boolean"); //NOI18N
583
objectToPrimitive.put("java.lang.Character", "char"); //NOI18N
584
objectToPrimitive.put("java.lang.Long", "long"); //NOI18N
585
}
586
587     protected MethodInfo getDispatcherMethod(String JavaDoc methodName, String JavaDoc[] parameterTypes, String JavaDoc returnType, HashMap features) throws IOException JavaDoc {
588         String JavaDoc desc = getMethodDescriptor(parameterTypes, returnType);
589         MethodInfo minfo = new MethodInfo(methodName, desc, ACC_PUBLIC | ACC_FINAL);
590         int[] parameterSlot = new int[parameterTypes.length];
591         int nextSlot = 1;
592         for (int i = 0; i < parameterSlot.length; i++) {
593             parameterSlot[i] = nextSlot;
594             nextSlot += getWordsPerType(parameterTypes[i]);
595         }
596         int localSlot0 = nextSlot;
597         int maxStack = 0;
598         
599         DataOutputStream JavaDoc out = new DataOutputStream JavaDoc(minfo.getCodeStream());
600         
601         for (Iterator it = features.keySet().iterator(); it.hasNext();) {
602             String JavaDoc featureName = (String JavaDoc) it.next();
603             MethodDescHolder item = (MethodDescHolder) features.get(featureName);
604             
605             // load name of feature
606
code_ldc(cp.getString(featureName), out);
607             
608             //compare it with passed name
609
code_aload(1, out);
610             out.writeByte(opc_invokevirtual);
611             out.writeShort(cp.getMethodRef("java/lang/String", "equals", "(Ljava/lang/Object;)Z")); //NOI18N
612

613             // if it is not equal, continue processing
614
out.writeByte(opc_ifeq);
615             out.writeShort(7 + getBytesForArgUnwrap(methodName, item.getParameterTypes()) + getBytesForReturn(methodName, item.getReturnType()) + getBytesForPreReturn(item.getReturnType()));
616             // if it is equal, return result of a proper method
617
codePreReturn(item.getReturnType(), out);
618             out.writeByte(opc_aload_0);
619             codeUnwrapArguments(methodName, item.getParameterTypes(), out);
620             out.writeByte(opc_invokevirtual);
621             out.writeShort(cp.getMethodRef(dotToSlash(className), item.getName(), getMethodDescriptor(item.getParameterTypes(), item.getReturnType())));
622             codeReturn(methodName, item.getReturnType(), out);
623             if (item.getParameterTypes().length > maxStack)
624                 maxStack = item.getParameterTypes().length;
625         }
626         short tryStop = (short) out.size();
627         
628         // if the field was not found, throw an exception
629
out.writeByte(opc_new); // new
630
out.writeShort(cp.getClass("javax/jmi/reflect/InvalidNameException")); //NOI18N
631
out.writeByte(opc_dup); // dup
632
code_aload(1, out);
633         out.writeByte(opc_invokespecial);
634         out.writeShort(cp.getMethodRef("javax/jmi/reflect/InvalidNameException", "<init>", "(Ljava/lang/String;)V")); //NOI18N
635
out.writeByte(opc_athrow);
636
637         if (tryStop != 0) {
638             short catchStart = (short) out.size();
639
640             code_astore(localSlot0, out);
641             out.writeByte(opc_new);
642             out.writeShort(cp.getClass("javax/jmi/reflect/TypeMismatchException")); //NOI18N
643
out.writeByte(opc_dup);
644             out.writeByte(opc_aconst_null);
645             out.writeByte(opc_dup);
646             out.writeByte(opc_dup);
647             out.writeByte(opc_invokespecial);
648             out.writeShort(cp.getMethodRef("javax/jmi/reflect/TypeMismatchException", "<init>", "(Ljava/lang/Class;Ljava/lang/Object;Ljavax/jmi/reflect/RefObject;)V")); //NOI18N
649
out.writeByte(opc_athrow);
650
651             minfo.getExceptionTable().add(new ExceptionTableEntry((short)0, tryStop, catchStart, cp.getClass("java/lang/ClassCastException"))); //NOI18N
652
}
653         minfo.setMaxStack((short)(maxStack + 6));
654         minfo.setMaxLocals((short) (localSlot0 + 2));
655         
656         return minfo;
657     }
658     
659     protected void codeUnwrapArguments(String JavaDoc methodName, String JavaDoc[] paramTypeNames, DataOutputStream JavaDoc out) throws IOException JavaDoc {
660         if (methodName.equals("_invokeOperation") || methodName.equals("_createStruct")) { //NOI18N
661
code_aload(2, out);
662             out.writeByte(opc_arraylength);
663             code_ipush(paramTypeNames.length, out);
664             out.writeByte(opc_if_icmpeq);
665             out.writeShort(12);
666             out.writeByte(opc_new);
667             out.writeShort(cp.getClass("javax/jmi/reflect/WrongSizeException")); //NOI18N
668
out.writeByte(opc_dup);
669             out.writeByte(opc_aconst_null);
670             out.writeByte(opc_invokespecial);
671             out.writeShort(cp.getMethodRef("javax/jmi/reflect/WrongSizeException", "<init>", "(Ljavax/jmi/reflect/RefObject;)V")); //NOI18N
672
out.writeByte(opc_athrow);
673             for (int i = 0; i < paramTypeNames.length; i++) {
674                 code_aload(2, out);
675                 out.writeByte(opc_sipush);
676                 out.writeShort(i & 0xFFFF);
677                 out.writeByte(opc_aaload);
678                 codeUnwrapArgument(paramTypeNames[i], out);
679             }
680         } else {
681             for (int i = 0; i < paramTypeNames.length; i++) {
682                 out.writeByte(opc_aload);
683                 out.writeByte(i + 2);
684                 codeUnwrapArgument(paramTypeNames[i], out);
685             }
686         }
687     }
688     
689     protected void codeUnwrapArgument(String JavaDoc typeName, DataOutputStream JavaDoc out) throws IOException JavaDoc {
690         PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(typeName);
691         if (prim != null) {
692             out.writeByte(opc_checkcast);
693             out.writeShort(cp.getClass(prim.wrapperClassName));
694             
695             out.writeByte(opc_invokevirtual);
696             out.writeShort(cp.getMethodRef(
697             prim.wrapperClassName,
698             prim.unwrapMethodName, prim.unwrapMethodDesc));
699         } else {
700             out.writeByte(opc_checkcast);
701             out.writeShort(cp.getClass(getParamType(typeName)));
702         }
703     }
704
705     protected static String JavaDoc getParamType(String JavaDoc typeName) {
706         if (typeName.endsWith("[]")) //NOI18N
707
return "[" + getFieldType(typeName.substring(0, typeName.length()-2).trim()); //NOI18N
708
else
709             return dotToSlash(typeName);
710     }
711
712     
713     protected int getBytesForArgUnwrap(String JavaDoc methodName, String JavaDoc[] parameterTypeNames) {
714         int result = 0;
715         if (methodName.equals("_invokeOperation") || methodName.equals("_createStruct")) { //NOI18N
716
result += 14 + getBytesForIPush(parameterTypeNames.length);
717             for (int i = 0; i < parameterTypeNames.length; i++) {
718                 result += 5;
719                 result += getBytesForOneArgUnwrap(parameterTypeNames[i]);
720             }
721         } else {
722             for (int i = 0; i < parameterTypeNames.length; i++) {
723                 result += 2;
724                 result += getBytesForOneArgUnwrap(parameterTypeNames[i]);
725             }
726         }
727         return result;
728     }
729     
730     protected int getBytesForOneArgUnwrap(String JavaDoc typeName) {
731         if (PrimitiveTypeInfo.get(typeName) != null)
732             return 6;
733         else
734             return 3;
735     }
736
737     protected int getBytesForIPush(int value) {
738         if (value >= -1 && value <= 5)
739             return 1;
740         if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE)
741             return 2;
742         return 3;
743     }
744     
745     protected int getBytesForReturn(String JavaDoc methodName, String JavaDoc typeName) {
746         if (typeName.equals("void")) { //NOI18N
747
return (methodName.equals("_invokeOperation") ? 2 : 1); //NOI18N
748
} else if (PrimitiveTypeInfo.get(typeName) != null) {
749             return 4;
750         } else {
751             return 1;
752         }
753     }
754     
755     protected int getBytesForPreReturn(String JavaDoc typeName) {
756         if (!"void".equals(typeName) && !"boolean".equals(typeName) && (PrimitiveTypeInfo.get(typeName) != null)) { //NOI18N
757
return 4;
758         } else {
759             return 0;
760         }
761     }
762     
763     protected void codePreReturn(String JavaDoc typeName, DataOutputStream JavaDoc out) throws IOException JavaDoc {
764         PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(typeName);
765         if (!"void".equals(typeName) && !"boolean".equals(typeName) && (prim != null)) { //NOI18N
766
out.writeByte(opc_new);
767             out.writeShort(cp.getClass(prim.wrapperClassName));
768             out.writeByte(opc_dup);
769         }
770     }
771     
772     protected void codeReturn(String JavaDoc methodName, String JavaDoc typeName, DataOutputStream JavaDoc out) throws IOException JavaDoc {
773         if (typeName.equals("void")) { //NOI18N
774
if (methodName.equals("_invokeOperation")) { //NOI18N
775
out.writeByte(opc_aconst_null);
776                 out.writeByte(opc_areturn);
777             } else {
778                 out.writeByte(opc_return);
779             }
780         } else {
781             PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(typeName);
782             if (prim != null) {
783                 if ("boolean".equals(typeName)) {
784                     out.writeByte(opc_invokestatic);
785                     out.writeShort(cp.getMethodRef("java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;"));
786                 } else {
787                     out.writeByte(opc_invokespecial);
788                     out.writeShort(cp.getMethodRef(prim.wrapperClassName, "<init>", prim.wrapperConstructorDesc)); //NOI18N
789
}
790             }
791             out.writeByte(opc_areturn);
792         }
793     }
794     
795     
796     protected class MethodDescHolder {
797         
798         private String JavaDoc name;
799         private String JavaDoc[] params;
800         private String JavaDoc ret;
801         
802         public MethodDescHolder(String JavaDoc methodName, String JavaDoc []parameterTypes, String JavaDoc returnType) {
803             name = methodName;
804             params = parameterTypes;
805             ret = returnType;
806         }
807         
808         public String JavaDoc getName() {
809             return name;
810         }
811         
812         public String JavaDoc[] getParameterTypes() {
813             return params;
814         }
815         
816         public String JavaDoc getReturnType() {
817             return ret;
818         }
819     }
820 }
821
Popular Tags