Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/classes/com/sun/beans/introspect/PropertyInfo.java
41171 views
1
/*
2
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package com.sun.beans.introspect;
27
28
import java.beans.BeanProperty;
29
import java.lang.reflect.Field;
30
import java.lang.reflect.Method;
31
import java.lang.reflect.Modifier;
32
import java.lang.reflect.Type;
33
import java.util.ArrayList;
34
import java.util.Collections;
35
import java.util.EnumMap;
36
import java.util.Iterator;
37
import java.util.List;
38
import java.util.Map;
39
import java.util.TreeMap;
40
41
import static com.sun.beans.finder.ClassFinder.findClass;
42
43
public final class PropertyInfo {
44
45
public enum Name {
46
bound, expert, hidden, preferred, required, visualUpdate, description,
47
enumerationValues
48
}
49
50
private static final String VETO_EXCEPTION_NAME = "java.beans.PropertyVetoException";
51
private static final Class<?> VETO_EXCEPTION;
52
53
static {
54
Class<?> type;
55
try {
56
type = Class.forName(VETO_EXCEPTION_NAME);
57
} catch (Exception exception) {
58
type = null;
59
}
60
VETO_EXCEPTION = type;
61
}
62
63
private Class<?> type;
64
private MethodInfo read;
65
private MethodInfo write;
66
private PropertyInfo indexed;
67
private List<MethodInfo> readList;
68
private List<MethodInfo> writeList;
69
private Map<Name,Object> map;
70
71
private PropertyInfo() {
72
}
73
74
private boolean initialize() {
75
boolean isInitedToIsGetter = false;
76
if (this.read != null) {
77
this.type = this.read.type;
78
isInitedToIsGetter = isPrefix(this.read.method.getName(), "is");
79
}
80
if (!isInitedToIsGetter && this.readList != null) {
81
for (MethodInfo info : this.readList) {
82
if ((this.read == null) || this.read.type.isAssignableFrom(info.type)) {
83
this.read = info;
84
this.type = info.type;
85
}
86
}
87
this.readList = null;
88
}
89
Class<?> writeType = this.type;
90
if (this.writeList != null) {
91
for (MethodInfo info : this.writeList) {
92
if (writeType == null) {
93
this.write = info;
94
writeType = info.type;
95
} else if (writeType.isAssignableFrom(info.type)) {
96
if ((this.write == null) || this.write.type.isAssignableFrom(info.type)) {
97
this.write = info;
98
writeType = info.type;
99
}
100
}
101
}
102
this.writeList = null;
103
}
104
if (this.type == null) {
105
this.type = writeType;
106
}
107
if (this.indexed != null) {
108
if ((this.type != null) && !this.type.isArray()) {
109
this.indexed = null; // property type is not an array
110
} else if (!this.indexed.initialize()) {
111
this.indexed = null; // cannot initialize indexed methods
112
} else if ((this.type != null) && (this.indexed.type != this.type.getComponentType())) {
113
this.indexed = null; // different property types
114
} else {
115
this.map = this.indexed.map;
116
this.indexed.map = null;
117
}
118
}
119
if ((this.type == null) && (this.indexed == null)) {
120
return false;
121
}
122
boolean done = initialize(this.read);
123
if (!done) {
124
initialize(this.write);
125
}
126
return true;
127
}
128
129
private boolean initialize(MethodInfo info) {
130
if (info != null) {
131
BeanProperty annotation = info.method.getAnnotation(BeanProperty.class);
132
if (annotation != null) {
133
if (!annotation.bound()) {
134
put(Name.bound, Boolean.FALSE);
135
}
136
put(Name.expert, annotation.expert());
137
put(Name.required, annotation.required());
138
put(Name.hidden, annotation.hidden());
139
put(Name.preferred, annotation.preferred());
140
put(Name.visualUpdate, annotation.visualUpdate());
141
put(Name.description, annotation.description());
142
String[] values = annotation.enumerationValues();
143
try {
144
Object[] array = new Object[3 * values.length];
145
int index = 0;
146
for (String value : values) {
147
Class<?> type = info.method.getDeclaringClass();
148
String name = value;
149
int pos = value.lastIndexOf('.');
150
if (pos > 0) {
151
name = value.substring(0, pos);
152
if (name.indexOf('.') < 0) {
153
String pkg = type.getName();
154
name = pkg.substring(0, 1 + Math.max(
155
pkg.lastIndexOf('.'),
156
pkg.lastIndexOf('$'))) + name;
157
}
158
type = findClass(name);
159
name = value.substring(pos + 1);
160
}
161
Field field = type.getField(name);
162
if (Modifier.isStatic(field.getModifiers()) && info.type.isAssignableFrom(field.getType())) {
163
array[index++] = name;
164
array[index++] = field.get(null);
165
array[index++] = value;
166
}
167
}
168
if (index == array.length) {
169
put(Name.enumerationValues, array);
170
}
171
} catch (Exception ignored) {
172
ignored.printStackTrace();
173
}
174
return true;
175
}
176
}
177
return false;
178
}
179
180
public Class<?> getPropertyType() {
181
return this.type;
182
}
183
184
public Method getReadMethod() {
185
return (this.read == null) ? null : this.read.method;
186
}
187
188
public Method getWriteMethod() {
189
return (this.write == null) ? null : this.write.method;
190
}
191
192
public PropertyInfo getIndexed() {
193
return this.indexed;
194
}
195
196
public boolean isConstrained() {
197
if (this.write != null) {
198
if (VETO_EXCEPTION == null) {
199
for (Class<?> type : this.write.method.getExceptionTypes()) {
200
if (type.getName().equals(VETO_EXCEPTION_NAME)) {
201
return true;
202
}
203
}
204
} else if (this.write.isThrow(VETO_EXCEPTION)) {
205
return true;
206
}
207
}
208
return (this.indexed != null) && this.indexed.isConstrained();
209
}
210
211
public boolean is(Name name) {
212
Object value = get(name);
213
return (value instanceof Boolean)
214
? (Boolean) value
215
: Name.bound.equals(name);
216
}
217
218
public Object get(Name name) {
219
return this.map == null ? null : this.map.get(name);
220
}
221
222
private void put(Name name, boolean value) {
223
if (value) {
224
put(name, Boolean.TRUE);
225
}
226
}
227
228
private void put(Name name, String value) {
229
if (0 < value.length()) {
230
put(name, (Object) value);
231
}
232
}
233
234
private void put(Name name, Object value) {
235
if (this.map == null) {
236
this.map = new EnumMap<>(Name.class);
237
}
238
this.map.put(name, value);
239
}
240
241
private static List<MethodInfo> add(List<MethodInfo> list, Method method, Type type) {
242
if (list == null) {
243
list = new ArrayList<>();
244
}
245
list.add(new MethodInfo(method, type));
246
return list;
247
}
248
249
private static boolean isPrefix(String name, String prefix) {
250
return name.length() > prefix.length() && name.startsWith(prefix);
251
}
252
253
private static PropertyInfo getInfo(Map<String,PropertyInfo> map, String key, boolean indexed) {
254
PropertyInfo info = map.get(key);
255
if (info == null) {
256
info = new PropertyInfo();
257
map.put(key, info);
258
}
259
if (!indexed) {
260
return info;
261
}
262
if (info.indexed == null) {
263
info.indexed = new PropertyInfo();
264
}
265
return info.indexed;
266
}
267
268
public static Map<String,PropertyInfo> get(Class<?> type) {
269
List<Method> methods = ClassInfo.get(type).getMethods();
270
if (methods.isEmpty()) {
271
return Collections.emptyMap();
272
}
273
Map<String,PropertyInfo> map = new TreeMap<>();
274
for (Method method : methods) {
275
if (!Modifier.isStatic(method.getModifiers())) {
276
Class<?> returnType = method.getReturnType();
277
String name = method.getName();
278
switch (method.getParameterCount()) {
279
case 0:
280
if (returnType.equals(boolean.class) && isPrefix(name, "is")) {
281
PropertyInfo info = getInfo(map, name.substring(2), false);
282
info.read = new MethodInfo(method, boolean.class);
283
} else if (!returnType.equals(void.class) && isPrefix(name, "get")) {
284
PropertyInfo info = getInfo(map, name.substring(3), false);
285
info.readList = add(info.readList, method, method.getGenericReturnType());
286
}
287
break;
288
case 1:
289
if (returnType.equals(void.class) && isPrefix(name, "set")) {
290
PropertyInfo info = getInfo(map, name.substring(3), false);
291
info.writeList = add(info.writeList, method, method.getGenericParameterTypes()[0]);
292
} else if (!returnType.equals(void.class) && method.getParameterTypes()[0].equals(int.class) && isPrefix(name, "get")) {
293
PropertyInfo info = getInfo(map, name.substring(3), true);
294
info.readList = add(info.readList, method, method.getGenericReturnType());
295
}
296
break;
297
case 2:
298
if (returnType.equals(void.class) && method.getParameterTypes()[0].equals(int.class) && isPrefix(name, "set")) {
299
PropertyInfo info = getInfo(map, name.substring(3), true);
300
info.writeList = add(info.writeList, method, method.getGenericParameterTypes()[1]);
301
}
302
break;
303
}
304
}
305
}
306
Iterator<PropertyInfo> iterator = map.values().iterator();
307
while (iterator.hasNext()) {
308
if (!iterator.next().initialize()) {
309
iterator.remove();
310
}
311
}
312
return !map.isEmpty()
313
? Collections.unmodifiableMap(map)
314
: Collections.emptyMap();
315
}
316
}
317
318