예제 #1
0
 private void visitType(java.lang.reflect.Type type, StringBuilder builder) {
   if (type instanceof Class) {
     Class<?> cl = (Class<?>) type;
     if (cl.isPrimitive()) {
       builder.append(Type.getType(cl).getDescriptor());
     } else {
       if (cl.isArray()) {
         builder.append(cl.getName().replace('.', '/'));
       } else {
         builder.append('L');
         builder.append(cl.getName().replace('.', '/'));
         builder.append(';');
       }
     }
   } else if (type instanceof ParameterizedType) {
     ParameterizedType parameterizedType = (ParameterizedType) type;
     visitNested(parameterizedType.getRawType(), builder);
     builder.append('<');
     for (java.lang.reflect.Type param : parameterizedType.getActualTypeArguments()) {
       visitType(param, builder);
     }
     builder.append(">;");
   } else if (type instanceof WildcardType) {
     WildcardType wildcardType = (WildcardType) type;
     if (wildcardType.getUpperBounds().length == 1
         && wildcardType.getUpperBounds()[0].equals(Object.class)) {
       if (wildcardType.getLowerBounds().length == 0) {
         builder.append('*');
         return;
       }
     } else {
       for (java.lang.reflect.Type upperType : wildcardType.getUpperBounds()) {
         builder.append('+');
         visitType(upperType, builder);
       }
     }
     for (java.lang.reflect.Type lowerType : wildcardType.getLowerBounds()) {
       builder.append('-');
       visitType(lowerType, builder);
     }
   } else if (type instanceof TypeVariable) {
     TypeVariable<?> typeVar = (TypeVariable) type;
     builder.append('T');
     builder.append(typeVar.getName());
     builder.append(';');
   } else if (type instanceof GenericArrayType) {
     GenericArrayType arrayType = (GenericArrayType) type;
     builder.append('[');
     visitType(arrayType.getGenericComponentType(), builder);
   } else {
     throw new IllegalArgumentException(
         String.format("Cannot generate signature for %s.", type));
   }
 }
 public static Class<?> malform(Class<?> type) throws Exception {
   ClassReader classReader = new ClassReader(type.getName());
   ClassWriter classWriter = new ClassWriter(classReader, 0);
   classReader.accept(new SignatureMalformer(classWriter), 0);
   ClassLoader classLoader =
       new ByteArrayClassLoader(
           null,
           Collections.singletonMap(type.getName(), classWriter.toByteArray()),
           null,
           ByteArrayClassLoader.PersistenceHandler.MANIFEST,
           PackageDefinitionStrategy.NoOp.INSTANCE);
   return classLoader.loadClass(type.getName());
 }
예제 #3
0
  private boolean isTransformed(Class clazz, String name, boolean isInterface) {
    if (isBytemanClass(name) || !isTransformable(name)) {
      return false;
    }

    boolean found = false;
    List<RuleScript> scripts;
    if (isInterface) {
      scripts = scriptRepository.scriptsForInterfaceName(name);
    } else {
      scripts = scriptRepository.scriptsForClassName(name);
    }
    if (scripts != null) {
      for (RuleScript script : scripts) {
        if (!script.hasTransform(clazz)) {
          found = true;
          if (isVerbose()) {
            System.out.println("Retransforming loaded bootstrap class " + clazz.getName());
          }
          break;
        }
      }
    }

    return found;
  }
예제 #4
0
  /**
   * check whether a class should not be considered for transformation
   *
   * @param clazz the class to check
   * @return true if clazz should not be considered for transformation otherwise false
   */
  protected boolean isSkipClass(Class<?> clazz) {
    if (!inst.isModifiableClass(clazz)) {
      return true;
    }

    // we can safely skip array classes, interfaces and primitive classes

    if (clazz.isArray()) {
      return true;
    }

    if (clazz.isInterface()) {
      return true;
    }

    if (clazz.isPrimitive()) {
      return true;
    }

    String name = clazz.getName();

    if (isBytemanClass(name) || !isTransformable(name)) {
      return true;
    }

    return false;
  }
예제 #5
0
  public static Class getHelperAdapter(Rule rule, Class helperClass, boolean compileToBytecode)
      throws CompileException {
    Class adapterClass;
    // ok we have to create the adapter class

    // n.b. we don't bother synchronizing here -- if another rule is racing to create an adapter
    // in parallel we don't really care about generating two of them -- we can use whichever
    // one gets installed last

    try {
      String helperName = Type.getInternalName(helperClass);
      String compiledHelperName;

      // we put the helper in the
      if (compileToBytecode) {
        compiledHelperName = helperName + "_HelperAdapter_Compiled_" + nextId();
      } else {
        compiledHelperName = helperName + "_HelperAdapter_Interpreted_" + nextId();
      }

      byte[] classBytes =
          compileBytes(rule, helperClass, helperName, compiledHelperName, compileToBytecode);
      String externalName = compiledHelperName.replace('/', '.');
      // dump the compiled class bytes if required
      Transformer.maybeDumpClass(externalName, classBytes);
      // ensure the class is loaded
      // think we need to load the generated helper using the class loader of the trigger class
      ClassLoader loader = rule.getLoader();
      adapterClass = loadHelperAdapter(loader, externalName, classBytes);
    } catch (CompileException ce) {
      throw ce;
    } catch (Throwable th) {
      if (compileToBytecode) {
        throw new CompileException(
            "Compiler.createHelperAdapter : exception creating compiled helper adapter for "
                + helperClass.getName(),
            th);
      } else {
        throw new CompileException(
            "Compiler.createHelperAdapter : exception creating interpreted helper adapter for "
                + helperClass.getName(),
            th);
      }
    }

    return adapterClass;
  }
예제 #6
0
    private ClassBuilderImpl(Class<T> type) {
      this.type = type;

      visitor = new ClassWriter(ClassWriter.COMPUTE_MAXS);
      typeName = type.getName() + "_Decorated";
      generatedType = Type.getType("L" + typeName.replaceAll("\\.", "/") + ";");
      superclassType = Type.getType(type);
    }
 @Test
 public void testSourceName() throws Exception {
   for (Class<?> type : standardTypes) {
     if (type.isArray()) {
       assertThat(describe(type).getActualName(), is(type.getComponentType().getName() + "[]"));
     } else {
       assertThat(describe(type).getActualName(), is(type.getName()));
     }
   }
 }
예제 #8
0
 /**
  * Creates a visitor which will be used as a base class for initiating the visit. It is not
  * necessary that the class is the superclass, any will do, as long as it can be loaded from a
  * byte[].
  *
  * @param baseClass
  * @return
  */
 private ClassReader createClassVisitor(final Class baseClass) {
   try {
     String name = baseClass.getName();
     String path = name.replace('.', '/') + ".class";
     InputStream in = loader.getResourceAsStream(path);
     return new ClassReader(in);
   } catch (IOException e) {
     throw new GroovyRuntimeException(
         "Unable to generate a proxy for " + baseClass + " from class loader " + loader, e);
   }
 }
예제 #9
0
 private void visitNested(java.lang.reflect.Type type, StringBuilder builder) {
   if (type instanceof Class) {
     Class<?> cl = (Class<?>) type;
     if (cl.isPrimitive()) {
       builder.append(Type.getType(cl).getDescriptor());
     } else {
       builder.append('L');
       builder.append(cl.getName().replace('.', '/'));
     }
   } else {
     visitType(type, builder);
   }
 }
예제 #10
0
 private String proxyName() {
   String name = delegateClass != null ? delegateClass.getName() : superClass.getName();
   int index = name.lastIndexOf('.');
   if (index == -1) return name + pxyCounter.incrementAndGet() + "_groovyProxy";
   return name.substring(index + 1, name.length()) + pxyCounter.incrementAndGet() + "_groovyProxy";
 }
 private void putClassOnStack(MethodVisitor methodVisitor, Class<?> managedTypeClass) {
   putConstantOnStack(methodVisitor, managedTypeClass.getName());
   methodVisitor.visitMethodInsn(
       INVOKESTATIC, CLASS_INTERNAL_NAME, "forName", FOR_NAME_METHOD_DESCRIPTOR, false);
 }
  protected void injectSetByIndex(
      ClassWriter classWriter, String targetClassName, List<Field> fields) {
    MethodVisitor methodVisitor =
        classWriter.visitMethod(
            ACC_PUBLIC,
            "set",
            "(Ljava/lang/Object;ILjava/lang/Object;)V",
            null,
            new String[] {getInternalName(ILLEGAL_ACCESS_EXCEPTION.getCanonicalName())});

    Boxer boxer = new Boxer(methodVisitor);

    methodVisitor.visitCode();
    methodVisitor.visitVarInsn(ILOAD, 2);

    int maxStack = 6;

    Label[] labels = new Label[fields.size()];
    Label errorLabel = new Label();

    for (int i = 0; i < fields.size(); i++) {
      labels[i] = new Label();
    }

    methodVisitor.visitTableSwitchInsn(0, labels.length - 1, errorLabel, labels);

    if (!fields.isEmpty()) {
      maxStack--;

      for (int i = 0; i < fields.size(); i++) {
        Field field = fields.get(i);
        Class<?> type = field.getType();
        Class<?> inputType = Boxer.wrap(type);
        String fieldDescriptor = Type.getDescriptor(type);
        String inputPath = getInternalName(inputType.getName());

        methodVisitor.visitLabel(labels[i]);

        if (i == 0) methodVisitor.visitFrame(F_APPEND, 1, new Object[] {targetClassName}, 0, null);
        else methodVisitor.visitFrame(F_SAME, 0, null, 0, null);

        if (isPublic(field) && !isFinal(field)) {
          methodVisitor.visitVarInsn(ALOAD, 1);
          methodVisitor.visitTypeInsn(CHECKCAST, targetClassName);
          methodVisitor.visitVarInsn(ALOAD, 3);

          if (!type.isPrimitive()) {
            methodVisitor.visitTypeInsn(CHECKCAST, inputPath);
          } else {
            boxer.unbox(Type.getType(type));
          }

          methodVisitor.visitFieldInsn(PUTFIELD, targetClassName, field.getName(), fieldDescriptor);
        } else {
          injectReflectiveSetter(methodVisitor);
        }

        methodVisitor.visitInsn(RETURN);
      }

      methodVisitor.visitLabel(errorLabel);
      methodVisitor.visitFrame(F_SAME, 0, null, 0, null);
    }

    injectException(methodVisitor, IllegalAccessException.class);
    methodVisitor.visitMaxs(maxStack, 4);
    methodVisitor.visitEnd();
  }
  public static List<InstantiatorDefinition> extractDefinitions(final Type target)
      throws IOException {
    final List<InstantiatorDefinition> constructors = new ArrayList<InstantiatorDefinition>();

    final Class<?> targetClass = TypeHelper.toClass(target);

    ClassLoader cl = targetClass.getClassLoader();
    if (cl == null) {
      cl = ClassLoader.getSystemClassLoader();
    }

    final String fileName = targetClass.getName().replace('.', '/') + ".class";
    final InputStream is = cl.getResourceAsStream(fileName);
    try {
      if (is == null) {
        throw new IOException("Cannot find file " + fileName + " in " + cl);
      }
      ClassReader classReader = new ClassReader(is);
      classReader.accept(
          new ClassVisitor(Opcodes.ASM5) {
            List<String> genericTypeNames;

            @Override
            public void visit(
                int version,
                int access,
                String name,
                String signature,
                String superName,
                String[] interfaces) {
              if (signature != null) {
                genericTypeNames = AsmUtils.extractGenericTypeNames(signature);
              } else {
                genericTypeNames = Collections.emptyList();
              }
              super.visit(version, access, name, signature, superName, interfaces);
            }

            @Override
            public MethodVisitor visitMethod(
                int access,
                final String methodName,
                String desc,
                String signature,
                String[] exceptions) {
              final boolean isConstructor = "<init>".equals(methodName);
              if ((Opcodes.ACC_PUBLIC & access) == Opcodes.ACC_PUBLIC
                  && (isConstructor
                      || ((Opcodes.ACC_STATIC & access) == Opcodes.ACC_STATIC
                          && !desc.endsWith("V")))) {
                final List<String> descTypes = AsmUtils.extractTypeNames(desc);

                final List<String> genericTypes;
                final List<String> names = new ArrayList<String>();
                if (signature != null) {
                  genericTypes = AsmUtils.extractTypeNames(signature);
                } else {
                  genericTypes = descTypes;
                }

                if (!isConstructor) {
                  if (descTypes.size() > 0) {
                    try {
                      final Type genericType =
                          AsmUtils.toGenericType(
                              descTypes.get(descTypes.size() - 1), genericTypeNames, target);
                      if (!targetClass.isAssignableFrom(TypeHelper.toClass(genericType))) {
                        return null;
                      }
                    } catch (ClassNotFoundException e) {
                      return null;
                    }
                  } else return null;
                }

                return new MethodVisitor(Opcodes.ASM5) {

                  Label firstLabel;
                  Label lastLabel;

                  @Override
                  public void visitLabel(Label label) {
                    if (firstLabel == null) {
                      firstLabel = label;
                    }
                    lastLabel = label;
                  }

                  @Override
                  public void visitLocalVariable(
                      String name,
                      String desc,
                      String signature,
                      Label start,
                      Label end,
                      int index) {
                    if (start.equals(firstLabel) && end.equals(lastLabel) && !"this".equals(name)) {
                      names.add(name);
                    }
                  }

                  @Override
                  public void visitEnd() {
                    try {
                      final List<Parameter> parameters = new ArrayList<Parameter>();

                      int l = descTypes.size() - (isConstructor ? 0 : 1);
                      for (int i = 0; i < l; i++) {
                        String name = "arg" + i;
                        if (i < names.size()) {
                          name = names.get(i);
                        }
                        parameters.add(
                            createParameter(i, name, descTypes.get(i), genericTypes.get(i)));
                      }

                      final Member executable;

                      if (isConstructor) {
                        executable = targetClass.getDeclaredConstructor(toTypeArray(parameters));
                      } else {
                        executable =
                            targetClass.getDeclaredMethod(methodName, toTypeArray(parameters));
                      }
                      constructors.add(
                          new ExecutableInstantiatorDefinition(
                              executable, parameters.toArray(new Parameter[0])));
                    } catch (Exception e) {
                      ErrorHelper.rethrow(e);
                    }
                  }

                  private Class<?>[] toTypeArray(List<Parameter> parameters) {
                    Class<?>[] types = new Class<?>[parameters.size()];
                    for (int i = 0; i < types.length; i++) {
                      types[i] = parameters.get(i).getType();
                    }
                    return types;
                  }

                  private Parameter createParameter(
                      int index, String name, String desc, String signature) {
                    try {

                      Type basicType = AsmUtils.toGenericType(desc, genericTypeNames, target);
                      Type genericType = basicType;
                      if (signature != null) {
                        Type type = AsmUtils.toGenericType(signature, genericTypeNames, target);
                        if (type != null) {
                          genericType = type;
                        }
                      }
                      return new Parameter(index, name, TypeHelper.toClass(basicType), genericType);
                    } catch (ClassNotFoundException e) {
                      throw new Error("Unexpected error " + e, e);
                    }
                  }
                };
              } else {
                return null;
              }
            }
          },
          0);
    } finally {
      try {
        is.close();
      } catch (Exception e) {
      }
    }

    return constructors;
  }
 @Test
 public void testName() throws Exception {
   for (Class<?> type : standardTypes) {
     assertThat(describe(type).getName(), is(type.getName()));
   }
 }