/** * {@inheritDoc} */ public String apply(TypeDescription instrumentedType, MethodDescription instrumentedMethod) { StringBuilder stringBuilder = new StringBuilder("("); boolean comma = false; for (TypeDescription typeDescription : instrumentedMethod.getParameters().asTypeList().asErasures()) { if (comma) { stringBuilder.append(','); } else { comma = true; } stringBuilder.append(typeDescription.getName()); } return stringBuilder.append(')').toString(); } }
/** * Creates an annotation description for the values that were defined for this builder. * * @return An appropriate annotation description. */ public AnnotationDescription build() { for (MethodDescription methodDescription : annotationType.getDeclaredMethods()) { if (annotationValues.get(methodDescription.getName()) == null && methodDescription.getDefaultValue() == null) { throw new IllegalStateException("No value or default value defined for " + methodDescription.getName()); } } return new Latent(annotationType, annotationValues); } }
/** * {@inheritDoc} */ public TypeList.Generic getInterfaces() { return typeDescription.getInterfaces(); }
/** * Creates a type creation for the given type. * * @param typeDescription The type to be create. * @return A stack manipulation that represents the creation of the given type. */ public static StackManipulation of(TypeDescription typeDescription) { if (typeDescription.isArray() || typeDescription.isPrimitive() || typeDescription.isAbstract()) { throw new IllegalArgumentException(typeDescription + " is not instantiable"); } return new TypeCreation(typeDescription); }
/** * Resolves a type locator based upon an annotation value. * * @param typeDescription The annotation's value. * @return The appropriate type locator. */ protected static TypeLocator of(TypeDescription typeDescription) { if (typeDescription.represents(void.class)) { return ForParameterType.INSTANCE; } else if (typeDescription.represents(TargetType.class)) { return ForInstrumentedType.INSTANCE; } else if (typeDescription.isPrimitive() || typeDescription.isArray()) { throw new IllegalStateException("Cannot assign proxy to " + typeDescription); } else { return new ForType(typeDescription); } }
/** * Creates a new differentiating type attribute appender. * * @param typeDescription The type for which to resolve all exclusion indices. */ public Differentiating(TypeDescription typeDescription) { this(typeDescription.getDeclaredAnnotations().size(), typeDescription.getTypeVariables().size(), typeDescription.getInterfaces().size()); }
/** * Creates a matcher where only overridable or declared methods are matched unless those are ignored. Methods that * are declared by the target type are only matched if they are not ignored. Declared methods that are not found on the * target type are always matched. * * @param ignoredMethods A method matcher that matches any ignored method. * @param originalType The original type of the instrumentation before adding any user methods. * @return A latent method matcher that identifies any method to instrument for a rebasement or redefinition. */ protected static LatentMatcher<MethodDescription> of(LatentMatcher<? super MethodDescription> ignoredMethods, TypeDescription originalType) { ElementMatcher.Junction<MethodDescription> predefinedMethodSignatures = none(); for (MethodDescription methodDescription : originalType.getDeclaredMethods()) { ElementMatcher.Junction<MethodDescription> signature = methodDescription.isConstructor() ? isConstructor() : ElementMatchers.<MethodDescription>named(methodDescription.getName()); signature = signature.and(returns(methodDescription.getReturnType().asErasure())); signature = signature.and(takesArguments(methodDescription.getParameters().asTypeList().asErasures())); predefinedMethodSignatures = predefinedMethodSignatures.or(signature); } return new InliningImplementationMatcher(ignoredMethods, predefinedMethodSignatures); }
@Override public boolean matches(MethodDescription targetMethod) { TypeDescription superClass = targetMethod.getDeclaringType().asErasure(); do { superClass = superClass.getSuperClass().asErasure(); if (declaresMethod(named(targetMethod.getName()) .and(returns(targetMethod.getReturnType().asErasure())) .and(takesArguments(targetMethod.getParameters().asTypeList().asErasures())) .and(extraMethodMatcher)) .matches(superClass)) { return true; } } while (superClassMatcher.matches(superClass)); return false; } }
/** * {@inheritDoc} */ public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) { TypeDescription.Generic parameterType = instrumentedMethod.getParameters().get(0).getType(); MethodDescription setterMethod = methodAccessorFactory.registerSetterFor(fieldDescription, MethodAccessorFactory.AccessType.DEFAULT); StackManipulation.Size stackSize = new StackManipulation.Compound( fieldDescription.isStatic() ? StackManipulation.Trivial.INSTANCE : new StackManipulation.Compound( MethodVariableAccess.loadThis(), FieldAccess.forField(typeDescription.getDeclaredFields() .filter((named(AccessorProxy.FIELD_NAME))).getOnly()).read()), MethodVariableAccess.of(parameterType).loadFrom(1), assigner.assign(parameterType, setterMethod.getParameters().get(0).getType(), Assigner.Typing.DYNAMIC), MethodInvocation.invoke(setterMethod), MethodReturn.VOID ).apply(methodVisitor, implementationContext); return new Size(stackSize.getMaximalSize(), instrumentedMethod.getStackSize()); } }
/** * Locates the only method of a type that is compatible to being overridden for invoking the proxy. * * @param typeDescription The type that is being installed. * @return Its only method after validation. */ private static MethodDescription onlyMethod(TypeDescription typeDescription) { if (!typeDescription.isInterface()) { throw new IllegalArgumentException(typeDescription + " is not an interface"); } else if (!typeDescription.getInterfaces().isEmpty()) { throw new IllegalArgumentException(typeDescription + " must not extend other interfaces"); } else if (!typeDescription.isPublic()) { throw new IllegalArgumentException(typeDescription + " is mot public"); } MethodList<?> methodCandidates = typeDescription.getDeclaredMethods().filter(isAbstract()); if (methodCandidates.size() != 1) { throw new IllegalArgumentException(typeDescription + " must declare exactly one abstract method"); } MethodDescription methodDescription = methodCandidates.getOnly(); if (!methodDescription.getReturnType().asErasure().represents(Object.class)) { throw new IllegalArgumentException(methodDescription + " does not return an Object-type"); } else if (methodDescription.getParameters().size() != 1 || !methodDescription.getParameters().getOnly().getType().asErasure().represents(Object.class)) { throw new IllegalArgumentException(methodDescription + " does not take a single Object-typed argument"); } return methodDescription; }
MethodDescription instrumentedMethod) { StackManipulation arrayReference = MethodVariableAccess.REFERENCE.loadFrom(1); StackManipulation[] parameterLoading = new StackManipulation[accessorMethod.getParameters().size()]; int index = 0; for (TypeDescription.Generic parameterType : accessorMethod.getParameters().asTypeList()) { parameterLoading[index] = new StackManipulation.Compound(arrayReference, IntegerConstant.forValue(index), accessorMethod.isStatic() ? Trivial.INSTANCE : new StackManipulation.Compound( MethodVariableAccess.loadThis(), FieldAccess.forField(typeDescription.getDeclaredFields() .filter((named(RedirectionProxy.FIELD_NAME))) .getOnly()).read()), new StackManipulation.Compound(parameterLoading),
/** * {@inheritDoc} */ protected FieldDescription.InDefinedShape initialize(TypeDescription instrumentedType) { return instrumentedType.getDeclaredFields().filter(named(name)).getOnly(); }
@Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { MethodVisitor methodVisitor = super.visitMethod(access, name, desc, signature, exceptions); MethodList<?> methodList = typeDescription.getDeclaredMethods().filter((name.equals(MethodDescription.CONSTRUCTOR_INTERNAL_NAME) ? isConstructor() : ElementMatchers.<MethodDescription>named(name)).and(hasDescriptor(desc))); if (methodList.size() == 1 && methodList.getOnly().getParameters().hasExplicitMetaData()) { for (ParameterDescription parameterDescription : methodList.getOnly().getParameters()) { methodVisitor.visitParameter(parameterDescription.getName(), parameterDescription.getModifiers()); } return new MethodParameterStrippingMethodVisitor(methodVisitor); } else { return methodVisitor; } } }
/** * {@inheritDoc} */ public MethodRegistry inject(TypeDescription instrumentedType, MethodRegistry methodRegistry) { MethodList<?> candidates = instrumentedType.getSuperClass().getDeclaredMethods().filter(isConstructor().and(elementMatcher)); if (candidates.isEmpty()) { throw new IllegalStateException("No possible candidate for super constructor invocation in " + instrumentedType.getSuperClass()); } else if (!candidates.filter(takesArguments(0)).isEmpty()) { candidates = candidates.filter(takesArguments(0)); } else if (candidates.size() > 1) { throw new IllegalStateException("More than one possible super constructor for constructor delegation: " + candidates); } MethodCall methodCall = MethodCall.invoke(candidates.getOnly()); for (TypeDescription typeDescription : candidates.getOnly().getParameters().asTypeList().asErasures()) { methodCall = methodCall.with(typeDescription.getDefaultValue()); } return methodRegistry.append(new LatentMatcher.Resolved<MethodDescription>(isConstructor().and(takesArguments(0))), new MethodRegistry.Handler.ForImplementation(methodCall), methodAttributeAppenderFactory, Transformer.NoOp.<MethodDescription>make()); } }
/** * Creates a new construction delegate that calls a default constructor. * * @param throwableType The type of the {@link Throwable}. */ public ForDefaultConstructor(TypeDescription throwableType) { this.throwableType = throwableType; this.targetConstructor = throwableType.getDeclaredMethods() .filter(isConstructor().and(takesArguments(0))).getOnly(); }
@Override protected FieldDescription resolve(TypeDescription instrumentedType) { if (!fieldType.asErasure().isVisibleTo(instrumentedType)) { throw new IllegalStateException(fieldType + " is not visible to " + instrumentedType); } else { return instrumentedType.getDeclaredFields() .filter(named(fieldName).and(fieldType(fieldType.asErasure()))) .getOnly(); } } }
/** * {@inheritDoc} */ public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) { FieldDescription valuesField = instrumentedType.getDeclaredFields().filter(named(ENUM_VALUES)).getOnly(); MethodDescription cloneMethod = TypeDescription.Generic.OBJECT.getDeclaredMethods().filter(named(CLONE_METHOD_NAME)).getOnly(); return new Size(new StackManipulation.Compound( FieldAccess.forField(valuesField).read(), MethodInvocation.invoke(cloneMethod).virtual(valuesField.getType().asErasure()), TypeCasting.to(valuesField.getType().asErasure()), MethodReturn.REFERENCE ).apply(methodVisitor, implementationContext).getMaximalSize(), instrumentedMethod.getStackSize()); } }
@Override public Target resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Advice.ArgumentHandler argumentHandler, Sort sort) { final String returnType = instrumentedMethod.getReturnType().asErasure().getSimpleName(); final String className = instrumentedMethod.getDeclaringType().getTypeName(); final String signature = String.format("%s %s.%s(%s)", returnType, className, instrumentedMethod.getName(), getSignature(instrumentedMethod)); return Target.ForStackManipulation.of(signature); } };
/** * {@inheritDoc} */ public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) { return ForInstance.this.apply(methodVisitor, implementationContext, instrumentedMethod, StackManipulation.Trivial.INSTANCE, instrumentedType.getDeclaredFields().filter(named(fieldName).and(genericFieldType(INVOCATION_HANDLER_TYPE))).getOnly()); } }
/** * {@inheritDoc} */ public ByteCodeAppender appender(Target implementationTarget) { if (implementationTarget.getInstrumentedType().isInterface()) { throw new IllegalStateException("Cannot implement meaningful hash code method for " + implementationTarget.getInstrumentedType()); } return new Appender(offsetProvider.resolve(implementationTarget.getInstrumentedType()), multiplier, implementationTarget.getInstrumentedType().getDeclaredFields().filter(not(isStatic().or(ignored))), nonNullable); }