Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/beans/Statement.java
38829 views
1
/*
2
* Copyright (c) 2000, 2012, 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 java.beans;
26
27
import java.lang.reflect.AccessibleObject;
28
import java.lang.reflect.Array;
29
import java.lang.reflect.Constructor;
30
import java.lang.reflect.InvocationTargetException;
31
import java.lang.reflect.Method;
32
import java.security.AccessControlContext;
33
import java.security.AccessController;
34
import java.security.PrivilegedActionException;
35
import java.security.PrivilegedExceptionAction;
36
37
import com.sun.beans.finder.ClassFinder;
38
import com.sun.beans.finder.ConstructorFinder;
39
import com.sun.beans.finder.MethodFinder;
40
import sun.reflect.misc.MethodUtil;
41
42
/**
43
* A <code>Statement</code> object represents a primitive statement
44
* in which a single method is applied to a target and
45
* a set of arguments - as in <code>"a.setFoo(b)"</code>.
46
* Note that where this example uses names
47
* to denote the target and its argument, a statement
48
* object does not require a name space and is constructed with
49
* the values themselves.
50
* The statement object associates the named method
51
* with its environment as a simple set of values:
52
* the target and an array of argument values.
53
*
54
* @since 1.4
55
*
56
* @author Philip Milne
57
*/
58
public class Statement {
59
60
private static Object[] emptyArray = new Object[]{};
61
62
static ExceptionListener defaultExceptionListener = new ExceptionListener() {
63
public void exceptionThrown(Exception e) {
64
System.err.println(e);
65
// e.printStackTrace();
66
System.err.println("Continuing ...");
67
}
68
};
69
70
private final AccessControlContext acc = AccessController.getContext();
71
private final Object target;
72
private final String methodName;
73
private final Object[] arguments;
74
ClassLoader loader;
75
76
/**
77
* Creates a new {@link Statement} object
78
* for the specified target object to invoke the method
79
* specified by the name and by the array of arguments.
80
* <p>
81
* The {@code target} and the {@code methodName} values should not be {@code null}.
82
* Otherwise an attempt to execute this {@code Expression}
83
* will result in a {@code NullPointerException}.
84
* If the {@code arguments} value is {@code null},
85
* an empty array is used as the value of the {@code arguments} property.
86
*
87
* @param target the target object of this statement
88
* @param methodName the name of the method to invoke on the specified target
89
* @param arguments the array of arguments to invoke the specified method
90
*/
91
@ConstructorProperties({"target", "methodName", "arguments"})
92
public Statement(Object target, String methodName, Object[] arguments) {
93
this.target = target;
94
this.methodName = methodName;
95
this.arguments = (arguments == null) ? emptyArray : arguments.clone();
96
}
97
98
/**
99
* Returns the target object of this statement.
100
* If this method returns {@code null},
101
* the {@link #execute} method
102
* throws a {@code NullPointerException}.
103
*
104
* @return the target object of this statement
105
*/
106
public Object getTarget() {
107
return target;
108
}
109
110
/**
111
* Returns the name of the method to invoke.
112
* If this method returns {@code null},
113
* the {@link #execute} method
114
* throws a {@code NullPointerException}.
115
*
116
* @return the name of the method
117
*/
118
public String getMethodName() {
119
return methodName;
120
}
121
122
/**
123
* Returns the arguments for the method to invoke.
124
* The number of arguments and their types
125
* must match the method being called.
126
* {@code null} can be used as a synonym of an empty array.
127
*
128
* @return the array of arguments
129
*/
130
public Object[] getArguments() {
131
return this.arguments.clone();
132
}
133
134
/**
135
* The {@code execute} method finds a method whose name is the same
136
* as the {@code methodName} property, and invokes the method on
137
* the target.
138
*
139
* When the target's class defines many methods with the given name
140
* the implementation should choose the most specific method using
141
* the algorithm specified in the Java Language Specification
142
* (15.11). The dynamic class of the target and arguments are used
143
* in place of the compile-time type information and, like the
144
* {@link java.lang.reflect.Method} class itself, conversion between
145
* primitive values and their associated wrapper classes is handled
146
* internally.
147
* <p>
148
* The following method types are handled as special cases:
149
* <ul>
150
* <li>
151
* Static methods may be called by using a class object as the target.
152
* <li>
153
* The reserved method name "new" may be used to call a class's constructor
154
* as if all classes defined static "new" methods. Constructor invocations
155
* are typically considered {@code Expression}s rather than {@code Statement}s
156
* as they return a value.
157
* <li>
158
* The method names "get" and "set" defined in the {@link java.util.List}
159
* interface may also be applied to array instances, mapping to
160
* the static methods of the same name in the {@code Array} class.
161
* </ul>
162
*
163
* @throws NullPointerException if the value of the {@code target} or
164
* {@code methodName} property is {@code null}
165
* @throws NoSuchMethodException if a matching method is not found
166
* @throws SecurityException if a security manager exists and
167
* it denies the method invocation
168
* @throws Exception that is thrown by the invoked method
169
*
170
* @see java.lang.reflect.Method
171
*/
172
public void execute() throws Exception {
173
invoke();
174
}
175
176
Object invoke() throws Exception {
177
AccessControlContext acc = this.acc;
178
if ((acc == null) && (System.getSecurityManager() != null)) {
179
throw new SecurityException("AccessControlContext is not set");
180
}
181
try {
182
return AccessController.doPrivileged(
183
new PrivilegedExceptionAction<Object>() {
184
public Object run() throws Exception {
185
return invokeInternal();
186
}
187
},
188
acc
189
);
190
}
191
catch (PrivilegedActionException exception) {
192
throw exception.getException();
193
}
194
}
195
196
private Object invokeInternal() throws Exception {
197
Object target = getTarget();
198
String methodName = getMethodName();
199
200
if (target == null || methodName == null) {
201
throw new NullPointerException((target == null ? "target" :
202
"methodName") + " should not be null");
203
}
204
205
Object[] arguments = getArguments();
206
if (arguments == null) {
207
arguments = emptyArray;
208
}
209
// Class.forName() won't load classes outside
210
// of core from a class inside core. Special
211
// case this method.
212
if (target == Class.class && methodName.equals("forName")) {
213
return ClassFinder.resolveClass((String)arguments[0], this.loader);
214
}
215
Class<?>[] argClasses = new Class<?>[arguments.length];
216
for(int i = 0; i < arguments.length; i++) {
217
argClasses[i] = (arguments[i] == null) ? null : arguments[i].getClass();
218
}
219
220
AccessibleObject m = null;
221
if (target instanceof Class) {
222
/*
223
For class methods, simluate the effect of a meta class
224
by taking the union of the static methods of the
225
actual class, with the instance methods of "Class.class"
226
and the overloaded "newInstance" methods defined by the
227
constructors.
228
This way "System.class", for example, will perform both
229
the static method getProperties() and the instance method
230
getSuperclass() defined in "Class.class".
231
*/
232
if (methodName.equals("new")) {
233
methodName = "newInstance";
234
}
235
// Provide a short form for array instantiation by faking an nary-constructor.
236
if (methodName.equals("newInstance") && ((Class)target).isArray()) {
237
Object result = Array.newInstance(((Class)target).getComponentType(), arguments.length);
238
for(int i = 0; i < arguments.length; i++) {
239
Array.set(result, i, arguments[i]);
240
}
241
return result;
242
}
243
if (methodName.equals("newInstance") && arguments.length != 0) {
244
// The Character class, as of 1.4, does not have a constructor
245
// which takes a String. All of the other "wrapper" classes
246
// for Java's primitive types have a String constructor so we
247
// fake such a constructor here so that this special case can be
248
// ignored elsewhere.
249
if (target == Character.class && arguments.length == 1 &&
250
argClasses[0] == String.class) {
251
return new Character(((String)arguments[0]).charAt(0));
252
}
253
try {
254
m = ConstructorFinder.findConstructor((Class)target, argClasses);
255
}
256
catch (NoSuchMethodException exception) {
257
m = null;
258
}
259
}
260
if (m == null && target != Class.class) {
261
m = getMethod((Class)target, methodName, argClasses);
262
}
263
if (m == null) {
264
m = getMethod(Class.class, methodName, argClasses);
265
}
266
}
267
else {
268
/*
269
This special casing of arrays is not necessary, but makes files
270
involving arrays much shorter and simplifies the archiving infrastrcure.
271
The Array.set() method introduces an unusual idea - that of a static method
272
changing the state of an instance. Normally statements with side
273
effects on objects are instance methods of the objects themselves
274
and we reinstate this rule (perhaps temporarily) by special-casing arrays.
275
*/
276
if (target.getClass().isArray() &&
277
(methodName.equals("set") || methodName.equals("get"))) {
278
int index = ((Integer)arguments[0]).intValue();
279
if (methodName.equals("get")) {
280
return Array.get(target, index);
281
}
282
else {
283
Array.set(target, index, arguments[1]);
284
return null;
285
}
286
}
287
m = getMethod(target.getClass(), methodName, argClasses);
288
}
289
if (m != null) {
290
try {
291
if (m instanceof Method) {
292
return MethodUtil.invoke((Method)m, target, arguments);
293
}
294
else {
295
return ((Constructor)m).newInstance(arguments);
296
}
297
}
298
catch (IllegalAccessException iae) {
299
throw new Exception("Statement cannot invoke: " +
300
methodName + " on " + target.getClass(),
301
iae);
302
}
303
catch (InvocationTargetException ite) {
304
Throwable te = ite.getTargetException();
305
if (te instanceof Exception) {
306
throw (Exception)te;
307
}
308
else {
309
throw ite;
310
}
311
}
312
}
313
throw new NoSuchMethodException(toString());
314
}
315
316
String instanceName(Object instance) {
317
if (instance == null) {
318
return "null";
319
} else if (instance.getClass() == String.class) {
320
return "\""+(String)instance + "\"";
321
} else {
322
// Note: there is a minor problem with using the non-caching
323
// NameGenerator method. The return value will not have
324
// specific information about the inner class name. For example,
325
// In 1.4.2 an inner class would be represented as JList$1 now
326
// would be named Class.
327
328
return NameGenerator.unqualifiedClassName(instance.getClass());
329
}
330
}
331
332
/**
333
* Prints the value of this statement using a Java-style syntax.
334
*/
335
public String toString() {
336
// Respect a subclass's implementation here.
337
Object target = getTarget();
338
String methodName = getMethodName();
339
Object[] arguments = getArguments();
340
if (arguments == null) {
341
arguments = emptyArray;
342
}
343
StringBuffer result = new StringBuffer(instanceName(target) + "." + methodName + "(");
344
int n = arguments.length;
345
for(int i = 0; i < n; i++) {
346
result.append(instanceName(arguments[i]));
347
if (i != n -1) {
348
result.append(", ");
349
}
350
}
351
result.append(");");
352
return result.toString();
353
}
354
355
static Method getMethod(Class<?> type, String name, Class<?>... args) {
356
try {
357
return MethodFinder.findMethod(type, name, args);
358
}
359
catch (NoSuchMethodException exception) {
360
return null;
361
}
362
}
363
}
364
365