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