/* |
|
* Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. |
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
* |
|
* This code is free software; you can redistribute it and/or modify it |
|
* under the terms of the GNU General Public License version 2 only, as |
|
* published by the Free Software Foundation. Oracle designates this |
|
* particular file as subject to the "Classpath" exception as provided |
|
* by Oracle in the LICENSE file that accompanied this code. |
|
* |
|
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
* version 2 for more details (a copy is included in the LICENSE file that |
|
* accompanied this code). |
|
* |
|
* You should have received a copy of the GNU General Public License version |
|
* 2 along with this work; if not, write to the Free Software Foundation, |
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
* |
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
* or visit www.oracle.com if you need additional information or have any |
|
* questions. |
|
*/ |
|
package com.sun.jmx.mbeanserver; |
|
import java.util.ArrayList; |
|
import java.util.Arrays; |
|
import java.util.Collection; |
|
import java.util.Collections; |
|
import java.util.Comparator; |
|
import java.util.HashMap; |
|
import java.util.HashSet; |
|
import java.util.IdentityHashMap; |
|
import java.util.LinkedHashMap; |
|
import java.util.List; |
|
import java.util.Map; |
|
import java.util.Set; |
|
import java.util.SortedMap; |
|
import java.util.TreeMap; |
|
import javax.management.MalformedObjectNameException; |
|
import javax.management.ObjectName; |
|
public class Util { |
|
public static ObjectName newObjectName(String string) { |
|
try { |
|
return new ObjectName(string); |
|
} catch (MalformedObjectNameException e) { |
|
throw new IllegalArgumentException(e); |
|
} |
|
} |
|
static <K, V> Map<K, V> newMap() { |
|
return new HashMap<K, V>(); |
|
} |
|
static <K, V> Map<K, V> newSynchronizedMap() { |
|
return Collections.synchronizedMap(Util.<K, V>newMap()); |
|
} |
|
static <K, V> IdentityHashMap<K, V> newIdentityHashMap() { |
|
return new IdentityHashMap<K, V>(); |
|
} |
|
static <K, V> Map<K, V> newSynchronizedIdentityHashMap() { |
|
Map<K, V> map = newIdentityHashMap(); |
|
return Collections.synchronizedMap(map); |
|
} |
|
static <K, V> SortedMap<K, V> newSortedMap() { |
|
return new TreeMap<K, V>(); |
|
} |
|
static <K, V> SortedMap<K, V> newSortedMap(Comparator<? super K> comp) { |
|
return new TreeMap<K, V>(comp); |
|
} |
|
static <K, V> Map<K, V> newInsertionOrderMap() { |
|
return new LinkedHashMap<K, V>(); |
|
} |
|
static <E> Set<E> newSet() { |
|
return new HashSet<E>(); |
|
} |
|
static <E> Set<E> newSet(Collection<E> c) { |
|
return new HashSet<E>(c); |
|
} |
|
static <E> List<E> newList() { |
|
return new ArrayList<E>(); |
|
} |
|
static <E> List<E> newList(Collection<E> c) { |
|
return new ArrayList<E>(c); |
|
} |
|
/* This method can be used by code that is deliberately violating the |
|
* allowed checked casts. Rather than marking the whole method containing |
|
* the code with @SuppressWarnings, you can use a call to this method for |
|
* the exact place where you need to escape the constraints. Typically |
|
* you will "import static" this method and then write either |
|
* X x = cast(y); |
|
* or, if that doesn't work (e.g. X is a type variable) |
|
* Util.<X>cast(y); |
|
*/ |
|
@SuppressWarnings("unchecked") |
|
public static <T> T cast(Object x) { |
|
return (T) x; |
|
} |
|
/** |
|
* Computes a descriptor hashcode from its names and values. |
|
* @param names the sorted array of descriptor names. |
|
* @param values the array of descriptor values. |
|
* @return a hash code value, as described in {@link #hashCode(Descriptor)} |
|
*/ |
|
public static int hashCode(String[] names, Object[] values) { |
|
int hash = 0; |
|
for (int i = 0; i < names.length; i++) { |
|
Object v = values[i]; |
|
int h; |
|
if (v == null) { |
|
h = 0; |
|
} else if (v instanceof Object[]) { |
|
h = Arrays.deepHashCode((Object[]) v); |
|
} else if (v.getClass().isArray()) { |
|
h = Arrays.deepHashCode(new Object[]{v}) - 31; |
|
// hashcode of a list containing just v is |
|
// v.hashCode() + 31, see List.hashCode() |
|
} else { |
|
h = v.hashCode(); |
|
} |
|
hash += names[i].toLowerCase().hashCode() ^ h; |
|
} |
|
return hash; |
|
} |
|
/** Match a part of a string against a shell-style pattern. |
|
The only pattern characters recognized are <code>?</code>, |
|
standing for any one character, |
|
and <code>*</code>, standing for any string of |
|
characters, including the empty string. For instance, |
|
{@code wildmatch("sandwich","sa?d*ch",1,4,1,4)} will match |
|
{@code "and"} against {@code "a?d"}. |
|
@param str the string containing the sequence to match. |
|
@param pat a string containing a pattern to match the sub string |
|
against. |
|
@param stri the index in the string at which matching should begin. |
|
@param strend the index in the string at which the matching should |
|
end. |
|
@param pati the index in the pattern at which matching should begin. |
|
@param patend the index in the pattern at which the matching should |
|
end. |
|
@return true if and only if the string matches the pattern. |
|
*/ |
|
/* The algorithm is a classical one. We advance pointers in |
|
parallel through str and pat. If we encounter a star in pat, |
|
we remember its position and continue advancing. If at any |
|
stage we get a mismatch between str and pat, we look to see if |
|
there is a remembered star. If not, we fail. If so, we |
|
retreat pat to just past that star and str to the position |
|
after the last one we tried, and we let the match advance |
|
again. |
|
|
|
Even though there is only one remembered star position, the |
|
algorithm works when there are several stars in the pattern. |
|
When we encounter the second star, we forget the first one. |
|
This is OK, because if we get to the second star in A*B*C |
|
(where A etc are arbitrary strings), we have already seen AXB. |
|
We're therefore setting up a match of *C against the remainder |
|
of the string, which will match if that remainder looks like |
|
YC, so the whole string looks like AXBYC. |
|
*/ |
|
private static boolean wildmatch(final String str, final String pat, |
|
int stri, final int strend, int pati, final int patend) { |
|
// System.out.println("matching "+pat.substring(pati,patend)+ |
|
// " against "+str.substring(stri, strend)); |
|
int starstri; // index for backtrack if "*" attempt fails |
|
int starpati; // index for backtrack if "*" attempt fails, +1 |
|
starstri = starpati = -1; |
|
/* On each pass through this loop, we either advance pati, |
|
or we backtrack pati and advance starstri. Since starstri |
|
is only ever assigned from pati, the loop must terminate. */ |
|
while (true) { |
|
if (pati < patend) { |
|
final char patc = pat.charAt(pati); |
|
switch (patc) { |
|
case '?': |
|
if (stri == strend) |
|
break; |
|
stri++; |
|
pati++; |
|
continue; |
|
case '*': |
|
pati++; |
|
starpati = pati; |
|
starstri = stri; |
|
continue; |
|
default: |
|
if (stri < strend && str.charAt(stri) == patc) { |
|
stri++; |
|
pati++; |
|
continue; |
|
} |
|
break; |
|
} |
|
} else if (stri == strend) |
|
return true; |
|
// Mismatched, can we backtrack to a "*"? |
|
if (starpati < 0 || starstri == strend) |
|
return false; |
|
// Retry the match one position later in str |
|
pati = starpati; |
|
starstri++; |
|
stri = starstri; |
|
} |
|
} |
|
/** Match a string against a shell-style pattern. The only pattern |
|
characters recognized are <code>?</code>, standing for any one |
|
character, and <code>*</code>, standing for any string of |
|
characters, including the empty string. |
|
|
|
@param str the string to match. |
|
@param pat the pattern to match the string against. |
|
|
|
@return true if and only if the string matches the pattern. |
|
*/ |
|
public static boolean wildmatch(String str, String pat) { |
|
return wildmatch(str,pat,0,str.length(),0,pat.length()); |
|
} |
|
} |