// Copyright (c) Corporation for National Research Initiatives package org.python.compiler; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.python.core.imp; public class ClassFile { ClassWriter cw; int access; long mtime; public String name; String superclass; String sfilename; String[] interfaces; List<MethodVisitor> methodVisitors; List<FieldVisitor> fieldVisitors; public static String fixName(String n) { if (n.indexOf('.') == -1) return n; char[] c = n.toCharArray(); for(int i=0; i<c.length; i++) { if (c[i] == '.') c[i] = '/'; } return new String(c); } public ClassFile(String name) { this(name, "java/lang/Object", Opcodes.ACC_SYNCHRONIZED | Opcodes.ACC_PUBLIC, org.python.core.imp.NO_MTIME); } public ClassFile(String name, String superclass, int access) { this(name, superclass, access, org.python.core.imp.NO_MTIME); } public ClassFile(String name, String superclass, int access, long mtime) { this.name = fixName(name); this.superclass = fixName(superclass); this.interfaces = new String[0]; this.access = access; this.mtime = mtime; cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); methodVisitors = Collections.synchronizedList(new ArrayList<MethodVisitor>()); fieldVisitors = Collections.synchronizedList(new ArrayList<FieldVisitor>()); } public void setSource(String name) { sfilename = name; } public void addInterface(String name) throws IOException { String[] new_interfaces = new String[interfaces.length+1]; System.arraycopy(interfaces, 0, new_interfaces, 0, interfaces.length); new_interfaces[interfaces.length] = name; interfaces = new_interfaces; } public Code addMethod(String name, String type, int access) throws IOException { MethodVisitor mv = cw.visitMethod(access, name, type, null, null); Code pmv = new Code(mv, type, access); methodVisitors.add(pmv); return pmv; } public void addField(String name, String type, int access) throws IOException { FieldVisitor fv = cw.visitField(access, name, type, null, null); fieldVisitors.add(fv); } public void endFields() throws IOException { for (FieldVisitor fv : fieldVisitors) { fv.visitEnd(); } } public void endMethods() throws IOException { for (int i=0; i<methodVisitors.size(); i++) { MethodVisitor mv = methodVisitors.get(i); mv.visitMaxs(0,0); mv.visitEnd(); } } public void write(OutputStream stream) throws IOException { cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, this.name, null, this.superclass, interfaces); AnnotationVisitor av = cw.visitAnnotation("Lorg/python/compiler/APIVersion;", true); // XXX: should imp.java really house this value or should imp.java point into // org.python.compiler? av.visit("value", new Integer(imp.getAPIVersion())); av.visitEnd(); av = cw.visitAnnotation("Lorg/python/compiler/MTime;", true); av.visit("value", new Long(mtime)); av.visitEnd(); if (sfilename != null) { cw.visitSource(sfilename, null); } endFields(); endMethods(); byte[] ba = cw.toByteArray(); //fos = io.FileOutputStream("%s.class" % self.name) ByteArrayOutputStream baos = new ByteArrayOutputStream(ba.length); baos.write(ba, 0, ba.length); baos.writeTo(stream); //debug(baos); baos.close(); } }