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.description.modifier;
17
18 import net.bytebuddy.build.HashCodeAndEqualsPlugin;
19 import net.bytebuddy.jar.asm.Opcodes;
20
21 import java.util.Arrays;
22 import java.util.Collection;
23
24 /**
25 * An element that describes a type modifier as described in the
26 * <a href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html">JVMS</a>.
27 * <p> </p>
28 * This allows for a more expressive and type safe alternative of defining a type's or type member's modifiers.
29 * However, note that modifier's that apply competing modifiers (such as {@code private} and {@code protected}
30 * should not be combined and will result in invalid types. An exception is thrown when built-in modifiers that
31 * cannot be combined are used together.
32 */
33 public interface ModifierContributor {
34
35 /**
36 * The empty modifier.
37 */
38 int EMPTY_MASK = 0;
39
40 /**
41 * Returns the mask of this modifier.
42 *
43 * @return The modifier mask that is to be applied to the target type or type member.
44 */
45 int getMask();
46
47 /**
48 * Returns the entire range of modifiers that address this contributor's property.
49 *
50 * @return The range of this contributor's property.
51 */
52 int getRange();
53
54 /**
55 * Determines if this is the default modifier.
56 *
57 * @return {@code true} if this contributor represents the default modifier.
58 */
59 boolean isDefault();
60
61 /**
62 * A marker interface for modifiers that can be applied to types.
63 */
64 interface ForType extends ModifierContributor {
65
66 /**
67 * A mask for all legal modifiers of a Java type.
68 */
69 int MASK = Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC
70 | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE | Opcodes.ACC_ANNOTATION | Opcodes.ACC_DEPRECATED
71 | Opcodes.ACC_ENUM | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC;
72 }
73
74 /**
75 * A marker interface for modifiers that can be applied to fields.
76 */
77 interface ForField extends ModifierContributor {
78
79 /**
80 * A mask for all legal modifiers of a Java field.
81 */
82 int MASK = Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE
83 | Opcodes.ACC_DEPRECATED | Opcodes.ACC_ENUM | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC
84 | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_TRANSIENT | Opcodes.ACC_VOLATILE;
85 }
86
87 /**
88 * A marker interface for modifiers that can be applied to methods.
89 */
90 interface ForMethod extends ModifierContributor {
91
92 /**
93 * A mask for all legal modifiers of a Java method.
94 */
95 int MASK = Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC
96 | Opcodes.ACC_BRIDGE | Opcodes.ACC_FINAL | Opcodes.ACC_NATIVE | Opcodes.ACC_ABSTRACT
97 | Opcodes.ACC_STATIC | Opcodes.ACC_STRICT | Opcodes.ACC_SYNCHRONIZED
98 | Opcodes.ACC_VARARGS;
99 }
100
101 /**
102 * A marker interface for modifiers that can be applied to method parameters.
103 */
104 interface ForParameter extends ModifierContributor {
105
106 /**
107 * A mask for all legal modifiers of a Java parameter.
108 */
109 int MASK = Opcodes.ACC_MANDATED | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC;
110
111 }
112
113 /**
114 * A resolver for Java modifiers represented by {@link ModifierContributor}s.
115 *
116 * @param <T> The type of the {@link ModifierContributor}s being resolved.
117 */
118 @HashCodeAndEqualsPlugin.Enhance
119 class Resolver<T extends ModifierContributor> {
120
121 /**
122 * The modifier contributors to resolve.
123 */
124 private final Collection<? extends T> modifierContributors;
125
126 /**
127 * Creates a new resolver.
128 *
129 * @param modifierContributors The modifier contributors to resolve.
130 */
131 protected Resolver(Collection<? extends T> modifierContributors) {
132 this.modifierContributors = modifierContributors;
133 }
134
135 /**
136 * Creates a new resolver for modifier contributors to a type.
137 *
138 * @param modifierContributor The modifier contributors to resolve.
139 * @return A resolver for the provided modifier contributors.
140 */
141 public static Resolver<ForType> of(ForType... modifierContributor) {
142 return of(Arrays.asList(modifierContributor));
143 }
144
145 /**
146 * Creates a new resolver for modifier contributors to a field.
147 *
148 * @param modifierContributor The modifier contributors to resolve.
149 * @return A resolver for the provided modifier contributors.
150 */
151 public static Resolver<ForField> of(ForField... modifierContributor) {
152 return of(Arrays.asList(modifierContributor));
153 }
154
155 /**
156 * Creates a new resolver for modifier contributors to a method.
157 *
158 * @param modifierContributor The modifier contributors to resolve.
159 * @return A resolver for the provided modifier contributors.
160 */
161 public static Resolver<ForMethod> of(ForMethod... modifierContributor) {
162 return of(Arrays.asList(modifierContributor));
163 }
164
165 /**
166 * Creates a new resolver for modifier contributors to a parameter.
167 *
168 * @param modifierContributor The modifier contributors to resolve.
169 * @return A resolver for the provided modifier contributors.
170 */
171 public static Resolver<ForParameter> of(ForParameter... modifierContributor) {
172 return Resolver.of(Arrays.asList(modifierContributor));
173 }
174
175 /**
176 * Creates a new resolver for any modifier contributor of a given type.
177 *
178 * @param modifierContributors The modifier contributors to resolve.
179 * @param <S> The modifier contributors type.
180 * @return A resolver for the provided modifier contributors.
181 */
182 public static <S extends ModifierContributor> Resolver<S> of(Collection<? extends S> modifierContributors) {
183 return new Resolver<S>(modifierContributors);
184 }
185
186 /**
187 * Resolves the modifier contributors based on a zero modifier.
188 *
189 * @return The resolved modifiers.
190 */
191 public int resolve() {
192 return resolve(EMPTY_MASK);
193 }
194
195 /**
196 * Resolves the modifier contributors based on a given modifier.
197 *
198 * @param modifiers The base modifiers.
199 * @return The resolved modifiers.
200 */
201 public int resolve(int modifiers) {
202 for (T modifierContributor : modifierContributors) {
203 modifiers = (modifiers & ~modifierContributor.getRange()) | modifierContributor.getMask();
204 }
205 return modifiers;
206 }
207 }
208 }
209