private static String getMappedByNotManyToMany(AnnotatedFieldDescription target) { try { AnnotationDescription.Loadable<OneToOne> oto = target.getAnnotation( OneToOne.class ); if ( oto != null ) { return oto.getValue( new MethodDescription.ForLoadedMethod( OneToOne.class.getDeclaredMethod( "mappedBy" ) ) ).resolve( String.class ); } AnnotationDescription.Loadable<OneToMany> otm = target.getAnnotation( OneToMany.class ); if ( otm != null ) { return otm.getValue( new MethodDescription.ForLoadedMethod( OneToMany.class.getDeclaredMethod( "mappedBy" ) ) ).resolve( String.class ); } AnnotationDescription.Loadable<ManyToMany> mtm = target.getAnnotation( ManyToMany.class ); if ( mtm != null ) { return mtm.getValue( new MethodDescription.ForLoadedMethod( ManyToMany.class.getDeclaredMethod( "mappedBy" ) ) ).resolve( String.class ); } } catch (NoSuchMethodException ignored) { } return null; }
@Override protected StackManipulation proxyFor(TypeDescription parameterType, Implementation.Target implementationTarget, AnnotationDescription.Loadable<Super> annotation) { return new TypeProxy.ForSuperMethodByConstructor(parameterType, implementationTarget, Arrays.asList(annotation.getValue(CONSTRUCTOR_PARAMETERS).resolve(TypeDescription[].class)), annotation.getValue(IGNORE_FINALIZER).resolve(Boolean.class), annotation.getValue(SERIALIZABLE_PROXY).resolve(Boolean.class)); } },
/** * Creates an offset mapping for a field with an implicit declaring type. * * @param target The target type. * @param annotation The annotation to represent. */ protected WithImplicitType(TypeDescription.Generic target, AnnotationDescription.Loadable<FieldValue> annotation) { this(target, annotation.getValue(READ_ONLY).resolve(Boolean.class), annotation.getValue(TYPING).loadSilent(Assigner.Typing.class.getClassLoader()).resolve(Assigner.Typing.class), annotation.getValue(VALUE).resolve(String.class)); }
OffsetMapping.ForThrowable.Factory.of(adviceMethod) ), userFactories), adviceMethod.getDeclaredAnnotations().ofType(OnMethodExit.class).getValue(SUPPRESS_EXIT).resolve(TypeDescription.class), adviceMethod.getDeclaredAnnotations().ofType(OnMethodExit.class).getValue(REPEAT_ON).resolve(TypeDescription.class), classReader); backupArguments = adviceMethod.getDeclaredAnnotations().ofType(OnMethodExit.class).getValue(BACKUP_ARGUMENTS).resolve(Boolean.class);
/** * Creates a new resolved dispatcher for implementing method enter advice. * * @param adviceMethod The represented advice method. * @param userFactories A list of user-defined factories for offset mappings. * @param exitType The exit type or {@code void} if no exit type is defined. */ @SuppressWarnings("unchecked") // In absence of @SafeVarargs protected ForMethodEnter(MethodDescription.InDefinedShape adviceMethod, List<? extends OffsetMapping.Factory<?>> userFactories, TypeDefinition exitType) { super(adviceMethod, CompoundList.of(Arrays.asList(OffsetMapping.ForArgument.Unresolved.Factory.INSTANCE, OffsetMapping.ForAllArguments.Factory.INSTANCE, OffsetMapping.ForThisReference.Factory.INSTANCE, OffsetMapping.ForField.Unresolved.Factory.INSTANCE, OffsetMapping.ForOrigin.Factory.INSTANCE, OffsetMapping.ForUnusedValue.Factory.INSTANCE, OffsetMapping.ForStubValue.INSTANCE, OffsetMapping.ForExitValue.Factory.of(exitType), new OffsetMapping.Factory.Illegal<Thrown>(Thrown.class), new OffsetMapping.Factory.Illegal<Enter>(Enter.class), new OffsetMapping.Factory.Illegal<Local>(Local.class), new OffsetMapping.Factory.Illegal<Return>(Return.class)), userFactories), adviceMethod.getDeclaredAnnotations().ofType(OnMethodEnter.class).getValue(SUPPRESS_ENTER).resolve(TypeDescription.class), adviceMethod.getDeclaredAnnotations().ofType(OnMethodEnter.class).getValue(SKIP_ON).resolve(TypeDescription.class)); prependLineNumber = adviceMethod.getDeclaredAnnotations().ofType(OnMethodEnter.class).getValue(PREPEND_LINE_NUMBER).resolve(Boolean.class); }
/** * {@inheritDoc} */ public MethodDelegationBinder.ParameterBinding<?> bind(AnnotationDescription.Loadable<Morph> annotation, MethodDescription source, ParameterDescription target, Implementation.Target implementationTarget, Assigner assigner, Assigner.Typing typing) { if (!target.getType().asErasure().equals(forwardingMethod.getDeclaringType())) { throw new IllegalStateException("Illegal use of @Morph for " + target + " which was installed for " + forwardingMethod.getDeclaringType()); } Implementation.SpecialMethodInvocation specialMethodInvocation; TypeDescription typeDescription = annotation.getValue(DEFAULT_TARGET).resolve(TypeDescription.class); if (typeDescription.represents(void.class) && !annotation.getValue(DEFAULT_METHOD).resolve(Boolean.class)) { specialMethodInvocation = implementationTarget.invokeSuper(source.asSignatureToken()); } else { specialMethodInvocation = (typeDescription.represents(void.class) ? DefaultMethodLocator.Implicit.INSTANCE : new DefaultMethodLocator.Explicit(typeDescription)).resolve(implementationTarget, source); } return specialMethodInvocation.isValid() ? new MethodDelegationBinder.ParameterBinding.Anonymous(new RedirectionProxy(forwardingMethod.getDeclaringType().asErasure(), implementationTarget.getInstrumentedType(), specialMethodInvocation, assigner, annotation.getValue(SERIALIZABLE_PROXY).resolve(Boolean.class))) : MethodDelegationBinder.ParameterBinding.Illegal.INSTANCE; }
/** * {@inheritDoc} */ public MethodDelegationBinder.ParameterBinding<?> bind(AnnotationDescription.Loadable<Super> annotation, MethodDescription source, ParameterDescription target, Implementation.Target implementationTarget, Assigner assigner, Assigner.Typing typing) { if (target.getType().isPrimitive() || target.getType().isArray()) { throw new IllegalStateException(target + " uses the @Super annotation on an invalid type"); } TypeDescription proxyType = TypeLocator.ForType .of(annotation.getValue(PROXY_TYPE).resolve(TypeDescription.class)) .resolve(implementationTarget.getInstrumentedType(), target.getType()); if (proxyType.isFinal()) { throw new IllegalStateException("Cannot extend final type as @Super proxy: " + proxyType); } else if (source.isStatic() || !implementationTarget.getInstrumentedType().isAssignableTo(proxyType)) { return MethodDelegationBinder.ParameterBinding.Illegal.INSTANCE; } else { return new MethodDelegationBinder.ParameterBinding.Anonymous(annotation .getValue(STRATEGY).resolve(EnumerationDescription.class).load(Instantiation.class) .proxyFor(proxyType, implementationTarget, annotation)); } }
/** * Resolves exit advice that handles exceptions depending on the specification of the exit advice. * * @param adviceMethod The advice method. * @param namedTypes A mapping of all available local variables by their name to their type. * @param userFactories A list of user-defined factories for offset mappings. * @param classReader The class reader for parsing the advice method's class file. * @param enterType The type of the value supplied by the enter advice method or {@code void} if no such value exists. * @return An appropriate exit handler. */ protected static Resolved.ForMethodExit of(MethodDescription.InDefinedShape adviceMethod, Map<String, TypeDefinition> namedTypes, List<? extends OffsetMapping.Factory<?>> userFactories, ClassReader classReader, TypeDefinition enterType) { TypeDescription throwable = adviceMethod.getDeclaredAnnotations() .ofType(OnMethodExit.class) .getValue(ON_THROWABLE).resolve(TypeDescription.class); return throwable.represents(NoExceptionHandler.class) ? new WithoutExceptionHandler(adviceMethod, namedTypes, userFactories, classReader, enterType) : new WithExceptionHandler(adviceMethod, namedTypes, userFactories, classReader, enterType, throwable); }
/** * {@inheritDoc} */ public MethodDelegationBinder.ParameterBinding<?> bind(AnnotationDescription.Loadable<Default> annotation, MethodDescription source, ParameterDescription target, Implementation.Target implementationTarget, Assigner assigner, Assigner.Typing typing) { TypeDescription proxyType = TypeLocator.ForType.of(annotation.getValue(PROXY_TYPE).resolve(TypeDescription.class)).resolve(target.getType()); if (!proxyType.isInterface()) { throw new IllegalStateException(target + " uses the @Default annotation on an invalid type"); } if (source.isStatic() || !implementationTarget.getInstrumentedType().getInterfaces().asErasures().contains(proxyType)) { return MethodDelegationBinder.ParameterBinding.Illegal.INSTANCE; } else { return new MethodDelegationBinder.ParameterBinding.Anonymous(new TypeProxy.ForDefaultMethod(proxyType, implementationTarget, annotation.getValue(SERIALIZABLE_PROXY).resolve(Boolean.class))); } }
/** * Resolves exit advice that handles exceptions depending on the specification of the exit advice. * * @param adviceMethod The advice method. * @param namedTypes A mapping of all available local variables by their name to their type. * @param userFactories A list of user-defined factories for offset mappings. * @param enterType The type of the value supplied by the enter advice method or {@code void} if no such value exists. * @return An appropriate exit handler. */ protected static Resolved.ForMethodExit of(MethodDescription.InDefinedShape adviceMethod, Map<String, TypeDefinition> namedTypes, List<? extends OffsetMapping.Factory<?>> userFactories, TypeDefinition enterType) { TypeDescription throwable = adviceMethod.getDeclaredAnnotations() .ofType(OnMethodExit.class) .getValue(ON_THROWABLE) .resolve(TypeDescription.class); return throwable.represents(NoExceptionHandler.class) ? new WithoutExceptionHandler(adviceMethod, namedTypes, userFactories, enterType) : new WithExceptionHandler(adviceMethod, namedTypes, userFactories, enterType, throwable); }
/** * {@inheritDoc} */ public OffsetMapping make(ParameterDescription.InDefinedShape target, AnnotationDescription.Loadable<T> annotation, AdviceType adviceType) { Object value = annotation.getValue(property).resolve(); OffsetMapping.Factory<T> factory; if (value instanceof TypeDescription) { factory = new Factory<T>(annotationType, (TypeDescription) value); } else if (value instanceof EnumerationDescription) { factory = new Factory<T>(annotationType, (EnumerationDescription) value); } else if (value instanceof AnnotationDescription) { throw new IllegalStateException("Cannot bind annotation as fixed value for " + property); } else { factory = Factory.of(annotationType, value); } return factory.make(target, annotation, adviceType); } }
/** * {@inheritDoc} */ public OffsetMapping make(ParameterDescription.InDefinedShape target, AnnotationDescription.Loadable<FieldValue> annotation, AdviceType adviceType) { if (adviceType.isDelegation() && !annotation.getValue(ForField.READ_ONLY).resolve(Boolean.class)) { throw new IllegalStateException("Cannot write to field for " + target + " in read-only context"); } else { TypeDescription declaringType = annotation.getValue(DECLARING_TYPE).resolve(TypeDescription.class); return declaringType.represents(void.class) ? new WithImplicitType(target.getType(), annotation) : new WithExplicitType(target.getType(), annotation, declaringType); } } }
/** * Creates an offset mapping for a field with an explicit declaring type. * * @param target The target type. * @param annotation The annotation to represent. * @param declaringType The field's declaring type. */ protected WithExplicitType(TypeDescription.Generic target, AnnotationDescription.Loadable<FieldValue> annotation, TypeDescription declaringType) { this(target, annotation.getValue(READ_ONLY).resolve(Boolean.class), annotation.getValue(TYPING).loadSilent(Assigner.Typing.class.getClassLoader()).resolve(Assigner.Typing.class), annotation.getValue(VALUE).resolve(String.class), declaringType); }
@Override protected MethodDelegationBinder.ParameterBinding<?> bind(FieldDescription fieldDescription, AnnotationDescription.Loadable<FieldProxy> annotation, MethodDescription source, ParameterDescription target, Implementation.Target implementationTarget, Assigner assigner) { FieldResolver fieldResolver = fieldResolverFactory.resolve(target.getType().asErasure(), fieldDescription); if (fieldResolver.isResolved()) { return new MethodDelegationBinder.ParameterBinding.Anonymous(new AccessorProxy(fieldDescription, implementationTarget.getInstrumentedType(), fieldResolver, assigner, annotation.getValue(SERIALIZABLE_PROXY).resolve(Boolean.class))); } else { return MethodDelegationBinder.ParameterBinding.Illegal.INSTANCE; } }
/** * Resolves an appropriate offset mapping factory for the {@link Thrown} parameter annotation. * * @param adviceMethod The exit advice method, annotated with {@link OnMethodExit}. * @return An appropriate offset mapping factory. */ @SuppressWarnings("unchecked") // In absence of @SafeVarargs protected static OffsetMapping.Factory<?> of(MethodDescription.InDefinedShape adviceMethod) { return adviceMethod.getDeclaredAnnotations() .ofType(OnMethodExit.class) .getValue(ON_THROWABLE) .resolve(TypeDescription.class) .represents(NoExceptionHandler.class) ? new OffsetMapping.Factory.Illegal<Thrown>(Thrown.class) : Factory.INSTANCE; }
@Override protected TypeDescription declaringType(AnnotationDescription.Loadable<FieldValue> annotation) { return annotation.getValue(DECLARING_TYPE).resolve(TypeDescription.class); }
@Override protected TypeDescription declaringType(AnnotationDescription.Loadable<FieldProxy> annotation) { return annotation.getValue(DECLARING_TYPE).resolve(TypeDescription.class); }
@Override protected String fieldName(AnnotationDescription.Loadable<FieldProxy> annotation) { return annotation.getValue(FIELD_NAME).resolve(String.class); }
@Override protected StackManipulation proxyFor(TypeDescription parameterType, Implementation.Target implementationTarget, AnnotationDescription.Loadable<Super> annotation) { return new TypeProxy.ForSuperMethodByReflectionFactory(parameterType, implementationTarget, annotation.getValue(IGNORE_FINALIZER).resolve(Boolean.class), annotation.getValue(SERIALIZABLE_PROXY).resolve(Boolean.class)); } };
@Override protected String fieldName(AnnotationDescription.Loadable<FieldValue> annotation) { return annotation.getValue(FIELD_NAME).resolve(String.class); }