1 /*
2 * Copyright 2014 - 2020 Rafael Winterhalter
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package net.bytebuddy.implementation.bind.annotation;
17
18 import net.bytebuddy.description.annotation.AnnotationDescription;
19 import net.bytebuddy.description.method.MethodDescription;
20 import net.bytebuddy.description.method.ParameterDescription;
21 import net.bytebuddy.description.type.TypeDescription;
22 import net.bytebuddy.implementation.Implementation;
23 import net.bytebuddy.implementation.bind.MethodDelegationBinder;
24 import net.bytebuddy.implementation.bytecode.StackManipulation;
25 import net.bytebuddy.implementation.bytecode.assign.Assigner;
26 import net.bytebuddy.implementation.bytecode.constant.DefaultValue;
27 import net.bytebuddy.implementation.bytecode.constant.NullConstant;
28
29 import java.lang.annotation.*;
30
31 /**
32 * A stub value represents the (boxed) default value of the intercepted method's return type. This value can
33 * only be assigned to a {@link java.lang.Object} parameter. This annotation is useful to conditionally return a
34 * default value from a method when using an {@link java.lang.Object} return type in combination with the
35 * {@link net.bytebuddy.implementation.bind.annotation.RuntimeType} annotation. The value is either representing
36 * {@code null} if a method returns a reference type or {@code void} or a boxed primitive of the return type
37 * representing the numeric value {@code 0}.
38 *
39 * @see net.bytebuddy.implementation.MethodDelegation
40 * @see net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder
41 */
42 @Documented
43 @Retention(RetentionPolicy.RUNTIME)
44 @Target({ElementType.PARAMETER})
45 public @interface StubValue {
46
47 /**
48 * Binds the {@link net.bytebuddy.implementation.bind.annotation.StubValue} annotation.
49 */
50 enum Binder implements TargetMethodAnnotationDrivenBinder.ParameterBinder<StubValue> {
51
52 /**
53 * The singleton instance.
54 */
55 INSTANCE;
56
57 /**
58 * {@inheritDoc}
59 */
60 public Class<StubValue> getHandledType() {
61 return StubValue.class;
62 }
63
64 /**
65 * {@inheritDoc}
66 */
67 public MethodDelegationBinder.ParameterBinding<?> bind(AnnotationDescription.Loadable<StubValue> annotation,
68 MethodDescription source,
69 ParameterDescription target,
70 Implementation.Target implementationTarget,
71 Assigner assigner,
72 Assigner.Typing typing) {
73 if (!target.getType().represents(Object.class)) {
74 throw new IllegalStateException(target + " uses StubValue annotation on non-Object type");
75 }
76 return new MethodDelegationBinder.ParameterBinding.Anonymous(source.getReturnType().represents(void.class)
77 ? NullConstant.INSTANCE
78 : new StackManipulation.Compound(DefaultValue.of(source.getReturnType().asErasure()),
79 assigner.assign(source.getReturnType(), TypeDescription.Generic.OBJECT, typing)));
80 }
81 }
82 }
83