1 23 24 package org.objectweb.fractal.julia.asm; 25 26 import org.objectweb.fractal.julia.loader.Initializable; 27 import org.objectweb.fractal.julia.loader.Tree; 28 29 import org.objectweb.asm.CodeVisitor; 30 import org.objectweb.asm.Label; 31 import org.objectweb.asm.Type; 32 33 import java.lang.reflect.Method ; 34 import java.util.ArrayList ; 35 import java.util.Arrays ; 36 37 113 114 public class InterfaceClassGenerator extends AbstractClassGenerator 115 implements Initializable 116 { 117 118 121 122 private String implFieldDesc; 123 124 133 134 public void initialize (final Tree args) throws Exception { 135 this.superClass = args.getSubTree(0).toString().replace('.', '/'); 136 } 137 138 146 147 protected void parseArgs (final Tree args) { 148 interfaces = new ArrayList (Arrays.asList(args.getSubTree(1).getSubTrees())); 149 for (int i = 0; i < interfaces.size(); ++i) { 150 interfaces.set(i, interfaces.get(i).toString().replace('.', '/')); 151 } 152 } 153 154 161 162 protected String getSource () { 163 String s = interfaces.get(0).toString(); 164 if (s.lastIndexOf('/') != -1) { 165 s = s.substring(s.lastIndexOf('/') + 1); 166 } 167 return "INTERFACE[" + s + "]"; 168 } 169 170 178 179 protected void generateConstructor () throws ClassGenerationException { 180 CodeVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); 182 mv.visitVarInsn(ALOAD, 0); 183 mv.visitMethodInsn(INVOKESPECIAL, superClass, "<init>", "()V"); 184 mv.visitInsn(RETURN); 185 mv.visitMaxs(1, 1); 186 187 mv = cw.visitMethod( 189 ACC_PUBLIC, 190 "<init>", 191 "(Lorg/objectweb/fractal/api/Component;" + 192 "Ljava/lang/String;" + 193 "Lorg/objectweb/fractal/api/Type;" + 194 "ZLjava/lang/Object;)V", 195 null, 196 null); 197 mv.visitVarInsn(ALOAD, 0); 198 mv.visitVarInsn(ALOAD, 1); 199 mv.visitVarInsn(ALOAD, 2); 200 mv.visitVarInsn(ALOAD, 3); 201 mv.visitVarInsn(ILOAD, 4); 202 mv.visitVarInsn(ALOAD, 5); 203 mv.visitMethodInsn( 204 INVOKESPECIAL, 205 superClass, 206 "<init>", 207 "(Lorg/objectweb/fractal/api/Component;" + 208 "Ljava/lang/String;" + 209 "Lorg/objectweb/fractal/api/Type;" + 210 "ZLjava/lang/Object;)V"); 211 mv.visitInsn(RETURN); 212 mv.visitMaxs(6, 6); 213 } 214 215 223 224 protected void generateDefaultMethods () throws ClassGenerationException { 225 super.generateDefaultMethods(); 226 if (interfaces.size() == 1) { 228 implFieldDesc = "L" + (String )interfaces.get(0) + ";"; 229 } else { 230 implFieldDesc = "Ljava/lang/Object;"; 231 } 232 cw.visitField(ACC_PRIVATE, "impl", implFieldDesc, null, null); 233 String mName = "getFcItfImpl"; 235 String mDesc = "()Ljava/lang/Object;"; 236 CodeVisitor mv = cw.visitMethod(ACC_PUBLIC, mName, mDesc, null, null); 237 mv.visitVarInsn(ALOAD, 0); 238 mv.visitFieldInsn(GETFIELD, name, "impl", implFieldDesc); 239 mv.visitInsn(ARETURN); 240 mv.visitMaxs(1, 1); 241 mName = "setFcItfImpl"; 243 mDesc = "(Ljava/lang/Object;)V"; 244 mv = cw.visitMethod(ACC_PUBLIC, mName, mDesc, null, null); 245 mv.visitVarInsn(ALOAD, 0); 246 mv.visitVarInsn(ALOAD, 1); 247 if (interfaces.size() == 1) { 248 mv.visitTypeInsn(CHECKCAST, (String )interfaces.get(0)); 250 } 251 mv.visitFieldInsn(PUTFIELD, name, "impl", implFieldDesc); 252 mv.visitInsn(RETURN); 253 mv.visitMaxs(2, 2); 254 } 255 256 261 262 protected void generateMethod (final Method m) { 263 String name = m.getName(); 265 String itf = Type.getInternalName(m.getDeclaringClass()); 266 String mDesc = Type.getMethodDescriptor(m); 267 Class [] exceptions = m.getExceptionTypes(); 268 String [] excepts = new String [exceptions.length]; 269 for (int i = 0; i < exceptions.length; ++i) { 270 excepts[i] = Type.getInternalName(exceptions[i]); 271 } 272 if (name.equals("hashCode") && m.getParameterTypes().length == 0) { 273 return; 275 } 276 if (name.equals("equals")) { 277 Class [] args = m.getParameterTypes(); 278 if (args.length == 1 && args[0].equals(Object .class)) { 279 return; 281 } 282 } 283 CodeVisitor mv = cw.visitMethod(ACC_PUBLIC, name, mDesc, excepts, null); 284 mv.visitVarInsn(ALOAD, 0); 286 mv.visitFieldInsn(GETFIELD, this.name, "impl", implFieldDesc); 287 Label l = new Label(); 289 mv.visitInsn(DUP); 290 mv.visitJumpInsn(IFNONNULL, l); 291 mv.visitTypeInsn(NEW, "java/lang/NullPointerException"); 292 mv.visitInsn(DUP); 293 mv.visitLdcInsn( 294 "Trying to invoke a method on a client interface, " + 295 "or on a server interface whose complementary interface is not bound."); 296 mv.visitMethodInsn( 297 INVOKESPECIAL, 298 "java/lang/NullPointerException", "<init>", "(Ljava/lang/String;)V"); 299 mv.visitInsn(ATHROW); 300 mv.visitLabel(l); 301 if (interfaces.size() > 1) { 303 mv.visitTypeInsn(CHECKCAST, itf); 304 } 305 Class [] params = m.getParameterTypes(); 307 int offset = 1; 308 for (int i = 0; i < params.length; ++i) { 309 mv.visitVarInsn(ILOAD + getOpcodeOffset(params[i]), offset); 310 offset += getSize(params[i]); 311 } 312 mv.visitMethodInsn(INVOKEINTERFACE, itf, name, mDesc); 314 Class result = m.getReturnType(); 316 if (result == Void.TYPE) { 317 mv.visitInsn(RETURN); 318 } else { 319 mv.visitInsn(IRETURN + getOpcodeOffset(result)); 320 } 321 int maxStack = Math.max(4, Math.max(offset, getSize(result))); 323 int maxLocals = Math.max(offset, getSize(result)); 324 mv.visitMaxs(maxStack, maxLocals); 325 } 326 } 327 | Popular Tags |