KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > proxy > compiler > ProxyAssembler


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.proxy.compiler;
23
24 import java.lang.reflect.*;
25 import java.util.*;
26 import java.io.*;
27
28 /**
29  * A simple bytecode assembler.
30  *
31  * @deprecated Use {@link ProxyCompiler} or Jakarta BCEL instead.
32  *
33  * @author Unknown
34  * @version $Revision: 37459 $
35  */

36 public class ProxyAssembler
37 {
38    // constant pool:
39
Vector cv = new Vector();
40    Hashtable ct = new Hashtable();
41    Hashtable ut = new Hashtable();
42    short cn = 1;
43
44    // members:
45
Vector members;
46    AMember current;
47    ByteArrayOutputStream code; // current.code
48
Stack stack; // current.stack
49

50    // other info:
51
String JavaDoc className;
52    int modifiers;
53    Class JavaDoc superClass;
54    Class JavaDoc interfaces[];
55
56    public short getIndex(Object JavaDoc x) {
57       Object JavaDoc n = ct.get(x);
58       if (n == null) {
59          n = new Short JavaDoc(cn++);
60          ct.put(x, n);
61          cv.addElement(x);
62       }
63       return ((Short JavaDoc)n).shortValue();
64    }
65
66    public short getUtfIndex(String JavaDoc x) {
67       Object JavaDoc n = ut.get(x);
68       if (n == null) {
69          n = new Short JavaDoc(cn++);
70          ut.put(x, n);
71          int xlen = 2 + x.length(); // x.utfLength(), really
72
ByteArrayOutputStream bytes = new ByteArrayOutputStream(xlen);
73          DataOutputStream ds = new DataOutputStream(bytes);
74          try {
75             ds.writeByte(CONSTANT_UTF8);
76             ds.writeUTF(x);
77          } catch (IOException ee) {
78             throw new RuntimeException JavaDoc(ee.toString());
79          }
80          cv.addElement(bytes.toByteArray());
81       }
82       return ((Short JavaDoc)n).shortValue();
83    }
84
85    public short getNTIndex(String JavaDoc name, String JavaDoc sig) {
86       NameAndType nt = new NameAndType();
87       nt.name = getUtfIndex(name);
88       nt.sig = getUtfIndex(sig);
89       return getIndex(nt);
90    }
91
92    public short getClassIndex( Class JavaDoc c )
93    {
94       short ci = getUtfIndex(c.getName().replace('.', '/'));
95       short data[] = { CONSTANT_CLASS, ci };
96       return getIndex( data );
97    }
98
99    public short getMemberIndex(Object JavaDoc cls, String JavaDoc name, Class JavaDoc ptypes[]) {
100       if (cls instanceof Class JavaDoc) {
101          Class JavaDoc c = (Class JavaDoc) cls;
102          Member m;
103          try {
104             if (ptypes == null) {
105                m = c.getField(name);
106             } else if (name.equals("<init>")) {
107                m = c.getConstructor(ptypes);
108             } else {
109                m = c.getMethod(name, ptypes);
110             }
111          } catch (NoSuchMethodException JavaDoc ee) {
112             throw new IllegalArgumentException JavaDoc(ee+" in "+c);
113          } catch (NoSuchFieldException JavaDoc ee) {
114             throw new IllegalArgumentException JavaDoc(ee+" in "+c);
115          }
116          return getIndex(m);
117       } else if (cls instanceof ProxyAssembler) {
118          ProxyAssembler asm = (ProxyAssembler) cls;
119          String JavaDoc sig = getSig(null, ptypes);
120          AMember m = asm.findMember(sig, name);
121          if (m == null) {
122             throw new IllegalArgumentException JavaDoc(sig + " " + name);
123          }
124          return getIndex(m);
125       } else {
126          throw new IllegalArgumentException JavaDoc("not a type: "+cls);
127       }
128    }
129    public short getMemberIndex(Object JavaDoc cls, String JavaDoc name) {
130       return getMemberIndex(cls, name, null);
131    }
132
133    public static String JavaDoc getSig(Class JavaDoc t) {
134       if (t == null) {
135          return "";
136       } else if (t.isPrimitive()) {
137          if (false) {
138             return "";
139          } else if (t == Boolean.TYPE) {
140             return "Z";
141          } else if (t == Character.TYPE) {
142             return "C";
143          } else if (t == Byte.TYPE) {
144             return "B";
145          } else if (t == Short.TYPE) {
146             return "S";
147          } else if (t == Integer.TYPE) {
148             return "I";
149          } else if (t == Long.TYPE) {
150             return "J";
151          } else if (t == Float.TYPE) {
152             return "F";
153          } else if (t == Double.TYPE) {
154             return "D";
155          } else if (t == Void.TYPE) {
156             return "V";
157          } else {
158             Class JavaDoc a = java.lang.reflect.Array.newInstance(t, 0).getClass();
159             return getSig(a).substring(1);
160          }
161       } else if (t.isArray()) {
162          return t.getName().replace('.', '/');
163       } else {
164          return "L" + t.getName().replace('.', '/') + ";";
165       }
166    }
167
168    public static String JavaDoc getSig(Class JavaDoc rt, Class JavaDoc pt[]) {
169       if (pt == null) {
170          return getSig(rt);
171       }
172       StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
173       sb.append("(");
174       for (int i = 0; i < pt.length; i++) {
175          sb.append(getSig(pt[i]));
176       }
177       sb.append(")");
178       sb.append(getSig(rt));
179       return sb.toString();
180    }
181
182    boolean isInterface() {
183       return Modifier.isInterface(modifiers);
184    }
185
186    public ProxyAssembler(String JavaDoc className, int modifiers,
187                          Class JavaDoc superClass, Class JavaDoc interfaces[]) {
188       if (interfaces == null) interfaces = new Class JavaDoc[0];
189       this.className = className;
190       this.modifiers = modifiers;
191       this.superClass = superClass;
192       this.interfaces = interfaces;
193       cv.addElement(null); // the first cpool entry is unused
194
members = new Vector();
195       addMember(0, "", null, "" );
196    }
197
198    private static class AMember {
199       int mods;
200       int sp;
201       int spmax;
202       int locmax;
203       int index;
204       Class JavaDoc type; // field or method return type
205
String JavaDoc sig;
206       String JavaDoc name;
207       Vector attr;
208       Stack stack;
209       ByteArrayOutputStream code;
210       ProxyAssembler asm;
211    }
212    private static class Attr {
213       String JavaDoc name;
214       Object JavaDoc data;
215    }
216    private static class AValue { // found in the stack
217
int num;
218       Object JavaDoc type;
219    }
220    private static class NameAndType {
221       short name;
222       short sig;
223       // must act as a hashtable key:
224
public boolean equals(Object JavaDoc x) {
225          if (x instanceof NameAndType) {
226             NameAndType that = (NameAndType)x;
227             return that.name == name && that.sig == sig;
228          }
229          return false;
230       }
231       public int hashCode() {
232          return name + sig * 1000;
233       }
234    }
235
236    public Object JavaDoc getCurrentMember() {
237       return current;
238    }
239    public void setCurrentMember(Object JavaDoc m) {
240       if (m == null) {
241          m = members.elementAt(0);
242       }
243       current = (AMember) m;
244       code = current.code;
245       stack = current.stack;
246    }
247
248    AMember findMember(String JavaDoc sig, String JavaDoc name) {
249       for (int i = 0; i < members.size(); i++) {
250          AMember m = (AMember) members.elementAt(i);
251          if (m.name.equals(name)) {
252             if (!sig.startsWith("(") ? !m.sig.startsWith("(")
253                 : m.sig.startsWith(sig)) {
254                return m;
255             }
256          }
257       }
258       return null;
259    }
260
261
262    void addExceptionAttribute( Class JavaDoc[] classes )
263    {
264       try
265       {
266
267          if ((classes == null) || (classes.length == 0))
268             return;
269
270          ByteArrayOutputStream baos = new ByteArrayOutputStream();
271          DataOutputStream dos = new DataOutputStream( baos );
272          short count = (short) classes.length;
273          dos.writeShort( count );
274          for (int iter=0; iter<classes.length; iter++)
275          {
276             dos.writeShort( getClassIndex(classes[iter]) );
277          }
278          dos.flush();
279          baos.flush();
280          addAttribute( "Exception", baos.toByteArray() );
281       }
282       catch (IOException cantHappen)
283       {
284          cantHappen.printStackTrace();
285       }
286    }
287
288    AMember addMember(int mods, String JavaDoc sig, Class JavaDoc[] exceptionClasses, String JavaDoc name) {
289       String JavaDoc qsig = sig.substring(0, 1 + sig.indexOf(')'));
290       AMember m = findMember(qsig, name);
291       if (m != null) {
292          setCurrentMember(m);
293          current.mods |= mods;
294          modifiers |= (mods & Modifier.ABSTRACT);
295          return m;
296       }
297       m = new AMember();
298       m.asm = this;
299       if (isMethodSig(sig)) {
300          m.code = new ByteArrayOutputStream();
301          m.stack = new Stack();
302       }
303       m.sig = sig;
304       m.name = name;
305       m.attr = new Vector();
306       m.index = members.size();
307       m.mods = mods;
308       members.addElement(m);
309       setCurrentMember(m);
310       this.addExceptionAttribute( exceptionClasses );
311       return m;
312    }
313
314    public Object JavaDoc addMember(int mods, Class JavaDoc rtype, String JavaDoc name, Class JavaDoc ptypes[], Class JavaDoc[] exceptionClasses) {
315       AMember m = addMember(mods, getSig(rtype, ptypes), exceptionClasses, name);
316       if (ptypes != null && stack.size() == 0) {
317          // push the arguments onto the stack
318
if (!Modifier.isStatic(mods)) {
319             declare(this);
320          }
321          for (int i = 0; i < ptypes.length; i++) {
322             declare(ptypes[i]);
323          }
324       }
325       m.type = rtype;
326       this.addExceptionAttribute( exceptionClasses );
327       return m;
328    }
329
330    public Object JavaDoc addMember(int mods, Class JavaDoc type, Class JavaDoc[] exceptionClasses, String JavaDoc name ) {
331       return addMember(mods, type, name, null, exceptionClasses);
332    }
333
334    public void addAttribute(AMember m, String JavaDoc name, Object JavaDoc data) {
335       if (m == null) {
336          m = (AMember) members.elementAt(0);
337       }
338       Attr a = new Attr();
339       a.name = name; a.data = data;
340       m.attr.addElement(a);
341    }
342
343    public void addAttribute(String JavaDoc name, Object JavaDoc data) {
344       addAttribute(current, name, data);
345    }
346
347    // instruction emitters
348
private final static int opc_iconst_0 = 3,
349       opc_bipush = 16,
350       opc_sipush = 17,
351       opc_ldc = 18,
352       opc_ldc_w = 19,
353       opc_ldc2_w = 20,
354       opc_aaload = 50,
355       opc_aastore = 83,
356       opc_dup = 89,
357       opc_getfield = 180,
358       field_put = 1,
359       field_static = -2,
360       opc_invokevirtual = 182,
361       opc_invokespecial = 183,
362       opc_invokestatic = 184,
363       opc_invokeinterface = 185,
364       opc_new = 187,
365       opc_newarray = 188,
366       opc_anewarray = 189,
367       opc_aload = 25,
368       opc_aload_0 = 42,
369       opc_wide = 196,
370       opc_areturn = 176,
371       opc_return = 177,
372       opc_checkcast = 192,
373       kind_a = 0,
374       kind_i = -4,
375       kind_l = -3,
376       kind_f = -2,
377       kind_d = -1,
378       kind_b = 1,
379       kind_c = 2,
380       kind_s = 3;
381
382    public int declare(Object JavaDoc t) {
383       int n = current.sp;
384       current.sp += 1;
385       if (t == Double.TYPE || t == Long.TYPE) {
386          current.sp += 1;
387       }
388       if (current.spmax < current.sp) {
389          current.spmax = current.sp;
390       }
391       AValue se = new AValue();
392       se.num = n; se.type = t;
393       stack.push(se);
394       return stack.size() - 1;
395    }
396
397    public void undeclare(Object JavaDoc t) {
398       AValue se = (AValue) stack.pop();
399       current.sp = se.num;
400    }
401
402    public void pushConstant(Object JavaDoc x) {
403       int op = opc_ldc_w;
404       if (x instanceof Integer JavaDoc) {
405          declare(Integer.TYPE);
406          int v = ((Integer JavaDoc)x).intValue();
407          if (v >= -1 && v <= 5) {
408             code.write(opc_iconst_0 + v);
409             return;
410          } else if ((v > -(1 << 7)) && (v < (1 << 7))) {
411             code.write(opc_bipush);
412             code.write(v);
413             return;
414          } else if ((v > -(1 << 15)) && (v < (1 << 15))) {
415             code.write(opc_sipush);
416             codeShort(v);
417             return;
418          }
419       } else if (x instanceof Float JavaDoc) {
420          declare(Float.TYPE);
421       } else if (x instanceof String JavaDoc) {
422          declare(String JavaDoc.class);
423       } else if (x instanceof Long JavaDoc) {
424          declare(Long.TYPE);
425          op = opc_ldc2_w;
426       } else if (x instanceof Double JavaDoc) {
427          declare(Double.TYPE);
428          op = opc_ldc2_w;
429       } else {
430          throw new RuntimeException JavaDoc("unexpected: "+x);
431       }
432       int xi = getIndex(x);
433       if (op == opc_ldc_w && xi < (1 << 8)) {
434          code.write(opc_ldc);
435          code.write(xi);
436       } else {
437          code.write(op);
438          codeShort(xi);
439       }
440    }
441    public void pushConstant(int x) {
442       pushConstant(new Integer JavaDoc(x));
443    }
444
445    public int pushLocal(int loc) {
446       if (current.locmax < loc) {
447          current.locmax = loc;
448       }
449       AValue se = (AValue) stack.elementAt(loc);
450       int kind = typeKind(se.type, false);
451       if (se.num <= 3) {
452          code.write(opc_aload_0 + (kind * 4) + se.num);
453       } else {
454          codeWide(opc_aload + kind, se.num);
455       }
456       return declare(se.type);
457    }
458
459    public int dup() {
460       code.write(opc_dup);
461       return declare(stack.peek());
462    }
463
464    public void checkCast(Object JavaDoc t) {
465       code.write(opc_checkcast);
466       codeShort(getIndex(t));
467       AValue se = (AValue) stack.pop();
468       if (se.type instanceof Class JavaDoc && ((Class JavaDoc)se.type).isPrimitive()) {
469          undeclare(Object JavaDoc.class); // get an error
470
declare(t);
471       }
472       se.type = t;
473    }
474
475    public int pushNewArray(Object JavaDoc etype) {
476       int kind = typeKind(etype, true);
477       int tcode;
478       Class JavaDoc t;
479       switch (kind) {
480        case kind_a:
481           code.write(opc_anewarray);
482           codeShort(getIndex(etype));
483           return declare(Object JavaDoc[].class);
484        case kind_f:
485           tcode = 0x00000006;
486           t = float[].class;
487           break;
488        case kind_d:
489           tcode = 0x00000007;
490           t = double[].class;
491           break;
492        case kind_i:
493           tcode = 0x0000000a;
494           t = int[].class;
495           break;
496        case kind_l:
497           tcode = 0x0000000b;
498           t = long[].class;
499           break;
500        case kind_b:
501           if (etype == Boolean.TYPE) {
502              tcode = 0x00000004;
503              t = boolean[].class;
504           } else {
505              tcode = 0x00000008;
506              t = byte[].class;
507           }
508           break;
509        case kind_c:
510           tcode = 0x00000005;
511           t = char[].class;
512           break;
513        case kind_s:
514           tcode = 0x00000009;
515           t = short[].class;
516           break;
517        default:
518           return 0;
519       }
520       code.write(opc_newarray);
521       code.write(tcode);
522       return declare(t); // etype[]
523
}
524
525    public void setElement(Object JavaDoc etype) {
526       int kind = typeKind(etype, true);
527       code.write(opc_aastore + kind);
528       undeclare(etype);
529       undeclare(Integer.TYPE);
530       undeclare(null); // etype[]
531
}
532
533    public void pushElement(Object JavaDoc etype) {
534       int kind = typeKind(etype, true);
535       code.write(opc_aaload + kind);
536       undeclare(Integer.TYPE);
537       undeclare(null); // etype[]
538
declare(etype);
539    }
540
541    public void ret() {
542       if (current.sig.endsWith("V")) {
543          code.write(opc_return);
544          return;
545       }
546       Object JavaDoc t = current.type;
547       undeclare(t);
548       code.write(opc_areturn + typeKind(t, false));
549       stack = null;
550    }
551
552    private int dofield(Object JavaDoc cls, String JavaDoc name, boolean isPut) {
553       int fi = getMemberIndex(cls, name);
554       Object JavaDoc x = cv.elementAt(fi);
555       int op = opc_getfield;
556       int mod;
557       Object JavaDoc t;
558       if (x instanceof Field) {
559          Field f = (Field) x;
560          mod = f.getModifiers();
561          t = f.getType();
562       } else {
563          AMember m = (AMember) x;
564          mod = m.mods;
565          t = m.type;
566       }
567       if (isPut) {
568          op += field_put;
569          undeclare(t);
570       }
571       if (Modifier.isStatic(mod)) {
572          op += field_static;
573       } else {
574          undeclare(cls);
575       }
576       code.write(op);
577       codeShort(fi);
578       return isPut ? -1 : declare(t);
579    }
580
581    public int pushField(Object JavaDoc cls, String JavaDoc name) {
582       return dofield(cls, name, false);
583    }
584
585    public void setField(Object JavaDoc cls, String JavaDoc name) {
586       dofield(cls, name, true);
587    }
588
589    public int invoke(Object JavaDoc cls, String JavaDoc name, Class JavaDoc ptypes[]) {
590       int mi = getMemberIndex(cls, name, ptypes);
591       Object JavaDoc x = cv.elementAt(mi);
592       int mod;
593       Object JavaDoc rtype;
594       int op = opc_invokevirtual;
595       if (x instanceof Method) {
596          Method m = (Method)x;
597          mod = m.getModifiers();
598          rtype = m.getReturnType();
599          if (m.getDeclaringClass().isInterface()) {
600             op = opc_invokeinterface;
601          }
602       } else if (x instanceof Constructor) {
603          Constructor m = (Constructor)x;
604          mod = m.getModifiers();
605          rtype = Void.TYPE;
606          op = opc_invokespecial;
607       } else {
608          AMember m = (AMember) x;
609          mod = m.mods;
610          rtype = m.type;
611          if (m.asm.isInterface()) {
612             op = opc_invokeinterface;
613          }
614       }
615       if (Modifier.isStatic(mod)) {
616          op = opc_invokestatic;
617       } else {
618          undeclare(cls);
619       }
620       for (int i = ptypes.length; --i >= 0; ) {
621          undeclare(ptypes[i]);
622       }
623       code.write(op);
624       codeShort(mi);
625       return declare(rtype);
626    }
627
628    private int typeKind(Object JavaDoc t, boolean subwords) {
629       if (t != null && t instanceof Class JavaDoc && ((Class JavaDoc)t).isPrimitive()) {
630          if (t == Float.TYPE) {
631             return kind_f;
632          } else if (t == Long.TYPE) {
633             return kind_l;
634          } else if (t == Double.TYPE) {
635             return kind_d;
636          } else if (t == Integer.TYPE || !subwords) {
637             return kind_i;
638          } else if (t == Character.TYPE) {
639             return kind_c;
640          } else if (t == Short.TYPE) {
641             return kind_s;
642          } else {
643             return kind_b;
644          }
645       } else {
646          return kind_a;
647       }
648    }
649
650    private void codeWide(int op, int n) {
651       if (n < (1 << 8)) {
652          code.write(op);
653          code.write(n);
654       } else {
655          code.write(opc_wide);
656          code.write(op);
657          codeShort(n);
658       }
659    }
660
661    private void codeShort(int v) {
662       code.write(v >>> 8);
663       code.write(v);
664    }
665
666    private static boolean isMethodSig(String JavaDoc sig) {
667       return (sig.indexOf('(') >= 0);
668    }
669
670    public byte[] getCode() {
671       try {
672          return internalGetCode();
673       } catch (IOException ee) {
674          throw new RuntimeException JavaDoc(ee.toString());
675       }
676    }
677
678    public byte[] internalGetCode() throws IOException {
679       // first, flush out all references to the cpool
680
getIndex(this);
681       getIndex(superClass);
682       for (int i = 0; i < interfaces.length; i++) {
683          getIndex(interfaces[i]);
684       }
685       int nfields = 0;
686       int nmethods = 0;
687       for (int i = 0; i < members.size(); i++) {
688          AMember m = (AMember) members.elementAt(i);
689
690          if (m.code != null) {
691             byte[] codeAttr = getMethodCode(m, m.code);
692             if (codeAttr != null) {
693                addAttribute(m, "Code", codeAttr);
694             }
695          }
696
697          for (int j = 0; j < m.attr.size(); j++) {
698             Attr a = (Attr) m.attr.elementAt(j);
699             getUtfIndex(a.name);
700          }
701
702          if (m.name.length() == 0) {
703             continue;
704          }
705          getUtfIndex(m.name);
706          getUtfIndex(m.sig);
707          if (isMethodSig(m.sig)) {
708             nmethods += 1;
709          } else {
710             nfields += 1;
711          }
712       }
713       // next, deal with internal references in the cpool
714
for (int i = 0; i < cv.size(); i++) {
715          Object JavaDoc x = cv.elementAt(i);
716          if (x == null) {
717             continue;
718          } else if (x instanceof String JavaDoc) {
719             String JavaDoc s = (String JavaDoc)x;
720             short si = getUtfIndex(s);
721             short data[] = { CONSTANT_STRING, si };
722             x = data;
723          }
724          else if (x instanceof Class JavaDoc) {
725             Class JavaDoc c = (Class JavaDoc)x;
726             short ci = getUtfIndex(c.getName().replace('.', '/'));
727             short data[] = { CONSTANT_CLASS, ci };
728             x = data;
729          } else if (x instanceof Field) {
730             Field m = (Field)x;
731             short ci = getIndex(m.getDeclaringClass());
732             short nt = getNTIndex(m.getName(),
733                                   getSig(m.getType()));
734             short data[] = { CONSTANT_FIELD, ci, nt };
735             x = data;
736          } else if (x instanceof Constructor) {
737             Constructor m = (Constructor)x;
738             short ci = getIndex(m.getDeclaringClass());
739             short nt = getNTIndex("<init>",
740                                   getSig(Void.TYPE,
741                                          m.getParameterTypes()));
742             short data[] = { CONSTANT_METHOD, ci, nt };
743             x = data;
744          } else if (x instanceof Method) {
745             Method m = (Method)x;
746             Class JavaDoc c = m.getDeclaringClass();
747             short kind = c.isInterface() ? CONSTANT_INTERFACEMETHOD
748                : CONSTANT_METHOD;
749             short ci = getIndex(c);
750             short nt = getNTIndex(m.getName(),
751                                   getSig(m.getReturnType(),
752                                          m.getParameterTypes()));
753             short data[] = { kind, ci, nt };
754             x = data;
755          } else if (x instanceof ProxyAssembler) {
756             ProxyAssembler asm = (ProxyAssembler)x;
757             short ci = getUtfIndex(asm.className.replace('.', '/'));
758             short data[] = { CONSTANT_CLASS, ci };
759             x = data;
760          } else if (x instanceof AMember) {
761             AMember m = (AMember) x;
762             short kind = !isMethodSig(m.sig) ? CONSTANT_FIELD
763                : m.asm.isInterface() ? CONSTANT_INTERFACEMETHOD
764                : CONSTANT_METHOD;
765             short ci = getIndex(m.asm);
766             short nt = getNTIndex(m.name, m.sig);
767             short data[] = { kind, ci, nt };
768             x = data;
769          } else if (x instanceof NameAndType) {
770             NameAndType nt = (NameAndType) x;
771             short data[] = { CONSTANT_NAMEANDTYPE, nt.name, nt.sig };
772             x = data;
773          }
774          cv.setElementAt(x, i); // update
775
}
776
777       ByteArrayOutputStream bytes = new ByteArrayOutputStream(400);
778       DataOutputStream ds = new DataOutputStream(bytes);
779       ds.writeInt(JAVA_MAGIC);
780       ds.writeShort(JAVA_MINOR_VERSION);
781       ds.writeShort(JAVA_VERSION);
782       int cvsize = cv.size();
783       ds.writeShort(cvsize);
784       for (int i = 0; i < cv.size(); i++) {
785          Object JavaDoc x = cv.elementAt(i);
786          if (x == null) {
787             continue;
788          } else if (x instanceof short[]) {
789             short data[] = (short[])x;
790             ds.writeByte(data[0]);
791             for (int j = 1; j < data.length; j++) {
792                ds.writeShort(data[j]);
793             }
794          } else if (x instanceof byte[]) {
795             ds.write((byte[])x);
796          } else if (x instanceof Integer JavaDoc) {
797             ds.writeByte(CONSTANT_INTEGER);
798             ds.writeInt(((Integer JavaDoc)x).intValue());
799             // (do other primitive literal types?)
800
} else {
801             throw new RuntimeException JavaDoc("unexpected");
802          }
803       }
804       ds.writeShort(modifiers);
805       ds.writeShort(getIndex(this));
806       ds.writeShort(getIndex(superClass));
807       ds.writeShort(interfaces.length);
808       for (int i = 0; i < interfaces.length; i++) {
809          ds.writeShort(getIndex(interfaces[i]));
810       }
811       for (int pass = 0; pass <= 1; pass++) {
812          boolean methods = (pass > 0);
813          ds.writeShort(methods ? nmethods : nfields);
814          for (int i = 0; i < members.size(); i++) {
815             AMember m = (AMember) members.elementAt(i);
816             if (m.name.length() == 0 || isMethodSig(m.sig) != methods) {
817                continue;
818             }
819             ds.writeShort(m.mods);
820             ds.writeShort(getUtfIndex(m.name));
821             ds.writeShort(getUtfIndex(m.sig));
822             writeAttrs(ds, m.attr);
823          }
824       }
825       AMember m0 = (AMember) members.elementAt(0);
826       writeAttrs(ds, (Vector) m0.attr);
827
828       // sanity check
829
if (cvsize != cv.size()) {
830          throw new RuntimeException JavaDoc("cvsize");
831       }
832
833       return bytes.toByteArray();
834    }
835
836    private byte[] getMethodCode(AMember m, ByteArrayOutputStream code) throws IOException {
837       if (code.size() == 0) {
838          if ((current.mods & (Modifier.NATIVE | Modifier.ABSTRACT)) == 0) {
839             current.mods |= Modifier.ABSTRACT;
840             modifiers |= Modifier.ABSTRACT;
841          }
842          return null;
843       }
844       ByteArrayOutputStream bytes
845          = new ByteArrayOutputStream(code.size()+30);
846       DataOutputStream ds = new DataOutputStream(bytes);
847       int slop = 10; // ??
848
int max_stack = current.locmax + slop;
849       int max_locals = current.spmax + slop;
850       ds.writeShort(max_stack);
851       ds.writeShort(max_locals);
852       ds.writeInt(code.size());
853       code.writeTo(ds);
854       ds.writeShort(0); // exception_table.length
855

856       Vector attrs = new Vector();
857       for (int i = m.attr.size(); --i >= 0; ) {
858          Attr ma = (Attr) m.attr.elementAt(i);
859          if (ma.name.startsWith("Code.")) {
860             m.attr.removeElementAt(i);
861             ma.name = ma.name.substring("Code.".length());
862             attrs.addElement(ma);
863             getUtfIndex(ma.name);
864          }
865       }
866       writeAttrs(ds, attrs);
867
868       return bytes.toByteArray();
869    }
870
871
872    private void writeAttrs(DataOutputStream ds, Vector attrs) throws IOException {
873       ds.writeShort(attrs.size());
874       for (int i = 0; i < attrs.size(); i++) {
875          Attr a = (Attr) attrs.elementAt(i);
876          ds.writeShort(getUtfIndex(a.name));
877          if (a.data instanceof byte[]) {
878             byte[] xa = (byte[])a.data;
879             ds.writeInt(xa.length);
880             ds.write(xa);
881          } else {
882             throw new RuntimeException JavaDoc("unexpected");
883          }
884       }
885    }
886
887    private static final int JAVA_MAGIC = 0xcafebabe;
888
889    private static final short JAVA_VERSION = 45,
890       JAVA_MINOR_VERSION = 3;
891
892    private static final short CONSTANT_UTF8 = 1,
893       CONSTANT_UNICODE = 2,
894       CONSTANT_INTEGER = 3,
895       CONSTANT_FLOAT = 4,
896       CONSTANT_LONG = 5,
897       CONSTANT_DOUBLE = 6,
898       CONSTANT_CLASS = 7,
899       CONSTANT_STRING = 8,
900       CONSTANT_FIELD = 9,
901       CONSTANT_METHOD = 10,
902       CONSTANT_INTERFACEMETHOD = 11,
903       CONSTANT_NAMEANDTYPE = 12;
904
905 }
906
907
Popular Tags