PanelClassEnhancer.java :  » Testing » UISpec4J » org » uispec4j » extension » Java Open Source

Java Open Source » Testing » UISpec4J 
UISpec4J » org » uispec4j » extension » PanelClassEnhancer.java
package org.uispec4j.extension;

import org.objectweb.asm.*;

class PanelClassEnhancer extends ClassAdapter implements Constants {
  private Extension[] extensions;

  public static byte[] transformClass(ClassReader reader, Extension[] extensions) {
    ClassWriter writer = new ClassWriter(true, true);
    PanelClassEnhancer transformer = new PanelClassEnhancer(writer, extensions);
    reader.accept(transformer, false);
    return writer.toByteArray();
  }

  private PanelClassEnhancer(ClassVisitor cv, Extension[] extensions) {
    super(cv);
    this.extensions = extensions;
  }

  public CodeVisitor visitMethod(int access,
                                 String name, String desc,
                                 String[] exceptions, Attribute attrs) {

    CodeVisitor cd = cv.visitMethod(access, name, desc, exceptions, attrs);
    if (cd == null) {
      return null;
    }
    if ("<clinit>".equals(name) && ((access & Constants.ACC_STATIC) != 0)) {
      return new StaticInitEnhancer(cd);
    }
    return cd;
  }

  private class StaticInitEnhancer extends CodeAdapter {
    public StaticInitEnhancer(CodeVisitor cd) {
      super(cd);
    }

    public void visitInsn(int opcode) {
      if (opcode == RETURN) {
        for (int i = 0; i < extensions.length; i++) {
          Extension extension = extensions[i];
          String componentClassName = extension.getComponentClassName();
          String transformedComponentClassName = transformClassName(componentClassName);
          addStaticInitializerForExtension(transformedComponentClassName, componentClassName);
        }
      }
      cv.visitInsn(opcode);
    }

    private void addStaticInitializerForExtension(String transformedComponentClassName, String componentClassName) {
      cv.visitFieldInsn(GETSTATIC, "org/uispec4j/Panel", transformedComponentClassName, "Ljava/lang/Class;");
      Label l12 = new Label();
      cv.visitJumpInsn(IFNONNULL, l12);
      cv.visitLdcInsn(componentClassName);
      cv.visitMethodInsn(INVOKESTATIC, "org/uispec4j/Panel", "class$", "(Ljava/lang/String;)Ljava/lang/Class;");
      cv.visitInsn(DUP);
      cv.visitFieldInsn(PUTSTATIC, "org/uispec4j/Panel", transformedComponentClassName, "Ljava/lang/Class;");
      Label l13 = new Label();
      cv.visitJumpInsn(GOTO, l13);
      cv.visitLabel(l12);
      cv.visitFieldInsn(GETSTATIC, "org/uispec4j/Panel", transformedComponentClassName, "Ljava/lang/Class;");
      cv.visitLabel(l13);
      cv.visitMethodInsn(INVOKESTATIC, "org/uispec4j/utils/UIComponentFactory", "addUIComponentClass", "(Ljava/lang/Class;)V");
    }
  }

  public void visitEnd() {
    for (int i = 0; i < extensions.length; i++) {
      Extension extension = extensions[i];
      addExtension(extension.getComponentName(),
                   extension.getComponentClassName());
    }
    cv.visitEnd();
  }

  private void addExtension(String componentName, String componentClassName) {
    String methodName = "get" + componentName;
    String transformedComponentClassName = transformClassName(componentClassName);
    String slashedComponentClassName = componentClassName.replace('.', '/');

    cv.visitField(ACC_STATIC + ACC_SYNTHETIC, transformedComponentClassName, "Ljava/lang/Class;", null, null);

    {
      CodeVisitor v = cv.visitMethod(ACC_PUBLIC, methodName,
                                     "(Ljava/lang/String;)L" + slashedComponentClassName + ";",
                                     new String[]{"org/uispec4j/ItemNotFoundException", "org/uispec4j/ComponentAmbiguityException"}, null);
      Label l0 = new Label();
      v.visitLabel(l0);
      v.visitVarInsn(ALOAD, 0);
      v.visitFieldInsn(GETFIELD, "org/uispec4j/Panel", "finder", "Lorg/uispec4j/finder/ComponentFinder;");
      v.visitFieldInsn(GETSTATIC, "org/uispec4j/Panel", transformedComponentClassName, "Ljava/lang/Class;");
      Label l1 = new Label();
      v.visitJumpInsn(IFNONNULL, l1);
      v.visitLdcInsn(componentClassName);
      v.visitMethodInsn(INVOKESTATIC, "org/uispec4j/Panel", "class$", "(Ljava/lang/String;)Ljava/lang/Class;");
      v.visitInsn(DUP);
      v.visitFieldInsn(PUTSTATIC, "org/uispec4j/Panel", transformedComponentClassName, "Ljava/lang/Class;");
      Label l2 = new Label();
      v.visitJumpInsn(GOTO, l2);
      v.visitLabel(l1);
      v.visitFieldInsn(GETSTATIC, "org/uispec4j/Panel", transformedComponentClassName, "Ljava/lang/Class;");
      v.visitLabel(l2);
      v.visitVarInsn(ALOAD, 1);
      v.visitMethodInsn(INVOKESTATIC, "org/uispec4j/Panel", "getComponent",
                        "(Lorg/uispec4j/finder/ComponentFinder;Ljava/lang/Class;Ljava/lang/String;)Lorg/uispec4j/UIComponent;");
      v.visitTypeInsn(CHECKCAST, slashedComponentClassName);
      v.visitInsn(ARETURN);
      v.visitMaxs(3, 2);
    }
    {
      CodeVisitor v = cv.visitMethod(ACC_PUBLIC, methodName,
                                     "()L" + slashedComponentClassName + ";",
                                     new String[]{"org/uispec4j/ItemNotFoundException", "org/uispec4j/ComponentAmbiguityException"}, null);
      Label l0 = new Label();
      v.visitLabel(l0);
      v.visitVarInsn(ALOAD, 0);
      v.visitFieldInsn(GETFIELD, "org/uispec4j/Panel", "finder", "Lorg/uispec4j/finder/ComponentFinder;");
      v.visitFieldInsn(GETSTATIC, "org/uispec4j/Panel", transformedComponentClassName, "Ljava/lang/Class;");
      Label l1 = new Label();
      v.visitJumpInsn(IFNONNULL, l1);
      v.visitLdcInsn(componentClassName);
      v.visitMethodInsn(INVOKESTATIC, "org/uispec4j/Panel", "class$", "(Ljava/lang/String;)Ljava/lang/Class;");
      v.visitInsn(DUP);
      v.visitFieldInsn(PUTSTATIC, "org/uispec4j/Panel", transformedComponentClassName, "Ljava/lang/Class;");
      Label l2 = new Label();
      v.visitJumpInsn(GOTO, l2);
      v.visitLabel(l1);
      v.visitFieldInsn(GETSTATIC, "org/uispec4j/Panel", transformedComponentClassName, "Ljava/lang/Class;");
      v.visitLabel(l2);
      v.visitInsn(ACONST_NULL);
      v.visitMethodInsn(INVOKESTATIC, "org/uispec4j/Panel", "getComponent",
                        "(Lorg/uispec4j/finder/ComponentFinder;Ljava/lang/Class;Ljava/lang/String;)Lorg/uispec4j/UIComponent;");
      v.visitTypeInsn(CHECKCAST, slashedComponentClassName);
      v.visitInsn(ARETURN);
      v.visitMaxs(3, 1);
    }
    {
      CodeVisitor v = cv.visitMethod(ACC_PUBLIC, methodName,
                                     "(Lorg/uispec4j/finder/ComponentMatcher;)L" + slashedComponentClassName + ";",
                                     new String[]{"org/uispec4j/ItemNotFoundException", "org/uispec4j/ComponentAmbiguityException"}, null);
      Label l0 = new Label();
      v.visitLabel(l0);
      v.visitVarInsn(ALOAD, 0);
      v.visitFieldInsn(GETFIELD, "org/uispec4j/Panel", "finder", "Lorg/uispec4j/finder/ComponentFinder;");
      v.visitVarInsn(ALOAD, 0);
      v.visitFieldInsn(GETSTATIC, "org/uispec4j/Panel", transformedComponentClassName, "Ljava/lang/Class;");
      Label l1 = new Label();
      v.visitJumpInsn(IFNONNULL, l1);
      v.visitLdcInsn(componentClassName);
      v.visitMethodInsn(INVOKESTATIC, "org/uispec4j/Panel", "class$", "(Ljava/lang/String;)Ljava/lang/Class;");
      v.visitInsn(DUP);
      v.visitFieldInsn(PUTSTATIC, "org/uispec4j/Panel", transformedComponentClassName, "Ljava/lang/Class;");
      Label l2 = new Label();
      v.visitJumpInsn(GOTO, l2);
      v.visitLabel(l1);
      v.visitFieldInsn(GETSTATIC, "org/uispec4j/Panel", transformedComponentClassName, "Ljava/lang/Class;");
      v.visitLabel(l2);
      v.visitVarInsn(ALOAD, 1);
      v.visitMethodInsn(INVOKESPECIAL, "org/uispec4j/Panel", "getMatcherByClass", "(Ljava/lang/Class;Lorg/uispec4j/finder/ComponentMatcher;)Lorg/uispec4j/finder/ComponentMatcher;");
      v.visitMethodInsn(INVOKESTATIC, "org/uispec4j/Panel", "getComponent", "(Lorg/uispec4j/finder/ComponentFinder;Lorg/uispec4j/finder/ComponentMatcher;)Lorg/uispec4j/UIComponent;");
      v.visitTypeInsn(CHECKCAST, slashedComponentClassName);
      v.visitInsn(ARETURN);
      Label l3 = new Label();
      v.visitLabel(l3);
      v.visitLineNumber(205, l0);
      v.visitLocalVariable("this", "Lorg/uispec4j/Panel;", l0, l3, 0);
      v.visitLocalVariable("matcher", "Lorg/uispec4j/finder/ComponentMatcher;", l0, l3, 1);
      v.visitMaxs(4, 2);
    }
  }

  private String transformClassName(String componentClassName) {
    return "class$" + componentClassName.replace('.', '$');
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.