/** * Creates a dispatcher for inlined advice method. * * @param adviceMethod The advice method. */ protected Inlining(MethodDescription.InDefinedShape adviceMethod) { this.adviceMethod = adviceMethod; namedTypes = new HashMap<String, TypeDefinition>(); for (ParameterDescription parameterDescription : adviceMethod.getParameters().filter(isAnnotatedWith(Local.class))) { String name = parameterDescription.getDeclaredAnnotations().ofType(Local.class).loadSilent().value(); TypeDefinition previous = namedTypes.put(name, parameterDescription.getType()); if (previous != null && !previous.equals(parameterDescription.getType())) { throw new IllegalStateException("Local variable for " + name + " is defined with inconsistent types"); } } }
/** * {@inheritDoc} */ public Dispatcher.Resolved.ForMethodExit asMethodExit(List<? extends OffsetMapping.Factory<?>> userFactories, ClassReader classReader, Unresolved methodEnter) { Map<String, TypeDefinition> namedTypes = methodEnter.getNamedTypes(); for (ParameterDescription parameterDescription : adviceMethod.getParameters().filter(isAnnotatedWith(Local.class))) { String name = parameterDescription.getDeclaredAnnotations().ofType(Local.class).loadSilent().value(); TypeDefinition typeDefinition = namedTypes.get(name); if (typeDefinition == null) { throw new IllegalStateException(adviceMethod + " attempts use of undeclared local variable " + name); } else if (!typeDefinition.equals(parameterDescription.getType())) { throw new IllegalStateException(adviceMethod + " does not read variable " + name + " as " + typeDefinition); } } return Resolved.ForMethodExit.of(adviceMethod, namedTypes, userFactories, methodEnter.getAdviceType()); }
for (ParameterDescription.InDefinedShape parameterDescription : adviceMethod.getParameters()) { OffsetMapping offsetMapping = null; for (AnnotationDescription annotationDescription : parameterDescription.getDeclaredAnnotations()) {
@Override public boolean matches(TypeDescription targetInterface) { if (ElementMatchers.declaresMethod(named(targetMethod.getName()) .and(returns(targetMethod.getReturnType().asErasure())) .and(takesArguments(targetMethod.getParameters().asTypeList().asErasures()))) .matches(targetInterface)) { return true; } else { for (TypeDescription typeDescription : targetInterface.getInterfaces().asErasures()) { if (matches(typeDescription)) { return true; } } } return false; } }
for (ParameterDescription.InDefinedShape parameterDescription : methodDescription.getParameters()) { Generic parameterType = parameterDescription.getType(); if (!parameterType.accept(Generic.Visitor.Validator.METHOD_PARAMETER)) {
if (!methodDescription.isConstructor() && methodDescription.getReturnType().represents(void.class)) { throw new IllegalArgumentException("Bootstrap method is no constructor or non-void static factory: " + methodDescription); } else if (methodDescription.getParameters().size() + (methodDescription.isStatic() || methodDescription.isConstructor() ? 0 : 1) != rawArguments.size()) { throw new IllegalArgumentException("Cannot assign " + rawArguments + " to " + methodDescription); ? methodDescription.getParameters().asTypeList().asErasures() : CompoundList.of(methodDescription.getDeclaringType(), methodDescription.getParameters().asTypeList().asErasures())).iterator(); List<Object> arguments = new ArrayList<Object>(rawArguments.size()); for (Object argument : rawArguments) {
int index = 0, currentStackSize = 0, maximumStackSize = 0; for (OffsetMapping.Target offsetMapping : offsetMappings) { currentStackSize += adviceMethod.getParameters().get(index++).getType().getStackSize().getSize(); maximumStackSize = Math.max(maximumStackSize, currentStackSize + offsetMapping.resolveRead() .apply(methodVisitor, implementationContext)
/** * Creates a binder by installing two proxy types which are implemented by this binder if a field getter * or a field setter is requested by using the * {@link FieldProxy} annotation. * * @param getterType The type which should be used for getter proxies. The type must * represent an interface which defines a single method which returns an * {@link java.lang.Object} return type and does not take any arguments. The use of generics * is permitted. * @param setterType The type which should be uses for setter proxies. The type must * represent an interface which defines a single method which returns {@code void} * and takes a single {@link java.lang.Object}-typed argument. The use of generics * is permitted. * @return A binder for the {@link FieldProxy} annotation. */ public static TargetMethodAnnotationDrivenBinder.ParameterBinder<FieldProxy> install(TypeDescription getterType, TypeDescription setterType) { MethodDescription.InDefinedShape getterMethod = onlyMethod(getterType); if (!getterMethod.getReturnType().asErasure().represents(Object.class)) { throw new IllegalArgumentException(getterMethod + " must take a single Object-typed parameter"); } else if (getterMethod.getParameters().size() != 0) { throw new IllegalArgumentException(getterMethod + " must not declare parameters"); } MethodDescription.InDefinedShape setterMethod = onlyMethod(setterType); if (!setterMethod.getReturnType().asErasure().represents(void.class)) { throw new IllegalArgumentException(setterMethod + " must return void"); } else if (setterMethod.getParameters().size() != 1 || !setterMethod.getParameters().get(0).getType().asErasure().represents(Object.class)) { throw new IllegalArgumentException(setterMethod + " must declare a single Object-typed parameters"); } return new Binder(getterMethod, setterMethod); }
/** * {@inheritDoc} */ public DynamicType.Builder<?> apply(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassFileLocator classFileLocator) { for (MethodDescription.InDefinedShape methodDescription : typeDescription.getDeclaredMethods() .filter(not(isBridge()).<MethodDescription>and(isAnnotatedWith(Enhance.class)))) { if (methodDescription.isAbstract()) { throw new IllegalStateException("Cannot cache the value of an abstract method: " + methodDescription); } else if (!methodDescription.getParameters().isEmpty()) { throw new IllegalStateException("Cannot cache the value of a method with parameters: " + methodDescription); } else if (methodDescription.getReturnType().represents(void.class)) { throw new IllegalStateException("Cannot cache void result for " + methodDescription); } String name = methodDescription.getDeclaredAnnotations().ofType(Enhance.class).loadSilent().value(); if (name.length() == 0) { name = methodDescription.getName() + NAME_INFIX + randomString.nextString(); } builder = builder .defineField(name, methodDescription.getReturnType().asErasure(), methodDescription.isStatic() ? Ownership.STATIC : Ownership.MEMBER, Visibility.PRIVATE, SyntheticState.SYNTHETIC, FieldPersistence.TRANSIENT) .visit(Advice.withCustomMapping() .bind(CacheField.class, new CacheFieldOffsetMapping(name)) .to(adviceByType.get(methodDescription.getReturnType().isPrimitive() ? methodDescription.getReturnType().asErasure() : TypeDescription.OBJECT), this.classFileLocator) .on(is(methodDescription))); } return builder; }
/** * {@inheritDoc} */ public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) { TypeDescription auxiliaryType = implementationContext.register(PrivilegedMemberLookupAction.of(methodDescription)); return new Compound( TypeCreation.of(auxiliaryType), Duplication.SINGLE, ClassConstant.of(methodDescription.getDeclaringType()), methodName, ArrayFactory.forType(TypeDescription.Generic.OfNonGenericType.CLASS) .withValues(typeConstantsFor(methodDescription.getParameters().asTypeList().asErasures())), MethodInvocation.invoke(auxiliaryType.getDeclaredMethods().filter(isConstructor()).getOnly()), MethodInvocation.invoke(DO_PRIVILEGED), TypeCasting.to(TypeDescription.ForLoadedType.of(methodDescription.isConstructor() ? Constructor.class : Method.class)) ).apply(methodVisitor, implementationContext); }
/** * Creates a method handle representation of the given method for an explicit special method invocation of an otherwise virtual method. * * @param methodDescription The method ro represent. * @param typeDescription The type on which the method is to be invoked on as a special method invocation. * @return A method handle representing the given method as special method invocation. */ public static MethodHandle ofSpecial(MethodDescription.InDefinedShape methodDescription, TypeDescription typeDescription) { if (!methodDescription.isSpecializableFor(typeDescription)) { throw new IllegalArgumentException("Cannot specialize " + methodDescription + " for " + typeDescription); } return new MethodHandle(HandleType.ofSpecial(methodDescription), typeDescription, methodDescription.getInternalName(), methodDescription.getReturnType().asErasure(), methodDescription.getParameters().asTypeList().asErasures()); }
/** * {@inheritDoc} */ @SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST", justification = "The implicit field type casting is not understood by Findbugs") public AnnotationList getDeclaredAnnotations() { Annotation[][] annotation = parameterAnnotationSource.getParameterAnnotations(); MethodDescription.InDefinedShape declaringMethod = getDeclaringMethod(); if (annotation.length != declaringMethod.getParameters().size() && declaringMethod.getDeclaringType().isInnerClass()) { return index == 0 ? new AnnotationList.Empty() : new AnnotationList.ForLoadedAnnotations(annotation[index - 1]); } else { return new AnnotationList.ForLoadedAnnotations(annotation[index]); } } }
/** * {@inheritDoc} */ public AnnotationList getDeclaredAnnotations() { MethodDescription.InDefinedShape declaringMethod = getDeclaringMethod(); Annotation[][] parameterAnnotation = parameterAnnotationSource.getParameterAnnotations(); if (parameterAnnotation.length != declaringMethod.getParameters().size() && declaringMethod.getDeclaringType().isInnerClass()) { return index == 0 ? new AnnotationList.Empty() : new AnnotationList.ForLoadedAnnotations(parameterAnnotation[index - 1]); } else { return new AnnotationList.ForLoadedAnnotations(parameterAnnotation[index]); } } }
/** * Creates a method handle representation of the given method. * * @param methodDescription The method ro represent. * @return A method handle representing the given method. */ public static MethodHandle of(MethodDescription.InDefinedShape methodDescription) { return new MethodHandle(HandleType.of(methodDescription), methodDescription.getDeclaringType().asErasure(), methodDescription.getInternalName(), methodDescription.getReturnType().asErasure(), methodDescription.getParameters().asTypeList().asErasures()); }
/** * {@inheritDoc} */ public ParameterList<ParameterDescription.InDefinedShape> getParameters() { return new ParameterList.Explicit.ForTypes(this, methodDescription.getParameters().asTypeList().asRawTypes()); }
/** * {@inheritDoc} */ public InDefinedShape asDefined() { return methodDescription.getParameters().get(index); } }
/** * {@inheritDoc} */ public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) { return new Compound( ClassConstant.of(methodDescription.getDeclaringType()), methodName(), ArrayFactory.forType(TypeDescription.Generic.OfNonGenericType.CLASS) .withValues(typeConstantsFor(methodDescription.getParameters().asTypeList().asErasures())), MethodInvocation.invoke(accessorMethod()) ).apply(methodVisitor, implementationContext); }
/** * {@inheritDoc} */ public ParameterList<ParameterDescription.InDefinedShape> getParameters() { return new ParameterList.Explicit.ForTypes(this, CompoundList.of(methodDescription.getParameters().asTypeList().asErasures(), placeholderType)); }