/** * {@inheritDoc} */ public MethodDescription.InDefinedShape getEnclosingMethod(TypePool typePool) { TypeDescription enclosingType = getEnclosingType(typePool); MethodList<MethodDescription.InDefinedShape> enclosingMethod = enclosingType.getDeclaredMethods() .filter(hasMethodName(methodName).and(hasDescriptor(methodDescriptor))); if (enclosingMethod.isEmpty()) { throw new IllegalStateException(methodName + methodDescriptor + " not declared by " + enclosingType); } return enclosingMethod.getOnly(); }
/** * Creates a binder by installing a single proxy type where annotating a parameter with {@link FieldProxy} allows * getting and setting values for a given field. * * @param typeDescription A type which declares exactly one abstract getter and an abstract setter for the {@link Object} * type. The type is allowed to be generic. * @return A binder for the {@link FieldProxy} annotation. */ public static TargetMethodAnnotationDrivenBinder.ParameterBinder<FieldProxy> install(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 not public"); } MethodList<MethodDescription.InDefinedShape> methodCandidates = typeDescription.getDeclaredMethods().filter(isAbstract()); if (methodCandidates.size() != 2) { throw new IllegalArgumentException(typeDescription + " does not declare exactly two non-abstract methods"); } MethodList<MethodDescription.InDefinedShape> getterCandidates = methodCandidates.filter(isGetter(Object.class)); if (getterCandidates.size() != 1) { throw new IllegalArgumentException(typeDescription + " does not declare a getter with an Object type"); } MethodList<MethodDescription.InDefinedShape> setterCandidates = methodCandidates.filter(isSetter(Object.class)); if (setterCandidates.size() != 1) { throw new IllegalArgumentException(typeDescription + " does not declare a setter with an Object type"); } return new Binder(typeDescription, getterCandidates.getOnly(), setterCandidates.getOnly()); }
/** * {@inheritDoc} */ public List<MethodDescription.Token> extractConstructors(TypeDescription instrumentedType) { if (instrumentedType.getSuperClass().getDeclaredMethods().filter(isConstructor()).isEmpty()) { throw new IllegalStateException("Cannot define default constructor for class without super class constructor"); } return Collections.singletonList(new MethodDescription.Token(Opcodes.ACC_PUBLIC)); }
/** * {@inheritDoc} */ public MethodDescription resolve(TypeDescription targetType, MethodDescription instrumentedMethod) { List<MethodDescription> candidates = CompoundList.<MethodDescription>of( instrumentedType.getSuperClass().getDeclaredMethods().filter(isConstructor().and(matcher)), methodGraphCompiler.compile(targetType, instrumentedType).listNodes().asMethodList().filter(matcher)); if (candidates.size() == 1) { return candidates.get(0); } else { throw new IllegalStateException(instrumentedType + " does not define exactly one virtual method or constructor for " + matcher); } }
/** * {@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()); } }
/** * {@inheritDoc} */ public Compiled compile(TypeDescription instrumentedType) { MethodList<?> targets = new MethodList.Explicit<MethodDescription>(CompoundList.<MethodDescription>of( instrumentedType.getDeclaredMethods().filter(isStatic().or(isPrivate())), methodGraphCompiler.compile(instrumentedType).listNodes().asMethodList()) ).filter(named(name).and(takesArguments(0)).and(not(returns(isPrimitive().or(isArray()))))); if (targets.size() != 1) { throw new IllegalStateException(instrumentedType + " does not define method without arguments with name " + name + ": " + targets); } else if (!targets.getOnly().getReturnType().asErasure().isVisibleTo(instrumentedType)) { throw new IllegalStateException(targets.getOnly() + " is not visible to " + instrumentedType); } else { MethodList<?> candidates = methodGraphCompiler.compile(targets.getOnly().getReturnType(), instrumentedType) .listNodes() .asMethodList() .filter(matcher); List<MethodDelegationBinder.Record> records = new ArrayList<MethodDelegationBinder.Record>(candidates.size()); MethodDelegationBinder methodDelegationBinder = TargetMethodAnnotationDrivenBinder.of(parameterBinders); for (MethodDescription candidate : candidates) { records.add(methodDelegationBinder.compile(candidate)); } return new Compiled.ForMethodReturn(targets.get(0), records); } }
.listNodes() .asMethodList() .filter(isAbstract()); if (methods.size() != 1) { throw new IllegalArgumentException(functionalInterface + " does not define exactly one abstract method: " + methods); AnnotationValue.UNDEFINED, TypeDescription.Generic.UNDEFINED), JavaConstant.MethodType.of(methods.asDefined().getOnly()), JavaConstant.MethodHandle.of(methodDescription), JavaConstant.MethodType.of(methods.asDefined().getOnly())).invoke(methods.asDefined().getOnly().getInternalName());
@Override protected List<MethodDescription.Token> doExtractConstructors(TypeDescription instrumentedType) { TypeDescription.Generic superClass = instrumentedType.getSuperClass(); return (superClass == null ? new MethodList.Empty<MethodDescription.InGenericShape>() : superClass.getDeclaredMethods().filter(isConstructor().and(isVisibleTo(instrumentedType)))).asTokenList(is(instrumentedType)); }
@Override protected List<MethodDescription.Token> doExtractConstructors(TypeDescription instrumentedType) { TypeDescription.Generic superClass = instrumentedType.getSuperClass(); MethodList<?> defaultConstructors = superClass == null ? new MethodList.Empty<MethodDescription.InGenericShape>() : superClass.getDeclaredMethods().filter(isConstructor().and(takesArguments(0)).<MethodDescription>and(isVisibleTo(instrumentedType))); if (defaultConstructors.size() == 1) { return Collections.singletonList(new MethodDescription.Token(Opcodes.ACC_PUBLIC)); } else { throw new IllegalArgumentException(instrumentedType.getSuperClass() + " declares no constructor that is visible to " + instrumentedType); } }
private void visitFields(Set<Class<?>> types, AnnotationCache cache, TypeDescription typeDescription, boolean inheriting) { typeDescription.getDeclaredFields().forEach(f -> { Consumer<Annotation> addToCache = a -> types.forEach(t -> cache.addFieldAnnotation(t, f.getName(), a)); // Regular field annotations f.getDeclaredAnnotations() .forEach(a -> cacheSupportedAnnotations(a, types, cache, addToCache, inheriting)); // Type-use annotations f.getType().getDeclaredAnnotations() .forEach(a -> cacheSupportedAnnotations(a, types, cache, addToCache, inheriting)); }); typeDescription.getDeclaredMethods() .filter(m -> m.getName().startsWith("get") && m.getName().length() > 3) .forEach(m -> { String methodName = m.getName(); String correspondingFieldName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4); Consumer<Annotation> addToCache = a -> types.forEach(t -> cache.addFieldAnnotation(t, correspondingFieldName, a)); m.getDeclaredAnnotations() .forEach(a -> cacheSupportedAnnotations(a, types, cache, addToCache, inheriting)); }); }
cached ? methodConstant.cached() : methodConstant, ArrayFactory.forType(TypeDescription.Generic.OBJECT).withValues(argumentValuesOf(instrumentedMethod)), MethodInvocation.invoke(INVOCATION_HANDLER_TYPE.getDeclaredMethods().getOnly()), assigner.assign(TypeDescription.Generic.OBJECT, instrumentedMethod.getReturnType(), Assigner.Typing.DYNAMIC), MethodReturn.of(instrumentedMethod.getReturnType())
/** * Precompiles a static method delegation for a given list of methods. * * @param methods The methods to consider. * @param methodDelegationBinder The method delegation binder to use. * @return An appropriate implementation delegate. */ protected static ImplementationDelegate of(MethodList<?> methods, MethodDelegationBinder methodDelegationBinder) { List<MethodDelegationBinder.Record> records = new ArrayList<MethodDelegationBinder.Record>(methods.size()); for (MethodDescription methodDescription : methods) { records.add(methodDelegationBinder.compile(methodDescription)); } return new ForStaticMethod(records); }
protected void onTypeMatch(TypeDescription typeDescription) { for (MethodDescription.InDefinedShape methodDescription : typeDescription.getDeclaredMethods() .filter(getMethodElementMatcher())) { onMethodMatch(methodDescription); } }
/** * {@inheritDoc} */ public DynamicType.Builder<?> apply(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassFileLocator classFileLocator) { Enhance enhance = typeDescription.getDeclaredAnnotations().ofType(Enhance.class).loadSilent(); if (typeDescription.getDeclaredMethods().filter(isToString()).isEmpty()) { builder = builder.method(isToString()).intercept(ToStringMethod.prefixedBy(enhance.prefix().getPrefixResolver()) .withIgnoredFields(enhance.includeSyntheticFields() ? ElementMatchers.<FieldDescription>none() : ElementMatchers.<FieldDescription>isSynthetic()) .withIgnoredFields(isAnnotatedWith(Exclude.class))); } return builder; }
@Override protected List<MethodDescription.Token> doExtractConstructors(TypeDescription instrumentedType) { TypeDescription.Generic superClass = instrumentedType.getSuperClass(); return (superClass == null ? new MethodList.Empty<MethodDescription.InGenericShape>() : superClass.getDeclaredMethods().filter(isPublic().and(isConstructor()))).asTokenList(is(instrumentedType)); }
/** * {@inheritDoc} */ public Compiled compile(TypeDescription instrumentedType) { FieldDescription fieldDescription = resolve(instrumentedType); if (!fieldDescription.getType().asErasure().isVisibleTo(instrumentedType)) { throw new IllegalStateException(fieldDescription + " is not visible to " + instrumentedType); } else { MethodList<?> candidates = methodGraphCompiler.compile(fieldDescription.getType(), instrumentedType) .listNodes() .asMethodList() .filter(matcher); List<MethodDelegationBinder.Record> records = new ArrayList<MethodDelegationBinder.Record>(candidates.size()); MethodDelegationBinder methodDelegationBinder = TargetMethodAnnotationDrivenBinder.of(parameterBinders); for (MethodDescription candidate : candidates) { records.add(methodDelegationBinder.compile(candidate)); } return new Compiled.ForField(fieldDescription, records); } }
/** * Creates an implementation delegate for constructing a new instance. * * @param typeDescription The type being constructed. * @param methods The constructors to consider. * @param methodDelegationBinder The method delegation binder to use. * @return An appropriate implementation delegate. */ protected static ImplementationDelegate of(TypeDescription typeDescription, MethodList<?> methods, MethodDelegationBinder methodDelegationBinder) { List<MethodDelegationBinder.Record> records = new ArrayList<MethodDelegationBinder.Record>(methods.size()); for (MethodDescription methodDescription : methods) { records.add(methodDelegationBinder.compile(methodDescription)); } return new ForConstruction(typeDescription, records); }