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/finder/AbstractFinder.java
41161 views
1
/*
2
* Copyright (c) 2008, 2013, 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
package com.sun.beans.finder;
26
27
import java.lang.reflect.Executable;
28
import java.lang.reflect.Modifier;
29
30
import java.util.HashMap;
31
import java.util.Map;
32
33
/**
34
* This abstract class provides functionality
35
* to find a public method or constructor
36
* with specified parameter types.
37
* It supports a variable number of parameters.
38
*
39
* @since 1.7
40
*
41
* @author Sergey A. Malenkov
42
*/
43
abstract class AbstractFinder<T extends Executable> {
44
private final Class<?>[] args;
45
46
/**
47
* Creates finder for array of classes of arguments.
48
* If a particular element of array equals {@code null},
49
* than the appropriate pair of classes
50
* does not take into consideration.
51
*
52
* @param args array of classes of arguments
53
*/
54
protected AbstractFinder(Class<?>[] args) {
55
this.args = args;
56
}
57
58
/**
59
* Checks validness of the method.
60
* At least the valid method should be public.
61
*
62
* @param method the object that represents method
63
* @return {@code true} if the method is valid,
64
* {@code false} otherwise
65
*/
66
protected boolean isValid(T method) {
67
return Modifier.isPublic(method.getModifiers());
68
}
69
70
/**
71
* Performs a search in the {@code methods} array.
72
* The one method is selected from the array of the valid methods.
73
* The list of parameters of the selected method shows
74
* the best correlation with the list of arguments
75
* specified at class initialization.
76
* If more than one method is both accessible and applicable
77
* to a method invocation, it is necessary to choose one
78
* to provide the descriptor for the run-time method dispatch.
79
* The most specific method should be chosen.
80
*
81
* @param methods the array of methods to search within
82
* @return the object that represents found method
83
* @throws NoSuchMethodException if no method was found or several
84
* methods meet the search criteria
85
* @see #isAssignable
86
*/
87
final T find(T[] methods) throws NoSuchMethodException {
88
Map<T, Class<?>[]> map = new HashMap<T, Class<?>[]>();
89
90
T oldMethod = null;
91
Class<?>[] oldParams = null;
92
boolean ambiguous = false;
93
94
for (T newMethod : methods) {
95
if (isValid(newMethod)) {
96
Class<?>[] newParams = newMethod.getParameterTypes();
97
if (newParams.length == this.args.length) {
98
PrimitiveWrapperMap.replacePrimitivesWithWrappers(newParams);
99
if (isAssignable(newParams, this.args)) {
100
if (oldMethod == null) {
101
oldMethod = newMethod;
102
oldParams = newParams;
103
} else {
104
boolean useNew = isAssignable(oldParams, newParams);
105
boolean useOld = isAssignable(newParams, oldParams);
106
107
if (useOld && useNew) {
108
// only if parameters are equal
109
useNew = !newMethod.isSynthetic();
110
useOld = !oldMethod.isSynthetic();
111
}
112
if (useOld == useNew) {
113
ambiguous = true;
114
} else if (useNew) {
115
oldMethod = newMethod;
116
oldParams = newParams;
117
ambiguous = false;
118
}
119
}
120
}
121
}
122
if (newMethod.isVarArgs()) {
123
int length = newParams.length - 1;
124
if (length <= this.args.length) {
125
Class<?>[] array = new Class<?>[this.args.length];
126
System.arraycopy(newParams, 0, array, 0, length);
127
if (length < this.args.length) {
128
Class<?> type = newParams[length].getComponentType();
129
if (type.isPrimitive()) {
130
type = PrimitiveWrapperMap.getType(type.getName());
131
}
132
for (int i = length; i < this.args.length; i++) {
133
array[i] = type;
134
}
135
}
136
map.put(newMethod, array);
137
}
138
}
139
}
140
}
141
for (T newMethod : methods) {
142
Class<?>[] newParams = map.get(newMethod);
143
if (newParams != null) {
144
if (isAssignable(newParams, this.args)) {
145
if (oldMethod == null) {
146
oldMethod = newMethod;
147
oldParams = newParams;
148
} else {
149
boolean useNew = isAssignable(oldParams, newParams);
150
boolean useOld = isAssignable(newParams, oldParams);
151
152
if (useOld && useNew) {
153
// only if parameters are equal
154
useNew = !newMethod.isSynthetic();
155
useOld = !oldMethod.isSynthetic();
156
}
157
if (useOld == useNew) {
158
if (oldParams == map.get(oldMethod)) {
159
ambiguous = true;
160
}
161
} else if (useNew) {
162
oldMethod = newMethod;
163
oldParams = newParams;
164
ambiguous = false;
165
}
166
}
167
}
168
}
169
}
170
171
if (ambiguous) {
172
throw new NoSuchMethodException("Ambiguous methods are found");
173
}
174
if (oldMethod == null) {
175
throw new NoSuchMethodException("Method is not found");
176
}
177
return oldMethod;
178
}
179
180
/**
181
* Determines if every class in {@code min} array is either the same as,
182
* or is a superclass of, the corresponding class in {@code max} array.
183
* The length of every array must equal the number of arguments.
184
* This comparison is performed in the {@link #find} method
185
* before the first call of the isAssignable method.
186
* If an argument equals {@code null}
187
* the appropriate pair of classes does not take into consideration.
188
*
189
* @param min the array of classes to be checked
190
* @param max the array of classes that is used to check
191
* @return {@code true} if all classes in {@code min} array
192
* are assignable from corresponding classes in {@code max} array,
193
* {@code false} otherwise
194
*
195
* @see Class#isAssignableFrom
196
*/
197
private boolean isAssignable(Class<?>[] min, Class<?>[] max) {
198
for (int i = 0; i < this.args.length; i++) {
199
if (null != this.args[i]) {
200
if (!min[i].isAssignableFrom(max[i])) {
201
return false;
202
}
203
}
204
}
205
return true;
206
}
207
}
208
209