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