blob: 1c42043714c43a5fdc7a8758d84cb660e79b947e [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24/*
25 * @test
26 * @bug 5106721
27 * @summary Check the emission of notifications when a Security Manager is
28 * installed. Test the property "jmx.remote.x.check.notification.emission".
29 * @author Luis-Miguel Alventosa
30 * @run clean NotificationEmissionTest
31 * @run build NotificationEmissionTest
32 * @run main NotificationEmissionTest 1
33 * @run main NotificationEmissionTest 2
34 * @run main NotificationEmissionTest 3
35 * @run main NotificationEmissionTest 4
36 * @run main NotificationEmissionTest 5
37 */
38
39import java.io.File;
40import java.util.ArrayList;
41import java.util.Collections;
42import java.util.HashMap;
43import java.util.List;
44import java.util.Map;
45import javax.management.MBeanServer;
46import javax.management.MBeanServerConnection;
47import javax.management.MBeanServerFactory;
48import javax.management.Notification;
49import javax.management.NotificationBroadcasterSupport;
50import javax.management.NotificationListener;
51import javax.management.ObjectName;
52import javax.management.remote.JMXAuthenticator;
53import javax.management.remote.JMXConnector;
54import javax.management.remote.JMXConnectorFactory;
55import javax.management.remote.JMXConnectorServer;
56import javax.management.remote.JMXConnectorServerFactory;
57import javax.management.remote.JMXPrincipal;
58import javax.management.remote.JMXServiceURL;
59import javax.security.auth.Subject;
60
61public class NotificationEmissionTest {
62
63 public class CustomJMXAuthenticator implements JMXAuthenticator {
64 public Subject authenticate(Object credentials) {
65 String role = ((String[]) credentials)[0];
66 echo("Create principal with name = " + role);
67 return new Subject(true,
68 Collections.singleton(new JMXPrincipal(role)),
69 Collections.EMPTY_SET,
70 Collections.EMPTY_SET);
71 }
72 }
73
74 public interface NBMBean {
75 public void emitNotification(int seqnum, ObjectName name);
76 }
77
78 public static class NB
79 extends NotificationBroadcasterSupport
80 implements NBMBean {
81 public void emitNotification(int seqnum, ObjectName name) {
82 if (name == null) {
83 sendNotification(new Notification("nb", this, seqnum));
84 } else {
85 sendNotification(new Notification("nb", name, seqnum));
86 }
87 }
88 }
89
90 public class Listener implements NotificationListener {
91 public List<Notification> notifs = new ArrayList<Notification>();
92 public void handleNotification(Notification n, Object h) {
93 echo("handleNotification:");
94 echo("\tNotification = " + n);
95 echo("\tNotification.SeqNum = " + n.getSequenceNumber());
96 echo("\tHandback = " + h);
97 notifs.add(n);
98 }
99 }
100
101 public int checkNotifs(int size,
102 List<Notification> received,
103 List<ObjectName> expected) {
104 if (received.size() != size) {
105 echo("Error: expecting " + size + " notifications");
106 return 1;
107 } else {
108 for (Notification n : received) {
109 echo("Received notification: " + n);
110 if (!n.getType().equals("nb")) {
111 echo("Notification type must be \"nb\"");
112 return 1;
113 }
114 ObjectName o = (ObjectName) n.getSource();
115 int index = (int) n.getSequenceNumber();
116 ObjectName nb = expected.get(index);
117 if (!o.equals(nb)) {
118 echo("Notification source must be " + nb);
119 return 1;
120 }
121 }
122 }
123 return 0;
124 }
125
126 public int runTest(int testcase) throws Exception {
127 echo("\n=-=-= Running testcase " + testcase + " =-=-=");
128 switch (testcase) {
129 case 1:
130 return testNotificationEmissionProperty();
131 case 2:
132 return testNotificationEmissionPositive(false);
133 case 3:
134 return testNotificationEmissionNegative(false);
135 case 4:
136 return testNotificationEmissionPositive(true);
137 case 5:
138 return testNotificationEmissionNegative(true);
139 default:
140 echo("Invalid testcase");
141 return 1;
142 }
143 }
144
145 public int testNotificationEmissionProperty(boolean exception,
146 Object propValue)
147 throws Exception {
148 try {
149 testNotificationEmission(propValue);
150 if (exception) {
151 echo("Did not get expected exception for value: " + propValue);
152 return 1;
153 } else {
154 echo("Property has been correctly set to value: " + propValue);
155 }
156 } catch (Exception e) {
157 if (exception) {
158 echo("Got expected exception for value: " + propValue);
159 echo("Exception: " + e);
160 } else {
161 echo("Got unexpected exception for value: " + propValue);
162 echo("Exception: " + e);
163 return 1;
164 }
165 }
166 return 0;
167 }
168
169 public int testNotificationEmissionProperty() throws Exception {
170 int error = 0;
171 error += testNotificationEmissionProperty(true, new Boolean(false));
172 error += testNotificationEmissionProperty(true, new Boolean(true));
173 error += testNotificationEmissionProperty(true, "dummy");
174 error += testNotificationEmissionProperty(false, "false");
175 error += testNotificationEmissionProperty(false, "true");
176 error += testNotificationEmissionProperty(false, "FALSE");
177 error += testNotificationEmissionProperty(false, "TRUE");
178 return error;
179 }
180
181 public int testNotificationEmissionPositive(boolean prop) throws Exception {
182 return testNotificationEmission(prop, "true", true, true);
183 }
184
185 public int testNotificationEmissionNegative(boolean prop) throws Exception {
186 return testNotificationEmission(prop, "true", true, false);
187 }
188
189 public int testNotificationEmission(Object propValue) throws Exception {
190 return testNotificationEmission(true, propValue, false, true);
191 }
192
193 public int testNotificationEmission(boolean prop,
194 Object propValue,
195 boolean sm,
196 boolean policyPositive)
197 throws Exception {
198
199 JMXConnectorServer server = null;
200 JMXConnector client = null;
201
202 // Set policy file
203 //
204 String policyFile =
205 System.getProperty("test.src") + File.separator +
206 (policyPositive ? "policy.positive" : "policy.negative");
207 echo("\nSetting policy file " + policyFile);
208 System.setProperty("java.security.policy", policyFile);
209
210 // Create a new MBeanServer
211 //
212 final MBeanServer mbs = MBeanServerFactory.createMBeanServer();
213
214 try {
215 // Create server environment map
216 //
217 final Map<String,Object> env = new HashMap<String,Object>();
218 env.put("jmx.remote.authenticator", new CustomJMXAuthenticator());
219 if (prop)
220 env.put("jmx.remote.x.check.notification.emission", propValue);
221
222 // Create the JMXServiceURL
223 //
224 final JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
225
226 // Create a JMXConnectorServer
227 //
228 server = JMXConnectorServerFactory.newJMXConnectorServer(url,
229 env,
230 mbs);
231
232 // Start the JMXConnectorServer
233 //
234 server.start();
235
236 // Create server environment map
237 //
238 final Map<String,Object> cenv = new HashMap<String,Object>();
239 String[] credentials = new String[] { "role" , "password" };
240 cenv.put("jmx.remote.credentials", credentials);
241
242 // Create JMXConnector and connect to JMXConnectorServer
243 //
244 client = JMXConnectorFactory.connect(server.getAddress(), cenv);
245
246 // Get non-secure MBeanServerConnection
247 //
248 final MBeanServerConnection mbsc =
249 client.getMBeanServerConnection();
250
251 // Create NB MBean
252 //
253 ObjectName nb1 = ObjectName.getInstance("domain:type=NB,name=1");
254 ObjectName nb2 = ObjectName.getInstance("domain:type=NB,name=2");
255 ObjectName nb3 = ObjectName.getInstance("domain:type=NB,name=3");
256 mbsc.createMBean(NB.class.getName(), nb1);
257 mbsc.createMBean(NB.class.getName(), nb2);
258 mbsc.createMBean(NB.class.getName(), nb3);
259
260 // Add notification listener
261 //
262 Listener li = new Listener();
263 mbsc.addNotificationListener(nb1, li, null, null);
264 mbsc.addNotificationListener(nb2, li, null, null);
265
266 // Set security manager
267 //
268 if (sm) {
269 echo("Setting SM");
270 System.setSecurityManager(new SecurityManager());
271 }
272
273 // Invoke the "sendNotification" method
274 //
275 mbsc.invoke(nb1, "emitNotification",
276 new Object[] {0, null},
277 new String[] {"int", "javax.management.ObjectName"});
278 mbsc.invoke(nb2, "emitNotification",
279 new Object[] {1, null},
280 new String[] {"int", "javax.management.ObjectName"});
281 mbsc.invoke(nb2, "emitNotification",
282 new Object[] {2, nb3},
283 new String[] {"int", "javax.management.ObjectName"});
284
285 // Wait for notifications to be emitted
286 //
287 Thread.sleep(2000);
288
289 // Remove notification listener
290 //
291 mbsc.removeNotificationListener(nb1, li);
292 mbsc.removeNotificationListener(nb2, li);
293
294 int result = 0;
295 List<ObjectName> sources = new ArrayList();
296 sources.add(nb1);
297 sources.add(nb2);
298 sources.add(nb3);
299
300 if (prop && sm && !policyPositive) {
301 // List must contain two notifs from sources nb2 and nb3
302 //
303 result = checkNotifs(2, li.notifs, sources);
304 } else {
305 // List must contain three notifs from sources nb1, nb2 and nb3
306 //
307 result = checkNotifs(3, li.notifs, sources);
308 }
309 if (result > 0) {
310 return result;
311 }
312 } finally {
313 // Close the connection
314 //
315 if (client != null)
316 client.close();
317
318 // Stop the connector server
319 //
320 if (server != null)
321 server.stop();
322
323 // Release the MBeanServer
324 //
325 if (mbs != null)
326 MBeanServerFactory.releaseMBeanServer(mbs);
327 }
328
329 return 0;
330 }
331
332 private static void echo(String message) {
333 System.out.println(message);
334 }
335
336 public static void main(String[] args) throws Exception {
337
338 echo("\n--- Check the emission of notifications " +
339 "when a Security Manager is installed ---");
340
341 NotificationEmissionTest net = new NotificationEmissionTest();
342
343 int error = 0;
344
345 error += net.runTest(Integer.parseInt(args[0]));
346
347 if (error > 0) {
348 final String msg = "\nTest FAILED! Got " + error + " error(s)";
349 echo(msg);
350 throw new IllegalArgumentException(msg);
351 } else {
352 echo("\nTest PASSED!");
353 }
354 }
355}