jdk/src/share/classes/com/sun/jmx/mbeanserver/Util.java
changeset 1156 bbc2d15aaf7a
parent 1004 5ba8217eb504
child 1222 78e3d021d528
equal deleted inserted replaced
1155:a9a142fcf1b5 1156:bbc2d15aaf7a
    23  * have any questions.
    23  * have any questions.
    24  */
    24  */
    25 
    25 
    26 package com.sun.jmx.mbeanserver;
    26 package com.sun.jmx.mbeanserver;
    27 
    27 
       
    28 import com.sun.jmx.defaults.JmxProperties;
       
    29 import java.io.IOException;
    28 import java.util.ArrayList;
    30 import java.util.ArrayList;
    29 import java.util.Arrays;
    31 import java.util.Arrays;
    30 import java.util.Collection;
    32 import java.util.Collection;
    31 import java.util.Collections;
    33 import java.util.Collections;
    32 import java.util.Comparator;
    34 import java.util.Comparator;
    40 import java.util.SortedMap;
    42 import java.util.SortedMap;
    41 import java.util.SortedSet;
    43 import java.util.SortedSet;
    42 import java.util.TreeMap;
    44 import java.util.TreeMap;
    43 import java.util.TreeSet;
    45 import java.util.TreeSet;
    44 import java.util.WeakHashMap;
    46 import java.util.WeakHashMap;
       
    47 import java.util.logging.Level;
       
    48 import javax.management.MBeanServer;
       
    49 import javax.management.MBeanServerDelegate;
       
    50 import javax.management.MBeanServerFactory;
    45 import javax.management.MalformedObjectNameException;
    51 import javax.management.MalformedObjectNameException;
       
    52 import javax.management.ObjectInstance;
    46 import javax.management.ObjectName;
    53 import javax.management.ObjectName;
    47 import javax.management.loading.ClassLoaderRepository;
    54 import javax.management.loading.ClassLoaderRepository;
       
    55 import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR;
    48 
    56 
    49 public class Util {
    57 public class Util {
       
    58     private final static int NAMESPACE_SEPARATOR_LENGTH =
       
    59             NAMESPACE_SEPARATOR.length();
       
    60     public final static String ILLEGAL_MBEANSERVER_NAME_CHARS=";:*?";
       
    61 
       
    62 
    50     static <K, V> Map<K, V> newMap() {
    63     static <K, V> Map<K, V> newMap() {
    51         return new HashMap<K, V>();
    64         return new HashMap<K, V>();
    52     }
    65     }
    53 
    66 
    54     static <K, V> Map<K, V> newSynchronizedMap() {
    67     static <K, V> Map<K, V> newSynchronizedMap() {
   143             hash += names[i].toLowerCase().hashCode() ^ h;
   156             hash += names[i].toLowerCase().hashCode() ^ h;
   144         }
   157         }
   145         return hash;
   158         return hash;
   146     }
   159     }
   147 
   160 
       
   161     /** Match a part of a string against a shell-style pattern.
       
   162         The only pattern characters recognized are <code>?</code>,
       
   163         standing for any one character,
       
   164         and <code>*</code>, standing for any string of
       
   165         characters, including the empty string. For instance,
       
   166         {@code wildmatch("sandwich","sa?d*ch",1,4,1,4)} will match
       
   167         {@code "and"} against {@code "a?d"}.
       
   168 
       
   169         @param str  the string containing the sequence to match.
       
   170         @param pat  a string containing a pattern to match the sub string
       
   171                     against.
       
   172         @param stri   the index in the string at which matching should begin.
       
   173         @param strend the index in the string at which the matching should
       
   174                       end.
       
   175         @param pati   the index in the pattern at which matching should begin.
       
   176         @param patend the index in the pattern at which the matching should
       
   177                       end.
       
   178 
       
   179         @return true if and only if the string matches the pattern.
       
   180     */
       
   181     /* The algorithm is a classical one.  We advance pointers in
       
   182        parallel through str and pat.  If we encounter a star in pat,
       
   183        we remember its position and continue advancing.  If at any
       
   184        stage we get a mismatch between str and pat, we look to see if
       
   185        there is a remembered star.  If not, we fail.  If so, we
       
   186        retreat pat to just past that star and str to the position
       
   187        after the last one we tried, and we let the match advance
       
   188        again.
       
   189 
       
   190        Even though there is only one remembered star position, the
       
   191        algorithm works when there are several stars in the pattern.
       
   192        When we encounter the second star, we forget the first one.
       
   193        This is OK, because if we get to the second star in A*B*C
       
   194        (where A etc are arbitrary strings), we have already seen AXB.
       
   195        We're therefore setting up a match of *C against the remainder
       
   196        of the string, which will match if that remainder looks like
       
   197        YC, so the whole string looks like AXBYC.
       
   198     */
       
   199     private static boolean wildmatch(final String str, final String pat,
       
   200             int stri, final int strend, int pati, final int patend) {
       
   201 
       
   202         // System.out.println("matching "+pat.substring(pati,patend)+
       
   203         //        " against "+str.substring(stri, strend));
       
   204         int starstri; // index for backtrack if "*" attempt fails
       
   205         int starpati; // index for backtrack if "*" attempt fails, +1
       
   206 
       
   207         starstri = starpati = -1;
       
   208 
       
   209         /* On each pass through this loop, we either advance pati,
       
   210            or we backtrack pati and advance starstri.  Since starstri
       
   211            is only ever assigned from pati, the loop must terminate.  */
       
   212         while (true) {
       
   213             if (pati < patend) {
       
   214                 final char patc = pat.charAt(pati);
       
   215                 switch (patc) {
       
   216                 case '?':
       
   217                     if (stri == strend)
       
   218                         break;
       
   219                     stri++;
       
   220                     pati++;
       
   221                     continue;
       
   222                 case '*':
       
   223                     pati++;
       
   224                     starpati = pati;
       
   225                     starstri = stri;
       
   226                     continue;
       
   227                 default:
       
   228                     if (stri < strend && str.charAt(stri) == patc) {
       
   229                         stri++;
       
   230                         pati++;
       
   231                         continue;
       
   232                     }
       
   233                     break;
       
   234                 }
       
   235             } else if (stri == strend)
       
   236                 return true;
       
   237 
       
   238             // Mismatched, can we backtrack to a "*"?
       
   239             if (starpati < 0 || starstri == strend)
       
   240                 return false;
       
   241 
       
   242             // Retry the match one position later in str
       
   243             pati = starpati;
       
   244             starstri++;
       
   245             stri = starstri;
       
   246         }
       
   247     }
       
   248 
       
   249     /** Match a string against a shell-style pattern.  The only pattern
       
   250         characters recognized are <code>?</code>, standing for any one
       
   251         character, and <code>*</code>, standing for any string of
       
   252         characters, including the empty string.
       
   253 
       
   254         @param str the string to match.
       
   255         @param pat the pattern to match the string against.
       
   256 
       
   257         @return true if and only if the string matches the pattern.
       
   258     */
       
   259     public static boolean wildmatch(String str, String pat) {
       
   260         return wildmatch(str,pat,0,str.length(),0,pat.length());
       
   261     }
       
   262 
       
   263     /**
       
   264      * Matches a string against a pattern, as a name space path.
       
   265      * This is a special matching where * and ?? don't match //.
       
   266      * The string is split in sub-strings separated by //, and the
       
   267      * pattern is split in sub-patterns separated by //. Each sub-string
       
   268      * is matched against its corresponding sub-pattern.
       
   269      * so <elt-1>//<elt2>//...//<elt-n> matches <pat-1>//<pat-2>//...//<pat-q>
       
   270      * only if n==q and for ( i = 1 => n) elt-i matches pat-i.
       
   271      *
       
   272      * In addition, if we encounter a pattern element which is exactly
       
   273      * **, it can match any number of path-elements - but it must match at
       
   274      * least one element.
       
   275      * When we encounter such a meta-wildcard, we remember its position
       
   276      * and the position in the string path, and we advance both the pattern
       
   277      * and the string. Later, if we encounter a mismatch in pattern & string,
       
   278      * we rewind the position in pattern to just after the meta-wildcard,
       
   279      * and we backtrack the string to i+1 element after the position
       
   280      * we had when we first encountered the meta-wildcard, i being the
       
   281      * position when we last backtracked the string.
       
   282      *
       
   283      * The backtracking logic is an adaptation of the logic in wildmatch
       
   284      * above.
       
   285      * See test/javax/mangement/ObjectName/ApplyWildcardTest.java
       
   286      *
       
   287      * Note: this thing is called 'wild' - and that's for a reason ;-)
       
   288      **/
       
   289     public static boolean wildpathmatch(String str, String pat) {
       
   290         final int strlen = str.length();
       
   291         final int patlen = pat.length();
       
   292         int stri = 0;
       
   293         int pati = 0;
       
   294 
       
   295         int starstri; // index for backtrack if "**" attempt fails
       
   296         int starpati; // index for backtrack if "**" attempt fails
       
   297 
       
   298         starstri = starpati = -1;
       
   299 
       
   300         while (true) {
       
   301             // System.out.println("pati="+pati+", stri="+stri);
       
   302             final int strend = str.indexOf(NAMESPACE_SEPARATOR, stri);
       
   303             final int patend = pat.indexOf(NAMESPACE_SEPARATOR, pati);
       
   304 
       
   305             // no // remaining in either string or pattern: simple wildmatch
       
   306             // until end of string.
       
   307             if (strend == -1 && patend == -1) {
       
   308                 // System.out.println("last sub pattern, last sub element...");
       
   309                 // System.out.println("wildmatch("+str.substring(stri,strlen)+
       
   310                 //    ","+pat.substring(pati,patlen)+")");
       
   311                 return wildmatch(str,pat,stri,strlen,pati,patlen);
       
   312             }
       
   313 
       
   314             // no // remaining in string, but at least one remaining in
       
   315             // pattern
       
   316             // => no match
       
   317             if (strend == -1) {
       
   318                 // System.out.println("pattern has more // than string...");
       
   319                 return false;
       
   320             }
       
   321 
       
   322             // strend is != -1, but patend might.
       
   323             // detect wildcard **
       
   324             if (patend == pati+2 && pat.charAt(pati)=='*' &&
       
   325                     pat.charAt(pati+1)=='*') {
       
   326                 // if we reach here we know that neither strend nor patend are
       
   327                 // equals to -1.
       
   328                 stri     = strend + NAMESPACE_SEPARATOR_LENGTH;
       
   329                 pati     = patend + NAMESPACE_SEPARATOR_LENGTH;
       
   330                 starpati = pati; // position just after **// in pattern
       
   331                 starstri = stri; // we eat 1 element in string, and remember
       
   332                                  // the position for backtracking and eating
       
   333                                  // one more element if needed.
       
   334                 // System.out.println("starpati="+pati);
       
   335                 continue;
       
   336             }
       
   337 
       
   338             // This is a bit hacky: * can match // when // is at the end
       
   339             // of the string, so we include the // delimiter in the pattern
       
   340             // matching. Either we're in the middle of the path, so including
       
   341             // // both at the end of the pattern and at the end of the string
       
   342             // has no effect - match(*//,dfsd//) is equivalent to match(*,dfsd)
       
   343             // or we're at the end of the pattern path, in which case
       
   344             // including // at the end of the string will have the desired
       
   345             // effect (provided that we detect the end of matching correctly,
       
   346             // see further on).
       
   347             //
       
   348             final int endpat =
       
   349                     ((patend > -1)?patend+NAMESPACE_SEPARATOR_LENGTH:patlen);
       
   350             final int endstr =
       
   351                     ((strend > -1)?strend+NAMESPACE_SEPARATOR_LENGTH:strlen);
       
   352 
       
   353             // if we reach the end of the pattern, or if elt-i & pat-i
       
   354             // don't match, we have a mismatch.
       
   355 
       
   356             // Note: we know that strend != -1, therefore patend==-1
       
   357             //       indicates a mismatch unless pattern can match
       
   358             //       a // at the end, and strend+2=strlen.
       
   359             // System.out.println("wildmatch("+str.substring(stri,endstr)+","+
       
   360             //        pat.substring(pati,endpat)+")");
       
   361             if (!wildmatch(str,pat,stri,endstr,pati,endpat)) {
       
   362 
       
   363                 // System.out.println("nomatch");
       
   364                 // if we have a mismatch and didn't encounter any meta-wildcard,
       
   365                 // we return false. String & pattern don't match.
       
   366                 if (starpati < 0) return false;
       
   367 
       
   368                 // If we reach here, we had a meta-wildcard.
       
   369                 // We need to backtrack to the wildcard, and make it eat an
       
   370                 // additional string element.
       
   371                 //
       
   372                 stri = str.indexOf(NAMESPACE_SEPARATOR, starstri);
       
   373                 // System.out.println("eating one additional element? "+stri);
       
   374 
       
   375                 // If there's no more elements to eat, string and pattern
       
   376                 // don't match => return false.
       
   377                 if (stri == -1) return false;
       
   378 
       
   379                 // Backtrack to where we were when we last matched against
       
   380                 // the meta-wildcard, make it eat an additional path element,
       
   381                 // remember the new positions, and continue from there...
       
   382                 //
       
   383                 stri = stri + NAMESPACE_SEPARATOR_LENGTH;
       
   384                 starstri = stri;
       
   385                 pati = starpati;
       
   386                 // System.out.println("skiping to stri="+stri);
       
   387                 continue;
       
   388             }
       
   389 
       
   390             // Here we know that strend > -1 but we can have patend == -1.
       
   391             //
       
   392             // So if we reach here, we know pat-i+//? has matched
       
   393             // elt-i+//
       
   394             //
       
   395             // If patend==-1, we know that there was no delimiter
       
   396             // at the end of the pattern, that we are at the last pattern,
       
   397             // and therefore that pat-i has matched elt-i+//
       
   398             //
       
   399             // In that case we can consider that we have a match only if
       
   400             // elt-i is also the last path element in the string, which is
       
   401             // equivalent to saying that strend+2==strlen.
       
   402             //
       
   403             if (patend == -1 && starpati == -1)
       
   404                 return (strend+NAMESPACE_SEPARATOR_LENGTH==strlen);
       
   405 
       
   406             // patend != -1, or starpati > -1 so there remains something
       
   407             // to match.
       
   408 
       
   409             // go to next pair: elt-(i+1) pat-(i+1);
       
   410             stri = strend + NAMESPACE_SEPARATOR_LENGTH;
       
   411             pati = (patend==-1)?pati:(patend + NAMESPACE_SEPARATOR_LENGTH);
       
   412         }
       
   413     }
       
   414 
       
   415     /**
       
   416      * Returns true if the ObjectName's {@code domain} is selected by the
       
   417      * given {@code pattern}.
       
   418      */
       
   419     public static boolean isDomainSelected(String domain, String pattern) {
       
   420         if  (domain == null || pattern == null)
       
   421             throw new IllegalArgumentException("null");
       
   422         return Util.wildpathmatch(domain,pattern);
       
   423     }
       
   424 
   148     /**
   425     /**
   149      * Filters a set of ObjectName according to a given pattern.
   426      * Filters a set of ObjectName according to a given pattern.
   150      *
   427      *
   151      * @param pattern the pattern that the returned names must match.
   428      * @param pattern the pattern that the returned names must match.
   152      * @param all     the set of names to filter.
   429      * @param all     the set of names to filter.
   165         final Set<ObjectName> res = equivalentEmptySet(all);
   442         final Set<ObjectName> res = equivalentEmptySet(all);
   166         for (ObjectName n : all) if (pattern.apply(n)) res.add(n);
   443         for (ObjectName n : all) if (pattern.apply(n)) res.add(n);
   167         return res;
   444         return res;
   168     }
   445     }
   169 
   446 
       
   447 
       
   448     /**
       
   449      * Filters a set of ObjectInstance according to a given pattern.
       
   450      *
       
   451      * @param pattern the pattern that the returned names must match.
       
   452      * @param all     the set of instances to filter.
       
   453      * @return a set of ObjectInstance from which non matching instances
       
   454      *         have been removed.
       
   455      */
       
   456     public static Set<ObjectInstance>
       
   457             filterMatchingInstances(ObjectName pattern,
       
   458                                         Set<ObjectInstance> all) {
       
   459         // If no pattern, just return all names
       
   460         if (pattern == null
       
   461                 || all.isEmpty()
       
   462                 || ObjectName.WILDCARD.equals(pattern))
       
   463             return all;
       
   464 
       
   465         // If there's a pattern, do the matching.
       
   466         final Set<ObjectInstance> res = equivalentEmptySet(all);
       
   467         for (ObjectInstance n : all) {
       
   468             if (n == null) continue;
       
   469             if (pattern.apply(n.getObjectName()))
       
   470                 res.add(n);
       
   471         }
       
   472         return res;
       
   473     }
       
   474 
   170     /**
   475     /**
   171      * An abstract ClassLoaderRepository that contains a single class loader.
   476      * An abstract ClassLoaderRepository that contains a single class loader.
   172      **/
   477      **/
   173     private final static class SingleClassLoaderRepository
   478     private final static class SingleClassLoaderRepository
   174             implements ClassLoaderRepository {
   479             implements ClassLoaderRepository {
   212      * @return a ClassLoaderRepository that contains the single loader.
   517      * @return a ClassLoaderRepository that contains the single loader.
   213      */
   518      */
   214     public static ClassLoaderRepository getSingleClassLoaderRepository(
   519     public static ClassLoaderRepository getSingleClassLoaderRepository(
   215             final ClassLoader loader) {
   520             final ClassLoader loader) {
   216         return new SingleClassLoaderRepository(loader);
   521         return new SingleClassLoaderRepository(loader);
       
   522     }
       
   523 
       
   524     /**
       
   525      * Returns the name of the given MBeanServer that should be put in a
       
   526      * permission you need.
       
   527      * This corresponds to the
       
   528      * {@code *[;mbeanServerName=<mbeanServerName>[;*]]} property
       
   529      * embedded in the MBeanServerId attribute of the
       
   530      * server's {@link MBeanServerDelegate}.
       
   531      *
       
   532      * @param server The MBean server
       
   533      * @return the name of the MBeanServer, or "*" if the name couldn't be
       
   534      *         obtained, or {@value MBeanServerFactory#DEFAULT_MBEANSERVER_NAME}
       
   535      *         if there was no name.
       
   536      */
       
   537     public static String getMBeanServerSecurityName(MBeanServer server) {
       
   538         final String notfound = "*";
       
   539         try {
       
   540             final String mbeanServerId = (String)
       
   541                     server.getAttribute(MBeanServerDelegate.DELEGATE_NAME,
       
   542                     "MBeanServerId");
       
   543             final String found = extractMBeanServerName(mbeanServerId);
       
   544             if (found.length()==0)
       
   545                 return MBeanServerFactory.DEFAULT_MBEANSERVER_NAME;
       
   546             return found;
       
   547         } catch (Exception x) {
       
   548             logshort("Failed to retrieve MBeanServerName for server, " +
       
   549                     "using \"*\"",x);
       
   550             return notfound;
       
   551         }
       
   552     }
       
   553 
       
   554     /**
       
   555      * Returns the name of the MBeanServer embedded in the given
       
   556      * mbeanServerId. If the given mbeanServerId doesn't contain any name,
       
   557      * an empty String is returned.
       
   558      * The MBeanServerId is expected to be of the form:
       
   559      * {@code *[;mbeanServerName=<mbeanServerName>[;*]]}
       
   560      * @param mbeanServerId The MBean server ID
       
   561      * @return the name of the MBeanServer if found, or "" if the name was
       
   562      *         not present in the mbeanServerId.
       
   563      */
       
   564     public static String extractMBeanServerName(String mbeanServerId) {
       
   565         if (mbeanServerId==null) return "";
       
   566         final String beginMarker=";mbeanServerName=";
       
   567         final String endMarker=";";
       
   568         final int found = mbeanServerId.indexOf(beginMarker);
       
   569         if (found < 0) return "";
       
   570         final int start = found + beginMarker.length();
       
   571         final int stop = mbeanServerId.indexOf(endMarker, start);
       
   572         return mbeanServerId.substring(start,
       
   573                 (stop < 0 ? mbeanServerId.length() : stop));
       
   574     }
       
   575 
       
   576     /**
       
   577      * Insert the given mbeanServerName into the given mbeanServerId.
       
   578      * If mbeanServerName is null, empty, or equals to "-", the returned
       
   579      * mbeanServerId will not contain any mbeanServerName.
       
   580      * @param mbeanServerId    The mbeanServerId in which to insert
       
   581      *                         mbeanServerName
       
   582      * @param mbeanServerName  The mbeanServerName
       
   583      * @return an mbeanServerId containing the given mbeanServerName
       
   584      * @throws IllegalArgumentException if mbeanServerId already contains
       
   585      *         a different name, or if the given mbeanServerName is not valid.
       
   586      */
       
   587     public static String insertMBeanServerName(String mbeanServerId,
       
   588             String mbeanServerName) {
       
   589         final String found = extractMBeanServerName(mbeanServerId);
       
   590         if (found.length() > 0 &&
       
   591                 found.equals(checkServerName(mbeanServerName)))
       
   592             return mbeanServerId;
       
   593         if (found.length() > 0 && !isMBeanServerNameUndefined(found))
       
   594             throw new IllegalArgumentException(
       
   595                     "MBeanServerName already defined");
       
   596         if (isMBeanServerNameUndefined(mbeanServerName))
       
   597             return mbeanServerId;
       
   598         final String beginMarker=";mbeanServerName=";
       
   599         return mbeanServerId+beginMarker+checkServerName(mbeanServerName);
       
   600     }
       
   601 
       
   602     /**
       
   603      * Returns true if the given mbeanServerName corresponds to an
       
   604      * undefined MBeanServerName.
       
   605      * The mbeanServerName is considered undefined if it is one of:
       
   606      * {@code null} or {@value MBeanServerFactory#DEFAULT_MBEANSERVER_NAME}.
       
   607      * @param mbeanServerName The mbeanServerName, as returned by
       
   608      *        {@link #extractMBeanServerName(String)}.
       
   609      * @return true if the given name corresponds to one of the forms that
       
   610      *         denotes an undefined MBeanServerName.
       
   611      */
       
   612     public static boolean isMBeanServerNameUndefined(String mbeanServerName) {
       
   613         return mbeanServerName == null ||
       
   614            MBeanServerFactory.DEFAULT_MBEANSERVER_NAME.equals(mbeanServerName);
       
   615     }
       
   616     /**
       
   617      * Check that the provided mbeanServername is syntactically valid.
       
   618      * @param mbeanServerName An mbeanServerName, or {@code null}.
       
   619      * @return mbeanServerName, or {@value
       
   620      * MBeanServerFactory#DEFAULT_MBEANSERVER_NAME} if {@code mbeanServerName}
       
   621      * is {@code null}.
       
   622      * @throws IllegalArgumentException if mbeanServerName contains illegal
       
   623      *         characters, or is empty, or is {@code "-"}.
       
   624      *         Illegal characters are {@value #ILLEGAL_MBEANSERVER_NAME_CHARS}.
       
   625      */
       
   626     public static String checkServerName(String mbeanServerName) {
       
   627         if ("".equals(mbeanServerName))
       
   628             throw new IllegalArgumentException(
       
   629                     "\"\" is not a valid MBean server name");
       
   630         if ("-".equals(mbeanServerName))
       
   631             throw new IllegalArgumentException(
       
   632                     "\"-\" is not a valid MBean server name");
       
   633         if (isMBeanServerNameUndefined(mbeanServerName))
       
   634             return MBeanServerFactory.DEFAULT_MBEANSERVER_NAME;
       
   635         for (char c : ILLEGAL_MBEANSERVER_NAME_CHARS.toCharArray()) {
       
   636             if (mbeanServerName.indexOf(c) >= 0)
       
   637                 throw new IllegalArgumentException(
       
   638                         "invalid character in MBeanServer name: "+c);
       
   639         }
       
   640         return mbeanServerName;
       
   641     }
       
   642 
       
   643     /**
       
   644      * Get the MBeanServer name that should be put in a permission you need.
       
   645      *
       
   646      * @param delegate The MBeanServerDelegate
       
   647      * @return The MBeanServer name - or {@value
       
   648      * MBeanServerFactory#DEFAULT_MBEANSERVER_NAME} if there was no name.
       
   649      */
       
   650     public static String getMBeanServerSecurityName(
       
   651             MBeanServerDelegate delegate) {
       
   652         try {
       
   653             final String serverName = delegate.getMBeanServerName();
       
   654             if (isMBeanServerNameUndefined(serverName))
       
   655                 return MBeanServerFactory.DEFAULT_MBEANSERVER_NAME;
       
   656             return serverName;
       
   657         } catch (Exception x) {
       
   658             logshort("Failed to retrieve MBeanServerName from delegate, " +
       
   659                     "using \"*\"",x);
       
   660             return "*";
       
   661         }
       
   662     }
       
   663 
       
   664     // Log the exception and its causes without logging the stack trace.
       
   665     // Use with care - it is usally preferable to log the whole stack trace!
       
   666     // We don't want to log the whole stack trace here: logshort() is
       
   667     // called in those cases where the exception might not be abnormal.
       
   668     private static void logshort(String msg, Throwable t) {
       
   669         if (JmxProperties.MISC_LOGGER.isLoggable(Level.FINE)) {
       
   670             StringBuilder toprint = new StringBuilder(msg);
       
   671                toprint.append("\nCaused By: ").append(String.valueOf(t));
       
   672             while ((t=t.getCause())!=null)
       
   673                toprint.append("\nCaused By: ").append(String.valueOf(t));
       
   674             JmxProperties.MISC_LOGGER.fine(toprint.toString());
       
   675        }
   217     }
   676     }
   218 
   677 
   219     public static <T> Set<T> cloneSet(Set<T> set) {
   678     public static <T> Set<T> cloneSet(Set<T> set) {
   220         if (set instanceof SortedSet) {
   679         if (set instanceof SortedSet) {
   221             @SuppressWarnings("unchecked")
   680             @SuppressWarnings("unchecked")
   230     public static <T> Set<T> equivalentEmptySet(Set<T> set) {
   689     public static <T> Set<T> equivalentEmptySet(Set<T> set) {
   231         if (set instanceof SortedSet) {
   690         if (set instanceof SortedSet) {
   232             @SuppressWarnings("unchecked")
   691             @SuppressWarnings("unchecked")
   233             SortedSet<T> sset = (SortedSet<T>) set;
   692             SortedSet<T> sset = (SortedSet<T>) set;
   234             set = new TreeSet<T>(sset.comparator());
   693             set = new TreeSet<T>(sset.comparator());
   235         } else if (set != null) {
       
   236             set = new HashSet<T>(set.size());
       
   237         } else
   694         } else
   238             set = new HashSet<T>();
   695             set = new HashSet<T>();
   239         return set;
   696         return set;
   240     }
   697     }
       
   698 
       
   699     // This exception is used when wrapping a class that throws IOException
       
   700     // in a class that doesn't.
       
   701     // The typical example for this are JMXNamespaces, when the sub
       
   702     // MBeanServer can be remote.
       
   703     //
       
   704     public static RuntimeException newRuntimeIOException(IOException io) {
       
   705         final String msg = "Communication failed with underlying resource: "+
       
   706                 io.getMessage();
       
   707         return new RuntimeException(msg,io);
       
   708     }
   241 }
   709 }