/
ModifierMirror.java
263 lines (240 loc) · 6.04 KB
/
ModifierMirror.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
package com.laytonsmith.PureUtilities.ClassLoading.ClassMirror;
import com.laytonsmith.PureUtilities.Common.StringUtils;
import java.io.Serializable;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import org.objectweb.asm.Opcodes;
/**
* This is a mirror for the {@link java.lang.reflect.Modifier} class. This provides is* methods for all the modifiers,
* instead of requiring bitwise logic to determine if various modifiers are present.
*/
public class ModifierMirror implements Serializable {
private static final long serialVersionUID = 1L;
private final int access;
private int modifiers = 0;
/**
* This is the canonical order of modifiers, used in the toString method.
*/
private static final transient Object[] order = new Object[]{
Modifier.PUBLIC, "public",
Modifier.PRIVATE, "private",
Modifier.PROTECTED, "protected",
Modifier.STATIC, "static",
Modifier.FINAL, "final",
Modifier.SYNCHRONIZED, "synchronized",
Modifier.VOLATILE, "volatile",
Modifier.TRANSIENT, "transient",
Modifier.NATIVE, "native",
Modifier.INTERFACE, "interface",
Modifier.ABSTRACT, "abstract",
Modifier.STRICT, "strictfp"};
/**
* This constructor is used when mirroring an already loaded class. The modifier is just the modifier returned by
* Class.
*
* @param modifier
*/
public ModifierMirror(int modifier) {
this.access = 0;
this.modifiers = modifier;
}
/**
* Creates a new ModifierMirror. Type is needed to determine which flags are applicable, and access is the access
* modifier stored with the class file.
*
* @param type Since asm encodes the parameters slightly differently for various types, the type must also be
* provided.
* @param access
*/
public ModifierMirror(Type type, int access) {
this.access = access;
//public, private, protected, final are all valid on all three types
if(type == Type.CLASS || type == Type.METHOD || type == Type.FIELD) {
if(hasFlag(Opcodes.ACC_PRIVATE)) {
modifiers |= Modifier.PRIVATE;
}
if(hasFlag(Opcodes.ACC_PROTECTED)) {
modifiers |= Modifier.PROTECTED;
}
if(hasFlag(Opcodes.ACC_PUBLIC)) {
modifiers |= Modifier.PUBLIC;
}
if(hasFlag(Opcodes.ACC_FINAL)) {
modifiers |= Modifier.FINAL;
}
}
//static is only valid on fields and methods
if(type == Type.FIELD || type == Type.METHOD) {
if(hasFlag(Opcodes.ACC_STATIC)) {
modifiers |= Modifier.STATIC;
}
}
//interface is only valid on a class
if(type == Type.CLASS) {
if(hasFlag(Opcodes.ACC_INTERFACE)) {
modifiers |= Modifier.INTERFACE;
}
}
//abstract is only valid on classes or methods
if(type == Type.CLASS || type == Type.METHOD) {
if(hasFlag(Opcodes.ACC_ABSTRACT)) {
modifiers |= Modifier.ABSTRACT;
}
}
//native, strict, and synchronized are only valid on methods
if(type == Type.METHOD) {
if(hasFlag(Opcodes.ACC_NATIVE)) {
modifiers |= Modifier.NATIVE;
}
if(hasFlag(Opcodes.ACC_STRICT)) {
modifiers |= Modifier.STRICT;
}
if(hasFlag(Opcodes.ACC_SYNCHRONIZED)) {
modifiers |= Modifier.SYNCHRONIZED;
}
}
//transient and volatile are only valid on fields
if(type == Type.FIELD) {
if(hasFlag(Opcodes.ACC_TRANSIENT)) {
modifiers |= Modifier.TRANSIENT;
}
if(hasFlag(Opcodes.ACC_VOLATILE)) {
modifiers |= Modifier.VOLATILE;
}
}
}
private boolean hasFlag(int flag) {
return (access & flag) > 0;
}
/**
* Returns true if the abstract modifier was present.
*
* @return
*/
public boolean isAbstract() {
return (modifiers & Modifier.ABSTRACT) > 0;
}
/**
* Returns true if the final modifier was present
*
* @return
*/
public boolean isFinal() {
return (modifiers & Modifier.FINAL) > 0;
}
/**
* Returns true if the class is an interface
*
* @return
*/
public boolean isInterface() {
return (modifiers & Modifier.ABSTRACT) > 0;
}
/**
* Returns true if the native modifier was present
*
* @return
*/
public boolean isNative() {
return (modifiers & Modifier.NATIVE) > 0;
}
/**
* Returns true if the private modifier was present
*
* @return
*/
public boolean isPrivate() {
return (modifiers & Modifier.PRIVATE) > 0;
}
/**
* Returns true if the protected modifier was present
*
* @return
*/
public boolean isProtected() {
return (modifiers & Modifier.PROTECTED) > 0;
}
/**
* Returns true if the public modifier was present
*
* @return
*/
public boolean isPublic() {
return (modifiers & Modifier.PUBLIC) > 0;
}
/**
* Returns true if this is package private, that is, it is not public, private, or protected. No access modifier is
* present, rather this is the lack of the other three modifiers.
*
* @return
*/
public boolean isPackagePrivate() {
return !(isPrivate()
|| isProtected()
|| isPublic());
}
/**
* Returns true if the static modifier was present
*
* @return
*/
public boolean isStatic() {
return (modifiers & Modifier.STATIC) > 0;
}
/**
* Returns true if the strictfp modifier was present
*
* @return
*/
public boolean isStrict() {
return (modifiers & Modifier.STRICT) > 0;
}
/**
* Returns true if the synchronized modifier was present
*
* @return
*/
public boolean isSynchronized() {
return (modifiers & Modifier.SYNCHRONIZED) > 0;
}
/**
* Returns true if the transient modifier was present
*
* @return
*/
public boolean isTransient() {
return (modifiers & Modifier.TRANSIENT) > 0;
}
/**
* Returns true if the volatile modifier was present
*
* @return
*/
public boolean isVolatile() {
return (modifiers & Modifier.VOLATILE) > 0;
}
/**
* Returns an int compatible with the {@link java.lang.reflect.Modifier} class.
*
* @return
*/
public int getModifiers() {
return modifiers;
}
@Override
public String toString() {
List<String> build = new ArrayList<String>();
for(int i = 0; i < order.length; i++) {
int type = (Integer) order[i];
String name = (String) order[++i];
if((modifiers & type) > 0) {
build.add(name);
}
}
return StringUtils.Join(build, " ");
}
public static enum Type {
CLASS, METHOD, FIELD;
}
}