Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/javax/management/MBeanInfo/NotificationInfoTest.java
41149 views
1
/*
2
* Copyright (c) 2004, 2015, 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.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
/*
25
* @test
26
* @bug 5012634
27
* @summary Test that JMX classes use fully-qualified class names
28
* in MBeanNotificationInfo
29
* @author Eamonn McManus
30
* @modules java.management.rmi
31
* @run clean NotificationInfoTest
32
* @run build NotificationInfoTest
33
* @run main NotificationInfoTest
34
*/
35
36
import java.io.*;
37
import java.lang.management.*;
38
import java.lang.reflect.*;
39
import java.net.*;
40
import java.nio.file.FileSystem;
41
import java.nio.file.FileSystems;
42
import java.nio.file.Files;
43
import java.nio.file.Path;
44
import java.nio.file.Paths;
45
import java.util.*;
46
import java.util.stream.Collectors;
47
import javax.management.*;
48
import javax.management.relation.*;
49
import javax.management.remote.*;
50
import javax.management.remote.rmi.*;
51
52
/*
53
* This test finds all classes in the same code-base as the JMX
54
* classes that look like Standard MBeans, and checks that if they are
55
* NotificationBroadcasters they declare existent notification types.
56
* A class looks like a Standard MBean if both Thing and ThingMBean
57
* classes exist. So for example javax.management.timer.Timer looks
58
* like a Standard MBean because javax.management.timer.TimerMBean
59
* exists. Timer is instanceof NotificationBroadcaster, so we expect
60
* that ((NotificationBroadcaster) timer).getNotificationInfo() will
61
* return an array of MBeanNotificationInfo where each entry has a
62
* getName() that names an existent Java class that is a Notification.
63
*
64
* An MBean is "suspicious" if it is a NotificationBroadcaster but its
65
* MBeanNotificationInfo[] is empty. This is legal, but surprising.
66
*
67
* In order to call getNotificationInfo(), we need an instance of the
68
* class. We attempt to make one by calling a public no-arg
69
* constructor. But the "construct" method below can be extended to
70
* construct specific MBean classes for which the no-arg constructor
71
* doesn't exist.
72
*
73
* The test is obviously not exhaustive, but does catch the cases that
74
* failed in 5012634.
75
*/
76
public class NotificationInfoTest {
77
// class or object names where the test failed
78
private static final Set<String> failed = new TreeSet<String>();
79
80
// class or object names where there were no MBeanNotificationInfo entries
81
private static final Set<String> suspicious = new TreeSet<String>();
82
83
public static void main(String[] args) throws Exception {
84
System.out.println("Checking that all known MBeans that are " +
85
"NotificationBroadcasters have sane " +
86
"MBeanInfo.getNotifications()");
87
88
System.out.println("Checking platform MBeans...");
89
checkPlatformMBeans();
90
91
URL codeBase;
92
String home = System.getProperty("java.home");
93
Path classFile = Paths.get(home, "modules", "java.management");
94
if (Files.isDirectory(classFile)) {
95
codeBase = classFile.toUri().toURL();
96
} else {
97
codeBase = URI.create("jrt:/java.management").toURL();
98
}
99
100
System.out.println();
101
System.out.println("Looking for standard MBeans...");
102
String[] classes = findStandardMBeans(codeBase);
103
104
System.out.println("Testing standard MBeans...");
105
for (int i = 0; i < classes.length; i++) {
106
String name = classes[i];
107
Class<?> c;
108
try {
109
c = Class.forName(name);
110
} catch (Throwable e) {
111
System.out.println(name + ": cannot load (not public?): " + e);
112
continue;
113
}
114
if (!NotificationBroadcaster.class.isAssignableFrom(c)) {
115
System.out.println(name + ": not a NotificationBroadcaster");
116
continue;
117
}
118
if (Modifier.isAbstract(c.getModifiers())) {
119
System.out.println(name + ": abstract class");
120
continue;
121
}
122
123
NotificationBroadcaster mbean;
124
Constructor<?> constr;
125
try {
126
constr = c.getConstructor();
127
} catch (Exception e) {
128
System.out.println(name + ": no public no-arg constructor: "
129
+ e);
130
continue;
131
}
132
try {
133
mbean = (NotificationBroadcaster) constr.newInstance();
134
} catch (Exception e) {
135
System.out.println(name + ": no-arg constructor failed: " + e);
136
continue;
137
}
138
139
check(mbean);
140
}
141
142
System.out.println();
143
System.out.println("Testing some explicit cases...");
144
145
check(new RelationService(false));
146
/*
147
We can't do this:
148
check(new RequiredModelMBean());
149
because the Model MBean spec more or less forces us to use the
150
names GENERIC and ATTRIBUTE_CHANGE for its standard notifs.
151
*/
152
checkRMIConnectorServer();
153
154
System.out.println();
155
if (!suspicious.isEmpty())
156
System.out.println("SUSPICIOUS CLASSES: " + suspicious);
157
158
if (failed.isEmpty())
159
System.out.println("TEST PASSED");
160
else {
161
System.out.println("TEST FAILED: " + failed);
162
System.exit(1);
163
}
164
}
165
166
private static void check(NotificationBroadcaster mbean)
167
throws Exception {
168
System.out.print(mbean.getClass().getName() + ": ");
169
170
check(mbean.getClass().getName(), mbean.getNotificationInfo());
171
}
172
173
private static void checkPlatformMBeans() throws Exception {
174
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
175
Set<ObjectName> mbeanNames = mbs.queryNames(null, null);
176
for (ObjectName name : mbeanNames) {
177
if (!mbs.isInstanceOf(name,
178
NotificationBroadcaster.class.getName())) {
179
System.out.println(name + ": not a NotificationBroadcaster");
180
} else {
181
MBeanInfo mbi = mbs.getMBeanInfo(name);
182
check(name.toString(), mbi.getNotifications());
183
}
184
}
185
}
186
187
private static void checkRMIConnectorServer() throws Exception {
188
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
189
RMIConnectorServer connector = new RMIConnectorServer(url, null);
190
check(connector);
191
}
192
193
private static void check(String what, MBeanNotificationInfo[] mbnis) {
194
System.out.print(what + ": checking notification info: ");
195
196
if (mbnis.length == 0) {
197
System.out.println("NONE (suspicious)");
198
suspicious.add(what);
199
return;
200
}
201
202
// Each MBeanNotificationInfo.getName() should be an existent
203
// Java class that is Notification or a subclass of it
204
for (int j = 0; j < mbnis.length; j++) {
205
String notifClassName = mbnis[j].getName();
206
Class notifClass;
207
try {
208
notifClass = Class.forName(notifClassName);
209
} catch (Exception e) {
210
System.out.print("FAILED(" + notifClassName + ": " + e +
211
") ");
212
failed.add(what);
213
continue;
214
}
215
if (!Notification.class.isAssignableFrom(notifClass)) {
216
System.out.print("FAILED(" + notifClassName +
217
": not a Notification) ");
218
failed.add(what);
219
continue;
220
}
221
System.out.print("OK(" + notifClassName + ") ");
222
}
223
System.out.println();
224
}
225
226
private static String[] findStandardMBeans(URL codeBase) throws Exception {
227
Set<String> names;
228
if (codeBase.getProtocol().equalsIgnoreCase("jrt")) {
229
names = findStandardMBeansFromRuntime();
230
} else {
231
names = findStandardMBeansFromDir(codeBase);
232
}
233
234
Set<String> standardMBeanNames = new TreeSet<String>();
235
for (String name : names) {
236
if (name.endsWith("MBean")) {
237
String prefix = name.substring(0, name.length() - 5);
238
if (names.contains(prefix))
239
standardMBeanNames.add(prefix);
240
}
241
}
242
return standardMBeanNames.toArray(new String[0]);
243
}
244
245
private static Set<String> findStandardMBeansFromRuntime() throws Exception {
246
FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
247
Path modules = fs.getPath("/modules");
248
return Files.walk(modules)
249
.filter(path -> path.toString().endsWith(".class"))
250
.map(path -> path.subpath(2, path.getNameCount()))
251
.map(Path::toString)
252
.map(s -> s.substring(0, s.length() - 6)) // drop .class
253
.filter(s -> !s.equals("module-info"))
254
.map(s -> s.replace('/', '.'))
255
.collect(Collectors.toSet());
256
}
257
258
private static Set<String> findStandardMBeansFromDir(URL codeBase)
259
throws Exception {
260
File dir = new File(new URI(codeBase.toString()));
261
Set<String> names = new TreeSet<String>();
262
scanDir(dir, "", names);
263
return names;
264
}
265
266
private static void scanDir(File dir, String prefix, Set<String> names)
267
throws Exception {
268
File[] files = dir.listFiles();
269
if (files == null)
270
return;
271
for (int i = 0; i < files.length; i++) {
272
File f = files[i];
273
String name = f.getName();
274
String p = (prefix.equals("")) ? name : prefix + "." + name;
275
if (f.isDirectory())
276
scanDir(f, p, names);
277
else if (name.endsWith(".class")) {
278
p = p.substring(0, p.length() - 6);
279
names.add(p);
280
}
281
}
282
}
283
}
284
285