/*
* Copyright (c) 1999, 2013, 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 javax.management;
import com.sun.jmx.mbeanserver.GetPropertyAction;
import com.sun.jmx.mbeanserver.Util;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.security.AccessController;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
Represents the object name of an MBean, or a pattern that can
match the names of several MBeans. Instances of this class are
immutable.
An instance of this class can be used to represent:
- An object name
- An object name pattern, within the context of a query
An object name consists of two parts, the domain and the key
properties.
The domain is a string of characters not including
the character colon (:
). It is recommended that the domain should not contain the string "//
", which is reserved for future use.
If the domain includes at least one occurrence of the wildcard
characters asterisk (*
) or question mark
(?
), then the object name is a pattern. The asterisk
matches any sequence of zero or more characters, while the question
mark matches any single character.
If the domain is empty, it will be replaced in certain contexts
by the default domain of the MBean server in which the
ObjectName is used.
The key properties are an unordered set of keys and
associated values.
Each key is a nonempty string of characters which may
not contain any of the characters comma (,
), equals
(=
), colon, asterisk, or question mark. The same key
may not occur twice in a given ObjectName.
Each value associated with a key is a string of
characters that is either unquoted or quoted.
An unquoted value is a possibly empty string of
characters which may not contain any of the characters comma,
equals, colon, or quote.
If the unquoted value contains at least one occurrence
of the wildcard characters asterisk or question mark, then the object
name is a property value pattern. The asterisk matches any
sequence of zero or more characters, while the question mark matches
any single character.
A quoted value consists of a quote ("
),
followed by a possibly empty string of characters, followed by
another quote. Within the string of characters, the backslash
(\
) has a special meaning. It must be followed by
one of the following characters:
- Another backslash. The second backslash has no special
meaning and the two characters represent a single backslash.
- The character 'n'. The two characters represent a newline
('\n' in Java).
- A quote. The two characters represent a quote, and that quote
is not considered to terminate the quoted value. An ending closing
quote must be present for the quoted value to be valid.
- A question mark (?) or asterisk (*). The two characters represent
a question mark or asterisk respectively.
A quote may not appear inside a quoted value except immediately
after an odd number of consecutive backslashes.
The quotes surrounding a quoted value, and any backslashes
within that value, are considered to be part of the value.
If the quoted value contains at least one occurrence of
the characters asterisk or question mark and they are not preceded
by a backslash, then they are considered as wildcard characters and
the object name is a property value pattern. The asterisk
matches any sequence of zero or more characters, while the question
mark matches any single character.
An ObjectName may be a property list pattern. In this
case it may have zero or more keys and associated values. It matches
a nonpattern ObjectName whose domain matches and that contains the
same keys and associated values, as well as possibly other keys and
values.
An ObjectName is a property value pattern when at least
one of its quoted or unquoted key property values
contains the wildcard characters asterisk or question mark as described
above. In this case it has one or more keys and associated values, with
at least one of the values containing wildcard characters. It matches a
nonpattern ObjectName whose domain matches and that contains the same
keys whose values match; if the property value pattern is also a
property list pattern then the nonpattern ObjectName can contain
other keys and values.
An ObjectName is a property pattern if it is either a
property list pattern or a property value pattern
or both.
An ObjectName is a pattern if its domain contains a wildcard or
if the ObjectName is a property pattern.
If an ObjectName is not a pattern, it must contain at least one
key with its associated value.
Examples of ObjectName patterns are:
*:type=Foo,name=Bar
to match names in any domain whose exact set of keys is type=Foo,name=Bar
.
d:type=Foo,name=Bar,*
to match names in the domain d
that have the keys type=Foo,name=Bar
plus zero or more other keys.
*:type=Foo,name=Bar,*
to match names in any domain that has the keys type=Foo,name=Bar
plus zero or more other keys.
d:type=F?o,name=Bar
will match e.g. d:type=Foo,name=Bar
and d:type=Fro,name=Bar
.
d:type=F*o,name=Bar
will match e.g. d:type=Fo,name=Bar
and d:type=Frodo,name=Bar
.
d:type=Foo,name="B*"
will match e.g. d:type=Foo,name="Bling"
. Wildcards are recognized even inside quotes, and like other special characters can be escaped with \
.
An ObjectName can be written as a String with the following
elements in order:
- The domain.
- A colon (
:
).
- A key property list as defined below.
A key property list written as a String is a comma-separated
list of elements. Each element is either an asterisk or a key
property. A key property consists of a key, an equals
(=
), and the associated value.
At most one element of a key property list may be an asterisk.
If the key property list contains an asterisk element, the
ObjectName is a property list pattern.
Spaces have no special significance in a String representing an
ObjectName. For example, the String:
domain: key1 = value1 , key2 = value2
represents an ObjectName with two keys. The name of each key
contains six characters, of which the first and last are spaces.
The value associated with the key " key1 "
also begins and ends with a space.
In addition to the restrictions on characters spelt out above,
no part of an ObjectName may contain a newline character
('\n'
), whether the domain, a key, or a value, whether
quoted or unquoted. The newline character can be represented in a
quoted value with the sequence \n
.
The rules on special characters and quoting apply regardless of
which constructor is used to make an ObjectName.
To avoid collisions between MBeans supplied by different
vendors, a useful convention is to begin the domain name with the
reverse DNS name of the organization that specifies the MBeans,
followed by a period and a string whose interpretation is
determined by that organization. For example, MBeans specified by
example.com
would have
domains such as com.example.MyDomain
. This is essentially
the same convention as for Java-language package names.
The serialVersionUID of this class is 1081892073854801359L
.
Since: 1.5
/**
* <p>Represents the object name of an MBean, or a pattern that can
* match the names of several MBeans. Instances of this class are
* immutable.</p>
*
* <p>An instance of this class can be used to represent:</p>
* <ul>
* <li>An object name</li>
* <li>An object name pattern, within the context of a query</li>
* </ul>
*
* <p>An object name consists of two parts, the domain and the key
* properties.</p>
*
* <p>The <em>domain</em> is a string of characters not including
* the character colon (<code>:</code>). It is recommended that the domain
* should not contain the string "{@code //}", which is reserved for future use.
*
* <p>If the domain includes at least one occurrence of the wildcard
* characters asterisk (<code>*</code>) or question mark
* (<code>?</code>), then the object name is a pattern. The asterisk
* matches any sequence of zero or more characters, while the question
* mark matches any single character.</p>
*
* <p>If the domain is empty, it will be replaced in certain contexts
* by the <em>default domain</em> of the MBean server in which the
* ObjectName is used.</p>
*
* <p>The <em>key properties</em> are an unordered set of keys and
* associated values.</p>
*
* <p>Each <em>key</em> is a nonempty string of characters which may
* not contain any of the characters comma (<code>,</code>), equals
* (<code>=</code>), colon, asterisk, or question mark. The same key
* may not occur twice in a given ObjectName.</p>
*
* <p>Each <em>value</em> associated with a key is a string of
* characters that is either unquoted or quoted.</p>
*
* <p>An <em>unquoted value</em> is a possibly empty string of
* characters which may not contain any of the characters comma,
* equals, colon, or quote.</p>
*
* <p>If the <em>unquoted value</em> contains at least one occurrence
* of the wildcard characters asterisk or question mark, then the object
* name is a <em>property value pattern</em>. The asterisk matches any
* sequence of zero or more characters, while the question mark matches
* any single character.</p>
*
* <p>A <em>quoted value</em> consists of a quote (<code>"</code>),
* followed by a possibly empty string of characters, followed by
* another quote. Within the string of characters, the backslash
* (<code>\</code>) has a special meaning. It must be followed by
* one of the following characters:</p>
*
* <ul>
* <li>Another backslash. The second backslash has no special
* meaning and the two characters represent a single backslash.</li>
*
* <li>The character 'n'. The two characters represent a newline
* ('\n' in Java).</li>
*
* <li>A quote. The two characters represent a quote, and that quote
* is not considered to terminate the quoted value. An ending closing
* quote must be present for the quoted value to be valid.</li>
*
* <li>A question mark (?) or asterisk (*). The two characters represent
* a question mark or asterisk respectively.</li>
* </ul>
*
* <p>A quote may not appear inside a quoted value except immediately
* after an odd number of consecutive backslashes.</p>
*
* <p>The quotes surrounding a quoted value, and any backslashes
* within that value, are considered to be part of the value.</p>
*
* <p>If the <em>quoted value</em> contains at least one occurrence of
* the characters asterisk or question mark and they are not preceded
* by a backslash, then they are considered as wildcard characters and
* the object name is a <em>property value pattern</em>. The asterisk
* matches any sequence of zero or more characters, while the question
* mark matches any single character.</p>
*
* <p>An ObjectName may be a <em>property list pattern</em>. In this
* case it may have zero or more keys and associated values. It matches
* a nonpattern ObjectName whose domain matches and that contains the
* same keys and associated values, as well as possibly other keys and
* values.</p>
*
* <p>An ObjectName is a <em>property value pattern</em> when at least
* one of its <em>quoted</em> or <em>unquoted</em> key property values
* contains the wildcard characters asterisk or question mark as described
* above. In this case it has one or more keys and associated values, with
* at least one of the values containing wildcard characters. It matches a
* nonpattern ObjectName whose domain matches and that contains the same
* keys whose values match; if the property value pattern is also a
* property list pattern then the nonpattern ObjectName can contain
* other keys and values.</p>
*
* <p>An ObjectName is a <em>property pattern</em> if it is either a
* <em>property list pattern</em> or a <em>property value pattern</em>
* or both.</p>
*
* <p>An ObjectName is a pattern if its domain contains a wildcard or
* if the ObjectName is a property pattern.</p>
*
* <p>If an ObjectName is not a pattern, it must contain at least one
* key with its associated value.</p>
*
* <p>Examples of ObjectName patterns are:</p>
*
* <ul>
* <li>{@code *:type=Foo,name=Bar} to match names in any domain whose
* exact set of keys is {@code type=Foo,name=Bar}.</li>
* <li>{@code d:type=Foo,name=Bar,*} to match names in the domain
* {@code d} that have the keys {@code type=Foo,name=Bar} plus
* zero or more other keys.</li>
* <li>{@code *:type=Foo,name=Bar,*} to match names in any domain
* that has the keys {@code type=Foo,name=Bar} plus zero or
* more other keys.</li>
* <li>{@code d:type=F?o,name=Bar} will match e.g.
* {@code d:type=Foo,name=Bar} and {@code d:type=Fro,name=Bar}.</li>
* <li>{@code d:type=F*o,name=Bar} will match e.g.
* {@code d:type=Fo,name=Bar} and {@code d:type=Frodo,name=Bar}.</li>
* <li>{@code d:type=Foo,name="B*"} will match e.g.
* {@code d:type=Foo,name="Bling"}. Wildcards are recognized even
* inside quotes, and like other special characters can be escaped
* with {@code \}.</li>
* </ul>
*
* <p>An ObjectName can be written as a String with the following
* elements in order:</p>
*
* <ul>
* <li>The domain.
* <li>A colon (<code>:</code>).
* <li>A key property list as defined below.
* </ul>
*
* <p>A key property list written as a String is a comma-separated
* list of elements. Each element is either an asterisk or a key
* property. A key property consists of a key, an equals
* (<code>=</code>), and the associated value.</p>
*
* <p>At most one element of a key property list may be an asterisk.
* If the key property list contains an asterisk element, the
* ObjectName is a property list pattern.</p>
*
* <p>Spaces have no special significance in a String representing an
* ObjectName. For example, the String:
* <pre>
* domain: key1 = value1 , key2 = value2
* </pre>
* represents an ObjectName with two keys. The name of each key
* contains six characters, of which the first and last are spaces.
* The value associated with the key <code>" key1 "</code>
* also begins and ends with a space.
*
* <p>In addition to the restrictions on characters spelt out above,
* no part of an ObjectName may contain a newline character
* (<code>'\n'</code>), whether the domain, a key, or a value, whether
* quoted or unquoted. The newline character can be represented in a
* quoted value with the sequence <code>\n</code>.
*
* <p>The rules on special characters and quoting apply regardless of
* which constructor is used to make an ObjectName.</p>
*
* <p>To avoid collisions between MBeans supplied by different
* vendors, a useful convention is to begin the domain name with the
* reverse DNS name of the organization that specifies the MBeans,
* followed by a period and a string whose interpretation is
* determined by that organization. For example, MBeans specified by
* <code>example.com</code> would have
* domains such as <code>com.example.MyDomain</code>. This is essentially
* the same convention as for Java-language package names.</p>
*
* <p>The <b>serialVersionUID</b> of this class is <code>1081892073854801359L</code>.
*
* @since 1.5
*/
@SuppressWarnings("serial") // don't complain serialVersionUID not constant
public class ObjectName implements Comparable<ObjectName>, QueryExp {
A structure recording property structure and
proposing minimal services
/**
* A structure recording property structure and
* proposing minimal services
*/
private static class Property {
int _key_index;
int _key_length;
int _value_length;
Constructor.
/**
* Constructor.
*/
Property(int key_index, int key_length, int value_length) {
_key_index = key_index;
_key_length = key_length;
_value_length = value_length;
}
Assigns the key index of property
/**
* Assigns the key index of property
*/
void setKeyIndex(int key_index) {
_key_index = key_index;
}
Returns a key string for receiver key
/**
* Returns a key string for receiver key
*/
String getKeyString(String name) {
return name.substring(_key_index, _key_index + _key_length);
}
Returns a value string for receiver key
/**
* Returns a value string for receiver key
*/
String getValueString(String name) {
int in_begin = _key_index + _key_length + 1;
int out_end = in_begin + _value_length;
return name.substring(in_begin, out_end);
}
}
Marker class for value pattern property.
/**
* Marker class for value pattern property.
*/
private static class PatternProperty extends Property {
Constructor.
/**
* Constructor.
*/
PatternProperty(int key_index, int key_length, int value_length) {
super(key_index, key_length, value_length);
}
}
// Inner classes <========================================
// Private fields ---------------------------------------->
// Serialization compatibility stuff -------------------->
// Two serial forms are supported in this class. The selected form depends
// on system property "jmx.serial.form":
// - "1.0" for JMX 1.0
// - any other value for JMX 1.1 and higher
//
// Serial version for old serial form
private static final long oldSerialVersionUID = -5467795090068647408L;
//
// Serial version for new serial form
private static final long newSerialVersionUID = 1081892073854801359L;
//
// Serializable fields in old serial form
private static final ObjectStreamField[] oldSerialPersistentFields =
{
new ObjectStreamField("domain", String.class),
new ObjectStreamField("propertyList", Hashtable.class),
new ObjectStreamField("propertyListString", String.class),
new ObjectStreamField("canonicalName", String.class),
new ObjectStreamField("pattern", Boolean.TYPE),
new ObjectStreamField("propertyPattern", Boolean.TYPE)
};
//
// Serializable fields in new serial form
private static final ObjectStreamField[] newSerialPersistentFields = { };
//
// Actual serial version and serial form
private static final long serialVersionUID;
private static final ObjectStreamField[] serialPersistentFields;
private static boolean compat = false;
static {
try {
GetPropertyAction act = new GetPropertyAction("jmx.serial.form");
String form = AccessController.doPrivileged(act);
compat = (form != null && form.equals("1.0"));
} catch (Exception e) {
// OK: exception means no compat with 1.0, too bad
}
if (compat) {
serialPersistentFields = oldSerialPersistentFields;
serialVersionUID = oldSerialVersionUID;
} else {
serialPersistentFields = newSerialPersistentFields;
serialVersionUID = newSerialVersionUID;
}
}
//
// Serialization compatibility stuff <==============================
// Class private fields ----------------------------------->
a shared empty array for empty property lists
/**
* a shared empty array for empty property lists
*/
static final private Property[] _Empty_property_array = new Property[0];
// Class private fields <==============================
// Instance private fields ----------------------------------->
a String containing the canonical name
/**
* a String containing the canonical name
*/
private transient String _canonicalName;
An array of properties in the same seq order as time creation
/**
* An array of properties in the same seq order as time creation
*/
private transient Property[] _kp_array;
An array of properties in the same seq order as canonical order
/**
* An array of properties in the same seq order as canonical order
*/
private transient Property[] _ca_array;
The length of the domain part of built objectname
/**
* The length of the domain part of built objectname
*/
private transient int _domain_length = 0;
The propertyList of built object name. Initialized lazily.
Table that contains all the pairs (key,value) for this ObjectName.
/**
* The propertyList of built object name. Initialized lazily.
* Table that contains all the pairs (key,value) for this ObjectName.
*/
private transient Map<String,String> _propertyList;
boolean that declares if this ObjectName domain part is a pattern
/**
* boolean that declares if this ObjectName domain part is a pattern
*/
private transient boolean _domain_pattern = false;
boolean that declares if this ObjectName contains a pattern on the
key property list
/**
* boolean that declares if this ObjectName contains a pattern on the
* key property list
*/
private transient boolean _property_list_pattern = false;
boolean that declares if this ObjectName contains a pattern on the
value of at least one key property
/**
* boolean that declares if this ObjectName contains a pattern on the
* value of at least one key property
*/
private transient boolean _property_value_pattern = false;
// Instance private fields <=======================================
// Private fields <========================================
// Private methods ---------------------------------------->
// Category : Instance construction ------------------------->
Initializes this ObjectName
from the given string representation. Params: - name – A string representation of the
ObjectName
Throws: - MalformedObjectNameException – The string passed as a
parameter does not have the right format.
- NullPointerException – The
name
parameter
is null.
/**
* Initializes this {@link ObjectName} from the given string
* representation.
*
* @param name A string representation of the {@link ObjectName}
*
* @exception MalformedObjectNameException The string passed as a
* parameter does not have the right format.
* @exception NullPointerException The <code>name</code> parameter
* is null.
*/
private void construct(String name)
throws MalformedObjectNameException {
// The name cannot be null
if (name == null)
throw new NullPointerException("name cannot be null");
// Test if the name is empty
if (name.length() == 0) {
// this is equivalent to the whole word query object name.
_canonicalName = "*:*";
_kp_array = _Empty_property_array;
_ca_array = _Empty_property_array;
_domain_length = 1;
_propertyList = null;
_domain_pattern = true;
_property_list_pattern = true;
_property_value_pattern = false;
return;
}
// initialize parsing of the string
final char[] name_chars = name.toCharArray();
final int len = name_chars.length;
final char[] canonical_chars = new char[len]; // canonical form will
// be same length at most
int cname_index = 0;
int index = 0;
char c, c1;
// parses domain part
domain_parsing:
while (index < len) {
switch (name_chars[index]) {
case ':' :
_domain_length = index++;
break domain_parsing;
case '=' :
// ":" omission check.
//
// Although "=" is a valid character in the domain part
// it is true that it is rarely used in the real world.
// So check straight away if the ":" has been omitted
// from the ObjectName. This allows us to provide a more
// accurate exception message.
int i = ++index;
while ((i < len) && (name_chars[i++] != ':'))
if (i == len)
throw new MalformedObjectNameException(
"Domain part must be specified");
break;
case '\n' :
throw new MalformedObjectNameException(
"Invalid character '\\n' in domain name");
case '*' :
case '?' :
_domain_pattern = true;
index++;
break;
default :
index++;
break;
}
}
// check for non-empty properties
if (index == len)
throw new MalformedObjectNameException(
"Key properties cannot be empty");
// we have got the domain part, begins building of _canonicalName
System.arraycopy(name_chars, 0, canonical_chars, 0, _domain_length);
canonical_chars[_domain_length] = ':';
cname_index = _domain_length + 1;
// parses property list
Property prop;
Map<String,Property> keys_map = new HashMap<String,Property>();
String[] keys;
String key_name;
boolean quoted_value;
int property_index = 0;
int in_index;
int key_index, key_length, value_index, value_length;
keys = new String[10];
_kp_array = new Property[10];
_property_list_pattern = false;
_property_value_pattern = false;
while (index < len) {
c = name_chars[index];
// case of pattern properties
if (c == '*') {
if (_property_list_pattern)
throw new MalformedObjectNameException(
"Cannot have several '*' characters in pattern " +
"property list");
else {
_property_list_pattern = true;
if ((++index < len ) && (name_chars[index] != ','))
throw new MalformedObjectNameException(
"Invalid character found after '*': end of " +
"name or ',' expected");
else if (index == len) {
if (property_index == 0) {
// empty properties case
_kp_array = _Empty_property_array;
_ca_array = _Empty_property_array;
_propertyList = Collections.emptyMap();
}
break;
} else {
// correct pattern spec in props, continue
index++;
continue;
}
}
}
// standard property case, key part
in_index = index;
key_index = in_index;
if (name_chars[in_index] == '=')
throw new MalformedObjectNameException("Invalid key (empty)");
while ((in_index < len) && ((c1 = name_chars[in_index++]) != '='))
switch (c1) {
// '=' considered to introduce value part
case '*' :
case '?' :
case ',' :
case ':' :
case '\n' :
final String ichar = ((c1=='\n')?"\\n":""+c1);
throw new MalformedObjectNameException(
"Invalid character '" + ichar +
"' in key part of property");
}
if (name_chars[in_index - 1] != '=')
throw new MalformedObjectNameException(
"Unterminated key property part");
value_index = in_index; // in_index pointing after '=' char
key_length = value_index - key_index - 1; // found end of key
// standard property case, value part
boolean value_pattern = false;
if (in_index < len && name_chars[in_index] == '\"') {
quoted_value = true;
// the case of quoted value part
quoted_value_parsing:
while ((++in_index < len) &&
((c1 = name_chars[in_index]) != '\"')) {
// the case of an escaped character
if (c1 == '\\') {
if (++in_index == len)
throw new MalformedObjectNameException(
"Unterminated quoted value");
switch (c1 = name_chars[in_index]) {
case '\\' :
case '\"' :
case '?' :
case '*' :
case 'n' :
break; // valid character
default :
throw new MalformedObjectNameException(
"Invalid escape sequence '\\" +
c1 + "' in quoted value");
}
} else if (c1 == '\n') {
throw new MalformedObjectNameException(
"Newline in quoted value");
} else {
switch (c1) {
case '?' :
case '*' :
value_pattern = true;
break;
}
}
}
if (in_index == len)
throw new MalformedObjectNameException(
"Unterminated quoted value");
else value_length = ++in_index - value_index;
} else {
// the case of standard value part
quoted_value = false;
while ((in_index < len) && ((c1 = name_chars[in_index]) != ','))
switch (c1) {
// ',' considered to be the value separator
case '*' :
case '?' :
value_pattern = true;
in_index++;
break;
case '=' :
case ':' :
case '"' :
case '\n' :
final String ichar = ((c1=='\n')?"\\n":""+c1);
throw new MalformedObjectNameException(
"Invalid character '" + ichar +
"' in value part of property");
default :
in_index++;
break;
}
value_length = in_index - value_index;
}
// Parsed property, checks the end of name
if (in_index == len - 1) {
if (quoted_value)
throw new MalformedObjectNameException(
"Invalid ending character `" +
name_chars[in_index] + "'");
else throw new MalformedObjectNameException(
"Invalid ending comma");
} else in_index++;
// we got the key and value part, prepare a property for this
if (!value_pattern) {
prop = new Property(key_index, key_length, value_length);
} else {
_property_value_pattern = true;
prop = new PatternProperty(key_index, key_length, value_length);
}
key_name = name.substring(key_index, key_index + key_length);
if (property_index == keys.length) {
String[] tmp_string_array = new String[property_index + 10];
System.arraycopy(keys, 0, tmp_string_array, 0, property_index);
keys = tmp_string_array;
}
keys[property_index] = key_name;
addProperty(prop, property_index, keys_map, key_name);
property_index++;
index = in_index;
}
// computes and set canonical name
setCanonicalName(name_chars, canonical_chars, keys,
keys_map, cname_index, property_index);
}
Construct an ObjectName from a domain and a Hashtable.
Params: - domain – Domain of the ObjectName.
- props – Map containing couples key -> value.
Throws: - MalformedObjectNameException – The
domain
contains an illegal character, or one of the keys or values in
table
contains an illegal character, or one of the
values in table
does not follow the rules for quoting. - NullPointerException – One of the parameters is null.
/**
* Construct an ObjectName from a domain and a Hashtable.
*
* @param domain Domain of the ObjectName.
* @param props Map containing couples <i>key</i> {@literal ->} <i>value</i>.
*
* @exception MalformedObjectNameException The <code>domain</code>
* contains an illegal character, or one of the keys or values in
* <code>table</code> contains an illegal character, or one of the
* values in <code>table</code> does not follow the rules for quoting.
* @exception NullPointerException One of the parameters is null.
*/
private void construct(String domain, Map<String,String> props)
throws MalformedObjectNameException {
// The domain cannot be null
if (domain == null)
throw new NullPointerException("domain cannot be null");
// The key property list cannot be null
if (props == null)
throw new NullPointerException("key property list cannot be null");
// The key property list cannot be empty
if (props.isEmpty())
throw new MalformedObjectNameException(
"key property list cannot be empty");
// checks domain validity
if (!isDomain(domain))
throw new MalformedObjectNameException("Invalid domain: " + domain);
// init canonicalname
final StringBuilder sb = new StringBuilder();
sb.append(domain).append(':');
_domain_length = domain.length();
// allocates the property array
int nb_props = props.size();
_kp_array = new Property[nb_props];
String[] keys = new String[nb_props];
final Map<String,Property> keys_map = new HashMap<String,Property>();
Property prop;
int key_index;
int i = 0;
for (Map.Entry<String,String> entry : props.entrySet()) {
if (sb.length() > 0)
sb.append(",");
String key = entry.getKey();
String value;
try {
value = entry.getValue();
} catch (ClassCastException e) {
throw new MalformedObjectNameException(e.getMessage());
}
key_index = sb.length();
checkKey(key);
sb.append(key);
keys[i] = key;
sb.append("=");
boolean value_pattern = checkValue(value);
sb.append(value);
if (!value_pattern) {
prop = new Property(key_index,
key.length(),
value.length());
} else {
_property_value_pattern = true;
prop = new PatternProperty(key_index,
key.length(),
value.length());
}
addProperty(prop, i, keys_map, key);
i++;
}
// initialize canonical name and data structure
int len = sb.length();
char[] initial_chars = new char[len];
sb.getChars(0, len, initial_chars, 0);
char[] canonical_chars = new char[len];
System.arraycopy(initial_chars, 0, canonical_chars, 0,
_domain_length + 1);
setCanonicalName(initial_chars, canonical_chars, keys, keys_map,
_domain_length + 1, _kp_array.length);
}
// Category : Instance construction <==============================
// Category : Internal utilities ------------------------------>
Add passed property to the list at the given index
for the passed key name
/**
* Add passed property to the list at the given index
* for the passed key name
*/
private void addProperty(Property prop, int index,
Map<String,Property> keys_map, String key_name)
throws MalformedObjectNameException {
if (keys_map.containsKey(key_name)) throw new
MalformedObjectNameException("key `" +
key_name +"' already defined");
// if no more space for property arrays, have to increase it
if (index == _kp_array.length) {
Property[] tmp_prop_array = new Property[index + 10];
System.arraycopy(_kp_array, 0, tmp_prop_array, 0, index);
_kp_array = tmp_prop_array;
}
_kp_array[index] = prop;
keys_map.put(key_name, prop);
}
Sets the canonical name of receiver from input 'specified_chars'
array, by filling 'canonical_chars' array with found 'nb-props'
properties starting at position 'prop_index'.
/**
* Sets the canonical name of receiver from input 'specified_chars'
* array, by filling 'canonical_chars' array with found 'nb-props'
* properties starting at position 'prop_index'.
*/
private void setCanonicalName(char[] specified_chars,
char[] canonical_chars,
String[] keys, Map<String,Property> keys_map,
int prop_index, int nb_props) {
// Sort the list of found properties
if (_kp_array != _Empty_property_array) {
String[] tmp_keys = new String[nb_props];
Property[] tmp_props = new Property[nb_props];
System.arraycopy(keys, 0, tmp_keys, 0, nb_props);
Arrays.sort(tmp_keys);
keys = tmp_keys;
System.arraycopy(_kp_array, 0, tmp_props, 0 , nb_props);
_kp_array = tmp_props;
_ca_array = new Property[nb_props];
// now assigns _ca_array to the sorted list of keys
// (there cannot be two identical keys in an objectname.
for (int i = 0; i < nb_props; i++)
_ca_array[i] = keys_map.get(keys[i]);
// now we build the canonical name and set begin indexes of
// properties to reflect canonical form
int last_index = nb_props - 1;
int prop_len;
Property prop;
for (int i = 0; i <= last_index; i++) {
prop = _ca_array[i];
// length of prop including '=' char
prop_len = prop._key_length + prop._value_length + 1;
System.arraycopy(specified_chars, prop._key_index,
canonical_chars, prop_index, prop_len);
prop.setKeyIndex(prop_index);
prop_index += prop_len;
if (i != last_index) {
canonical_chars[prop_index] = ',';
prop_index++;
}
}
}
// terminate canonicalname with '*' in case of pattern
if (_property_list_pattern) {
if (_kp_array != _Empty_property_array)
canonical_chars[prop_index++] = ',';
canonical_chars[prop_index++] = '*';
}
// we now build the canonicalname string
_canonicalName = (new String(canonical_chars, 0, prop_index)).intern();
}
Parse a key.
final int endKey=parseKey(s,startKey);
key starts at startKey (included), and ends at endKey (excluded).
If (startKey == endKey), then the key is empty.
Params: - s – The char array of the original string.
- startKey – index at which to begin parsing.
Returns: The index following the last character of the key.
/**
* Parse a key.
* <pre>final int endKey=parseKey(s,startKey);</pre>
* <p>key starts at startKey (included), and ends at endKey (excluded).
* If (startKey == endKey), then the key is empty.
*
* @param s The char array of the original string.
* @param startKey index at which to begin parsing.
* @return The index following the last character of the key.
**/
private static int parseKey(final char[] s, final int startKey)
throws MalformedObjectNameException {
int next = startKey;
int endKey = startKey;
final int len = s.length;
while (next < len) {
final char k = s[next++];
switch (k) {
case '*':
case '?':
case ',':
case ':':
case '\n':
final String ichar = ((k=='\n')?"\\n":""+k);
throw new
MalformedObjectNameException("Invalid character in key: `"
+ ichar + "'");
case '=':
// we got the key.
endKey = next-1;
break;
default:
if (next < len) continue;
else endKey=next;
}
break;
}
return endKey;
}
Parse a value.
final int endVal=parseValue(s,startVal);
value starts at startVal (included), and ends at endVal (excluded).
If (startVal == endVal), then the key is empty.
Params: - s – The char array of the original string.
- startValue – index at which to begin parsing.
Returns: The first element of the int array indicates the index
following the last character of the value. The second
element of the int array indicates that the value is
a pattern when its value equals 1.
/**
* Parse a value.
* <pre>final int endVal=parseValue(s,startVal);</pre>
* <p>value starts at startVal (included), and ends at endVal (excluded).
* If (startVal == endVal), then the key is empty.
*
* @param s The char array of the original string.
* @param startValue index at which to begin parsing.
* @return The first element of the int array indicates the index
* following the last character of the value. The second
* element of the int array indicates that the value is
* a pattern when its value equals 1.
**/
private static int[] parseValue(final char[] s, final int startValue)
throws MalformedObjectNameException {
boolean value_pattern = false;
int next = startValue;
int endValue = startValue;
final int len = s.length;
final char q=s[startValue];
if (q == '"') {
// quoted value
if (++next == len) throw new
MalformedObjectNameException("Invalid quote");
while (next < len) {
char last = s[next];
if (last == '\\') {
if (++next == len) throw new
MalformedObjectNameException(
"Invalid unterminated quoted character sequence");
last = s[next];
switch (last) {
case '\\' :
case '?' :
case '*' :
case 'n' :
break;
case '\"' :
// We have an escaped quote. If this escaped
// quote is the last character, it does not
// qualify as a valid termination quote.
//
if (next+1 == len) throw new
MalformedObjectNameException(
"Missing termination quote");
break;
default:
throw new
MalformedObjectNameException(
"Invalid quoted character sequence '\\" +
last + "'");
}
} else if (last == '\n') {
throw new MalformedObjectNameException(
"Newline in quoted value");
} else if (last == '\"') {
next++;
break;
} else {
switch (last) {
case '?' :
case '*' :
value_pattern = true;
break;
}
}
next++;
// Check that last character is a termination quote.
// We have already handled the case were the last
// character is an escaped quote earlier.
//
if ((next >= len) && (last != '\"')) throw new
MalformedObjectNameException("Missing termination quote");
}
endValue = next;
if (next < len) {
if (s[next++] != ',') throw new
MalformedObjectNameException("Invalid quote");
}
} else {
// Non quoted value.
while (next < len) {
final char v=s[next++];
switch(v) {
case '*':
case '?':
value_pattern = true;
if (next < len) continue;
else endValue=next;
break;
case '=':
case ':':
case '\n' :
final String ichar = ((v=='\n')?"\\n":""+v);
throw new
MalformedObjectNameException("Invalid character `" +
ichar + "' in value");
case ',':
endValue = next-1;
break;
default:
if (next < len) continue;
else endValue=next;
}
break;
}
}
return new int[] { endValue, value_pattern ? 1 : 0 };
}
Check if the supplied value is a valid value.
Returns: true if the value is a pattern, otherwise false.
/**
* Check if the supplied value is a valid value.
*
* @return true if the value is a pattern, otherwise false.
*/
private static boolean checkValue(String val)
throws MalformedObjectNameException {
if (val == null) throw new
NullPointerException("Invalid value (null)");
final int len = val.length();
if (len == 0)
return false;
final char[] s = val.toCharArray();
final int[] result = parseValue(s,0);
final int endValue = result[0];
final boolean value_pattern = result[1] == 1;
if (endValue < len) throw new
MalformedObjectNameException("Invalid character in value: `" +
s[endValue] + "'");
return value_pattern;
}
Check if the supplied key is a valid key.
/**
* Check if the supplied key is a valid key.
*/
private static void checkKey(String key)
throws MalformedObjectNameException {
if (key == null) throw new
NullPointerException("Invalid key (null)");
final int len = key.length();
if (len == 0) throw new
MalformedObjectNameException("Invalid key (empty)");
final char[] k=key.toCharArray();
final int endKey = parseKey(k,0);
if (endKey < len) throw new
MalformedObjectNameException("Invalid character in value: `" +
k[endKey] + "'");
}
// Category : Internal utilities <==============================
// Category : Internal accessors ------------------------------>
Check if domain is a valid domain. Set _domain_pattern if appropriate.
/**
* Check if domain is a valid domain. Set _domain_pattern if appropriate.
*/
private boolean isDomain(String domain) {
if (domain == null) return true;
final int len = domain.length();
int next = 0;
while (next < len) {
final char c = domain.charAt(next++);
switch (c) {
case ':' :
case '\n' :
return false;
case '*' :
case '?' :
_domain_pattern = true;
break;
}
}
return true;
}
// Category : Internal accessors <==============================
// Category : Serialization ----------------------------------->
Deserializes an ObjectName
from an ObjectInputStream
. @serialData
- In the current serial form (value of property
jmx.serial.form
differs from
1.0
): the string
"<domain>:<properties><wild>",
where:
- <domain> represents the domain part of the
ObjectName
- <properties> represents the list of properties, as returned by
getKeyPropertyListString
- <wild> is empty if not
isPropertyPattern
, or
is the character "*
" if
isPropertyPattern
and <properties> is empty, or
is ",*
" if
isPropertyPattern
and
<properties> is not empty.
The intent is that this string could be supplied to the ObjectName(String)
constructor to produce an equivalent ObjectName
.
- In the old serial form (value of property
jmx.serial.form
is
1.0
): <domain> <propertyList>
<propertyListString> <canonicalName>
<pattern> <propertyPattern>,
where:
- <domain> represents the domain part of the
ObjectName
- <propertyList> is the
Hashtable
that contains all the pairs (key,value) for this ObjectName
- <propertyListString> is the
String
representation of the list of properties in any order (not mandatorily a canonical representation)
- <canonicalName> is the
String
containing this ObjectName
's canonical name
- <pattern> is a boolean which is
true
if this ObjectName
contains a pattern
- <propertyPattern> is a boolean which
is
true
if this ObjectName
contains a pattern in the list of properties
/**
* Deserializes an {@link ObjectName} from an {@link ObjectInputStream}.
* @serialData <ul>
* <li>In the current serial form (value of property
* <code>jmx.serial.form</code> differs from
* <code>1.0</code>): the string
* "<domain>:<properties><wild>",
* where: <ul>
* <li><domain> represents the domain part
* of the {@link ObjectName}</li>
* <li><properties> represents the list of
* properties, as returned by
* {@link #getKeyPropertyListString}
* <li><wild> is empty if not
* <code>isPropertyPattern</code>, or
* is the character "<code>*</code>" if
* <code>isPropertyPattern</code>
* and <properties> is empty, or
* is "<code>,*</code>" if
* <code>isPropertyPattern</code> and
* <properties> is not empty.
* </li>
* </ul>
* The intent is that this string could be supplied
* to the {@link #ObjectName(String)} constructor to
* produce an equivalent {@link ObjectName}.
* </li>
* <li>In the old serial form (value of property
* <code>jmx.serial.form</code> is
* <code>1.0</code>): <domain> <propertyList>
* <propertyListString> <canonicalName>
* <pattern> <propertyPattern>,
* where: <ul>
* <li><domain> represents the domain part
* of the {@link ObjectName}</li>
* <li><propertyList> is the
* {@link Hashtable} that contains all the
* pairs (key,value) for this
* {@link ObjectName}</li>
* <li><propertyListString> is the
* {@link String} representation of the
* list of properties in any order (not
* mandatorily a canonical representation)
* </li>
* <li><canonicalName> is the
* {@link String} containing this
* {@link ObjectName}'s canonical name</li>
* <li><pattern> is a boolean which is
* <code>true</code> if this
* {@link ObjectName} contains a pattern</li>
* <li><propertyPattern> is a boolean which
* is <code>true</code> if this
* {@link ObjectName} contains a pattern in
* the list of properties</li>
* </ul>
* </li>
* </ul>
*/
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException {
String cn;
if (compat) {
// Read an object serialized in the old serial form
//
//in.defaultReadObject();
final ObjectInputStream.GetField fields = in.readFields();
String propListString =
(String)fields.get("propertyListString", "");
// 6616825: take care of property patterns
final boolean propPattern =
fields.get("propertyPattern" , false);
if (propPattern) {
propListString =
(propListString.length()==0?"*":(propListString+",*"));
}
cn = (String)fields.get("domain", "default")+
":"+ propListString;
} else {
// Read an object serialized in the new serial form
//
in.defaultReadObject();
cn = (String)in.readObject();
}
try {
construct(cn);
} catch (NullPointerException e) {
throw new InvalidObjectException(e.toString());
} catch (MalformedObjectNameException e) {
throw new InvalidObjectException(e.toString());
}
}
Serializes an ObjectName
to an ObjectOutputStream
. @serialData
- In the current serial form (value of property
jmx.serial.form
differs from
1.0
): the string
"<domain>:<properties><wild>",
where:
- <domain> represents the domain part of the
ObjectName
- <properties> represents the list of properties, as returned by
getKeyPropertyListString
- <wild> is empty if not
isPropertyPattern
, or
is the character "*
" if
this isPropertyPattern
and <properties> is empty, or
is ",*
" if
isPropertyPattern
and
<properties> is not empty.
The intent is that this string could be supplied to the ObjectName(String)
constructor to produce an equivalent ObjectName
.
- In the old serial form (value of property
jmx.serial.form
is
1.0
): <domain> <propertyList>
<propertyListString> <canonicalName>
<pattern> <propertyPattern>,
where:
- <domain> represents the domain part of the
ObjectName
- <propertyList> is the
Hashtable
that contains all the pairs (key,value) for this ObjectName
- <propertyListString> is the
String
representation of the list of properties in any order (not mandatorily a canonical representation)
- <canonicalName> is the
String
containing this ObjectName
's canonical name
- <pattern> is a boolean which is
true
if this ObjectName
contains a pattern
- <propertyPattern> is a boolean which
is
true
if this ObjectName
contains a pattern in the list of properties
/**
* Serializes an {@link ObjectName} to an {@link ObjectOutputStream}.
* @serialData <ul>
* <li>In the current serial form (value of property
* <code>jmx.serial.form</code> differs from
* <code>1.0</code>): the string
* "<domain>:<properties><wild>",
* where: <ul>
* <li><domain> represents the domain part
* of the {@link ObjectName}</li>
* <li><properties> represents the list of
* properties, as returned by
* {@link #getKeyPropertyListString}
* <li><wild> is empty if not
* <code>isPropertyPattern</code>, or
* is the character "<code>*</code>" if
* this <code>isPropertyPattern</code>
* and <properties> is empty, or
* is "<code>,*</code>" if
* <code>isPropertyPattern</code> and
* <properties> is not empty.
* </li>
* </ul>
* The intent is that this string could be supplied
* to the {@link #ObjectName(String)} constructor to
* produce an equivalent {@link ObjectName}.
* </li>
* <li>In the old serial form (value of property
* <code>jmx.serial.form</code> is
* <code>1.0</code>): <domain> <propertyList>
* <propertyListString> <canonicalName>
* <pattern> <propertyPattern>,
* where: <ul>
* <li><domain> represents the domain part
* of the {@link ObjectName}</li>
* <li><propertyList> is the
* {@link Hashtable} that contains all the
* pairs (key,value) for this
* {@link ObjectName}</li>
* <li><propertyListString> is the
* {@link String} representation of the
* list of properties in any order (not
* mandatorily a canonical representation)
* </li>
* <li><canonicalName> is the
* {@link String} containing this
* {@link ObjectName}'s canonical name</li>
* <li><pattern> is a boolean which is
* <code>true</code> if this
* {@link ObjectName} contains a pattern</li>
* <li><propertyPattern> is a boolean which
* is <code>true</code> if this
* {@link ObjectName} contains a pattern in
* the list of properties</li>
* </ul>
* </li>
* </ul>
*/
private void writeObject(ObjectOutputStream out)
throws IOException {
if (compat)
{
// Serializes this instance in the old serial form
// Read CR 6441274 before making any changes to this code
ObjectOutputStream.PutField fields = out.putFields();
fields.put("domain", _canonicalName.substring(0, _domain_length));
fields.put("propertyList", getKeyPropertyList());
fields.put("propertyListString", getKeyPropertyListString());
fields.put("canonicalName", _canonicalName);
fields.put("pattern", (_domain_pattern || _property_list_pattern));
fields.put("propertyPattern", _property_list_pattern);
out.writeFields();
}
else
{
// Serializes this instance in the new serial form
//
out.defaultWriteObject();
out.writeObject(getSerializedNameString());
}
}
// Category : Serialization <===================================
// Private methods <========================================
// Public methods ---------------------------------------->
// Category : ObjectName Construction ------------------------------>
Return an instance of ObjectName that can be used anywhere an object obtained with new
ObjectName(name)
can be used. The returned object may be of a subclass of ObjectName. Calling this method twice with the same parameters may return the same object or two equal but not identical objects.
Params: - name – A string representation of the object name.
Throws: - MalformedObjectNameException – The string passed as a
parameter does not have the right format.
- NullPointerException – The
name
parameter
is null.
Returns: an ObjectName corresponding to the given String.
/**
* <p>Return an instance of ObjectName that can be used anywhere
* an object obtained with {@link #ObjectName(String) new
* ObjectName(name)} can be used. The returned object may be of
* a subclass of ObjectName. Calling this method twice with the
* same parameters may return the same object or two equal but
* not identical objects.</p>
*
* @param name A string representation of the object name.
*
* @return an ObjectName corresponding to the given String.
*
* @exception MalformedObjectNameException The string passed as a
* parameter does not have the right format.
* @exception NullPointerException The <code>name</code> parameter
* is null.
*
*/
public static ObjectName getInstance(String name)
throws MalformedObjectNameException, NullPointerException {
return new ObjectName(name);
}
Return an instance of ObjectName that can be used anywhere an object obtained with new ObjectName(domain, key, value)
can be used. The returned object may be of a subclass of ObjectName. Calling this method twice with the same parameters may return the same object or two equal but not identical objects.
Params: - domain – The domain part of the object name.
- key – The attribute in the key property of the object name.
- value – The value in the key property of the object name.
Throws: - MalformedObjectNameException – The
domain
, key
, or value
contains an illegal character, or value
does not
follow the rules for quoting. - NullPointerException – One of the parameters is null.
Returns: an ObjectName corresponding to the given domain,
key, and value.
/**
* <p>Return an instance of ObjectName that can be used anywhere
* an object obtained with {@link #ObjectName(String, String,
* String) new ObjectName(domain, key, value)} can be used. The
* returned object may be of a subclass of ObjectName. Calling
* this method twice with the same parameters may return the same
* object or two equal but not identical objects.</p>
*
* @param domain The domain part of the object name.
* @param key The attribute in the key property of the object name.
* @param value The value in the key property of the object name.
*
* @return an ObjectName corresponding to the given domain,
* key, and value.
*
* @exception MalformedObjectNameException The
* <code>domain</code>, <code>key</code>, or <code>value</code>
* contains an illegal character, or <code>value</code> does not
* follow the rules for quoting.
* @exception NullPointerException One of the parameters is null.
*
*/
public static ObjectName getInstance(String domain, String key,
String value)
throws MalformedObjectNameException {
return new ObjectName(domain, key, value);
}
Return an instance of ObjectName that can be used anywhere an object obtained with
new ObjectName(domain, table)
can be used. The returned object may be of a subclass of ObjectName. Calling this method twice with the same parameters may return the same object or two equal but not identical objects.
Params: - domain – The domain part of the object name.
- table – A hash table containing one or more key
properties. The key of each entry in the table is the key of a
key property in the object name. The associated value in the
table is the associated value in the object name.
Throws: - MalformedObjectNameException – The
domain
contains an illegal character, or one of the keys or values in
table
contains an illegal character, or one of the
values in table
does not follow the rules for
quoting. - NullPointerException – One of the parameters is null.
Returns: an ObjectName corresponding to the given domain and
key mappings.
/**
* <p>Return an instance of ObjectName that can be used anywhere
* an object obtained with {@link #ObjectName(String, Hashtable)
* new ObjectName(domain, table)} can be used. The returned
* object may be of a subclass of ObjectName. Calling this method
* twice with the same parameters may return the same object or
* two equal but not identical objects.</p>
*
* @param domain The domain part of the object name.
* @param table A hash table containing one or more key
* properties. The key of each entry in the table is the key of a
* key property in the object name. The associated value in the
* table is the associated value in the object name.
*
* @return an ObjectName corresponding to the given domain and
* key mappings.
*
* @exception MalformedObjectNameException The <code>domain</code>
* contains an illegal character, or one of the keys or values in
* <code>table</code> contains an illegal character, or one of the
* values in <code>table</code> does not follow the rules for
* quoting.
* @exception NullPointerException One of the parameters is null.
*
*/
public static ObjectName getInstance(String domain,
Hashtable<String,String> table)
throws MalformedObjectNameException {
return new ObjectName(domain, table);
}
Return an instance of ObjectName that can be used anywhere
the given object can be used. The returned object may be of a
subclass of ObjectName. If name
is of a subclass
of ObjectName, it is not guaranteed that the returned object
will be of the same class.
The returned value may or may not be identical to
name
. Calling this method twice with the same
parameters may return the same object or two equal but not
identical objects.
Since ObjectName is immutable, it is not usually useful to
make a copy of an ObjectName. The principal use of this method
is to guard against a malicious caller who might pass an
instance of a subclass with surprising behavior to sensitive
code. Such code can call this method to obtain an ObjectName
that is known not to have surprising behavior.
Params: - name – an instance of the ObjectName class or of a subclass
Throws: - NullPointerException – The
name
is null.
Returns: an instance of ObjectName or a subclass that is known to
have the same semantics. If name
respects the
semantics of ObjectName, then the returned object is equal
(though not necessarily identical) to name
.
/**
* <p>Return an instance of ObjectName that can be used anywhere
* the given object can be used. The returned object may be of a
* subclass of ObjectName. If <code>name</code> is of a subclass
* of ObjectName, it is not guaranteed that the returned object
* will be of the same class.</p>
*
* <p>The returned value may or may not be identical to
* <code>name</code>. Calling this method twice with the same
* parameters may return the same object or two equal but not
* identical objects.</p>
*
* <p>Since ObjectName is immutable, it is not usually useful to
* make a copy of an ObjectName. The principal use of this method
* is to guard against a malicious caller who might pass an
* instance of a subclass with surprising behavior to sensitive
* code. Such code can call this method to obtain an ObjectName
* that is known not to have surprising behavior.</p>
*
* @param name an instance of the ObjectName class or of a subclass
*
* @return an instance of ObjectName or a subclass that is known to
* have the same semantics. If <code>name</code> respects the
* semantics of ObjectName, then the returned object is equal
* (though not necessarily identical) to <code>name</code>.
*
* @exception NullPointerException The <code>name</code> is null.
*
*/
public static ObjectName getInstance(ObjectName name) {
if (name.getClass().equals(ObjectName.class))
return name;
return Util.newObjectName(name.getSerializedNameString());
}
Construct an object name from the given string.
Params: - name – A string representation of the object name.
Throws: - MalformedObjectNameException – The string passed as a
parameter does not have the right format.
- NullPointerException – The
name
parameter
is null.
/**
* Construct an object name from the given string.
*
* @param name A string representation of the object name.
*
* @exception MalformedObjectNameException The string passed as a
* parameter does not have the right format.
* @exception NullPointerException The <code>name</code> parameter
* is null.
*/
public ObjectName(String name)
throws MalformedObjectNameException {
construct(name);
}
Construct an object name with exactly one key property.
Params: - domain – The domain part of the object name.
- key – The attribute in the key property of the object name.
- value – The value in the key property of the object name.
Throws: - MalformedObjectNameException – The
domain
, key
, or value
contains an illegal character, or value
does not
follow the rules for quoting. - NullPointerException – One of the parameters is null.
/**
* Construct an object name with exactly one key property.
*
* @param domain The domain part of the object name.
* @param key The attribute in the key property of the object name.
* @param value The value in the key property of the object name.
*
* @exception MalformedObjectNameException The
* <code>domain</code>, <code>key</code>, or <code>value</code>
* contains an illegal character, or <code>value</code> does not
* follow the rules for quoting.
* @exception NullPointerException One of the parameters is null.
*/
public ObjectName(String domain, String key, String value)
throws MalformedObjectNameException {
// If key or value are null a NullPointerException
// will be thrown by the put method in Hashtable.
//
Map<String,String> table = Collections.singletonMap(key, value);
construct(domain, table);
}
Construct an object name with several key properties from a Hashtable.
Params: - domain – The domain part of the object name.
- table – A hash table containing one or more key
properties. The key of each entry in the table is the key of a
key property in the object name. The associated value in the
table is the associated value in the object name.
Throws: - MalformedObjectNameException – The
domain
contains an illegal character, or one of the keys or values in
table
contains an illegal character, or one of the
values in table
does not follow the rules for
quoting. - NullPointerException – One of the parameters is null.
/**
* Construct an object name with several key properties from a Hashtable.
*
* @param domain The domain part of the object name.
* @param table A hash table containing one or more key
* properties. The key of each entry in the table is the key of a
* key property in the object name. The associated value in the
* table is the associated value in the object name.
*
* @exception MalformedObjectNameException The <code>domain</code>
* contains an illegal character, or one of the keys or values in
* <code>table</code> contains an illegal character, or one of the
* values in <code>table</code> does not follow the rules for
* quoting.
* @exception NullPointerException One of the parameters is null.
*/
public ObjectName(String domain, Hashtable<String,String> table)
throws MalformedObjectNameException {
construct(domain, table);
/* The exception for when a key or value in the table is not a
String is now ClassCastException rather than
MalformedObjectNameException. This was not previously
specified. */
}
// Category : ObjectName Construction <==============================
// Category : Getter methods ------------------------------>
Checks whether the object name is a pattern.
An object name is a pattern if its domain contains a
wildcard or if the object name is a property pattern.
Returns: True if the name is a pattern, otherwise false.
/**
* Checks whether the object name is a pattern.
* <p>
* An object name is a pattern if its domain contains a
* wildcard or if the object name is a property pattern.
*
* @return True if the name is a pattern, otherwise false.
*/
public boolean isPattern() {
return (_domain_pattern ||
_property_list_pattern ||
_property_value_pattern);
}
Checks whether the object name is a pattern on the domain part.
Returns: True if the name is a domain pattern, otherwise false.
/**
* Checks whether the object name is a pattern on the domain part.
*
* @return True if the name is a domain pattern, otherwise false.
*
*/
public boolean isDomainPattern() {
return _domain_pattern;
}
Checks whether the object name is a pattern on the key properties.
An object name is a pattern on the key properties if it is a
pattern on the key property list (e.g. "d:k=v,*") or on the
property values (e.g. "d:k=*") or on both (e.g. "d:k=*,*").
Returns: True if the name is a property pattern, otherwise false.
/**
* Checks whether the object name is a pattern on the key properties.
* <p>
* An object name is a pattern on the key properties if it is a
* pattern on the key property list (e.g. "d:k=v,*") or on the
* property values (e.g. "d:k=*") or on both (e.g. "d:k=*,*").
*
* @return True if the name is a property pattern, otherwise false.
*/
public boolean isPropertyPattern() {
return _property_list_pattern || _property_value_pattern;
}
Checks whether the object name is a pattern on the key property list.
For example, "d:k=v,*" and "d:k=*,*" are key property list patterns
whereas "d:k=*" is not.
Returns: True if the name is a property list pattern, otherwise false. Since: 1.6
/**
* Checks whether the object name is a pattern on the key property list.
* <p>
* For example, "d:k=v,*" and "d:k=*,*" are key property list patterns
* whereas "d:k=*" is not.
*
* @return True if the name is a property list pattern, otherwise false.
*
* @since 1.6
*/
public boolean isPropertyListPattern() {
return _property_list_pattern;
}
Checks whether the object name is a pattern on the value part
of at least one of the key properties.
For example, "d:k=*" and "d:k=*,*" are property value patterns
whereas "d:k=v,*" is not.
Returns: True if the name is a property value pattern, otherwise false. Since: 1.6
/**
* Checks whether the object name is a pattern on the value part
* of at least one of the key properties.
* <p>
* For example, "d:k=*" and "d:k=*,*" are property value patterns
* whereas "d:k=v,*" is not.
*
* @return True if the name is a property value pattern, otherwise false.
*
* @since 1.6
*/
public boolean isPropertyValuePattern() {
return _property_value_pattern;
}
Checks whether the value associated with a key in a key
property is a pattern.
Params: - property – The property whose value is to be checked.
Throws: - NullPointerException – If
property
is null. - IllegalArgumentException – If
property
is not
a valid key property for this ObjectName.
Returns: True if the value associated with the given key property
is a pattern, otherwise false. Since: 1.6
/**
* Checks whether the value associated with a key in a key
* property is a pattern.
*
* @param property The property whose value is to be checked.
*
* @return True if the value associated with the given key property
* is a pattern, otherwise false.
*
* @exception NullPointerException If <code>property</code> is null.
* @exception IllegalArgumentException If <code>property</code> is not
* a valid key property for this ObjectName.
*
* @since 1.6
*/
public boolean isPropertyValuePattern(String property) {
if (property == null)
throw new NullPointerException("key property can't be null");
for (int i = 0; i < _ca_array.length; i++) {
Property prop = _ca_array[i];
String key = prop.getKeyString(_canonicalName);
if (key.equals(property))
return (prop instanceof PatternProperty);
}
throw new IllegalArgumentException("key property not found");
}
Returns the canonical form of the name; that is, a string
representation where the properties are sorted in lexical
order.
More precisely, the canonical form of the name is a String
consisting of the domain part, a colon
(:
), the canonical key property list, and
a pattern indication.
The canonical key property list is the same string as described for getCanonicalKeyPropertyListString()
.
The pattern indication is:
- empty for an ObjectName
that is not a property list pattern;
- an asterisk for an ObjectName
that is a property list pattern with no keys; or
- a comma and an
asterisk (
,*
) for an ObjectName that is a property
list pattern with at least one key.
Returns: The canonical form of the name.
/**
* <p>Returns the canonical form of the name; that is, a string
* representation where the properties are sorted in lexical
* order.</p>
*
* <p>More precisely, the canonical form of the name is a String
* consisting of the <em>domain part</em>, a colon
* (<code>:</code>), the <em>canonical key property list</em>, and
* a <em>pattern indication</em>.</p>
*
* <p>The <em>canonical key property list</em> is the same string
* as described for {@link #getCanonicalKeyPropertyListString()}.</p>
*
* <p>The <em>pattern indication</em> is:
* <ul>
* <li>empty for an ObjectName
* that is not a property list pattern;
* <li>an asterisk for an ObjectName
* that is a property list pattern with no keys; or
* <li>a comma and an
* asterisk (<code>,*</code>) for an ObjectName that is a property
* list pattern with at least one key.
* </ul>
*
* @return The canonical form of the name.
*/
public String getCanonicalName() {
return _canonicalName;
}
Returns the domain part.
Returns: The domain.
/**
* Returns the domain part.
*
* @return The domain.
*/
public String getDomain() {
return _canonicalName.substring(0, _domain_length);
}
Obtains the value associated with a key in a key property.
Params: - property – The property whose value is to be obtained.
Throws: - NullPointerException – If
property
is null.
Returns: The value of the property, or null if there is no such
property in this ObjectName.
/**
* Obtains the value associated with a key in a key property.
*
* @param property The property whose value is to be obtained.
*
* @return The value of the property, or null if there is no such
* property in this ObjectName.
*
* @exception NullPointerException If <code>property</code> is null.
*/
public String getKeyProperty(String property) {
return _getKeyPropertyList().get(property);
}
Returns the key properties as a Map. The returned
value is a Map in which each key is a key in the
ObjectName's key property list and each value is the associated
value.
The returned value must not be modified.
Returns: The table of key properties.
/**
* <p>Returns the key properties as a Map. The returned
* value is a Map in which each key is a key in the
* ObjectName's key property list and each value is the associated
* value.</p>
*
* <p>The returned value must not be modified.</p>
*
* @return The table of key properties.
*/
private Map<String,String> _getKeyPropertyList() {
synchronized (this) {
if (_propertyList == null) {
// build (lazy eval) the property list from the canonical
// properties array
_propertyList = new HashMap<String,String>();
int len = _ca_array.length;
Property prop;
for (int i = len - 1; i >= 0; i--) {
prop = _ca_array[i];
_propertyList.put(prop.getKeyString(_canonicalName),
prop.getValueString(_canonicalName));
}
}
}
return _propertyList;
}
Returns the key properties as a Hashtable. The returned
value is a Hashtable in which each key is a key in the
ObjectName's key property list and each value is the associated
value.
The returned value may be unmodifiable. If it is
modifiable, changing it has no effect on this ObjectName.
Returns: The table of key properties.
/**
* <p>Returns the key properties as a Hashtable. The returned
* value is a Hashtable in which each key is a key in the
* ObjectName's key property list and each value is the associated
* value.</p>
*
* <p>The returned value may be unmodifiable. If it is
* modifiable, changing it has no effect on this ObjectName.</p>
*
* @return The table of key properties.
*/
// CR 6441274 depends on the modification property defined above
public Hashtable<String,String> getKeyPropertyList() {
return new Hashtable<String,String>(_getKeyPropertyList());
}
Returns a string representation of the list of key properties specified at creation time. If this ObjectName was constructed with the constructor ObjectName(String)
, the key properties in the returned String will be in the same order as in the argument to the constructor.
Returns: The key property list string. This string is
independent of whether the ObjectName is a pattern.
/**
* <p>Returns a string representation of the list of key
* properties specified at creation time. If this ObjectName was
* constructed with the constructor {@link #ObjectName(String)},
* the key properties in the returned String will be in the same
* order as in the argument to the constructor.</p>
*
* @return The key property list string. This string is
* independent of whether the ObjectName is a pattern.
*/
public String getKeyPropertyListString() {
// BEWARE : we rebuild the propertyliststring at each call !!
if (_kp_array.length == 0) return "";
// the size of the string is the canonical one minus domain
// part and pattern part
final int total_size = _canonicalName.length() - _domain_length - 1
- (_property_list_pattern?2:0);
final char[] dest_chars = new char[total_size];
final char[] value = _canonicalName.toCharArray();
writeKeyPropertyListString(value,dest_chars,0);
return new String(dest_chars);
}
Returns the serialized string of the ObjectName. properties specified at creation time. If this ObjectName was constructed with the constructor ObjectName(String)
, the key properties in the returned String will be in the same order as in the argument to the constructor.
Returns: The key property list string. This string is
independent of whether the ObjectName is a pattern.
/**
* <p>Returns the serialized string of the ObjectName.
* properties specified at creation time. If this ObjectName was
* constructed with the constructor {@link #ObjectName(String)},
* the key properties in the returned String will be in the same
* order as in the argument to the constructor.</p>
*
* @return The key property list string. This string is
* independent of whether the ObjectName is a pattern.
*/
private String getSerializedNameString() {
// the size of the string is the canonical one
final int total_size = _canonicalName.length();
final char[] dest_chars = new char[total_size];
final char[] value = _canonicalName.toCharArray();
final int offset = _domain_length+1;
// copy "domain:" into dest_chars
//
System.arraycopy(value, 0, dest_chars, 0, offset);
// Add property list string
final int end = writeKeyPropertyListString(value,dest_chars,offset);
// Add ",*" if necessary
if (_property_list_pattern) {
if (end == offset) {
// Property list string is empty.
dest_chars[end] = '*';
} else {
// Property list string is not empty.
dest_chars[end] = ',';
dest_chars[end+1] = '*';
}
}
return new String(dest_chars);
}
Write a string representation of the list of key properties specified at creation time in the given array, starting at the specified offset. If this ObjectName was constructed with the constructor ObjectName(String)
, the key properties in the returned String will be in the same order as in the argument to the constructor.
Returns: offset + #of chars written
/**
* <p>Write a string representation of the list of key
* properties specified at creation time in the given array, starting
* at the specified offset. If this ObjectName was
* constructed with the constructor {@link #ObjectName(String)},
* the key properties in the returned String will be in the same
* order as in the argument to the constructor.</p>
*
* @return offset + #of chars written
*/
private int writeKeyPropertyListString(char[] canonicalChars,
char[] data, int offset) {
if (_kp_array.length == 0) return offset;
final char[] dest_chars = data;
final char[] value = canonicalChars;
int index = offset;
final int len = _kp_array.length;
final int last = len - 1;
for (int i = 0; i < len; i++) {
final Property prop = _kp_array[i];
final int prop_len = prop._key_length + prop._value_length + 1;
System.arraycopy(value, prop._key_index, dest_chars, index,
prop_len);
index += prop_len;
if (i < last ) dest_chars[index++] = ',';
}
return index;
}
Returns a string representation of the list of key properties, in which the key properties are sorted in lexical order. This is used in lexicographic comparisons performed in order to select MBeans based on their key property list. Lexical order is the order implied by
String.compareTo(String)
. Returns: The canonical key property list string. This string is
independent of whether the ObjectName is a pattern.
/**
* Returns a string representation of the list of key properties,
* in which the key properties are sorted in lexical order. This
* is used in lexicographic comparisons performed in order to
* select MBeans based on their key property list. Lexical order
* is the order implied by {@link String#compareTo(String)
* String.compareTo(String)}.
*
* @return The canonical key property list string. This string is
* independent of whether the ObjectName is a pattern.
*/
public String getCanonicalKeyPropertyListString() {
if (_ca_array.length == 0) return "";
int len = _canonicalName.length();
if (_property_list_pattern) len -= 2;
return _canonicalName.substring(_domain_length +1, len);
}
// Category : Getter methods <===================================
// Category : Utilities ---------------------------------------->
Returns a string representation of the object name. The
format of this string is not specified, but users can expect
that two ObjectNames return the same string if and only if they
are equal.
Returns: a string representation of this object name.
/**
* <p>Returns a string representation of the object name. The
* format of this string is not specified, but users can expect
* that two ObjectNames return the same string if and only if they
* are equal.</p>
*
* @return a string representation of this object name.
*/
@Override
public String toString() {
return getSerializedNameString();
}
Compares the current object name with another object name. Two ObjectName instances are equal if and only if their canonical forms are equal. The canonical form is the string described for getCanonicalName()
. Params: - object – The object name that the current object name is to be
compared with.
Returns: True if object
is an ObjectName whose
canonical form is equal to that of this ObjectName.
/**
* Compares the current object name with another object name. Two
* ObjectName instances are equal if and only if their canonical
* forms are equal. The canonical form is the string described
* for {@link #getCanonicalName()}.
*
* @param object The object name that the current object name is to be
* compared with.
*
* @return True if <code>object</code> is an ObjectName whose
* canonical form is equal to that of this ObjectName.
*/
@Override
public boolean equals(Object object) {
// same object case
if (this == object) return true;
// object is not an object name case
if (!(object instanceof ObjectName)) return false;
// equality when canonical names are the same
// (because usage of intern())
ObjectName on = (ObjectName) object;
String on_string = on._canonicalName;
if (_canonicalName == on_string) return true; // ES: OK
// Because we are sharing canonical form between object names,
// we have finished the comparison at this stage ==> unequal
return false;
}
Returns a hash code for this object name.
/**
* Returns a hash code for this object name.
*
*/
@Override
public int hashCode() {
return _canonicalName.hashCode();
}
Returns a quoted form of the given String, suitable for
inclusion in an ObjectName. The returned value can be used as
the value associated with a key in an ObjectName. The String
s
may contain any character. Appropriate quoting
ensures that the returned value is legal in an ObjectName.
The returned value consists of a quote ('"'), a sequence of
characters corresponding to the characters of s
,
and another quote. Characters in s
appear
unchanged within the returned value except:
- A quote ('"') is replaced by a backslash (\) followed by a quote.
- An asterisk ('*') is replaced by a backslash (\) followed by an
asterisk.
- A question mark ('?') is replaced by a backslash (\) followed by
a question mark.
- A backslash ('\') is replaced by two backslashes.
- A newline character (the character '\n' in Java) is replaced
by a backslash followed by the character '\n'.
Params: - s – the String to be quoted.
Throws: - NullPointerException – if
s
is null.
Returns: the quoted String.
/**
* <p>Returns a quoted form of the given String, suitable for
* inclusion in an ObjectName. The returned value can be used as
* the value associated with a key in an ObjectName. The String
* <code>s</code> may contain any character. Appropriate quoting
* ensures that the returned value is legal in an ObjectName.</p>
*
* <p>The returned value consists of a quote ('"'), a sequence of
* characters corresponding to the characters of <code>s</code>,
* and another quote. Characters in <code>s</code> appear
* unchanged within the returned value except:</p>
*
* <ul>
* <li>A quote ('"') is replaced by a backslash (\) followed by a quote.</li>
* <li>An asterisk ('*') is replaced by a backslash (\) followed by an
* asterisk.</li>
* <li>A question mark ('?') is replaced by a backslash (\) followed by
* a question mark.</li>
* <li>A backslash ('\') is replaced by two backslashes.</li>
* <li>A newline character (the character '\n' in Java) is replaced
* by a backslash followed by the character '\n'.</li>
* </ul>
*
* @param s the String to be quoted.
*
* @return the quoted String.
*
* @exception NullPointerException if <code>s</code> is null.
*
*/
public static String quote(String s) {
final StringBuilder buf = new StringBuilder("\"");
final int len = s.length();
for (int i = 0; i < len; i++) {
char c = s.charAt(i);
switch (c) {
case '\n':
c = 'n';
buf.append('\\');
break;
case '\\':
case '\"':
case '*':
case '?':
buf.append('\\');
break;
}
buf.append(c);
}
buf.append('"');
return buf.toString();
}
Returns an unquoted form of the given String. If
q
is a String returned by quote(s)
, then unquote(q).equals(s)
. If there is no String
s
for which quote(s).equals(q)
, then
unquote(q) throws an IllegalArgumentException.
These rules imply that there is a one-to-one mapping between
quoted and unquoted forms.
Params: - q – the String to be unquoted.
Throws: - IllegalArgumentException – if
q
could not have been returned by the quote
method, for instance if it does not begin and end with a quote ("). - NullPointerException – if
q
is null.
Returns: the unquoted String.
/**
* <p>Returns an unquoted form of the given String. If
* <code>q</code> is a String returned by {@link #quote quote(s)},
* then <code>unquote(q).equals(s)</code>. If there is no String
* <code>s</code> for which <code>quote(s).equals(q)</code>, then
* unquote(q) throws an IllegalArgumentException.</p>
*
* <p>These rules imply that there is a one-to-one mapping between
* quoted and unquoted forms.</p>
*
* @param q the String to be unquoted.
*
* @return the unquoted String.
*
* @exception IllegalArgumentException if <code>q</code> could not
* have been returned by the {@link #quote} method, for instance
* if it does not begin and end with a quote (").
*
* @exception NullPointerException if <code>q</code> is null.
*
*/
public static String unquote(String q) {
final StringBuilder buf = new StringBuilder();
final int len = q.length();
if (len < 2 || q.charAt(0) != '"' || q.charAt(len - 1) != '"')
throw new IllegalArgumentException("Argument not quoted");
for (int i = 1; i < len - 1; i++) {
char c = q.charAt(i);
if (c == '\\') {
if (i == len - 2)
throw new IllegalArgumentException("Trailing backslash");
c = q.charAt(++i);
switch (c) {
case 'n':
c = '\n';
break;
case '\\':
case '\"':
case '*':
case '?':
break;
default:
throw new IllegalArgumentException(
"Bad character '" + c + "' after backslash");
}
} else {
switch (c) {
case '*' :
case '?' :
case '\"':
case '\n':
throw new IllegalArgumentException(
"Invalid unescaped character '" + c +
"' in the string to unquote");
}
}
buf.append(c);
}
return buf.toString();
}
Defines the wildcard "*:*" ObjectName.
Since: 1.6
/**
* Defines the wildcard "*:*" ObjectName.
*
* @since 1.6
*/
public static final ObjectName WILDCARD = Util.newObjectName("*:*");
// Category : Utilities <===================================
// Category : QueryExp Interface ---------------------------------------->
Test whether this ObjectName, which may be a pattern,
matches another ObjectName. If name
is a pattern,
the result is false. If this ObjectName is a pattern, the
result is true if and only if name
matches the
pattern. If neither this ObjectName nor name
is a pattern, the result is true if and only if the two ObjectNames are equal as described for the equals(Object)
method.
Params: - name – The name of the MBean to compare to.
Throws: - NullPointerException – if
name
is null.
Returns: True if name
matches this ObjectName.
/**
* <p>Test whether this ObjectName, which may be a pattern,
* matches another ObjectName. If <code>name</code> is a pattern,
* the result is false. If this ObjectName is a pattern, the
* result is true if and only if <code>name</code> matches the
* pattern. If neither this ObjectName nor <code>name</code> is
* a pattern, the result is true if and only if the two
* ObjectNames are equal as described for the {@link
* #equals(Object)} method.</p>
*
* @param name The name of the MBean to compare to.
*
* @return True if <code>name</code> matches this ObjectName.
*
* @exception NullPointerException if <code>name</code> is null.
*
*/
public boolean apply(ObjectName name) {
if (name == null) throw new NullPointerException();
if (name._domain_pattern ||
name._property_list_pattern ||
name._property_value_pattern)
return false;
// No pattern
if (!_domain_pattern &&
!_property_list_pattern &&
!_property_value_pattern)
return _canonicalName.equals(name._canonicalName);
return matchDomains(name) && matchKeys(name);
}
private final boolean matchDomains(ObjectName name) {
if (_domain_pattern) {
// wildmatch domains
// This ObjectName is the pattern
// The other ObjectName is the string.
return Util.wildmatch(name.getDomain(),getDomain());
}
return getDomain().equals(name.getDomain());
}
private final boolean matchKeys(ObjectName name) {
// If key property value pattern but not key property list
// pattern, then the number of key properties must be equal
//
if (_property_value_pattern &&
!_property_list_pattern &&
(name._ca_array.length != _ca_array.length))
return false;
// If key property value pattern or key property list pattern,
// then every property inside pattern should exist in name
//
if (_property_value_pattern || _property_list_pattern) {
final Map<String,String> nameProps = name._getKeyPropertyList();
final Property[] props = _ca_array;
final String cn = _canonicalName;
for (int i = props.length - 1; i >= 0 ; i--) {
// Find value in given object name for key at current
// index in receiver
//
final Property p = props[i];
final String k = p.getKeyString(cn);
final String v = nameProps.get(k);
// Did we find a value for this key ?
//
if (v == null) return false;
// If this property is ok (same key, same value), go to next
//
if (_property_value_pattern && (p instanceof PatternProperty)) {
// wildmatch key property values
// p is the property pattern, v is the string
if (Util.wildmatch(v,p.getValueString(cn)))
continue;
else
return false;
}
if (v.equals(p.getValueString(cn))) continue;
return false;
}
return true;
}
// If no pattern, then canonical names must be equal
//
final String p1 = name.getCanonicalKeyPropertyListString();
final String p2 = getCanonicalKeyPropertyListString();
return (p1.equals(p2));
}
/* Method inherited from QueryExp, no implementation needed here
because ObjectName is not relative to an MBeanServer and does
not contain a subquery.
*/
public void setMBeanServer(MBeanServer mbs) { }
// Category : QueryExp Interface <=========================
// Category : Comparable Interface ---------------------------------------->
Compares two ObjectName instances. The ordering relation between
ObjectNames is not completely specified but is intended to be such
that a sorted list of ObjectNames will appear in an order that is
convenient for a person to read.
In particular, if the two ObjectName instances have different
domains then their order is the lexicographical order of the domains.
The ordering of the key property list remains unspecified.
For example, the ObjectName instances below:
- Shapes:type=Square,name=3
- Colors:type=Red,name=2
- Shapes:type=Triangle,side=isosceles,name=2
- Colors:type=Red,name=1
- Shapes:type=Square,name=1
- Colors:type=Blue,name=1
- Shapes:type=Square,name=2
- JMImplementation:type=MBeanServerDelegate
- Shapes:type=Triangle,side=scalene,name=1
could be ordered as follows:
- Colors:type=Blue,name=1
- Colors:type=Red,name=1
- Colors:type=Red,name=2
- JMImplementation:type=MBeanServerDelegate
- Shapes:type=Square,name=1
- Shapes:type=Square,name=2
- Shapes:type=Square,name=3
- Shapes:type=Triangle,side=scalene,name=1
- Shapes:type=Triangle,side=isosceles,name=2
Params: - name – the ObjectName to be compared.
Returns: a negative integer, zero, or a positive integer as this
ObjectName is less than, equal to, or greater than the
specified ObjectName. Since: 1.6
/**
* <p>Compares two ObjectName instances. The ordering relation between
* ObjectNames is not completely specified but is intended to be such
* that a sorted list of ObjectNames will appear in an order that is
* convenient for a person to read.</p>
*
* <p>In particular, if the two ObjectName instances have different
* domains then their order is the lexicographical order of the domains.
* The ordering of the key property list remains unspecified.</p>
*
* <p>For example, the ObjectName instances below:</p>
* <ul>
* <li>Shapes:type=Square,name=3</li>
* <li>Colors:type=Red,name=2</li>
* <li>Shapes:type=Triangle,side=isosceles,name=2</li>
* <li>Colors:type=Red,name=1</li>
* <li>Shapes:type=Square,name=1</li>
* <li>Colors:type=Blue,name=1</li>
* <li>Shapes:type=Square,name=2</li>
* <li>JMImplementation:type=MBeanServerDelegate</li>
* <li>Shapes:type=Triangle,side=scalene,name=1</li>
* </ul>
* <p>could be ordered as follows:</p>
* <ul>
* <li>Colors:type=Blue,name=1</li>
* <li>Colors:type=Red,name=1</li>
* <li>Colors:type=Red,name=2</li>
* <li>JMImplementation:type=MBeanServerDelegate</li>
* <li>Shapes:type=Square,name=1</li>
* <li>Shapes:type=Square,name=2</li>
* <li>Shapes:type=Square,name=3</li>
* <li>Shapes:type=Triangle,side=scalene,name=1</li>
* <li>Shapes:type=Triangle,side=isosceles,name=2</li>
* </ul>
*
* @param name the ObjectName to be compared.
*
* @return a negative integer, zero, or a positive integer as this
* ObjectName is less than, equal to, or greater than the
* specified ObjectName.
*
* @since 1.6
*/
public int compareTo(ObjectName name) {
// Quick optimization:
//
if (name == this) return 0;
// (1) Compare domains
//
int domainValue = this.getDomain().compareTo(name.getDomain());
if (domainValue != 0)
return domainValue;
// (2) Compare "type=" keys
//
// Within a given domain, all names with missing or empty "type="
// come before all names with non-empty type.
//
// When both types are missing or empty, canonical-name ordering
// applies which is a total order.
//
String thisTypeKey = this.getKeyProperty("type");
String anotherTypeKey = name.getKeyProperty("type");
if (thisTypeKey == null)
thisTypeKey = "";
if (anotherTypeKey == null)
anotherTypeKey = "";
int typeKeyValue = thisTypeKey.compareTo(anotherTypeKey);
if (typeKeyValue != 0)
return typeKeyValue;
// (3) Compare canonical names
//
return this.getCanonicalName().compareTo(name.getCanonicalName());
}
// Category : Comparable Interface <=========================
// Public methods <========================================
}