1 /*
2  * Copyright (c) 2004, 2005, 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 4847959 6191402
27  * @summary Test newly-generified APIs
28  * @author Eamonn McManus
29  * @run clean GenericTest
30  * @run build GenericTest
31  * @run main GenericTest
32  */
33 
34 import java.lang.management.ManagementFactory;
35 import java.lang.reflect.*;
36 import java.util.*;
37 import javax.management.*;
38 import javax.management.openmbean.*;
39 import javax.management.relation.*;
40 import javax.management.timer.Timer;
41 import javax.management.timer.TimerMBean;
42 
43 public class GenericTest {
44     private static int failures;
45 
main(String[] args)46     public static void main(String[] args) throws Exception {
47         MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
48 
49         // Check we are really using the generified version
50         boolean generic;
51         Method findmbs = MBeanServerFactory.class.getMethod("findMBeanServer",
52                                                             String.class);
53         Type findmbstype = findmbs.getGenericReturnType();
54         if (!(findmbstype instanceof ParameterizedType)) {
55             System.out.println("FAILURE: API NOT GENERIC!");
56             System.out.println("  MBeanServerFactory.findMBeanServer -> " +
57                                findmbstype);
58             failures++;
59             generic = false;
60         } else {
61             System.out.println("OK: this API is generic");
62             generic = true;
63         }
64 
65         ArrayList<MBeanServer> mbsList1 =
66             MBeanServerFactory.findMBeanServer(null);
67         checked(mbsList1, MBeanServer.class);
68         ArrayList mbsList2 = MBeanServerFactory.findMBeanServer(null);
69         check("ArrayList<MBeanServer> findMBeanServer", mbsList1.size() == 1);
70         check("ArrayList findMBeanServer", mbsList1.equals(mbsList2));
71 
72         Set<ObjectName> names1 =
73             checked(mbs.queryNames(null, null), ObjectName.class);
74         Set names2 = mbs.queryNames(null, null);
75         Set<ObjectName> names3 =
76             checked(((MBeanServerConnection) mbs).queryNames(null, null),
77                     ObjectName.class);
78         check("Set<ObjectName> MBeanServer.queryNames", names1.size() >= 1);
79         check("Set MBeanServer.queryNames", names2.size() >= 1);
80         check("Set<ObjectName> MBeanServerConnection.queryNames",
81               names3.size() >= 1);
82         check("queryNames sets same",
83               names1.equals(names2) && names2.equals(names3));
84 
85         Set<ObjectInstance> mbeans1 =
86             checked(mbs.queryMBeans(null, null), ObjectInstance.class);
87         Set mbeans2 = mbs.queryMBeans(null, null);
88         Set<ObjectInstance> mbeans3 =
89             checked(((MBeanServerConnection) mbs).queryMBeans(null, null),
90                     ObjectInstance.class);
91         check("Set<ObjectInstsance> MBeanServer.queryMBeans",
92               mbeans1.size() >= 1);
93         check("Set MBeanServer.queryMBeans", mbeans2.size() >= 1);
94         check("Set<ObjectInstsance> MBeanServerConnection.queryMBeans",
95               mbeans3.size() >= 1);
96         check("queryMBeans sets same",
97               mbeans1.equals(mbeans2) && mbeans2.equals(mbeans3));
98 
99 
100         AttributeChangeNotificationFilter acnf =
101             new AttributeChangeNotificationFilter();
102         acnf.enableAttribute("foo");
103         Vector<String> acnfs = acnf.getEnabledAttributes();
104         checked(acnfs, String.class);
105         check("Vector<String> AttributeChangeNotificationFilter.getEnabled" +
106               "Attributes", acnfs.equals(Arrays.asList(new String[] {"foo"})));
107 
108         if (generic) {
109             Attribute a = new Attribute("foo", "bar");
110             AttributeList al1 = new AttributeList();
111             al1.add(a);
112             AttributeList al2 =
113                 new AttributeList(Arrays.asList(new Attribute[] {a}));
114             check("new AttributeList(List<Attribute>)", al1.equals(al2));
115             List<Attribute> al3 = checked(al1.asList(), Attribute.class);
116             al3.remove(a);
117             check("List<Attribute> AttributeList.asList()",
118                   al1.equals(al3) && al1.isEmpty());
119         }
120 
121         List<ObjectName> namelist1 = new ArrayList<ObjectName>(names1);
122         Role role = new Role("rolename", namelist1);
123         List<ObjectName> namelist2 =
124             checked(role.getRoleValue(), ObjectName.class);
125         check("new Role(String,List<ObjectName>).getRoleValue() -> " +
126               "List<ObjectName>", namelist1.equals(namelist2));
127 
128         RoleList rl1 = new RoleList();
129         rl1.add(role);
130         RoleList rl2 = new RoleList(Arrays.asList(new Role[] {role}));
131         check("new RoleList(List<Role>)", rl1.equals(rl2));
132         if (generic) {
133             List<Role> rl3 = checked(rl1.asList(), Role.class);
134             rl3.remove(role);
135             check("List<Role> RoleList.asList()",
136                   rl1.equals(rl3) && rl1.isEmpty());
137         }
138 
139         RoleUnresolved ru =
140             new RoleUnresolved("rolename", namelist1,
141                                RoleStatus.LESS_THAN_MIN_ROLE_DEGREE);
142         List<ObjectName> namelist3 =
143             checked(ru.getRoleValue(), ObjectName.class);
144         check("new RoleUnresolved(...List<ObjectName>...).getRoleValue() -> " +
145               "List<ObjectName>", namelist1.equals(namelist3));
146 
147         RoleUnresolvedList rul1 = new RoleUnresolvedList();
148         rul1.add(ru);
149         RoleUnresolvedList rul2 =
150             new RoleUnresolvedList(Arrays.asList(new RoleUnresolved[] {ru}));
151         check("new RoleUnresolvedList(List<RoleUnresolved>", rul1.equals(rul2));
152         if (generic) {
153             List<RoleUnresolved> rul3 =
154                 checked(rul1.asList(), RoleUnresolved.class);
155             rul3.remove(ru);
156             check("List<RoleUnresolved> RoleUnresolvedList.asList()",
157                   rul1.equals(rul3) && rul1.isEmpty());
158         }
159 
160         // This case basically just tests that we can compile this sort of thing
161         OpenMBeanAttributeInfo ombai1 =
162             new OpenMBeanAttributeInfoSupport("a", "a descr",
163                                                 SimpleType.INTEGER,
164                                                 true, true, false);
165         CompositeType ct =
166             new CompositeType("ct", "ct descr", new String[] {"item1"},
167                               new String[] {"item1 descr"},
168                               new OpenType[] {SimpleType.INTEGER});
169         OpenMBeanAttributeInfo ombai2 =
170             new OpenMBeanAttributeInfoSupport("a", "a descr",
171                                                       ct, true, true, false);
172         TabularType tt =
173             new TabularType("tt", "tt descr", ct, new String[] {"item1"});
174         OpenMBeanAttributeInfo ombai3 =
175             new OpenMBeanAttributeInfoSupport("a", "a descr",
176                                                     tt, true, true, false);
177         ArrayType<String[][]> at =
178             new ArrayType<String[][]>(2, SimpleType.STRING);
179         OpenMBeanAttributeInfo ombai4 =
180             new OpenMBeanAttributeInfoSupport("a", "a descr",
181                                                    at, true, true, false);
182         OpenMBeanAttributeInfo ombai4a =
183             new OpenMBeanAttributeInfoSupport("a", "a descr",
184                                               (ArrayType) at,
185                                               true, true, false);
186         OpenMBeanAttributeInfo ombai5 =
187             new OpenMBeanAttributeInfoSupport("a", "a descr",
188                                                        SimpleType.INTEGER,
189                                                        true, true, false,
190                                                        5, 1, 9);
191         OpenMBeanAttributeInfo ombai6 =
192             new OpenMBeanAttributeInfoSupport("a", "a descr",
193                                                        SimpleType.INTEGER,
194                                                        true, true, false,
195                                                        5, new Integer[] {1, 5});
196 
197         OpenMBeanInfo ombi =
198             new OpenMBeanInfoSupport("a.a", "a.a descr",
199                                      new OpenMBeanAttributeInfo[] {
200                                          ombai1, ombai2, ombai3, ombai4,
201                                          ombai5, ombai6,
202                                      },
203                                      null, null, null);
204 
205         Map<String,Integer> itemMap =
206             checked(singletonMap("item1", 5),
207                     String.class, Integer.class);
208         CompositeData cd =
209             new CompositeDataSupport(ct, itemMap);
210         check("CompositeDataSupport(CompositeType, Map<String,?>",
211               cd.get("item1").equals(5));
212 
213         Set<String> ctkeys = checked(ct.keySet(), String.class);
214         check("Set<String> CompositeType.keySet()",
215               ctkeys.equals(singleton("item1")));
216 
217         List<String> ttindex = checked(tt.getIndexNames(), String.class);
218         check("Set<String> TabularType.getIndexNames()",
219               ttindex.equals(singletonList("item1")));
220 
221         TabularData td = new TabularDataSupport(tt);
222         td.putAll(new CompositeData[] {cd});
223         List<Integer> tdkey = checked(singletonList(5), Integer.class);
224         Set<List<Integer>> tdkeys = checked(singleton(tdkey),
225             (Class<List<Integer>>) tdkey.getClass());
226         Collection<CompositeData> tdvalues = checked(singleton(cd),
227             CompositeData.class);
228         check("Set<List<?>> TabularDataSupport.keySet()",
229               td.keySet().equals(tdkeys));
230         check("Collection<CompositeData> TabularDataSupport.values()",
231               td.values().iterator().next().equals(tdvalues.iterator().next()));
232 
233         ObjectName stupidName = new ObjectName("stupid:a=b");
234         mbs.registerMBean(new Stupid(), stupidName);
235         StupidMBean proxy =
236             MBeanServerInvocationHandler.newProxyInstance(mbs,
237                                                           stupidName,
238                                                           StupidMBean.class,
239                                                           false);
240         check("MBeanServerInvocationHandler.newProxyInstance",
241               proxy.getFive() == 5);
242         mbs.unregisterMBean(stupidName);
243 
244         mbs.registerMBean(new StandardMBean(new Stupid(), StupidMBean.class),
245                           stupidName);
246         check("<T> StandardMBean(T impl, Class<T> intf)",
247               proxy.getFive() == 5);
248 
249         // Following is based on the package.html for javax.management.relation
250         // Create the Relation Service MBean
251         ObjectName relSvcName = new ObjectName(":type=RelationService");
252         RelationService relSvcObject = new RelationService(true);
253         mbs.registerMBean(relSvcObject, relSvcName);
254 
255         // Create an MBean proxy for easier access to the Relation Service
256         RelationServiceMBean relSvc =
257         MBeanServerInvocationHandler.newProxyInstance(mbs, relSvcName,
258                                                       RelationServiceMBean.class,
259                                                       false);
260 
261         // Define the DependsOn relation type
262         RoleInfo[] dependsOnRoles = {
263             new RoleInfo("dependent", Module.class.getName()),
264             new RoleInfo("dependedOn", Module.class.getName())
265         };
266         relSvc.createRelationType("DependsOn", dependsOnRoles);
267 
268         // Now define a relation instance "moduleA DependsOn moduleB"
269 
270         ObjectName moduleA = new ObjectName(":type=Module,name=A");
271         ObjectName moduleB = new ObjectName(":type=Module,name=B");
272 
273         // Following two lines added to example:
274         mbs.registerMBean(new Module(), moduleA);
275         mbs.registerMBean(new Module(), moduleB);
276 
277         Role dependent = new Role("dependent", singletonList(moduleA));
278         Role dependedOn = new Role("dependedOn", singletonList(moduleB));
279         Role[] roleArray = {dependent, dependedOn};
280         RoleList roles = new RoleList(Arrays.asList(roleArray));
281         relSvc.createRelation("A-DependsOn-B", "DependsOn", roles);
282 
283         // Query the Relation Service to find what modules moduleA depends on
284         Map<ObjectName,List<String>> dependentAMap =
285         relSvc.findAssociatedMBeans(moduleA, "DependsOn", "dependent");
286         Set<ObjectName> dependentASet = dependentAMap.keySet();
287         dependentASet = checked(dependentASet, ObjectName.class);
288         // Set of ObjectName containing moduleB
289         check("Map<ObjectName,List<String>> RelationService.findAssociatedMBeans",
290               dependentAMap.size() == 1 &&
291               dependentASet.equals(singleton(moduleB)));
292 
293         Map<String,List<String>> refRels =
294             relSvc.findReferencingRelations(moduleA, "DependsOn", "dependent");
295         List<String> refRoles =
296             checked(refRels.get("A-DependsOn-B"), String.class);
297         check("Map<String,List<String>> RelationService.findReferencingRelations",
298               refRoles.equals(singletonList("dependent")));
299 
300         List<String> relsOfType = relSvc.findRelationsOfType("DependsOn");
301         relsOfType = checked(relsOfType, String.class);
302         check("List<String> RelationService.findRelationsOfType",
303               relsOfType.equals(singletonList("A-DependsOn-B")));
304 
305         List<String> allRelIds = relSvc.getAllRelationIds();
306         allRelIds = checked(allRelIds, String.class);
307         check("List<String> RelationService.getAllRelationIds()",
308               allRelIds.equals(singletonList("A-DependsOn-B")));
309 
310         List<String> allRelTypes = relSvc.getAllRelationTypeNames();
311         allRelTypes = checked(allRelTypes, String.class);
312         check("List<String> RelationService.getAllRelationTypeNames",
313               allRelTypes.equals(singletonList("DependsOn")));
314 
315         Map<ObjectName,List<String>> refdMBeans =
316             relSvc.getReferencedMBeans("A-DependsOn-B");
317         check("Map<ObjectName,List<String>> RelationService.getReferencedMBeans",
318               refdMBeans.get(moduleA).equals(singletonList("dependent")) &&
319               refdMBeans.get(moduleB).equals(singletonList("dependedOn")));
320 
321         List<ObjectName> roleContents =
322             checked(relSvc.getRole("A-DependsOn-B", "dependent"),
323                     ObjectName.class);
324         check("List<ObjectName> RelationService.getRole",
325               roleContents.equals(singletonList(moduleA)));
326 
327         RoleInfo roleInfoDependent =
328             relSvc.getRoleInfo("DependsOn", "dependent");
329         RoleInfo roleInfoDependedOn =
330             relSvc.getRoleInfo("DependsOn", "dependedOn");
331         List<RoleInfo> expectedRoleInfos =
332             Arrays.asList(new RoleInfo[] {roleInfoDependent, roleInfoDependedOn});
333         List<RoleInfo> roleInfos =
334             checked(relSvc.getRoleInfos("DependsOn"), RoleInfo.class);
335         check("List<RoleInfo> RelationService.getRoleInfos",
336               equalListContents(expectedRoleInfos, roleInfos));
337 
338         RelationType relType =
339             new RelationTypeSupport("DependsOn", dependsOnRoles);
340         List<RoleInfo> relTypeRoleInfos =
341             checked(relType.getRoleInfos(), RoleInfo.class);
342         // Since there's no RoleInfo.equals and since the RelationTypeSupport
343         // constructor clones the RoleInfos passed to it, it's tricky to
344         // test equality here so we check type and size and have done with it
345         check("List<RoleInfo> RelationType.getRoleInfos",
346               relTypeRoleInfos.size() == 2);
347 
348         MBeanServerNotificationFilter mbsnf =
349             new MBeanServerNotificationFilter();
350         mbsnf.enableObjectName(moduleA);
351         check("Vector<ObjectName> MBeanServerNotificationFilter." +
352               "getEnabledObjectNames",
353               mbsnf.getEnabledObjectNames().equals(Arrays.asList(moduleA)));
354         mbsnf.enableAllObjectNames();
355         mbsnf.disableObjectName(moduleB);
356         check("Vector<ObjectName> MBeanServerNotificationFilter." +
357               "getDisabledObjectNames",
358               mbsnf.getDisabledObjectNames().equals(Arrays.asList(moduleB)));
359 
360         RelationService unusedRelSvc = new RelationService(false);
361         RelationNotification rn1 =
362             new RelationNotification(RelationNotification.RELATION_MBEAN_REMOVAL,
363                                      unusedRelSvc, 0L, 0L, "yo!",
364                                      "A-DependsOn-B", "DependsOn", null,
365                                      singletonList(moduleA));
366         List<ObjectName> toUnreg =
367             checked(rn1.getMBeansToUnregister(), ObjectName.class);
368         check("List<ObjectName> RelationNotification.getMBeansToUnregister",
369               toUnreg.equals(singletonList(moduleA)));
370 
371         RelationNotification rn2 =
372             new RelationNotification(RelationNotification.RELATION_MBEAN_UPDATE,
373                                      unusedRelSvc, 0L, 0L, "yo!",
374                                      "A-DependsOn-B", "DependsOn", null,
375                                      "dependent", singletonList(moduleA),
376                                      singletonList(moduleB));
377         check("List<ObjectName> RelationNotification.getOldRoleValue",
378               checked(rn2.getOldRoleValue(), ObjectName.class)
379               .equals(singletonList(moduleB)));
380         check("List<ObjectName> RelationNotification.getNewRoleValue",
381               checked(rn2.getNewRoleValue(), ObjectName.class)
382               .equals(singletonList(moduleA)));
383 
384         ObjectName timerName = new ObjectName(":type=timer");
385         mbs.registerMBean(new Timer(), timerName);
386         TimerMBean timer =
387             MBeanServerInvocationHandler.newProxyInstance(mbs,
388                                                           timerName,
389                                                           TimerMBean.class,
390                                                           false);
391         Date doomsday = new Date(Long.MAX_VALUE);
392         int timer1 = timer.addNotification("one", "one", null, doomsday);
393         int timer2 = timer.addNotification("two", "two", null, doomsday);
394         Vector<Integer> idsOne = timer.getNotificationIDs("one");
395         check("Vector<Integer> TimerMBean.getNotificationIDs",
396               idsOne.equals(singletonList(timer1)));
397         Vector<Integer> allIds = timer.getAllNotificationIDs();
398         check("Vector<Integer> TimerMBean.getAllNotificationIDs",
399               equalListContents(allIds,
400                                 Arrays.asList(new Integer[]{timer1, timer2})));
401 
402         // ADD NEW TEST CASES ABOVE THIS COMMENT
403 
404         if (failures == 0)
405             System.out.println("All tests passed");
406         else {
407             System.out.println("TEST FAILURES: " + failures);
408             System.exit(1);
409         }
410 
411         // DO NOT ADD NEW TEST CASES HERE, ADD THEM ABOVE THE PREVIOUS COMMENT
412     }
413 
414     public static interface StupidMBean {
getFive()415         public int getFive();
416     }
417 
418     public static class Stupid implements StupidMBean {
getFive()419         public int getFive() {
420             return 5;
421         }
422     }
423 
424     public static class Module extends StandardMBean implements StupidMBean {
Module()425         public Module() throws NotCompliantMBeanException {
426             super(StupidMBean.class);
427         }
428 
getFive()429         public int getFive() {
430             return 5;
431         }
432     }
433 
singletonList(E value)434     private static <E> List<E> singletonList(E value) {
435         return Collections.singletonList(value);
436     }
437 
singleton(E value)438     private static <E> Set<E> singleton(E value) {
439         return Collections.singleton(value);
440     }
441 
singletonMap(K key, V value)442     private static <K,V> Map<K,V> singletonMap(K key, V value) {
443         return Collections.singletonMap(key, value);
444     }
445 
checked(List<E> c, Class<E> type)446     private static <E> List<E> checked(List<E> c, Class<E> type) {
447         List<E> unchecked = new ArrayList<E>();
448         List<E> checked = Collections.checkedList(unchecked, type);
449         checked.addAll(c);
450         return Collections.checkedList(c, type);
451     }
452 
checked(Set<E> c, Class<E> type)453     private static <E> Set<E> checked(Set<E> c, Class<E> type) {
454         Set<E> unchecked = new HashSet<E>();
455         Set<E> checked = Collections.checkedSet(unchecked, type);
456         checked.addAll(c);
457         return Collections.checkedSet(c, type);
458     }
459 
checked(Map<K,V> m, Class<K> keyType, Class<V> valueType)460     private static <K,V> Map<K,V> checked(Map<K,V> m,
461                                           Class<K> keyType,
462                                           Class<V> valueType) {
463         Map<K,V> unchecked = new HashMap<K,V>();
464         Map<K,V> checked = Collections.checkedMap(unchecked, keyType, valueType);
465         checked.putAll(m);
466         return Collections.checkedMap(m, keyType, valueType);
467     }
468 
469     /* The fact that we have to call this method is a clear signal that
470      * the API says List where it means Set.
471      */
equalListContents(List<E> l1, List<E> l2)472     private static <E> boolean equalListContents(List<E> l1, List<E> l2) {
473         return new HashSet<E>(l1).equals(new HashSet<E>(l2));
474     }
475 
check(String what, boolean cond)476     private static void check(String what, boolean cond) {
477         if (cond)
478             System.out.println("OK: " + what);
479         else {
480             System.out.println("FAILED: " + what);
481             failures++;
482         }
483     }
484 }
485