Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/javax/management/MBeanInfo/NotificationInfoTest.java
38840 views
1
/*
2
* Copyright (c) 2004, 2008, 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
* @run clean NotificationInfoTest
31
* @run build NotificationInfoTest
32
* @run main NotificationInfoTest
33
*/
34
35
import java.io.*;
36
import java.lang.management.*;
37
import java.lang.reflect.*;
38
import java.net.*;
39
import java.security.CodeSource;
40
import java.util.*;
41
import java.util.jar.*;
42
import javax.management.*;
43
import javax.management.relation.*;
44
import javax.management.remote.*;
45
import javax.management.remote.rmi.*;
46
47
/*
48
* This test finds all classes in the same code-base as the JMX
49
* classes that look like Standard MBeans, and checks that if they are
50
* NotificationBroadcasters they declare existent notification types.
51
* A class looks like a Standard MBean if both Thing and ThingMBean
52
* classes exist. So for example javax.management.timer.Timer looks
53
* like a Standard MBean because javax.management.timer.TimerMBean
54
* exists. Timer is instanceof NotificationBroadcaster, so we expect
55
* that ((NotificationBroadcaster) timer).getNotificationInfo() will
56
* return an array of MBeanNotificationInfo where each entry has a
57
* getName() that names an existent Java class that is a Notification.
58
*
59
* An MBean is "suspicious" if it is a NotificationBroadcaster but its
60
* MBeanNotificationInfo[] is empty. This is legal, but surprising.
61
*
62
* In order to call getNotificationInfo(), we need an instance of the
63
* class. We attempt to make one by calling a public no-arg
64
* constructor. But the "construct" method below can be extended to
65
* construct specific MBean classes for which the no-arg constructor
66
* doesn't exist.
67
*
68
* The test is obviously not exhaustive, but does catch the cases that
69
* failed in 5012634.
70
*/
71
public class NotificationInfoTest {
72
// class or object names where the test failed
73
private static final Set<String> failed = new TreeSet<String>();
74
75
// class or object names where there were no MBeanNotificationInfo entries
76
private static final Set<String> suspicious = new TreeSet<String>();
77
78
public static void main(String[] args) throws Exception {
79
System.out.println("Checking that all known MBeans that are " +
80
"NotificationBroadcasters have sane " +
81
"MBeanInfo.getNotifications()");
82
83
System.out.println("Checking platform MBeans...");
84
checkPlatformMBeans();
85
86
CodeSource cs =
87
javax.management.MBeanServer.class.getProtectionDomain()
88
.getCodeSource();
89
URL codeBase;
90
if (cs == null) {
91
String javaHome = System.getProperty("java.home");
92
String[] candidates = {"/lib/rt.jar", "/classes/"};
93
codeBase = null;
94
for (String candidate : candidates) {
95
File file = new File(javaHome + candidate);
96
if (file.exists()) {
97
codeBase = file.toURI().toURL();
98
break;
99
}
100
}
101
if (codeBase == null) {
102
throw new Exception(
103
"Could not determine codeBase for java.home=" + javaHome);
104
}
105
} else
106
codeBase = cs.getLocation();
107
108
System.out.println();
109
System.out.println("Looking for standard MBeans...");
110
String[] classes = findStandardMBeans(codeBase);
111
112
System.out.println("Testing standard MBeans...");
113
for (int i = 0; i < classes.length; i++) {
114
String name = classes[i];
115
Class<?> c;
116
try {
117
c = Class.forName(name);
118
} catch (Throwable e) {
119
System.out.println(name + ": cannot load (not public?): " + e);
120
continue;
121
}
122
if (!NotificationBroadcaster.class.isAssignableFrom(c)) {
123
System.out.println(name + ": not a NotificationBroadcaster");
124
continue;
125
}
126
if (Modifier.isAbstract(c.getModifiers())) {
127
System.out.println(name + ": abstract class");
128
continue;
129
}
130
131
NotificationBroadcaster mbean;
132
Constructor<?> constr;
133
try {
134
constr = c.getConstructor();
135
} catch (Exception e) {
136
System.out.println(name + ": no public no-arg constructor: "
137
+ e);
138
continue;
139
}
140
try {
141
mbean = (NotificationBroadcaster) constr.newInstance();
142
} catch (Exception e) {
143
System.out.println(name + ": no-arg constructor failed: " + e);
144
continue;
145
}
146
147
check(mbean);
148
}
149
150
System.out.println();
151
System.out.println("Testing some explicit cases...");
152
153
check(new RelationService(false));
154
/*
155
We can't do this:
156
check(new RequiredModelMBean());
157
because the Model MBean spec more or less forces us to use the
158
names GENERIC and ATTRIBUTE_CHANGE for its standard notifs.
159
*/
160
checkRMIConnectorServer();
161
162
System.out.println();
163
if (!suspicious.isEmpty())
164
System.out.println("SUSPICIOUS CLASSES: " + suspicious);
165
166
if (failed.isEmpty())
167
System.out.println("TEST PASSED");
168
else {
169
System.out.println("TEST FAILED: " + failed);
170
System.exit(1);
171
}
172
}
173
174
private static void check(NotificationBroadcaster mbean)
175
throws Exception {
176
System.out.print(mbean.getClass().getName() + ": ");
177
178
check(mbean.getClass().getName(), mbean.getNotificationInfo());
179
}
180
181
private static void checkPlatformMBeans() throws Exception {
182
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
183
Set<ObjectName> mbeanNames = mbs.queryNames(null, null);
184
for (ObjectName name : mbeanNames) {
185
if (!mbs.isInstanceOf(name,
186
NotificationBroadcaster.class.getName())) {
187
System.out.println(name + ": not a NotificationBroadcaster");
188
} else {
189
MBeanInfo mbi = mbs.getMBeanInfo(name);
190
check(name.toString(), mbi.getNotifications());
191
}
192
}
193
}
194
195
private static void checkRMIConnectorServer() throws Exception {
196
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
197
RMIConnectorServer connector = new RMIConnectorServer(url, null);
198
check(connector);
199
}
200
201
private static void check(String what, MBeanNotificationInfo[] mbnis) {
202
System.out.print(what + ": checking notification info: ");
203
204
if (mbnis.length == 0) {
205
System.out.println("NONE (suspicious)");
206
suspicious.add(what);
207
return;
208
}
209
210
// Each MBeanNotificationInfo.getName() should be an existent
211
// Java class that is Notification or a subclass of it
212
for (int j = 0; j < mbnis.length; j++) {
213
String notifClassName = mbnis[j].getName();
214
Class notifClass;
215
try {
216
notifClass = Class.forName(notifClassName);
217
} catch (Exception e) {
218
System.out.print("FAILED(" + notifClassName + ": " + e +
219
") ");
220
failed.add(what);
221
continue;
222
}
223
if (!Notification.class.isAssignableFrom(notifClass)) {
224
System.out.print("FAILED(" + notifClassName +
225
": not a Notification) ");
226
failed.add(what);
227
continue;
228
}
229
System.out.print("OK(" + notifClassName + ") ");
230
}
231
System.out.println();
232
}
233
234
private static String[] findStandardMBeans(URL codeBase)
235
throws Exception {
236
Set<String> names;
237
if (codeBase.getProtocol().equalsIgnoreCase("file")
238
&& codeBase.toString().endsWith("/"))
239
names = findStandardMBeansFromDir(codeBase);
240
else
241
names = findStandardMBeansFromJar(codeBase);
242
243
Set<String> standardMBeanNames = new TreeSet<String>();
244
for (String name : names) {
245
if (name.endsWith("MBean")) {
246
String prefix = name.substring(0, name.length() - 5);
247
if (names.contains(prefix))
248
standardMBeanNames.add(prefix);
249
}
250
}
251
return standardMBeanNames.toArray(new String[0]);
252
}
253
254
private static Set<String> findStandardMBeansFromJar(URL codeBase)
255
throws Exception {
256
InputStream is = codeBase.openStream();
257
JarInputStream jis = new JarInputStream(is);
258
Set<String> names = new TreeSet<String>();
259
JarEntry entry;
260
while ((entry = jis.getNextJarEntry()) != null) {
261
String name = entry.getName();
262
if (!name.endsWith(".class"))
263
continue;
264
name = name.substring(0, name.length() - 6);
265
name = name.replace('/', '.');
266
names.add(name);
267
}
268
return names;
269
}
270
271
private static Set<String> findStandardMBeansFromDir(URL codeBase)
272
throws Exception {
273
File dir = new File(new URI(codeBase.toString()));
274
Set<String> names = new TreeSet<String>();
275
scanDir(dir, "", names);
276
return names;
277
}
278
279
private static void scanDir(File dir, String prefix, Set<String> names)
280
throws Exception {
281
File[] files = dir.listFiles();
282
if (files == null)
283
return;
284
for (int i = 0; i < files.length; i++) {
285
File f = files[i];
286
String name = f.getName();
287
String p = (prefix.equals("")) ? name : prefix + "." + name;
288
if (f.isDirectory())
289
scanDir(f, p, names);
290
else if (name.endsWith(".class")) {
291
p = p.substring(0, p.length() - 6);
292
names.add(p);
293
}
294
}
295
}
296
}
297
298