jdk/test/javax/management/namespace/QueryNamesTest.java
changeset 4156 acaa49a2768a
parent 4155 460e37d40f12
child 4159 9e3aae7675f1
equal deleted inserted replaced
4155:460e37d40f12 4156:acaa49a2768a
     1 /*
       
     2  * Copyright 2008 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 QueryNamesTest.java 1.4
       
    26  * @summary Test how queryNames works with Namespaces.
       
    27  * @author Daniel Fuchs
       
    28  * @bug 5072476 6768935
       
    29  * @run clean QueryNamesTest Wombat WombatMBean
       
    30  * @run build QueryNamesTest Wombat WombatMBean
       
    31  * @run main QueryNamesTest
       
    32  */
       
    33 
       
    34 
       
    35 import java.io.IOException;
       
    36 import java.lang.management.ManagementFactory;
       
    37 import java.util.ArrayList;
       
    38 import java.util.Arrays;
       
    39 import java.util.Collections;
       
    40 import java.util.HashMap;
       
    41 import java.util.HashSet;
       
    42 import java.util.LinkedHashMap;
       
    43 import java.util.LinkedHashSet;
       
    44 import java.util.LinkedList;
       
    45 import java.util.List;
       
    46 import java.util.Map;
       
    47 import java.util.Random;
       
    48 import java.util.Set;
       
    49 import java.util.logging.Logger;
       
    50 import javax.management.InstanceNotFoundException;
       
    51 import javax.management.JMException;
       
    52 import javax.management.MBeanServer;
       
    53 import javax.management.MBeanServerConnection;
       
    54 import javax.management.MBeanServerFactory;
       
    55 import javax.management.MalformedObjectNameException;
       
    56 import javax.management.ObjectInstance;
       
    57 import javax.management.ObjectName;
       
    58 import javax.management.RuntimeOperationsException;
       
    59 import javax.management.namespace.JMXNamespace;
       
    60 import javax.management.namespace.JMXNamespaces;
       
    61 
       
    62 /**
       
    63  * Class QueryNamesTest
       
    64  * @author Sun Microsystems, 2005 - All rights reserved.
       
    65  */
       
    66 public class QueryNamesTest {
       
    67 
       
    68     /**
       
    69      * A logger for this class.
       
    70      **/
       
    71     private static final Logger LOG =
       
    72             Logger.getLogger(QueryNamesTest.class.getName());
       
    73 
       
    74     public static class LocalNamespace
       
    75             extends JMXNamespace {
       
    76 
       
    77         private static MBeanServer check(MBeanServer server) {
       
    78             if (server == null)
       
    79                 throw new IllegalArgumentException("MBeanServer can't be null");
       
    80             return server;
       
    81         }
       
    82 
       
    83         public LocalNamespace() {
       
    84             this(MBeanServerFactory.createMBeanServer());
       
    85         }
       
    86 
       
    87         public LocalNamespace(MBeanServer server) {
       
    88             super(check(server));
       
    89         }
       
    90 
       
    91 
       
    92         public static String add(MBeanServerConnection server,
       
    93                 String nspath)
       
    94                 throws IOException, JMException {
       
    95             server.createMBean(LocalNamespace.class.getName(),
       
    96                     JMXNamespaces.getNamespaceObjectName(nspath));
       
    97             return nspath;
       
    98         }
       
    99     }
       
   100 
       
   101     /** Creates a new instance of QueryNamesTest */
       
   102     public QueryNamesTest() {
       
   103     }
       
   104 
       
   105     private static String[] namespaces = {
       
   106         "greg", "greg//chichille", "greg//chichille//petard",
       
   107         "greg//alambic", "greg//alambic//canette",
       
   108         "greg//chichille/virgule", "greg//chichille/funeste",
       
   109         "greg//chichille/virgule//bidouble",
       
   110         "greg//chichille/virgule//bi/double",
       
   111         "fran", "fran//gast", "fran//gast//gaf",
       
   112         "fran//longtar", "fran//longtar//parcmetre"
       
   113     };
       
   114 
       
   115     private static void createNamespaces(MBeanServer server) throws Exception {
       
   116         final LinkedList<String> all = new LinkedList<String>();
       
   117         try {
       
   118             for (String ns : namespaces)
       
   119                 all.addFirst(LocalNamespace.add(server,ns));
       
   120         } catch (Exception e) {
       
   121             removeNamespaces(server,all.toArray(new String[all.size()]));
       
   122             throw e;
       
   123         }
       
   124     }
       
   125 
       
   126     // Dummy test that checks that all JMXNamespaces are registered,
       
   127     // but are not returned by queryNames("*:*");
       
   128     //
       
   129     private static void checkRegistration(MBeanServer server)
       
   130         throws Exception {
       
   131         final Set<ObjectName> handlerNames = new HashSet<ObjectName>(namespaces.length);
       
   132         for (String ns : namespaces)
       
   133             handlerNames.add(JMXNamespaces.getNamespaceObjectName(ns));
       
   134         for (ObjectName nh : handlerNames) // check handler registration
       
   135             if (!server.isRegistered(nh))
       
   136                 throw new InstanceNotFoundException("handler "+nh+
       
   137                         " is not registered");
       
   138 
       
   139         // global: queryNames("*:*") from top level
       
   140         final Set<ObjectName> all1 = server.queryNames(null,null);
       
   141         final Set<ObjectName> all2 = server.queryNames(ObjectName.WILDCARD,null);
       
   142         if (!all1.equals(all2))
       
   143             throw new Exception("queryNames(*:*) != queryNames(null)");
       
   144         final Set<ObjectName> common = new HashSet<ObjectName>(all1);
       
   145         common.retainAll(handlerNames);
       
   146 
       
   147         final Set<ObjectName> ref = new HashSet<ObjectName>();
       
   148         for (String ns : namespaces) {
       
   149             if (!ns.contains(JMXNamespaces.NAMESPACE_SEPARATOR))
       
   150                 ref.add(JMXNamespaces.getNamespaceObjectName(ns));
       
   151         }
       
   152         if (!common.equals(ref)) {
       
   153             throw new Exception("some handler names were not returned by " +
       
   154                     "wildcard query - only returned: "+common+
       
   155                     ", expected: "+ref);
       
   156         }
       
   157 
       
   158         // for each namespace: queryNames("<namespace>//*:*");
       
   159         for (String ns : namespaces) {
       
   160             final ObjectName pattern = new ObjectName(ns+
       
   161                     JMXNamespaces.NAMESPACE_SEPARATOR+"*:*");
       
   162             final Set<ObjectName> all4 =
       
   163                     server.queryNames(pattern,null);
       
   164             final Set<ObjectName> common4 = new HashSet<ObjectName>(all4);
       
   165             common4.retainAll(handlerNames);
       
   166 
       
   167             final Set<ObjectName> ref4 = new HashSet<ObjectName>();
       
   168             for (String ns2 : namespaces) {
       
   169                 if (! ns2.startsWith(ns+JMXNamespaces.NAMESPACE_SEPARATOR))
       
   170                     continue;
       
   171                 if (!ns2.substring(ns.length()+
       
   172                         JMXNamespaces.NAMESPACE_SEPARATOR.length()).
       
   173                         contains(JMXNamespaces.NAMESPACE_SEPARATOR))
       
   174                     ref4.add(JMXNamespaces.getNamespaceObjectName(ns2));
       
   175             }
       
   176             if (!common4.equals(ref4)) {
       
   177                 throw new Exception("some handler names were not returned by " +
       
   178                     "wildcard query on "+pattern+" - only returned: "+common4+
       
   179                     ", expected: "+ref4);
       
   180             }
       
   181         }
       
   182     }
       
   183 
       
   184     // Make a Map<parent, direct children>
       
   185     private static Map<String,Set<String>> makeNsTree(String[] nslist) {
       
   186         final Map<String,Set<String>> nsTree =
       
   187                 new LinkedHashMap<String,Set<String>>(nslist.length);
       
   188         for (String ns : nslist) {
       
   189             if (nsTree.get(ns) == null)
       
   190                 nsTree.put(ns,new LinkedHashSet<String>());
       
   191             final String[] elts = ns.split(JMXNamespaces.NAMESPACE_SEPARATOR);
       
   192             int last = ns.lastIndexOf(JMXNamespaces.NAMESPACE_SEPARATOR);
       
   193             if (last<0) continue;
       
   194             while (last > 0 && ns.charAt(last-1) == '/') last--;
       
   195             final String parent = ns.substring(0,last);
       
   196             if (nsTree.get(parent) == null)
       
   197                 nsTree.put(parent,new LinkedHashSet<String>());
       
   198             nsTree.get(parent).add(ns);
       
   199         }
       
   200         return nsTree;
       
   201     }
       
   202 
       
   203     private static class Rigolo {
       
   204         final static String[] ones = { "a", "e", "i", "o", "u", "y", "ai", "oo",
       
   205         "ae", "ey", "ay", "oy", "au", "ou", "eu", "oi", "ei", "ea"};
       
   206         final static String[] twos = { "b", "bz", "c", "cz", "ch",
       
   207         "ct", "ck", "cs", "d", "ds", "f",  "g", "gh", "h", "j", "k", "l", "m",
       
   208         "n", "p", "ps", "q", "r", "s", "sh", "t", "v", "w", "x",
       
   209         "z"};
       
   210         final static String[] threes = {"rr","tt","pp","ss","dd","ff","ll", "mm", "nn",
       
   211         "zz", "cc", "bb"};
       
   212         final static String[] fours = {"x", "s", "ght", "cks", "rt", "rts", "ghts", "bs",
       
   213           "ts", "gg" };
       
   214         final static String[] fives = { "br", "bl", "cr", "cn", "cth", "dr",
       
   215         "fr", "fl", "cl", "chr",  "gr", "gl", "kr", "kh", "pr", "pl", "ph",
       
   216         "rh", "sr", "tr", "vr"};
       
   217 
       
   218         private Random rg = new Random();
       
   219 
       
   220         private String next(String[] table) {
       
   221             return table[rg.nextInt(table.length)];
       
   222         }
       
   223 
       
   224         public String nextName(int max) {
       
   225             final Random rg = new Random();
       
   226             final int nl = 3 + rg.nextInt(max);
       
   227             boolean begin = rg.nextBoolean();
       
   228             StringBuilder sb = new StringBuilder();
       
   229             for (int j = 0; j < nl ; j++) {
       
   230                 if (begin) {
       
   231                     sb.append(next(ones));
       
   232                 } else if (j > 0 && j < nl-1 && rg.nextInt(4)==0) {
       
   233                     sb.append(next(threes));
       
   234                 } else if (j < nl-1 && rg.nextInt(3)==0) {
       
   235                     sb.append(next(fives));
       
   236                 } else {
       
   237                     sb.append(next(twos));
       
   238                 }
       
   239                 begin = !begin;
       
   240             }
       
   241             if (!begin && rg.nextInt(2)==0)
       
   242                 sb.append(next(fours));
       
   243             return sb.toString();
       
   244         }
       
   245 
       
   246         private ObjectName getWombatName(String ns, String domain, String name)
       
   247             throws MalformedObjectNameException {
       
   248             String d = domain;
       
   249             if (ns != null && !ns.equals(""))
       
   250                 d = ns + JMXNamespaces.NAMESPACE_SEPARATOR + domain;
       
   251             return new ObjectName(d+":type=Wombat,name="+name);
       
   252         }
       
   253 
       
   254         public Set<ObjectName> nextWombats(String ns)
       
   255             throws MalformedObjectNameException  {
       
   256             final int dcount = 1 + rg.nextInt(5);
       
   257             final Set<ObjectName> wombats = new HashSet<ObjectName>();
       
   258             for (int i = 0; i < dcount ; i++) {
       
   259                 final String d = nextName(7);
       
   260                 final int ncount = 5 + rg.nextInt(20);
       
   261                 for (int j = 0 ; j<ncount; j++) {
       
   262                     final String n = nextName(5);
       
   263                     wombats.add(getWombatName(ns,d,n));
       
   264                 }
       
   265             }
       
   266             return wombats;
       
   267         }
       
   268     }
       
   269 
       
   270     public static void checkNsQuery(MBeanServer server)
       
   271         throws Exception {
       
   272         final Map<String,Set<String>> nsTree = makeNsTree(namespaces);
       
   273         final Random rg = new Random();
       
   274         final Rigolo rigolo = new Rigolo();
       
   275         for (String ns : namespaces) {
       
   276             final ObjectName name = JMXNamespaces.getNamespaceObjectName(ns);
       
   277             final String[] doms =
       
   278                     (String[])server.getAttribute(name,"Domains");
       
   279             final Set<String> subs = new HashSet<String>();
       
   280             for (String d : doms) {
       
   281                 if (d.endsWith(JMXNamespaces.NAMESPACE_SEPARATOR)) {
       
   282                     subs.add(ns+JMXNamespaces.NAMESPACE_SEPARATOR+d.substring(0,
       
   283                             d.length()-JMXNamespaces.NAMESPACE_SEPARATOR.length()));
       
   284                 }
       
   285             }
       
   286 
       
   287             final Set<String> expectNs = new HashSet<String>(nsTree.get(ns));
       
   288 
       
   289             if (! subs.containsAll(expectNs))
       
   290                 throw new Exception("getDomains didn't return all namespaces: "+
       
   291                         "returned="+subs+", expected="+expectNs);
       
   292             if (! expectNs.containsAll(subs))
       
   293                 throw new Exception("getDomains returned additional namespaces: "+
       
   294                         "returned="+subs+", expected="+expectNs);
       
   295 
       
   296             final Set<ObjectName> nsNames = server.queryNames(
       
   297                     new ObjectName(ns+
       
   298                     JMXNamespaces.NAMESPACE_SEPARATOR+"*"+
       
   299                     JMXNamespaces.NAMESPACE_SEPARATOR+":*"),null);
       
   300 
       
   301             final Set<ObjectName> expect =
       
   302                     new HashSet<ObjectName>(expectNs.size());
       
   303             for (String sub : expectNs) {
       
   304                 expect.add(JMXNamespaces.getNamespaceObjectName(sub));
       
   305             }
       
   306 
       
   307             if (! nsNames.containsAll(expect))
       
   308                 throw new Exception("queryNames didn't return all namespaces: "+
       
   309                         "returned="+nsNames+", expected="+expect);
       
   310             if (! expect.containsAll(nsNames))
       
   311                 throw new Exception("getDomains returned additional namespaces: "+
       
   312                         "returned="+nsNames+", expected="+expect);
       
   313 
       
   314         }
       
   315     }
       
   316 
       
   317     private static void addWombats(MBeanServer server, Set<ObjectName> names)
       
   318         throws Exception {
       
   319         for (ObjectName on : names) {
       
   320             if (! server.isRegistered(on)) {
       
   321                 server.createMBean(Wombat.class.getName(),on);
       
   322                 System.out.println("A new wombat is born: "+on);
       
   323             }
       
   324         }
       
   325     }
       
   326 
       
   327     private static void addWombats(MBeanServer server,
       
   328              Map<String,Set<ObjectName>> wombats)
       
   329         throws Exception {
       
   330         for (String ns : wombats.keySet()) {
       
   331             addWombats(server,wombats.get(ns));
       
   332         }
       
   333     }
       
   334 
       
   335     private static Map<String,Set<ObjectName>> nameWombats()
       
   336         throws Exception {
       
   337         final Rigolo rigolo = new Rigolo();
       
   338         final Map<String,Set<ObjectName>> wombats =
       
   339                 new HashMap<String,Set<ObjectName>>(namespaces.length);
       
   340 
       
   341         for (String ns : namespaces) {
       
   342             wombats.put(ns,rigolo.nextWombats(ns));
       
   343         }
       
   344         wombats.put("",rigolo.nextWombats(""));
       
   345         return wombats;
       
   346     }
       
   347 
       
   348     private static boolean removeWombats(MBeanServer server,
       
   349             Map<String,Set<ObjectName>> wombats) {
       
   350         boolean res = true;
       
   351         for (String ns : wombats.keySet()) {
       
   352             res = res && removeWombats(server,wombats.get(ns));
       
   353         }
       
   354         return res;
       
   355     }
       
   356 
       
   357     private static boolean removeWombats(MBeanServer server,
       
   358             Set<ObjectName> wombats) {
       
   359         boolean res = true;
       
   360         for (ObjectName on : wombats) {
       
   361             try {
       
   362                 if (server.isRegistered(on))
       
   363                     server.unregisterMBean(on);
       
   364             } catch (Exception x) {
       
   365                 res = false;
       
   366                 System.out.println("Failed to remove "+on+": "+x);
       
   367             }
       
   368         }
       
   369         return res;
       
   370     }
       
   371 
       
   372     private static void checkNsPattern(MBeanServer server) throws Exception {
       
   373         final List<String> list = new ArrayList<String>();
       
   374         for (String s : namespaces) {
       
   375             final String[] cmpnt = s.split("//");
       
   376             for (int i=0;i<cmpnt.length;i++) {
       
   377                 final String[] clone = cmpnt.clone();
       
   378                 if (clone[i].length() < 3) {
       
   379                     clone[i] = "*";
       
   380                 } else {
       
   381                     clone[i] = "?"+cmpnt[i].substring(1, cmpnt[i].length()-2)+"*";
       
   382                 }
       
   383                 final StringBuilder sb = new StringBuilder();
       
   384                 for (int j=0;j<cmpnt.length;j++) {
       
   385                     sb.append(clone[j]).append("//");
       
   386                 }
       
   387                 list.add(sb.toString()+"*:*");
       
   388             }
       
   389         }
       
   390         for (String s : list) {
       
   391             final Set<ObjectName> res = new HashSet<ObjectName>();
       
   392 
       
   393             try {
       
   394                 res.addAll(server.queryNames(ObjectName.valueOf(s),null));
       
   395             } catch (RuntimeOperationsException x) {
       
   396                 if (x.getCause() instanceof IllegalArgumentException) {
       
   397                     System.out.println("queryNames("+s+"): OK - received "+x.getCause());
       
   398                     continue;
       
   399                 }
       
   400                 System.err.println("queryNames("+s+"): Bad cause: "+x.getCause());
       
   401                 throw x;
       
   402             } catch (Exception x) {
       
   403                 System.err.println("queryNames("+s+"): Bad exception: "+x);
       
   404                 throw x;
       
   405             }
       
   406             System.err.println("queryNames("+s+"): Bad result: "+res);
       
   407             System.err.println("queryNames("+s+"): Excpected exception not thrown.");
       
   408             throw new Exception("queryNames("+s+"): Excpected exception not thrown.");
       
   409         }
       
   410         for (String s : list) {
       
   411             final Set<ObjectInstance> res = new HashSet<ObjectInstance>();
       
   412 
       
   413             try {
       
   414                 res.addAll(server.queryMBeans(ObjectName.valueOf(s),null));
       
   415             } catch (RuntimeOperationsException x) {
       
   416                 if (x.getCause() instanceof IllegalArgumentException) {
       
   417                     System.out.println("queryMBeans("+s+"): OK - received "+x.getCause());
       
   418                     continue;
       
   419                 }
       
   420                 System.err.println("queryMBeans("+s+"): Bad cause: "+x.getCause());
       
   421                 throw x;
       
   422             } catch (Exception x) {
       
   423                 System.err.println("queryMBeans("+s+"): Bad exception: "+x);
       
   424                 throw x;
       
   425             }
       
   426             System.err.println("queryMBeans("+s+"): Bad result: "+res);
       
   427             System.err.println("queryMBeans("+s+"): Excpected exception not thrown.");
       
   428             throw new Exception("queryMBeans("+s+"): Excpected exception not thrown.");
       
   429         }
       
   430     }
       
   431 
       
   432     public static void main(String[] args)
       
   433         throws Exception {
       
   434         final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
       
   435         Map<String,Set<ObjectName>>  wombats = nameWombats();
       
   436         createNamespaces(server);
       
   437         try {
       
   438             addWombats(server,wombats);
       
   439             System.out.println("MBeans: " +server.getMBeanCount());
       
   440             System.out.println("Visible: " +server.queryNames(null,null).size());
       
   441             System.out.println("Domains: " +Arrays.asList(server.getDomains()));
       
   442             checkRegistration(server);
       
   443             checkNsQuery(server);
       
   444             checkNsPattern(server);
       
   445         } finally {
       
   446             boolean res = true;
       
   447             res = res && removeWombats(server, wombats);
       
   448             if (!res)
       
   449                 throw new RuntimeException("failed to cleanup some namespaces");
       
   450         }
       
   451 
       
   452     }
       
   453 
       
   454     private static boolean removeNamespaces(MBeanServer server) {
       
   455         final List<String> l = Arrays.asList(namespaces);
       
   456         Collections.reverse(l);
       
   457         return removeNamespaces(server, l.toArray(new String[namespaces.length]));
       
   458     }
       
   459 
       
   460     private static boolean removeNamespaces(MBeanServer server, String[] t) {
       
   461         boolean success = true;
       
   462         for (String ns : t) {
       
   463             try {
       
   464                 server.unregisterMBean(JMXNamespaces.getNamespaceObjectName(ns));
       
   465             } catch (Exception x) {
       
   466                 System.out.println("failed to remove namespace: "+ ns);
       
   467                 success = false;
       
   468             }
       
   469         }
       
   470         return success;
       
   471     }
       
   472 
       
   473 }