blob: f5e4e5b80d49009b236142f66bb3117e99d96c24 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003 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 4950756
27 * @summary Test that RequiredModelMBean.invoke will not invoke methods
28 * from the RequiredModelMBean class itself if they are not in the
29 * ModelMBeanInfo
30 * @author Eamonn McManus
31 * @run clean RequiredModelMBeanMethodTest
32 * @run build RequiredModelMBeanMethodTest
33 * @run main RequiredModelMBeanMethodTest
34 */
35
36import java.lang.reflect.*;
37import javax.management.*;
38import javax.management.modelmbean.*;
39
40/*
41 * We do the same test with a number of different operations:
42 *
43 * - A plain operation that is directed to the managed resource in the
44 * usual way. We give it some parameters so we can test that the
45 * class loading logic for signature parameters is reasonable.
46 *
47 * - An operation (removeNotificationListener) that is directed to the
48 * RequiredModelMBean itself. We use this particular operation because
49 * it will throw an exception, which allows us to check that it did in
50 * fact execute.
51 *
52 * - An operation (load()) that has the same signature as a
53 * RequiredModelMBean operation but is directed to the resource
54 * because of a "class" field in the descriptor.
55 *
56 * - An operation (store()) that has the same signature as a
57 * RequiredModelMBean operation but is directed to the resource
58 * because of a "targetObject" field in the descriptor.
59 *
60 * In each case we check that the operation does not work if it is not
61 * in the ModelMBeanInfo, and does work if it is.
62 */
63public class RequiredModelMBeanMethodTest {
64 public static void main(String[] args) throws Exception {
65 boolean ok = true;
66 MBeanServer mbs = MBeanServerFactory.createMBeanServer();
67
68 Descriptor tralalaDescriptor =
69 new DescriptorSupport(new String[] {
70 "name=tralala",
71 "descriptorType=operation",
72 "role=operation",
73 "targetType=ObjectReference",
74 });
75 Method tralalaMethod =
76 Resource.class.getMethod("tralala",
77 new Class[] {int.class, Resource.class});
78 ModelMBeanOperationInfo tralalaInfo =
79 new ModelMBeanOperationInfo("tralala descr", tralalaMethod,
80 tralalaDescriptor);
81
82 Method remACNLMethod =
83 RequiredModelMBean.class.getMethod("removeAttributeChangeNotificationListener",
84 new Class[] {
85 NotificationListener.class,
86 String.class
87 });
88 ModelMBeanOperationInfo remACNLInfo =
89 new ModelMBeanOperationInfo("remACNL descr", remACNLMethod);
90
91 Descriptor loadDescriptor =
92 new DescriptorSupport(new String[] {
93 "name=load",
94 "descriptorType=operation",
95 "role=operation",
96 "targetType=ObjectReference",
97 "class=" + Resource.class.getName(),
98 });
99 ModelMBeanOperationInfo loadInfo =
100 new ModelMBeanOperationInfo("load", "load descr",
101 new MBeanParameterInfo[0],
102 "void", ModelMBeanOperationInfo.ACTION,
103 loadDescriptor);
104
105 Descriptor storeDescriptor =
106 new DescriptorSupport(new String[] {
107 "name=store",
108 "descriptorType=operation",
109 "role=operation",
110 "targetType=ObjectReference",
111 });
112 storeDescriptor.setField("targetObject", resource);
113 ModelMBeanOperationInfo storeInfo =
114 new ModelMBeanOperationInfo("store", "store descr",
115 new MBeanParameterInfo[0],
116 "void", ModelMBeanOperationInfo.ACTION,
117 storeDescriptor);
118
119 ModelMBeanInfo emptyMMBI =
120 new ModelMBeanInfoSupport(Resource.class.getName(),
121 "empty descr",
122 null, null, null, null);
123 ModelMBean emptyMMB = new RequiredModelMBean(emptyMMBI);
124 emptyMMB.setManagedResource(resource, "ObjectReference");
125 ObjectName emptyMMBName = new ObjectName("test:type=Empty");
126 mbs.registerMBean(emptyMMB, emptyMMBName);
127
128 System.out.println("Testing that we cannot call methods not in the " +
129 "ModelMBeanInfo");
130 try {
131 boolean thisok = test(mbs, emptyMMBName, false);
132 if (thisok)
133 System.out.println("...OK");
134 else
135 ok = false;
136 } catch (Exception e) {
137 System.out.println("TEST FAILED: Caught exception:");
138 e.printStackTrace(System.out);
139 ok = false;
140 }
141
142 ModelMBeanOperationInfo[] opInfos = {
143 tralalaInfo, remACNLInfo, loadInfo, storeInfo,
144 };
145 ModelMBeanInfo fullMMBI =
146 new ModelMBeanInfoSupport(Resource.class.getName(),
147 "full descr",
148 null, null, opInfos, null);
149 ModelMBean fullMMB = new RequiredModelMBean(fullMMBI);
150 fullMMB.setManagedResource(resource, "ObjectReference");
151 ObjectName fullMMBName = new ObjectName("test:type=Full");
152 mbs.registerMBean(fullMMB, fullMMBName);
153
154
155 System.out.println();
156 System.out.println("Testing that we can call methods in the " +
157 "ModelMBeanInfo");
158 System.out.println(" and that \"class\" or \"targetObject\" in " +
159 "descriptor directs methods to resource");
160 try {
161 boolean thisok = test(mbs, fullMMBName, true);
162 if (thisok)
163 System.out.println("...OK");
164 else
165 ok = false;
166 } catch (Exception e) {
167 System.out.println("TEST FAILED: Caught exception:");
168 e.printStackTrace(System.out);
169 ok = false;
170 }
171
172 if (ok) {
173 if (!resource.loadCalled || !resource.storeCalled) {
174 System.out.println("TEST FAILED: not called:" +
175 (resource.loadCalled ? "" : " load") +
176 (resource.storeCalled ? "" : " store"));
177 ok = false;
178 }
179 }
180
181 // Test the invoke("class.method") form
182 if (ok) {
183 System.out.println("Testing invoke(\"class.method\")");
184 resource.loadCalled = false;
185 mbs.invoke(fullMMBName, Resource.class.getName() + ".load",
186 null, null);
187 if (!resource.loadCalled) {
188 System.out.println("TEST FAILED: load not called");
189 ok = false;
190 }
191 try {
192 mbs.invoke(fullMMBName,
193 RequiredModelMBean.class.getName() +
194 ".removeAttributeChangeNotificationListener",
195 new Object[] {boringListener, null},
196 new String[] {
197 NotificationListener.class.getName(),
198 String.class.getName(),
199 });
200 System.out.println("TEST FAILED: removeNotificationListener" +
201 " returned successfully but " +
202 "should not have");
203 ok = false;
204 } catch (MBeanException e) {
205 final Exception target = e.getTargetException();
206 if (target instanceof ListenerNotFoundException) {
207 // OK: there is no such listener
208 } else
209 throw e;
210 }
211 }
212
213 if (ok)
214 System.out.println("Test passed");
215 else {
216 System.out.println("TEST FAILED");
217 System.exit(1);
218 }
219 }
220
221 private static boolean test(MBeanServer mbs, ObjectName name,
222 boolean shouldWork)
223 throws Exception {
224
225 boolean ok = true;
226
227 final String[] names = {
228 "tralala",
229 "removeAttributeChangeNotificationListener",
230 "load",
231 "store",
232 };
233
234 for (int i = 0; i < 4; i++) {
235 boolean thisok = true;
236 try {
237 switch (i) {
238 case 0:
239 String tralala = (String)
240 mbs.invoke(name, names[i],
241 new Object[] {new Integer(5), resource},
242 new String[] {"int",
243 Resource.class.getName()});
244 if (!"tralala".equals(tralala)) {
245 System.out.println("TEST FAILED: tralala returned: " +
246 tralala);
247 thisok = false;
248 }
249 break;
250 case 1:
251 try {
252 mbs.invoke(name,
253 names[i],
254 new Object[] {boringListener, null},
255 new String[] {
256 NotificationListener.class.getName(),
257 String.class.getName(),
258 });
259 System.out.println("TEST FAILED: " + names[i] +
260 " returned successfully but " +
261 "should not have");
262 thisok = false;
263 } catch (MBeanException e) {
264 final Exception target = e.getTargetException();
265 if (target instanceof ListenerNotFoundException) {
266 // OK: there is no such listener
267 } else
268 throw e;
269 }
270 break;
271 case 2:
272 case 3:
273 mbs.invoke(name,
274 names[i],
275 new Object[0],
276 new String[0]);
277 break;
278 default:
279 throw new AssertionError();
280 }
281
282 thisok = shouldWork;
283 if (!shouldWork) {
284 System.out.println("TEST FAILED: " + names[i] +
285 " worked but should not");
286 }
287 } catch (MBeanException e) {
288 if (shouldWork) {
289 System.out.println("TEST FAILED: " + names[i] + ": " + e);
290 e.printStackTrace(System.out);
291 thisok = false;
292 } else {
293 Exception target = e.getTargetException();
294 if (!(target instanceof ServiceNotFoundException)) {
295 System.out.println("TEST FAILED: " + names[i] +
296 ": wrong exception: " + target);
297 thisok = false;
298 }
299 }
300 } catch (Exception e) {
301 System.out.println("TEST FAILED: " + names[i] + ": " + e);
302 e.printStackTrace(System.out);
303 thisok = false;
304 }
305
306 if (thisok)
307 System.out.println("OK: " + names[i]);
308 else
309 ok = false;
310 }
311
312 return ok;
313 }
314
315 public static class Resource {
316 public String tralala(int x, Resource y) {
317 if (x != 5 || y != this)
318 return "wrong params: " + x + " " + y;
319 return "tralala";
320 }
321
322 public void load() {
323 loadCalled = true;
324 }
325
326 public void store() {
327 storeCalled = true;
328 }
329
330 boolean loadCalled, storeCalled;
331 }
332
333 private static Resource resource = new Resource();
334
335 private static NotificationListener boringListener =
336 new NotificationListener() {
337 public void handleNotification(Notification n, Object h) {
338 }
339 };
340}