Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AccessibleMembersLookup.java
41161 views
1
/*
2
* Copyright (c) 2010, 2016, 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
/*
27
* This file is available under and governed by the GNU General Public
28
* License version 2 only, as published by the Free Software Foundation.
29
* However, the following notice accompanied the original version of this
30
* file, and Oracle licenses the original version of this file under the BSD
31
* license:
32
*/
33
/*
34
Copyright 2009-2013 Attila Szegedi
35
36
Redistribution and use in source and binary forms, with or without
37
modification, are permitted provided that the following conditions are
38
met:
39
* Redistributions of source code must retain the above copyright
40
notice, this list of conditions and the following disclaimer.
41
* Redistributions in binary form must reproduce the above copyright
42
notice, this list of conditions and the following disclaimer in the
43
documentation and/or other materials provided with the distribution.
44
* Neither the name of the copyright holder nor the names of
45
contributors may be used to endorse or promote products derived from
46
this software without specific prior written permission.
47
48
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
49
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
50
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
51
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
52
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
53
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
54
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
55
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
56
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
57
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
58
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59
*/
60
61
package jdk.dynalink.beans;
62
63
import java.lang.reflect.Method;
64
import java.lang.reflect.Modifier;
65
import java.util.Arrays;
66
import java.util.Collection;
67
import java.util.HashMap;
68
import java.util.LinkedHashMap;
69
import java.util.Map;
70
71
/**
72
* Utility class for discovering accessible methods and inner classes. Normally, a public member declared on a class is
73
* accessible (that is, it can be invoked from anywhere). However, this is not the case if the class itself is not
74
* public, or belongs to a restricted-access package. In that case, it is required to lookup a member in a publicly
75
* accessible superclass or implemented interface of the class, and use it instead of the member discovered on the
76
* class.
77
*/
78
class AccessibleMembersLookup {
79
private final Map<MethodSignature, Method> methods;
80
private final Map<String, Class<?>> innerClasses;
81
private final boolean instance;
82
83
/**
84
* Creates a mapping for all accessible methods and inner classes on a class.
85
*
86
* @param clazz the inspected class
87
* @param instance true to inspect instance methods, false to inspect static methods.
88
*/
89
AccessibleMembersLookup(final Class<?> clazz, final boolean instance) {
90
this.methods = new HashMap<>();
91
this.innerClasses = new LinkedHashMap<>();
92
this.instance = instance;
93
lookupAccessibleMembers(clazz);
94
}
95
96
Collection<Method> getMethods() {
97
return methods.values();
98
}
99
100
Class<?>[] getInnerClasses() {
101
return innerClasses.values().toArray(new Class<?>[0]);
102
}
103
104
Method getAccessibleMethod(final Method m) {
105
return methods.get(new MethodSignature(m));
106
}
107
108
/**
109
* A helper class that represents a method signature - name and argument types.
110
*/
111
static final class MethodSignature {
112
private final String name;
113
private final Class<?>[] args;
114
115
/**
116
* Creates a new method signature from arbitrary data.
117
*
118
* @param name the name of the method this signature represents.
119
* @param args the argument types of the method.
120
*/
121
MethodSignature(final String name, final Class<?>[] args) {
122
this.name = name;
123
this.args = args;
124
}
125
126
/**
127
* Creates a signature for the given method.
128
*
129
* @param method the method for which a signature is created.
130
*/
131
MethodSignature(final Method method) {
132
this(method.getName(), method.getParameterTypes());
133
}
134
135
/**
136
* Compares this object to another object
137
*
138
* @param o the other object
139
* @return true if the other object is also a method signature with the same name, same number of arguments, and
140
* same types of arguments.
141
*/
142
@Override
143
public boolean equals(final Object o) {
144
if(o instanceof MethodSignature) {
145
final MethodSignature ms = (MethodSignature)o;
146
return ms.name.equals(name) && Arrays.equals(args, ms.args);
147
}
148
return false;
149
}
150
151
/**
152
* Returns a hash code, consistent with the overridden {@link #equals(Object)}.
153
*/
154
@Override
155
public int hashCode() {
156
return name.hashCode() ^ Arrays.hashCode(args);
157
}
158
159
@Override
160
public String toString() {
161
final StringBuilder b = new StringBuilder();
162
b.append("[MethodSignature ").append(name).append('(');
163
if(args.length > 0) {
164
b.append(args[0].getCanonicalName());
165
for(int i = 1; i < args.length; ++i) {
166
b.append(", ").append(args[i].getCanonicalName());
167
}
168
}
169
return b.append(")]").toString();
170
}
171
}
172
173
private void lookupAccessibleMembers(final Class<?> clazz) {
174
boolean searchSuperTypes;
175
176
if(!CheckRestrictedPackage.isRestrictedClass(clazz)) {
177
searchSuperTypes = false;
178
for(final Method method: clazz.getMethods()) {
179
final boolean isStatic = Modifier.isStatic(method.getModifiers());
180
if(instance != isStatic) {
181
final MethodSignature sig = new MethodSignature(method);
182
if(!methods.containsKey(sig)) {
183
final Class<?> declaringClass = method.getDeclaringClass();
184
if(declaringClass != clazz && CheckRestrictedPackage.isRestrictedClass(declaringClass)) {
185
//Sometimes, the declaring class of a method (Method.getDeclaringClass())
186
//retrieved through Class.getMethods() for a public class will be a
187
//non-public superclass. For such a method, we need to find a method with
188
//the same name and signature in a public superclass or implemented
189
//interface.
190
//This typically doesn't happen with classes emitted by a reasonably modern
191
//javac, as it'll create synthetic delegator methods in all public
192
//immediate subclasses of the non-public class. We have, however, observed
193
//this in the wild with class files compiled with older javac that doesn't
194
//generate the said synthetic delegators.
195
searchSuperTypes = true;
196
} else {
197
// don't allow inherited static
198
if (!isStatic || clazz == declaringClass) {
199
methods.put(sig, method);
200
}
201
}
202
}
203
}
204
}
205
for(final Class<?> innerClass: clazz.getClasses()) {
206
// Add both static and non-static classes, regardless of instance flag. StaticClassLinker will just
207
// expose non-static classes with explicit constructor outer class argument.
208
// NOTE: getting inner class objects through getClasses() does not resolve them, so if those classes
209
// were not yet loaded, they'll only get loaded in a non-resolved state; no static initializers for
210
// them will trigger just by doing this.
211
// Don't overwrite an inner class with an inherited inner class with the same name.
212
Class<?> previousClass = innerClasses.get(innerClass.getSimpleName());
213
if (previousClass == null || previousClass.getDeclaringClass().isAssignableFrom(innerClass.getDeclaringClass())) {
214
innerClasses.put(innerClass.getSimpleName(), innerClass);
215
}
216
}
217
} else {
218
searchSuperTypes = true;
219
}
220
221
// don't need to search super types for static methods
222
if(instance && searchSuperTypes) {
223
// If we reach here, the class is either not public, or it is in a restricted package. Alternatively, it is
224
// public, but some of its methods claim that their declaring class is non-public. We'll try superclasses
225
// and implemented interfaces then looking for public ones.
226
for (final Class<?> itf: clazz.getInterfaces()) {
227
lookupAccessibleMembers(itf);
228
}
229
final Class<?> superclass = clazz.getSuperclass();
230
if(superclass != null) {
231
lookupAccessibleMembers(superclass);
232
}
233
}
234
}
235
}
236
237