001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.proxy.compiler;
023:
024: import java.lang.reflect.*;
025: import java.util.*;
026: import java.io.*;
027:
028: /**
029: * A simple bytecode assembler.
030: *
031: * @deprecated Use {@link ProxyCompiler} or Jakarta BCEL instead.
032: *
033: * @author Unknown
034: * @version $Revision: 57209 $
035: */
036: public class ProxyAssembler {
037: // constant pool:
038: Vector cv = new Vector();
039: Hashtable ct = new Hashtable();
040: Hashtable ut = new Hashtable();
041: short cn = 1;
042:
043: // members:
044: Vector members;
045: AMember current;
046: ByteArrayOutputStream code; // current.code
047: Stack stack; // current.stack
048:
049: // other info:
050: String className;
051: int modifiers;
052: Class super Class;
053: Class interfaces[];
054:
055: public short getIndex(Object x) {
056: Object n = ct.get(x);
057: if (n == null) {
058: n = new Short(cn++);
059: ct.put(x, n);
060: cv.addElement(x);
061: }
062: return ((Short) n).shortValue();
063: }
064:
065: public short getUtfIndex(String x) {
066: Object n = ut.get(x);
067: if (n == null) {
068: n = new Short(cn++);
069: ut.put(x, n);
070: int xlen = 2 + x.length(); // x.utfLength(), really
071: ByteArrayOutputStream bytes = new ByteArrayOutputStream(
072: xlen);
073: DataOutputStream ds = new DataOutputStream(bytes);
074: try {
075: ds.writeByte(CONSTANT_UTF8);
076: ds.writeUTF(x);
077: } catch (IOException ee) {
078: throw new RuntimeException(ee.toString());
079: }
080: cv.addElement(bytes.toByteArray());
081: }
082: return ((Short) n).shortValue();
083: }
084:
085: public short getNTIndex(String name, String sig) {
086: NameAndType nt = new NameAndType();
087: nt.name = getUtfIndex(name);
088: nt.sig = getUtfIndex(sig);
089: return getIndex(nt);
090: }
091:
092: public short getClassIndex(Class c) {
093: short ci = getUtfIndex(c.getName().replace('.', '/'));
094: short data[] = { CONSTANT_CLASS, ci };
095: return getIndex(data);
096: }
097:
098: public short getMemberIndex(Object cls, String name, Class ptypes[]) {
099: if (cls instanceof Class) {
100: Class c = (Class) cls;
101: Member m;
102: try {
103: if (ptypes == null) {
104: m = c.getField(name);
105: } else if (name.equals("<init>")) {
106: m = c.getConstructor(ptypes);
107: } else {
108: m = c.getMethod(name, ptypes);
109: }
110: } catch (NoSuchMethodException ee) {
111: throw new IllegalArgumentException(ee + " in " + c);
112: } catch (NoSuchFieldException ee) {
113: throw new IllegalArgumentException(ee + " in " + c);
114: }
115: return getIndex(m);
116: } else if (cls instanceof ProxyAssembler) {
117: ProxyAssembler asm = (ProxyAssembler) cls;
118: String sig = getSig(null, ptypes);
119: AMember m = asm.findMember(sig, name);
120: if (m == null) {
121: throw new IllegalArgumentException(sig + " " + name);
122: }
123: return getIndex(m);
124: } else {
125: throw new IllegalArgumentException("not a type: " + cls);
126: }
127: }
128:
129: public short getMemberIndex(Object cls, String name) {
130: return getMemberIndex(cls, name, null);
131: }
132:
133: public static String getSig(Class 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 a = java.lang.reflect.Array.newInstance(t, 0)
159: .getClass();
160: return getSig(a).substring(1);
161: }
162: } else if (t.isArray()) {
163: return t.getName().replace('.', '/');
164: } else {
165: return "L" + t.getName().replace('.', '/') + ";";
166: }
167: }
168:
169: public static String getSig(Class rt, Class pt[]) {
170: if (pt == null) {
171: return getSig(rt);
172: }
173: StringBuffer sb = new StringBuffer();
174: sb.append("(");
175: for (int i = 0; i < pt.length; i++) {
176: sb.append(getSig(pt[i]));
177: }
178: sb.append(")");
179: sb.append(getSig(rt));
180: return sb.toString();
181: }
182:
183: boolean isInterface() {
184: return Modifier.isInterface(modifiers);
185: }
186:
187: public ProxyAssembler(String className, int modifiers,
188: Class super Class, Class interfaces[]) {
189: if (interfaces == null)
190: interfaces = new Class[0];
191: this .className = className;
192: this .modifiers = modifiers;
193: this .super Class = super Class;
194: this .interfaces = interfaces;
195: cv.addElement(null); // the first cpool entry is unused
196: members = new Vector();
197: addMember(0, "", null, "");
198: }
199:
200: private static class AMember {
201: int mods;
202: int sp;
203: int spmax;
204: int locmax;
205: int index;
206: Class type; // field or method return type
207: String sig;
208: String name;
209: Vector attr;
210: Stack stack;
211: ByteArrayOutputStream code;
212: ProxyAssembler asm;
213: }
214:
215: private static class Attr {
216: String name;
217: Object data;
218: }
219:
220: private static class AValue { // found in the stack
221: int num;
222: Object type;
223: }
224:
225: private static class NameAndType {
226: short name;
227: short sig;
228:
229: // must act as a hashtable key:
230: public boolean equals(Object x) {
231: if (x instanceof NameAndType) {
232: NameAndType that = (NameAndType) x;
233: return that.name == name && that.sig == sig;
234: }
235: return false;
236: }
237:
238: public int hashCode() {
239: return name + sig * 1000;
240: }
241: }
242:
243: public Object getCurrentMember() {
244: return current;
245: }
246:
247: public void setCurrentMember(Object m) {
248: if (m == null) {
249: m = members.elementAt(0);
250: }
251: current = (AMember) m;
252: code = current.code;
253: stack = current.stack;
254: }
255:
256: AMember findMember(String sig, String name) {
257: for (int i = 0; i < members.size(); i++) {
258: AMember m = (AMember) members.elementAt(i);
259: if (m.name.equals(name)) {
260: if (!sig.startsWith("(") ? !m.sig.startsWith("(")
261: : m.sig.startsWith(sig)) {
262: return m;
263: }
264: }
265: }
266: return null;
267: }
268:
269: void addExceptionAttribute(Class[] classes) {
270: try {
271:
272: if ((classes == null) || (classes.length == 0))
273: return;
274:
275: ByteArrayOutputStream baos = new ByteArrayOutputStream();
276: DataOutputStream dos = new DataOutputStream(baos);
277: short count = (short) classes.length;
278: dos.writeShort(count);
279: for (int iter = 0; iter < classes.length; iter++) {
280: dos.writeShort(getClassIndex(classes[iter]));
281: }
282: dos.flush();
283: baos.flush();
284: addAttribute("Exception", baos.toByteArray());
285: } catch (IOException cantHappen) {
286: cantHappen.printStackTrace();
287: }
288: }
289:
290: AMember addMember(int mods, String sig, Class[] exceptionClasses,
291: String name) {
292: String qsig = sig.substring(0, 1 + sig.indexOf(')'));
293: AMember m = findMember(qsig, name);
294: if (m != null) {
295: setCurrentMember(m);
296: current.mods |= mods;
297: modifiers |= (mods & Modifier.ABSTRACT);
298: return m;
299: }
300: m = new AMember();
301: m.asm = this ;
302: if (isMethodSig(sig)) {
303: m.code = new ByteArrayOutputStream();
304: m.stack = new Stack();
305: }
306: m.sig = sig;
307: m.name = name;
308: m.attr = new Vector();
309: m.index = members.size();
310: m.mods = mods;
311: members.addElement(m);
312: setCurrentMember(m);
313: this .addExceptionAttribute(exceptionClasses);
314: return m;
315: }
316:
317: public Object addMember(int mods, Class rtype, String name,
318: Class ptypes[], Class[] exceptionClasses) {
319: AMember m = addMember(mods, getSig(rtype, ptypes),
320: exceptionClasses, name);
321: if (ptypes != null && stack.size() == 0) {
322: // push the arguments onto the stack
323: if (!Modifier.isStatic(mods)) {
324: declare(this );
325: }
326: for (int i = 0; i < ptypes.length; i++) {
327: declare(ptypes[i]);
328: }
329: }
330: m.type = rtype;
331: this .addExceptionAttribute(exceptionClasses);
332: return m;
333: }
334:
335: public Object addMember(int mods, Class type,
336: Class[] exceptionClasses, String name) {
337: return addMember(mods, type, name, null, exceptionClasses);
338: }
339:
340: public void addAttribute(AMember m, String name, Object data) {
341: if (m == null) {
342: m = (AMember) members.elementAt(0);
343: }
344: Attr a = new Attr();
345: a.name = name;
346: a.data = data;
347: m.attr.addElement(a);
348: }
349:
350: public void addAttribute(String name, Object data) {
351: addAttribute(current, name, data);
352: }
353:
354: // instruction emitters
355: private final static int opc_iconst_0 = 3, opc_bipush = 16,
356: opc_sipush = 17, opc_ldc = 18, opc_ldc_w = 19,
357: opc_ldc2_w = 20, opc_aaload = 50, opc_aastore = 83,
358: opc_dup = 89, opc_getfield = 180, field_put = 1,
359: field_static = -2, opc_invokevirtual = 182,
360: opc_invokespecial = 183, opc_invokestatic = 184,
361: opc_invokeinterface = 185, opc_new = 187,
362: opc_newarray = 188, opc_anewarray = 189, opc_aload = 25,
363: opc_aload_0 = 42, opc_wide = 196, opc_areturn = 176,
364: opc_return = 177, opc_checkcast = 192, kind_a = 0,
365: kind_i = -4, kind_l = -3, kind_f = -2, kind_d = -1,
366: kind_b = 1, kind_c = 2, kind_s = 3;
367:
368: public int declare(Object t) {
369: int n = current.sp;
370: current.sp += 1;
371: if (t == Double.TYPE || t == Long.TYPE) {
372: current.sp += 1;
373: }
374: if (current.spmax < current.sp) {
375: current.spmax = current.sp;
376: }
377: AValue se = new AValue();
378: se.num = n;
379: se.type = t;
380: stack.push(se);
381: return stack.size() - 1;
382: }
383:
384: public void undeclare(Object t) {
385: AValue se = (AValue) stack.pop();
386: current.sp = se.num;
387: }
388:
389: public void pushConstant(Object x) {
390: int op = opc_ldc_w;
391: if (x instanceof Integer) {
392: declare(Integer.TYPE);
393: int v = ((Integer) x).intValue();
394: if (v >= -1 && v <= 5) {
395: code.write(opc_iconst_0 + v);
396: return;
397: } else if ((v > -(1 << 7)) && (v < (1 << 7))) {
398: code.write(opc_bipush);
399: code.write(v);
400: return;
401: } else if ((v > -(1 << 15)) && (v < (1 << 15))) {
402: code.write(opc_sipush);
403: codeShort(v);
404: return;
405: }
406: } else if (x instanceof Float) {
407: declare(Float.TYPE);
408: } else if (x instanceof String) {
409: declare(String.class);
410: } else if (x instanceof Long) {
411: declare(Long.TYPE);
412: op = opc_ldc2_w;
413: } else if (x instanceof Double) {
414: declare(Double.TYPE);
415: op = opc_ldc2_w;
416: } else {
417: throw new RuntimeException("unexpected: " + x);
418: }
419: int xi = getIndex(x);
420: if (op == opc_ldc_w && xi < (1 << 8)) {
421: code.write(opc_ldc);
422: code.write(xi);
423: } else {
424: code.write(op);
425: codeShort(xi);
426: }
427: }
428:
429: public void pushConstant(int x) {
430: pushConstant(new Integer(x));
431: }
432:
433: public int pushLocal(int loc) {
434: if (current.locmax < loc) {
435: current.locmax = loc;
436: }
437: AValue se = (AValue) stack.elementAt(loc);
438: int kind = typeKind(se.type, false);
439: if (se.num <= 3) {
440: code.write(opc_aload_0 + (kind * 4) + se.num);
441: } else {
442: codeWide(opc_aload + kind, se.num);
443: }
444: return declare(se.type);
445: }
446:
447: public int dup() {
448: code.write(opc_dup);
449: return declare(stack.peek());
450: }
451:
452: public void checkCast(Object t) {
453: code.write(opc_checkcast);
454: codeShort(getIndex(t));
455: AValue se = (AValue) stack.pop();
456: if (se.type instanceof Class && ((Class) se.type).isPrimitive()) {
457: undeclare(Object.class); // get an error
458: declare(t);
459: }
460: se.type = t;
461: }
462:
463: public int pushNewArray(Object etype) {
464: int kind = typeKind(etype, true);
465: int tcode;
466: Class t;
467: switch (kind) {
468: case kind_a:
469: code.write(opc_anewarray);
470: codeShort(getIndex(etype));
471: return declare(Object[].class);
472: case kind_f:
473: tcode = 0x00000006;
474: t = float[].class;
475: break;
476: case kind_d:
477: tcode = 0x00000007;
478: t = double[].class;
479: break;
480: case kind_i:
481: tcode = 0x0000000a;
482: t = int[].class;
483: break;
484: case kind_l:
485: tcode = 0x0000000b;
486: t = long[].class;
487: break;
488: case kind_b:
489: if (etype == Boolean.TYPE) {
490: tcode = 0x00000004;
491: t = boolean[].class;
492: } else {
493: tcode = 0x00000008;
494: t = byte[].class;
495: }
496: break;
497: case kind_c:
498: tcode = 0x00000005;
499: t = char[].class;
500: break;
501: case kind_s:
502: tcode = 0x00000009;
503: t = short[].class;
504: break;
505: default:
506: return 0;
507: }
508: code.write(opc_newarray);
509: code.write(tcode);
510: return declare(t); // etype[]
511: }
512:
513: public void setElement(Object etype) {
514: int kind = typeKind(etype, true);
515: code.write(opc_aastore + kind);
516: undeclare(etype);
517: undeclare(Integer.TYPE);
518: undeclare(null); // etype[]
519: }
520:
521: public void pushElement(Object etype) {
522: int kind = typeKind(etype, true);
523: code.write(opc_aaload + kind);
524: undeclare(Integer.TYPE);
525: undeclare(null); // etype[]
526: declare(etype);
527: }
528:
529: public void ret() {
530: if (current.sig.endsWith("V")) {
531: code.write(opc_return);
532: return;
533: }
534: Object t = current.type;
535: undeclare(t);
536: code.write(opc_areturn + typeKind(t, false));
537: stack = null;
538: }
539:
540: private int dofield(Object cls, String name, boolean isPut) {
541: int fi = getMemberIndex(cls, name);
542: Object x = cv.elementAt(fi);
543: int op = opc_getfield;
544: int mod;
545: Object t;
546: if (x instanceof Field) {
547: Field f = (Field) x;
548: mod = f.getModifiers();
549: t = f.getType();
550: } else {
551: AMember m = (AMember) x;
552: mod = m.mods;
553: t = m.type;
554: }
555: if (isPut) {
556: op += field_put;
557: undeclare(t);
558: }
559: if (Modifier.isStatic(mod)) {
560: op += field_static;
561: } else {
562: undeclare(cls);
563: }
564: code.write(op);
565: codeShort(fi);
566: return isPut ? -1 : declare(t);
567: }
568:
569: public int pushField(Object cls, String name) {
570: return dofield(cls, name, false);
571: }
572:
573: public void setField(Object cls, String name) {
574: dofield(cls, name, true);
575: }
576:
577: public int invoke(Object cls, String name, Class ptypes[]) {
578: int mi = getMemberIndex(cls, name, ptypes);
579: Object x = cv.elementAt(mi);
580: int mod;
581: Object rtype;
582: int op = opc_invokevirtual;
583: if (x instanceof Method) {
584: Method m = (Method) x;
585: mod = m.getModifiers();
586: rtype = m.getReturnType();
587: if (m.getDeclaringClass().isInterface()) {
588: op = opc_invokeinterface;
589: }
590: } else if (x instanceof Constructor) {
591: Constructor m = (Constructor) x;
592: mod = m.getModifiers();
593: rtype = Void.TYPE;
594: op = opc_invokespecial;
595: } else {
596: AMember m = (AMember) x;
597: mod = m.mods;
598: rtype = m.type;
599: if (m.asm.isInterface()) {
600: op = opc_invokeinterface;
601: }
602: }
603: if (Modifier.isStatic(mod)) {
604: op = opc_invokestatic;
605: } else {
606: undeclare(cls);
607: }
608: for (int i = ptypes.length; --i >= 0;) {
609: undeclare(ptypes[i]);
610: }
611: code.write(op);
612: codeShort(mi);
613: return declare(rtype);
614: }
615:
616: private int typeKind(Object t, boolean subwords) {
617: if (t != null && t instanceof Class
618: && ((Class) t).isPrimitive()) {
619: if (t == Float.TYPE) {
620: return kind_f;
621: } else if (t == Long.TYPE) {
622: return kind_l;
623: } else if (t == Double.TYPE) {
624: return kind_d;
625: } else if (t == Integer.TYPE || !subwords) {
626: return kind_i;
627: } else if (t == Character.TYPE) {
628: return kind_c;
629: } else if (t == Short.TYPE) {
630: return kind_s;
631: } else {
632: return kind_b;
633: }
634: } else {
635: return kind_a;
636: }
637: }
638:
639: private void codeWide(int op, int n) {
640: if (n < (1 << 8)) {
641: code.write(op);
642: code.write(n);
643: } else {
644: code.write(opc_wide);
645: code.write(op);
646: codeShort(n);
647: }
648: }
649:
650: private void codeShort(int v) {
651: code.write(v >>> 8);
652: code.write(v);
653: }
654:
655: private static boolean isMethodSig(String sig) {
656: return (sig.indexOf('(') >= 0);
657: }
658:
659: public byte[] getCode() {
660: try {
661: return internalGetCode();
662: } catch (IOException ee) {
663: throw new RuntimeException(ee.toString());
664: }
665: }
666:
667: public byte[] internalGetCode() throws IOException {
668: // first, flush out all references to the cpool
669: getIndex(this );
670: getIndex(super Class);
671: for (int i = 0; i < interfaces.length; i++) {
672: getIndex(interfaces[i]);
673: }
674: int nfields = 0;
675: int nmethods = 0;
676: for (int i = 0; i < members.size(); i++) {
677: AMember m = (AMember) members.elementAt(i);
678:
679: if (m.code != null) {
680: byte[] codeAttr = getMethodCode(m, m.code);
681: if (codeAttr != null) {
682: addAttribute(m, "Code", codeAttr);
683: }
684: }
685:
686: for (int j = 0; j < m.attr.size(); j++) {
687: Attr a = (Attr) m.attr.elementAt(j);
688: getUtfIndex(a.name);
689: }
690:
691: if (m.name.length() == 0) {
692: continue;
693: }
694: getUtfIndex(m.name);
695: getUtfIndex(m.sig);
696: if (isMethodSig(m.sig)) {
697: nmethods += 1;
698: } else {
699: nfields += 1;
700: }
701: }
702: // next, deal with internal references in the cpool
703: for (int i = 0; i < cv.size(); i++) {
704: Object x = cv.elementAt(i);
705: if (x == null) {
706: continue;
707: } else if (x instanceof String) {
708: String s = (String) x;
709: short si = getUtfIndex(s);
710: short data[] = { CONSTANT_STRING, si };
711: x = data;
712: } else if (x instanceof Class) {
713: Class c = (Class) x;
714: short ci = getUtfIndex(c.getName().replace('.', '/'));
715: short data[] = { CONSTANT_CLASS, ci };
716: x = data;
717: } else if (x instanceof Field) {
718: Field m = (Field) x;
719: short ci = getIndex(m.getDeclaringClass());
720: short nt = getNTIndex(m.getName(), getSig(m.getType()));
721: short data[] = { CONSTANT_FIELD, ci, nt };
722: x = data;
723: } else if (x instanceof Constructor) {
724: Constructor m = (Constructor) x;
725: short ci = getIndex(m.getDeclaringClass());
726: short nt = getNTIndex("<init>", getSig(Void.TYPE, m
727: .getParameterTypes()));
728: short data[] = { CONSTANT_METHOD, ci, nt };
729: x = data;
730: } else if (x instanceof Method) {
731: Method m = (Method) x;
732: Class c = m.getDeclaringClass();
733: short kind = c.isInterface() ? CONSTANT_INTERFACEMETHOD
734: : CONSTANT_METHOD;
735: short ci = getIndex(c);
736: short nt = getNTIndex(m.getName(), getSig(m
737: .getReturnType(), m.getParameterTypes()));
738: short data[] = { kind, ci, nt };
739: x = data;
740: } else if (x instanceof ProxyAssembler) {
741: ProxyAssembler asm = (ProxyAssembler) x;
742: short ci = getUtfIndex(asm.className.replace('.', '/'));
743: short data[] = { CONSTANT_CLASS, ci };
744: x = data;
745: } else if (x instanceof AMember) {
746: AMember m = (AMember) x;
747: short kind = !isMethodSig(m.sig) ? CONSTANT_FIELD
748: : m.asm.isInterface() ? CONSTANT_INTERFACEMETHOD
749: : CONSTANT_METHOD;
750: short ci = getIndex(m.asm);
751: short nt = getNTIndex(m.name, m.sig);
752: short data[] = { kind, ci, nt };
753: x = data;
754: } else if (x instanceof NameAndType) {
755: NameAndType nt = (NameAndType) x;
756: short data[] = { CONSTANT_NAMEANDTYPE, nt.name, nt.sig };
757: x = data;
758: }
759: cv.setElementAt(x, i); // update
760: }
761:
762: ByteArrayOutputStream bytes = new ByteArrayOutputStream(400);
763: DataOutputStream ds = new DataOutputStream(bytes);
764: ds.writeInt(JAVA_MAGIC);
765: ds.writeShort(JAVA_MINOR_VERSION);
766: ds.writeShort(JAVA_VERSION);
767: int cvsize = cv.size();
768: ds.writeShort(cvsize);
769: for (int i = 0; i < cv.size(); i++) {
770: Object x = cv.elementAt(i);
771: if (x == null) {
772: continue;
773: } else if (x instanceof short[]) {
774: short data[] = (short[]) x;
775: ds.writeByte(data[0]);
776: for (int j = 1; j < data.length; j++) {
777: ds.writeShort(data[j]);
778: }
779: } else if (x instanceof byte[]) {
780: ds.write((byte[]) x);
781: } else if (x instanceof Integer) {
782: ds.writeByte(CONSTANT_INTEGER);
783: ds.writeInt(((Integer) x).intValue());
784: // (do other primitive literal types?)
785: } else {
786: throw new RuntimeException("unexpected");
787: }
788: }
789: ds.writeShort(modifiers);
790: ds.writeShort(getIndex(this ));
791: ds.writeShort(getIndex(super Class));
792: ds.writeShort(interfaces.length);
793: for (int i = 0; i < interfaces.length; i++) {
794: ds.writeShort(getIndex(interfaces[i]));
795: }
796: for (int pass = 0; pass <= 1; pass++) {
797: boolean methods = (pass > 0);
798: ds.writeShort(methods ? nmethods : nfields);
799: for (int i = 0; i < members.size(); i++) {
800: AMember m = (AMember) members.elementAt(i);
801: if (m.name.length() == 0
802: || isMethodSig(m.sig) != methods) {
803: continue;
804: }
805: ds.writeShort(m.mods);
806: ds.writeShort(getUtfIndex(m.name));
807: ds.writeShort(getUtfIndex(m.sig));
808: writeAttrs(ds, m.attr);
809: }
810: }
811: AMember m0 = (AMember) members.elementAt(0);
812: writeAttrs(ds, (Vector) m0.attr);
813:
814: // sanity check
815: if (cvsize != cv.size()) {
816: throw new RuntimeException("cvsize");
817: }
818:
819: return bytes.toByteArray();
820: }
821:
822: private byte[] getMethodCode(AMember m, ByteArrayOutputStream code)
823: throws IOException {
824: if (code.size() == 0) {
825: if ((current.mods & (Modifier.NATIVE | Modifier.ABSTRACT)) == 0) {
826: current.mods |= Modifier.ABSTRACT;
827: modifiers |= Modifier.ABSTRACT;
828: }
829: return null;
830: }
831: ByteArrayOutputStream bytes = new ByteArrayOutputStream(code
832: .size() + 30);
833: DataOutputStream ds = new DataOutputStream(bytes);
834: int slop = 10; // ??
835: int max_stack = current.locmax + slop;
836: int max_locals = current.spmax + slop;
837: ds.writeShort(max_stack);
838: ds.writeShort(max_locals);
839: ds.writeInt(code.size());
840: code.writeTo(ds);
841: ds.writeShort(0); // exception_table.length
842:
843: Vector attrs = new Vector();
844: for (int i = m.attr.size(); --i >= 0;) {
845: Attr ma = (Attr) m.attr.elementAt(i);
846: if (ma.name.startsWith("Code.")) {
847: m.attr.removeElementAt(i);
848: ma.name = ma.name.substring("Code.".length());
849: attrs.addElement(ma);
850: getUtfIndex(ma.name);
851: }
852: }
853: writeAttrs(ds, attrs);
854:
855: return bytes.toByteArray();
856: }
857:
858: private void writeAttrs(DataOutputStream ds, Vector attrs)
859: throws IOException {
860: ds.writeShort(attrs.size());
861: for (int i = 0; i < attrs.size(); i++) {
862: Attr a = (Attr) attrs.elementAt(i);
863: ds.writeShort(getUtfIndex(a.name));
864: if (a.data instanceof byte[]) {
865: byte[] xa = (byte[]) a.data;
866: ds.writeInt(xa.length);
867: ds.write(xa);
868: } else {
869: throw new RuntimeException("unexpected");
870: }
871: }
872: }
873:
874: private static final int JAVA_MAGIC = 0xcafebabe;
875:
876: private static final short JAVA_VERSION = 45,
877: JAVA_MINOR_VERSION = 3;
878:
879: private static final short CONSTANT_UTF8 = 1, CONSTANT_UNICODE = 2,
880: CONSTANT_INTEGER = 3, CONSTANT_FLOAT = 4,
881: CONSTANT_LONG = 5, CONSTANT_DOUBLE = 6, CONSTANT_CLASS = 7,
882: CONSTANT_STRING = 8, CONSTANT_FIELD = 9,
883: CONSTANT_METHOD = 10, CONSTANT_INTERFACEMETHOD = 11,
884: CONSTANT_NAMEANDTYPE = 12;
885:
886: }
|