Source Code Cross Referenced for ObjectName.java in  » 6.0-JDK-Core » management » javax » management » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » management » javax.management 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025
0026        package javax.management;
0027
0028        import com.sun.jmx.mbeanserver.GetPropertyAction;
0029        import java.io.IOException;
0030        import java.io.InvalidObjectException;
0031        import java.io.ObjectInputStream;
0032        import java.io.ObjectOutputStream;
0033        import java.io.ObjectStreamField;
0034        import java.security.AccessController;
0035        import java.util.Arrays;
0036        import java.util.Collections;
0037        import java.util.HashMap;
0038        import java.util.Hashtable;
0039        import java.util.Map;
0040        import javax.management.MBeanServer;
0041        import javax.management.MalformedObjectNameException;
0042        import javax.management.QueryExp;
0043
0044        /**
0045         * <p>Represents the object name of an MBean, or a pattern that can
0046         * match the names of several MBeans.  Instances of this class are
0047         * immutable.</p>
0048         *
0049         * <p>An instance of this class can be used to represent:</p>
0050         * <ul>
0051         * <li>An object name</li>
0052         * <li>An object name pattern, within the context of a query</li>
0053         * </ul>
0054         *
0055         * <p>An object name consists of two parts, the domain and the key
0056         * properties.</p>
0057         *
0058         * <p>The <em>domain</em> is a string of characters not including
0059         * the character colon (<code>:</code>).  It is recommended that the domain
0060         * should not contain the string "{@code //}", which is reserved for future use.
0061         *
0062         * <p>If the domain includes at least one occurrence of the wildcard
0063         * characters asterisk (<code>*</code>) or question mark
0064         * (<code>?</code>), then the object name is a pattern.  The asterisk
0065         * matches any sequence of zero or more characters, while the question
0066         * mark matches any single character.</p>
0067         *
0068         * <p>If the domain is empty, it will be replaced in certain contexts
0069         * by the <em>default domain</em> of the MBean server in which the
0070         * ObjectName is used.</p>
0071         *
0072         * <p>The <em>key properties</em> are an unordered set of keys and
0073         * associated values.</p>
0074         *
0075         * <p>Each <em>key</em> is a nonempty string of characters which may
0076         * not contain any of the characters comma (<code>,</code>), equals
0077         * (<code>=</code>), colon, asterisk, or question mark.  The same key
0078         * may not occur twice in a given ObjectName.</p>
0079         *
0080         * <p>Each <em>value</em> associated with a key is a string of
0081         * characters that is either unquoted or quoted.</p>
0082         *
0083         * <p>An <em>unquoted value</em> is a possibly empty string of
0084         * characters which may not contain any of the characters comma,
0085         * equals, colon, or quote.</p>
0086         *
0087         * <p>If the <em>unquoted value</em> contains at least one occurrence
0088         * of the wildcard characters asterisk or question mark, then the object
0089         * name is a <em>property value pattern</em>. The asterisk matches any
0090         * sequence of zero or more characters, while the question mark matches
0091         * any single character.</p>
0092         *
0093         * <p>A <em>quoted value</em> consists of a quote (<code>"</code>),
0094         * followed by a possibly empty string of characters, followed by
0095         * another quote.  Within the string of characters, the backslash
0096         * (<code>\</code>) has a special meaning.  It must be followed by
0097         * one of the following characters:</p>
0098         *
0099         * <ul>
0100         * <li>Another backslash.  The second backslash has no special
0101         * meaning and the two characters represent a single backslash.</li>
0102         *
0103         * <li>The character 'n'.  The two characters represent a newline
0104         * ('\n' in Java).</li>
0105         *
0106         * <li>A quote.  The two characters represent a quote, and that quote
0107         * is not considered to terminate the quoted value. An ending closing
0108         * quote must be present for the quoted value to be valid.</li>
0109         *
0110         * <li>A question mark (?) or asterisk (*).  The two characters represent
0111         * a question mark or asterisk respectively.</li>
0112         * </ul>
0113         *
0114         * <p>A quote may not appear inside a quoted value except immediately
0115         * after an odd number of consecutive backslashes.</p>
0116         *
0117         * <p>The quotes surrounding a quoted value, and any backslashes
0118         * within that value, are considered to be part of the value.</p>
0119         *
0120         * <p>If the <em>quoted value</em> contains at least one occurrence of
0121         * the characters asterisk or question mark and they are not preceded
0122         * by a backslash, then they are considered as wildcard characters and
0123         * the object name is a <em>property value pattern</em>. The asterisk
0124         * matches any sequence of zero or more characters, while the question
0125         * mark matches any single character.</p>
0126         *
0127         * <p>An ObjectName may be a <em>property list pattern</em>. In this
0128         * case it may have zero or more keys and associated values. It matches
0129         * a nonpattern ObjectName whose domain matches and that contains the
0130         * same keys and associated values, as well as possibly other keys and
0131         * values.</p>
0132         *
0133         * <p>An ObjectName is a <em>property value pattern</em> when at least
0134         * one of its <em>quoted</em> or <em>unquoted</em> key property values
0135         * contains the wildcard characters asterisk or question mark as described
0136         * above. In this case it has one or more keys and associated values, with
0137         * at least one of the values containing wildcard characters. It matches a
0138         * nonpattern ObjectName whose domain matches and that contains the same
0139         * keys whose values match; if the property value pattern is also a
0140         * property list pattern then the nonpattern ObjectName can contain
0141         * other keys and values.</p>
0142         *
0143         * <p>An ObjectName is a <em>property pattern</em> if it is either a
0144         * <em>property list pattern</em> or a <em>property value pattern</em>
0145         * or both.</p>
0146         *
0147         * <p>An ObjectName is a pattern if its domain contains a wildcard or
0148         * if the ObjectName is a property pattern.</p>
0149         *
0150         * <p>If an ObjectName is not a pattern, it must contain at least one
0151         * key with its associated value.</p>
0152         *
0153         * <p>Examples of ObjectName patterns are:</p>
0154         *
0155         * <ul>
0156         * <li>{@code *:type=Foo,name=Bar} to match names in any domain whose
0157         *     exact set of keys is {@code type=Foo,name=Bar}.</li>
0158         * <li>{@code d:type=Foo,name=Bar,*} to match names in the domain
0159         *     {@code d} that have the keys {@code type=Foo,name=Bar} plus
0160         *     zero or more other keys.</li>
0161         * <li>{@code *:type=Foo,name=Bar,*} to match names in any domain
0162         *     that has the keys {@code type=Foo,name=Bar} plus zero or
0163         *     more other keys.</li>
0164         * <li>{@code d:type=F?o,name=Bar} will match e.g.
0165         *     {@code d:type=Foo,name=Bar} and {@code d:type=Fro,name=Bar}.</li>
0166         * <li>{@code d:type=F*o,name=Bar} will match e.g.
0167         *     {@code d:type=Fo,name=Bar} and {@code d:type=Frodo,name=Bar}.</li>
0168         * <li>{@code d:type=Foo,name="B*"} will match e.g.
0169         *     {@code d:type=Foo,name="Bling"}. Wildcards are recognized even
0170         *     inside quotes, and like other special characters can be escaped
0171         *     with {@code \}.</li>
0172         * </ul>
0173         *
0174         * <p>An ObjectName can be written as a String with the following
0175         * elements in order:</p>
0176         *
0177         * <ul>
0178         * <li>The domain.
0179         * <li>A colon (<code>:</code>).
0180         * <li>A key property list as defined below.
0181         * </ul>
0182         *
0183         * <p>A key property list written as a String is a comma-separated
0184         * list of elements.  Each element is either an asterisk or a key
0185         * property.  A key property consists of a key, an equals
0186         * (<code>=</code>), and the associated value.</p>
0187         *
0188         * <p>At most one element of a key property list may be an asterisk.
0189         * If the key property list contains an asterisk element, the
0190         * ObjectName is a property list pattern.</p>
0191         *
0192         * <p>Spaces have no special significance in a String representing an
0193         * ObjectName.  For example, the String:
0194         * <pre>
0195         * domain: key1 = value1 , key2 = value2
0196         * </pre>
0197         * represents an ObjectName with two keys.  The name of each key
0198         * contains six characters, of which the first and last are spaces.
0199         * The value associated with the key <code>"&nbsp;key1&nbsp;"</code>
0200         * also begins and ends with a space.</p>
0201         *
0202         * <p>In addition to the restrictions on characters spelt out above,
0203         * no part of an ObjectName may contain a newline character
0204         * (<code>'\n'</code>), whether the domain, a key, or a value, whether
0205         * quoted or unquoted.  The newline character can be represented in a
0206         * quoted value with the sequence <code>\n</code>.
0207         *
0208         * <p>The rules on special characters and quoting apply regardless of
0209         * which constructor is used to make an ObjectName.</p>
0210         *
0211         * <p>To avoid collisions between MBeans supplied by different
0212         * vendors, a useful convention is to begin the domain name with the
0213         * reverse DNS name of the organization that specifies the MBeans,
0214         * followed by a period and a string whose interpretation is
0215         * determined by that organization.  For example, MBeans specified by
0216         * Sun Microsystems Inc., DNS name <code>sun.com</code>, would have
0217         * domains such as <code>com.sun.MyDomain</code>.  This is essentially
0218         * the same convention as for Java-language package names.</p>
0219         *
0220         * <p>The <b>serialVersionUID</b> of this class is <code>1081892073854801359L</code>.
0221         * 
0222         * @since 1.5
0223         */
0224        @SuppressWarnings("serial")
0225        // don't complain serialVersionUID not constant
0226        public class ObjectName implements  Comparable<ObjectName>, QueryExp {
0227
0228            /**
0229             * A structure recording property structure and
0230             * proposing minimal services
0231             */
0232            private static class Property {
0233
0234                int _key_index;
0235                int _key_length;
0236                int _value_length;
0237
0238                /**
0239                 * Constructor.
0240                 */
0241                Property(int key_index, int key_length, int value_length) {
0242                    _key_index = key_index;
0243                    _key_length = key_length;
0244                    _value_length = value_length;
0245                }
0246
0247                /**
0248                 * Assigns the key index of property
0249                 */
0250                void setKeyIndex(int key_index) {
0251                    _key_index = key_index;
0252                }
0253
0254                /**
0255                 * Returns a key string for receiver key
0256                 */
0257                String getKeyString(String name) {
0258                    return name.substring(_key_index, _key_index + _key_length);
0259                }
0260
0261                /**
0262                 * Returns a value string for receiver key
0263                 */
0264                String getValueString(String name) {
0265                    int in_begin = _key_index + _key_length + 1;
0266                    int out_end = in_begin + _value_length;
0267                    return name.substring(in_begin, out_end);
0268                }
0269            }
0270
0271            /**
0272             * Marker class for value pattern property.
0273             */
0274            private static class PatternProperty extends Property {
0275                /**
0276                 * Constructor.
0277                 */
0278                PatternProperty(int key_index, int key_length, int value_length) {
0279                    super (key_index, key_length, value_length);
0280                }
0281            }
0282
0283            // Inner classes <========================================
0284
0285            // Private fields ---------------------------------------->
0286
0287            // Serialization compatibility stuff -------------------->
0288
0289            // Two serial forms are supported in this class. The selected form depends
0290            // on system property "jmx.serial.form":
0291            //  - "1.0" for JMX 1.0
0292            //  - any other value for JMX 1.1 and higher
0293            //
0294            // Serial version for old serial form
0295            private static final long oldSerialVersionUID = -5467795090068647408L;
0296            //
0297            // Serial version for new serial form
0298            private static final long newSerialVersionUID = 1081892073854801359L;
0299            //
0300            // Serializable fields in old serial form
0301            private static final ObjectStreamField[] oldSerialPersistentFields = {
0302                    new ObjectStreamField("domain", String.class),
0303                    new ObjectStreamField("propertyList", Hashtable.class),
0304                    new ObjectStreamField("propertyListString", String.class),
0305                    new ObjectStreamField("canonicalName", String.class),
0306                    new ObjectStreamField("pattern", Boolean.TYPE),
0307                    new ObjectStreamField("propertyPattern", Boolean.TYPE) };
0308            //
0309            // Serializable fields in new serial form
0310            private static final ObjectStreamField[] newSerialPersistentFields = {};
0311            //
0312            // Actual serial version and serial form
0313            private static final long serialVersionUID;
0314            private static final ObjectStreamField[] serialPersistentFields;
0315            private static boolean compat = false;
0316            static {
0317                try {
0318                    GetPropertyAction act = new GetPropertyAction(
0319                            "jmx.serial.form");
0320                    String form = AccessController.doPrivileged(act);
0321                    compat = (form != null && form.equals("1.0"));
0322                } catch (Exception e) {
0323                    // OK: exception means no compat with 1.0, too bad
0324                }
0325                if (compat) {
0326                    serialPersistentFields = oldSerialPersistentFields;
0327                    serialVersionUID = oldSerialVersionUID;
0328                } else {
0329                    serialPersistentFields = newSerialPersistentFields;
0330                    serialVersionUID = newSerialVersionUID;
0331                }
0332            }
0333
0334            //
0335            // Serialization compatibility stuff <==============================
0336
0337            // Class private fields ----------------------------------->
0338
0339            /**
0340             * a shared empty array for empty property lists
0341             */
0342            static final private Property[] _Empty_property_array = new Property[0];
0343
0344            // Class private fields <==============================
0345
0346            // Instance private fields ----------------------------------->
0347
0348            /**
0349             * a String containing the canonical name
0350             */
0351            private transient String _canonicalName;
0352
0353            /**
0354             * An array of properties in the same seq order as time creation
0355             */
0356            private transient Property[] _kp_array;
0357
0358            /**
0359             * An array of properties in the same seq order as canonical order
0360             */
0361            private transient Property[] _ca_array;
0362
0363            /**
0364             * The length of the domain part of built objectname
0365             */
0366            private transient int _domain_length = 0;
0367
0368            /**
0369             * The propertyList of built object name. Initialized lazily.
0370             * Table that contains all the pairs (key,value) for this ObjectName.
0371             */
0372            private transient Map<String, String> _propertyList;
0373
0374            /**
0375             * boolean that declares if this ObjectName domain part is a pattern
0376             */
0377            private transient boolean _domain_pattern = false;
0378
0379            /**
0380             * boolean that declares if this ObjectName contains a pattern on the
0381             * key property list
0382             */
0383            private transient boolean _property_list_pattern = false;
0384
0385            /**
0386             * boolean that declares if this ObjectName contains a pattern on the
0387             * value of at least one key property
0388             */
0389            private transient boolean _property_value_pattern = false;
0390
0391            // Instance private fields <=======================================
0392
0393            // Private fields <========================================
0394
0395            //  Private methods ---------------------------------------->
0396
0397            // Category : Instance construction ------------------------->
0398
0399            /**
0400             * Initializes this {@link ObjectName} from the given string
0401             * representation.
0402             *
0403             * @param name A string representation of the {@link ObjectName}
0404             *
0405             * @exception MalformedObjectNameException The string passed as a
0406             * parameter does not have the right format.
0407             * @exception NullPointerException The <code>name</code> parameter
0408             * is null.
0409             */
0410            private void construct(String name)
0411                    throws MalformedObjectNameException, NullPointerException {
0412
0413                // The name cannot be null
0414                if (name == null)
0415                    throw new NullPointerException("name cannot be null");
0416
0417                // Test if the name is empty
0418                if (name.length() == 0) {
0419                    // this is equivalent to the whole word query object name.
0420                    _canonicalName = "*:*";
0421                    _kp_array = _Empty_property_array;
0422                    _ca_array = _Empty_property_array;
0423                    _domain_length = 1;
0424                    _propertyList = null;
0425                    _domain_pattern = true;
0426                    _property_list_pattern = true;
0427                    _property_value_pattern = false;
0428                    return;
0429                }
0430
0431                // initialize parsing of the string
0432                char[] name_chars = name.toCharArray();
0433                int len = name_chars.length;
0434                char[] canonical_chars = new char[len]; // canonical form will be same
0435                // length at most
0436                int cname_index = 0;
0437                int index = 0;
0438                char c, c1;
0439
0440                // parses domain part
0441                domain_parsing: while (index < len) {
0442                    switch (c = name_chars[index]) {
0443                    case ':':
0444                        _domain_length = index++;
0445                        break domain_parsing;
0446                    case '=':
0447                        // ":" omission check.
0448                        //
0449                        // Although "=" is a valid character in the domain part
0450                        // it is true that it is rarely used in the real world.
0451                        // So check straight away if the ":" has been omitted
0452                        // from the ObjectName. This allows us to provide a more
0453                        // accurate exception message.
0454                        int i = ++index;
0455                        while ((i < len) && (name_chars[i++] != ':'))
0456                            if (i == len)
0457                                throw new MalformedObjectNameException(
0458                                        "Domain part must be specified");
0459                        break;
0460                    case '\n':
0461                        throw new MalformedObjectNameException(
0462                                "Invalid character '\\n' in domain name");
0463                    case '*':
0464                    case '?':
0465                        _domain_pattern = true;
0466                        index++;
0467                        break;
0468                    default:
0469                        index++;
0470                        break;
0471                    }
0472                }
0473
0474                // check for non-empty properties
0475                if (index == len)
0476                    throw new MalformedObjectNameException(
0477                            "Key properties cannot be empty");
0478
0479                // we have got the domain part, begins building of _canonicalName
0480                System.arraycopy(name_chars, 0, canonical_chars, 0,
0481                        _domain_length);
0482                canonical_chars[_domain_length] = ':';
0483                cname_index = _domain_length + 1;
0484
0485                // parses property list
0486                Property prop;
0487                Map<String, Property> keys_map = new HashMap<String, Property>();
0488                String[] keys;
0489                String key_name;
0490                boolean quoted_value;
0491                int property_index = 0;
0492                int in_index;
0493                int key_index, key_length, value_index, value_length;
0494
0495                keys = new String[10];
0496                _kp_array = new Property[10];
0497                _property_list_pattern = false;
0498                _property_value_pattern = false;
0499
0500                while (index < len) {
0501                    c = name_chars[index];
0502
0503                    // case of pattern properties
0504                    if (c == '*') {
0505                        if (_property_list_pattern)
0506                            throw new MalformedObjectNameException(
0507                                    "Cannot have several '*' characters in pattern "
0508                                            + "property list");
0509                        else {
0510                            _property_list_pattern = true;
0511                            if ((++index < len) && (name_chars[index] != ','))
0512                                throw new MalformedObjectNameException(
0513                                        "Invalid character found after '*': end of "
0514                                                + "name or ',' expected");
0515                            else if (index == len) {
0516                                if (property_index == 0) {
0517                                    // empty properties case
0518                                    _kp_array = _Empty_property_array;
0519                                    _ca_array = _Empty_property_array;
0520                                    _propertyList = Collections.emptyMap();
0521                                }
0522                                break;
0523                            } else {
0524                                // correct pattern spec in props, continue
0525                                index++;
0526                                continue;
0527                            }
0528                        }
0529                    }
0530
0531                    // standard property case, key part
0532                    in_index = index;
0533                    key_index = in_index;
0534                    if (name_chars[in_index] == '=')
0535                        throw new MalformedObjectNameException(
0536                                "Invalid key (empty)");
0537                    while ((in_index < len)
0538                            && ((c1 = name_chars[in_index++]) != '='))
0539                        switch (c1) {
0540                        // '=' considered to introduce value part
0541                        case '*':
0542                        case '?':
0543                        case ',':
0544                        case ':':
0545                        case '\n':
0546                            final String ichar = ((c1 == '\n') ? "\\n" : ""
0547                                    + c1);
0548                            throw new MalformedObjectNameException(
0549                                    "Invalid character '" + ichar
0550                                            + "' in key part of property");
0551                        }
0552                    if (name_chars[in_index - 1] != '=')
0553                        throw new MalformedObjectNameException(
0554                                "Unterminated key property part");
0555                    value_index = in_index; // in_index pointing after '=' char
0556                    key_length = value_index - key_index - 1; // found end of key
0557
0558                    // standard property case, value part
0559                    boolean value_pattern = false;
0560                    if (in_index < len && name_chars[in_index] == '\"') {
0561                        quoted_value = true;
0562                        // the case of quoted value part
0563                        quoted_value_parsing: while ((++in_index < len)
0564                                && ((c1 = name_chars[in_index]) != '\"')) {
0565                            // the case of an escaped character
0566                            if (c1 == '\\') {
0567                                if (++in_index == len)
0568                                    throw new MalformedObjectNameException(
0569                                            "Unterminated quoted value");
0570                                switch (c1 = name_chars[in_index]) {
0571                                case '\\':
0572                                case '\"':
0573                                case '?':
0574                                case '*':
0575                                case 'n':
0576                                    break; // valid character
0577                                default:
0578                                    throw new MalformedObjectNameException(
0579                                            "Invalid escape sequence '\\" + c1
0580                                                    + "' in quoted value");
0581                                }
0582                            } else if (c1 == '\n') {
0583                                throw new MalformedObjectNameException(
0584                                        "Newline in quoted value");
0585                            } else {
0586                                switch (c1) {
0587                                case '?':
0588                                case '*':
0589                                    value_pattern = true;
0590                                    break;
0591                                }
0592                            }
0593                        }
0594                        if (in_index == len)
0595                            throw new MalformedObjectNameException(
0596                                    "Unterminated quoted value");
0597                        else
0598                            value_length = ++in_index - value_index;
0599                    } else {
0600                        // the case of standard value part
0601                        quoted_value = false;
0602                        while ((in_index < len)
0603                                && ((c1 = name_chars[in_index]) != ','))
0604                            switch (c1) {
0605                            // ',' considered to be the value separator
0606                            case '*':
0607                            case '?':
0608                                value_pattern = true;
0609                                in_index++;
0610                                break;
0611                            case '=':
0612                            case ':':
0613                            case '"':
0614                            case '\n':
0615                                final String ichar = ((c1 == '\n') ? "\\n" : ""
0616                                        + c1);
0617                                throw new MalformedObjectNameException(
0618                                        "Invalid character '" + c1
0619                                                + "' in value part of property");
0620                            default:
0621                                in_index++;
0622                                break;
0623                            }
0624                        value_length = in_index - value_index;
0625                    }
0626
0627                    // Parsed property, checks the end of name
0628                    if (in_index == len - 1) {
0629                        if (quoted_value)
0630                            throw new MalformedObjectNameException(
0631                                    "Invalid ending character `"
0632                                            + name_chars[in_index] + "'");
0633                        else
0634                            throw new MalformedObjectNameException(
0635                                    "Invalid ending comma");
0636                    } else
0637                        in_index++;
0638
0639                    // we got the key and value part, prepare a property for this
0640                    if (!value_pattern) {
0641                        prop = new Property(key_index, key_length, value_length);
0642                    } else {
0643                        _property_value_pattern = true;
0644                        prop = new PatternProperty(key_index, key_length,
0645                                value_length);
0646                    }
0647                    key_name = name
0648                            .substring(key_index, key_index + key_length);
0649
0650                    if (property_index == keys.length) {
0651                        String[] tmp_string_array = new String[property_index + 10];
0652                        System.arraycopy(keys, 0, tmp_string_array, 0,
0653                                property_index);
0654                        keys = tmp_string_array;
0655                    }
0656                    keys[property_index] = key_name;
0657
0658                    addProperty(prop, property_index, keys_map, key_name);
0659                    property_index++;
0660                    index = in_index;
0661                }
0662
0663                // computes and set canonical name
0664                setCanonicalName(name_chars, canonical_chars, keys, keys_map,
0665                        cname_index, property_index);
0666            }
0667
0668            /**
0669             * Construct an ObjectName from a domain and a Hashtable.
0670             *
0671             * @param domain Domain of the ObjectName.
0672             * @param props  Map containing couples <i>key</i> -> <i>value</i>.
0673             *
0674             * @exception MalformedObjectNameException The <code>domain</code>
0675             * contains an illegal character, or one of the keys or values in
0676             * <code>table</code> contains an illegal character, or one of the
0677             * values in <code>table</code> does not follow the rules for quoting.
0678             * @exception NullPointerException One of the parameters is null.
0679             */
0680            private void construct(String domain, Map<String, String> props)
0681                    throws MalformedObjectNameException, NullPointerException {
0682
0683                // The domain cannot be null
0684                if (domain == null)
0685                    throw new NullPointerException("domain cannot be null");
0686
0687                // The key property list cannot be null
0688                if (props == null)
0689                    throw new NullPointerException(
0690                            "key property list cannot be null");
0691
0692                // The key property list cannot be empty
0693                if (props.isEmpty())
0694                    throw new MalformedObjectNameException(
0695                            "key property list cannot be empty");
0696
0697                // checks domain validity
0698                if (!isDomain(domain))
0699                    throw new MalformedObjectNameException("Invalid domain: "
0700                            + domain);
0701
0702                // init canonicalname
0703                final StringBuilder sb = new StringBuilder();
0704                sb.append(domain).append(':');
0705                _domain_length = domain.length();
0706
0707                // allocates the property array
0708                int nb_props = props.size();
0709                _kp_array = new Property[nb_props];
0710
0711                String[] keys = new String[nb_props];
0712                final Map<String, Property> keys_map = new HashMap<String, Property>();
0713                Property prop;
0714                int key_index;
0715                int i = 0;
0716                for (Map.Entry<String, String> entry : props.entrySet()) {
0717                    if (sb.length() > 0)
0718                        sb.append(",");
0719                    String key = entry.getKey();
0720                    String value;
0721                    try {
0722                        value = entry.getValue();
0723                    } catch (ClassCastException e) {
0724                        throw new MalformedObjectNameException(e.getMessage());
0725                    }
0726                    key_index = sb.length();
0727                    checkKey(key);
0728                    sb.append(key);
0729                    keys[i] = key;
0730                    sb.append("=");
0731                    boolean value_pattern = checkValue(value);
0732                    sb.append(value);
0733                    if (!value_pattern) {
0734                        prop = new Property(key_index, key.length(), value
0735                                .length());
0736                    } else {
0737                        _property_value_pattern = true;
0738                        prop = new PatternProperty(key_index, key.length(),
0739                                value.length());
0740                    }
0741                    addProperty(prop, i, keys_map, key);
0742                    i++;
0743                }
0744
0745                // initialize canonical name and data structure
0746                int len = sb.length();
0747                char[] initial_chars = new char[len];
0748                sb.getChars(0, len, initial_chars, 0);
0749                char[] canonical_chars = new char[len];
0750                System.arraycopy(initial_chars, 0, canonical_chars, 0,
0751                        _domain_length + 1);
0752                setCanonicalName(initial_chars, canonical_chars, keys,
0753                        keys_map, _domain_length + 1, _kp_array.length);
0754            }
0755
0756            // Category : Instance construction <==============================
0757
0758            // Category : Internal utilities ------------------------------>
0759
0760            /**
0761             * Add passed property to the list at the given index
0762             * for the passed key name
0763             */
0764            private void addProperty(Property prop, int index,
0765                    Map<String, Property> keys_map, String key_name)
0766                    throws MalformedObjectNameException {
0767
0768                if (keys_map.containsKey(key_name))
0769                    throw new MalformedObjectNameException("key `" + key_name
0770                            + "' already defined");
0771
0772                // if no more space for property arrays, have to increase it
0773                if (index == _kp_array.length) {
0774                    Property[] tmp_prop_array = new Property[index + 10];
0775                    System.arraycopy(_kp_array, 0, tmp_prop_array, 0, index);
0776                    _kp_array = tmp_prop_array;
0777                }
0778                _kp_array[index] = prop;
0779                keys_map.put(key_name, prop);
0780            }
0781
0782            /**
0783             * Sets the canonical name of receiver from input 'specified_chars'
0784             * array, by filling 'canonical_chars' array with found 'nb-props'
0785             * properties starting at position 'prop_index'.
0786             */
0787            private void setCanonicalName(char[] specified_chars,
0788                    char[] canonical_chars, String[] keys,
0789                    Map<String, Property> keys_map, int prop_index, int nb_props) {
0790
0791                // Sort the list of found properties
0792                if (_kp_array != _Empty_property_array) {
0793                    String[] tmp_keys = new String[nb_props];
0794                    Property[] tmp_props = new Property[nb_props];
0795
0796                    System.arraycopy(keys, 0, tmp_keys, 0, nb_props);
0797                    Arrays.sort(tmp_keys);
0798                    keys = tmp_keys;
0799                    System.arraycopy(_kp_array, 0, tmp_props, 0, nb_props);
0800                    _kp_array = tmp_props;
0801                    _ca_array = new Property[nb_props];
0802
0803                    // now assigns _ca_array to the sorted list of keys
0804                    // (there cannot be two identical keys in an objectname.
0805                    for (int i = 0; i < nb_props; i++)
0806                        _ca_array[i] = keys_map.get(keys[i]);
0807
0808                    // now we build the canonical name and set begin indexes of
0809                    // properties to reflect canonical form
0810                    int last_index = nb_props - 1;
0811                    int prop_len;
0812                    Property prop;
0813                    for (int i = 0; i <= last_index; i++) {
0814                        prop = _ca_array[i];
0815                        // length of prop including '=' char
0816                        prop_len = prop._key_length + prop._value_length + 1;
0817                        System.arraycopy(specified_chars, prop._key_index,
0818                                canonical_chars, prop_index, prop_len);
0819                        prop.setKeyIndex(prop_index);
0820                        prop_index += prop_len;
0821                        if (i != last_index) {
0822                            canonical_chars[prop_index] = ',';
0823                            prop_index++;
0824                        }
0825                    }
0826                }
0827
0828                // terminate canonicalname with '*' in case of pattern
0829                if (_property_list_pattern) {
0830                    if (_kp_array != _Empty_property_array)
0831                        canonical_chars[prop_index++] = ',';
0832                    canonical_chars[prop_index++] = '*';
0833                }
0834
0835                // we now build the canonicalname string
0836                _canonicalName = (new String(canonical_chars, 0, prop_index))
0837                        .intern();
0838            }
0839
0840            /**
0841             * Parse a key.
0842             * <pre>final int endKey=parseKey(s,startKey);</pre>
0843             * <p>key starts at startKey (included), and ends at endKey (excluded).
0844             * If (startKey == endKey), then the key is empty.
0845             *
0846             * @param s The char array of the original string.
0847             * @param startKey index at which to begin parsing.
0848             * @return The index following the last character of the key.
0849             **/
0850            private static int parseKey(final char[] s, final int startKey)
0851                    throws MalformedObjectNameException {
0852                int next = startKey;
0853                int endKey = startKey;
0854                final int len = s.length;
0855                while (next < len) {
0856                    final char k = s[next++];
0857                    switch (k) {
0858                    case '*':
0859                    case '?':
0860                    case ',':
0861                    case ':':
0862                    case '\n':
0863                        final String ichar = ((k == '\n') ? "\\n" : "" + k);
0864                        throw new MalformedObjectNameException(
0865                                "Invalid character in key: `" + ichar + "'");
0866                    case '=':
0867                        // we got the key.
0868                        endKey = next - 1;
0869                        break;
0870                    default:
0871                        if (next < len)
0872                            continue;
0873                        else
0874                            endKey = next;
0875                    }
0876                    break;
0877                }
0878                return endKey;
0879            }
0880
0881            /**
0882             * Parse a value.
0883             * <pre>final int endVal=parseValue(s,startVal);</pre>
0884             * <p>value starts at startVal (included), and ends at endVal (excluded).
0885             * If (startVal == endVal), then the key is empty.
0886             *
0887             * @param s The char array of the original string.
0888             * @param startValue index at which to begin parsing.
0889             * @return The first element of the int array indicates the index
0890             *         following the last character of the value. The second
0891             *         element of the int array indicates that the value is
0892             *         a pattern when its value equals 1.
0893             **/
0894            private static int[] parseValue(final char[] s, final int startValue)
0895                    throws MalformedObjectNameException {
0896
0897                boolean value_pattern = false;
0898
0899                int next = startValue;
0900                int endValue = startValue;
0901
0902                final int len = s.length;
0903                final char q = s[startValue];
0904
0905                if (q == '"') {
0906                    // quoted value
0907                    if (++next == len)
0908                        throw new MalformedObjectNameException("Invalid quote");
0909                    while (next < len) {
0910                        char last = s[next];
0911                        if (last == '\\') {
0912                            if (++next == len)
0913                                throw new MalformedObjectNameException(
0914                                        "Invalid unterminated quoted character sequence");
0915                            last = s[next];
0916                            switch (last) {
0917                            case '\\':
0918                            case '?':
0919                            case '*':
0920                            case 'n':
0921                                break;
0922                            case '\"':
0923                                // We have an escaped quote. If this escaped
0924                                // quote is the last character, it does not
0925                                // qualify as a valid termination quote.
0926                                //
0927                                if (next + 1 == len)
0928                                    throw new MalformedObjectNameException(
0929                                            "Missing termination quote");
0930                                break;
0931                            default:
0932                                throw new MalformedObjectNameException(
0933                                        "Invalid quoted character sequence '\\"
0934                                                + last + "'");
0935                            }
0936                        } else if (last == '\n') {
0937                            throw new MalformedObjectNameException(
0938                                    "Newline in quoted value");
0939                        } else if (last == '\"') {
0940                            next++;
0941                            break;
0942                        } else {
0943                            switch (last) {
0944                            case '?':
0945                            case '*':
0946                                value_pattern = true;
0947                                break;
0948                            }
0949                        }
0950                        next++;
0951
0952                        // Check that last character is a termination quote.
0953                        // We have already handled the case were the last
0954                        // character is an escaped quote earlier.
0955                        //
0956                        if ((next >= len) && (last != '\"'))
0957                            throw new MalformedObjectNameException(
0958                                    "Missing termination quote");
0959                    }
0960                    endValue = next;
0961                    if (next < len) {
0962                        if (s[next++] != ',')
0963                            throw new MalformedObjectNameException(
0964                                    "Invalid quote");
0965                    }
0966                } else {
0967                    // Non quoted value.
0968                    while (next < len) {
0969                        final char v = s[next++];
0970                        switch (v) {
0971                        case '*':
0972                        case '?':
0973                            value_pattern = true;
0974                            if (next < len)
0975                                continue;
0976                            else
0977                                endValue = next;
0978                            break;
0979                        case '=':
0980                        case ':':
0981                        case '\n':
0982                            final String ichar = ((v == '\n') ? "\\n" : "" + v);
0983                            throw new MalformedObjectNameException(
0984                                    "Invalid character `" + ichar
0985                                            + "' in value");
0986                        case ',':
0987                            endValue = next - 1;
0988                            break;
0989                        default:
0990                            if (next < len)
0991                                continue;
0992                            else
0993                                endValue = next;
0994                        }
0995                        break;
0996                    }
0997                }
0998                return new int[] { endValue, value_pattern ? 1 : 0 };
0999            }
1000
1001            /**
1002             * Check if the supplied value is a valid value.
1003             *
1004             * @return true if the value is a pattern, otherwise false.
1005             */
1006            private static boolean checkValue(String val)
1007                    throws MalformedObjectNameException {
1008
1009                if (val == null)
1010                    throw new NullPointerException("Invalid value (null)");
1011
1012                final int len = val.length();
1013                if (len == 0)
1014                    return false;
1015
1016                final char[] s = val.toCharArray();
1017                final int[] result = parseValue(s, 0);
1018                final int endValue = result[0];
1019                final boolean value_pattern = result[1] == 1;
1020                if (endValue < len)
1021                    throw new MalformedObjectNameException(
1022                            "Invalid character in value: `" + s[endValue] + "'");
1023                return value_pattern;
1024            }
1025
1026            /**
1027             * Check if the supplied key is a valid key.
1028             */
1029            private static void checkKey(String key)
1030                    throws MalformedObjectNameException, NullPointerException {
1031
1032                if (key == null)
1033                    throw new NullPointerException("Invalid key (null)");
1034
1035                final int len = key.length();
1036                if (len == 0)
1037                    throw new MalformedObjectNameException(
1038                            "Invalid key (empty)");
1039                final char[] k = key.toCharArray();
1040                final int endKey = parseKey(k, 0);
1041                if (endKey < len)
1042                    throw new MalformedObjectNameException(
1043                            "Invalid character in value: `" + k[endKey] + "'");
1044            }
1045
1046            /*
1047             * Tests whether string s is matched by pattern p.
1048             * Supports "?", "*" each of which may be escaped with "\";
1049             * Not yet supported: internationalization; "\" inside brackets.<P>
1050             * Wildcard matching routine by Karl Heuer.  Public Domain.<P>
1051             */
1052            private static boolean wildmatch(char[] s, char[] p, int si, int pi) {
1053                char c;
1054                final int slen = s.length;
1055                final int plen = p.length;
1056
1057                while (pi < plen) { // While still string
1058                    c = p[pi++];
1059                    if (c == '?') {
1060                        if (++si > slen)
1061                            return false;
1062                    } else if (c == '*') { // Wildcard
1063                        if (pi >= plen)
1064                            return true;
1065                        do {
1066                            if (wildmatch(s, p, si, pi))
1067                                return true;
1068                        } while (++si < slen);
1069                        return false;
1070                    } else {
1071                        if (si >= slen || c != s[si++])
1072                            return false;
1073                    }
1074                }
1075                return (si == slen);
1076            }
1077
1078            // Category : Internal utilities <==============================
1079
1080            // Category : Internal accessors ------------------------------>
1081
1082            /**
1083             * Check if domain is a valid domain.  Set _domain_pattern if appropriate.
1084             */
1085            private boolean isDomain(String domain) {
1086                if (domain == null)
1087                    return true;
1088                final char[] d = domain.toCharArray();
1089                final int len = d.length;
1090                int next = 0;
1091                while (next < len) {
1092                    final char c = d[next++];
1093                    switch (c) {
1094                    case ':':
1095                    case '\n':
1096                        return false;
1097                    case '*':
1098                    case '?':
1099                        _domain_pattern = true;
1100                        break;
1101                    }
1102                }
1103                return true;
1104            }
1105
1106            // Category : Internal accessors <==============================
1107
1108            // Category : Serialization ----------------------------------->
1109
1110            /**
1111             * Deserializes an {@link ObjectName} from an {@link ObjectInputStream}.
1112             * @serialData <ul>
1113             *               <li>In the current serial form (value of property
1114             *                   <code>jmx.serial.form</code> differs from
1115             *                   <code>1.0</code>): the string
1116             *                   &quot;&lt;domain&gt;:&lt;properties&gt;&lt;wild&gt;&quot;,
1117             *                   where: <ul>
1118             *                            <li>&lt;domain&gt; represents the domain part
1119             *                                of the {@link ObjectName}</li>
1120             *                            <li>&lt;properties&gt; represents the list of
1121             *                                properties, as returned by
1122             *                                {@link #getKeyPropertyListString}
1123             *                            <li>&lt;wild&gt; is empty if not
1124             *                                <code>isPropertyPattern</code>, or
1125             *                                is the character "<code>*</code>" if
1126             *                                <code>isPropertyPattern</code>
1127             *                                and &lt;properties&gt; is empty, or
1128             *                                is "<code>,*</code>" if
1129             *                                <code>isPropertyPattern</code> and
1130             *                                &lt;properties&gt; is not empty.
1131             *                            </li>
1132             *                          </ul>
1133             *                   The intent is that this string could be supplied
1134             *                   to the {@link #ObjectName(String)} constructor to
1135             *                   produce an equivalent {@link ObjectName}.
1136             *               </li>
1137             *               <li>In the old serial form (value of property
1138             *                   <code>jmx.serial.form</code> is
1139             *                   <code>1.0</code>): &lt;domain&gt; &lt;propertyList&gt;
1140             *                   &lt;propertyListString&gt; &lt;canonicalName&gt;
1141             *                   &lt;pattern&gt; &lt;propertyPattern&gt;,
1142             *                   where: <ul>
1143             *                            <li>&lt;domain&gt; represents the domain part
1144             *                                of the {@link ObjectName}</li>
1145             *                            <li>&lt;propertyList&gt; is the
1146             *                                {@link Hashtable} that contains all the
1147             *                                pairs (key,value) for this
1148             *                                {@link ObjectName}</li>
1149             *                            <li>&lt;propertyListString&gt; is the
1150             *                                {@link String} representation of the
1151             *                                list of properties in any order (not
1152             *                                mandatorily a canonical representation)
1153             *                                </li>
1154             *                            <li>&lt;canonicalName&gt; is the
1155             *                                {@link String} containing this
1156             *                                {@link ObjectName}'s canonical name</li>
1157             *                            <li>&lt;pattern&gt; is a boolean which is
1158             *                                <code>true</code> if this
1159             *                                {@link ObjectName} contains a pattern</li>
1160             *                            <li>&lt;propertyPattern&gt; is a boolean which
1161             *                                is <code>true</code> if this
1162             *                                {@link ObjectName} contains a pattern in
1163             *                                the list of properties</li>
1164             *                          </ul>
1165             *               </li>
1166             *             </ul>
1167             */
1168            private void readObject(ObjectInputStream in) throws IOException,
1169                    ClassNotFoundException {
1170
1171                String cn;
1172                if (compat) {
1173                    // Read an object serialized in the old serial form
1174                    //
1175                    //in.defaultReadObject();
1176                    final ObjectInputStream.GetField fields = in.readFields();
1177                    cn = (String) fields.get("domain", "default") + ":"
1178                            + (String) fields.get("propertyListString", "");
1179                } else {
1180                    // Read an object serialized in the new serial form
1181                    //
1182                    in.defaultReadObject();
1183                    cn = (String) in.readObject();
1184                }
1185
1186                try {
1187                    construct(cn);
1188                } catch (NullPointerException e) {
1189                    throw new InvalidObjectException(e.toString());
1190                } catch (MalformedObjectNameException e) {
1191                    throw new InvalidObjectException(e.toString());
1192                }
1193            }
1194
1195            /**
1196             * Serializes an {@link ObjectName} to an {@link ObjectOutputStream}.
1197             * @serialData <ul>
1198             *               <li>In the current serial form (value of property
1199             *                   <code>jmx.serial.form</code> differs from
1200             *                   <code>1.0</code>): the string
1201             *                   &quot;&lt;domain&gt;:&lt;properties&gt;&lt;wild&gt;&quot;,
1202             *                   where: <ul>
1203             *                            <li>&lt;domain&gt; represents the domain part
1204             *                                of the {@link ObjectName}</li>
1205             *                            <li>&lt;properties&gt; represents the list of
1206             *                                properties, as returned by
1207             *                                {@link #getKeyPropertyListString}
1208             *                            <li>&lt;wild&gt; is empty if not
1209             *                                <code>isPropertyPattern</code>, or
1210             *                                is the character "<code>*</code>" if
1211             *                                this <code>isPropertyPattern</code>
1212             *                                and &lt;properties&gt; is empty, or
1213             *                                is "<code>,*</code>" if
1214             *                                <code>isPropertyPattern</code> and
1215             *                                &lt;properties&gt; is not empty.
1216             *                            </li>
1217             *                          </ul>
1218             *                   The intent is that this string could be supplied
1219             *                   to the {@link #ObjectName(String)} constructor to
1220             *                   produce an equivalent {@link ObjectName}.
1221             *               </li>
1222             *               <li>In the old serial form (value of property
1223             *                   <code>jmx.serial.form</code> is
1224             *                   <code>1.0</code>): &lt;domain&gt; &lt;propertyList&gt;
1225             *                   &lt;propertyListString&gt; &lt;canonicalName&gt;
1226             *                   &lt;pattern&gt; &lt;propertyPattern&gt;,
1227             *                   where: <ul>
1228             *                            <li>&lt;domain&gt; represents the domain part
1229             *                                of the {@link ObjectName}</li>
1230             *                            <li>&lt;propertyList&gt; is the
1231             *                                {@link Hashtable} that contains all the
1232             *                                pairs (key,value) for this
1233             *                                {@link ObjectName}</li>
1234             *                            <li>&lt;propertyListString&gt; is the
1235             *                                {@link String} representation of the
1236             *                                list of properties in any order (not
1237             *                                mandatorily a canonical representation)
1238             *                                </li>
1239             *                            <li>&lt;canonicalName&gt; is the
1240             *                                {@link String} containing this
1241             *                                {@link ObjectName}'s canonical name</li>
1242             *                            <li>&lt;pattern&gt; is a boolean which is
1243             *                                <code>true</code> if this
1244             *                                {@link ObjectName} contains a pattern</li>
1245             *                            <li>&lt;propertyPattern&gt; is a boolean which
1246             *                                is <code>true</code> if this
1247             *                                {@link ObjectName} contains a pattern in
1248             *                                the list of properties</li>
1249             *                          </ul>
1250             *               </li>
1251             *             </ul>
1252             */
1253            private void writeObject(ObjectOutputStream out) throws IOException {
1254
1255                if (compat) {
1256                    // Serializes this instance in the old serial form
1257                    // Read CR 6441274 before making any changes to this code
1258                    ObjectOutputStream.PutField fields = out.putFields();
1259                    fields.put("domain", _canonicalName.substring(0,
1260                            _domain_length));
1261                    fields.put("propertyList", getKeyPropertyList());
1262                    fields
1263                            .put("propertyListString",
1264                                    getKeyPropertyListString());
1265                    fields.put("canonicalName", _canonicalName);
1266                    fields.put("pattern",
1267                            (_domain_pattern || _property_list_pattern));
1268                    fields.put("propertyPattern", _property_list_pattern);
1269                    out.writeFields();
1270                } else {
1271                    // Serializes this instance in the new serial form
1272                    //
1273                    out.defaultWriteObject();
1274                    out.writeObject(getSerializedNameString());
1275                }
1276            }
1277
1278            //  Category : Serialization <===================================
1279
1280            // Private methods <========================================
1281
1282            // Public methods ---------------------------------------->
1283
1284            // Category : ObjectName Construction ------------------------------>
1285
1286            /**
1287             * <p>Return an instance of ObjectName that can be used anywhere
1288             * an object obtained with {@link #ObjectName(String) new
1289             * ObjectName(name)} can be used.  The returned object may be of
1290             * a subclass of ObjectName.  Calling this method twice with the
1291             * same parameters may return the same object or two equal but
1292             * not identical objects.</p>
1293             *
1294             * @param name  A string representation of the object name.
1295             *
1296             * @return an ObjectName corresponding to the given String.
1297             *
1298             * @exception MalformedObjectNameException The string passed as a
1299             * parameter does not have the right format.
1300             * @exception NullPointerException The <code>name</code> parameter
1301             * is null.
1302             *
1303             */
1304            public static ObjectName getInstance(String name)
1305                    throws MalformedObjectNameException, NullPointerException {
1306                return new ObjectName(name);
1307            }
1308
1309            /**
1310             * <p>Return an instance of ObjectName that can be used anywhere
1311             * an object obtained with {@link #ObjectName(String, String,
1312             * String) new ObjectName(domain, key, value)} can be used.  The
1313             * returned object may be of a subclass of ObjectName.  Calling
1314             * this method twice with the same parameters may return the same
1315             * object or two equal but not identical objects.</p>
1316             *
1317             * @param domain  The domain part of the object name.
1318             * @param key  The attribute in the key property of the object name.
1319             * @param value The value in the key property of the object name.
1320             *
1321             * @return an ObjectName corresponding to the given domain,
1322             * key, and value.
1323             *
1324             * @exception MalformedObjectNameException The
1325             * <code>domain</code>, <code>key</code>, or <code>value</code>
1326             * contains an illegal character, or <code>value</code> does not
1327             * follow the rules for quoting.
1328             * @exception NullPointerException One of the parameters is null.
1329             *
1330             */
1331            public static ObjectName getInstance(String domain, String key,
1332                    String value) throws MalformedObjectNameException,
1333                    NullPointerException {
1334                return new ObjectName(domain, key, value);
1335            }
1336
1337            /**
1338             * <p>Return an instance of ObjectName that can be used anywhere
1339             * an object obtained with {@link #ObjectName(String, Hashtable)
1340             * new ObjectName(domain, table)} can be used.  The returned
1341             * object may be of a subclass of ObjectName.  Calling this method
1342             * twice with the same parameters may return the same object or
1343             * two equal but not identical objects.</p>
1344             *
1345             * @param domain  The domain part of the object name.
1346             * @param table A hash table containing one or more key
1347             * properties.  The key of each entry in the table is the key of a
1348             * key property in the object name.  The associated value in the
1349             * table is the associated value in the object name.
1350             *
1351             * @return an ObjectName corresponding to the given domain and
1352             * key mappings.
1353             *
1354             * @exception MalformedObjectNameException The <code>domain</code>
1355             * contains an illegal character, or one of the keys or values in
1356             * <code>table</code> contains an illegal character, or one of the
1357             * values in <code>table</code> does not follow the rules for
1358             * quoting.
1359             * @exception NullPointerException One of the parameters is null.
1360             *
1361             */
1362            public static ObjectName getInstance(String domain,
1363                    Hashtable<String, String> table)
1364                    throws MalformedObjectNameException, NullPointerException {
1365                return new ObjectName(domain, table);
1366            }
1367
1368            /**
1369             * <p>Return an instance of ObjectName that can be used anywhere
1370             * the given object can be used.  The returned object may be of a
1371             * subclass of ObjectName.  If <code>name</code> is of a subclass
1372             * of ObjectName, it is not guaranteed that the returned object
1373             * will be of the same class.</p>
1374             *
1375             * <p>The returned value may or may not be identical to
1376             * <code>name</code>.  Calling this method twice with the same
1377             * parameters may return the same object or two equal but not
1378             * identical objects.</p>
1379             *
1380             * <p>Since ObjectName is immutable, it is not usually useful to
1381             * make a copy of an ObjectName.  The principal use of this method
1382             * is to guard against a malicious caller who might pass an
1383             * instance of a subclass with surprising behavior to sensitive
1384             * code.  Such code can call this method to obtain an ObjectName
1385             * that is known not to have surprising behavior.</p>
1386             *
1387             * @param name an instance of the ObjectName class or of a subclass
1388             *
1389             * @return an instance of ObjectName or a subclass that is known to
1390             * have the same semantics.  If <code>name</code> respects the
1391             * semantics of ObjectName, then the returned object is equal
1392             * (though not necessarily identical) to <code>name</code>.
1393             *
1394             * @exception NullPointerException The <code>name</code> is null.
1395             *
1396             */
1397            public static ObjectName getInstance(ObjectName name)
1398                    throws NullPointerException {
1399                if (name.getClass().equals(ObjectName.class))
1400                    return name;
1401                try {
1402                    return new ObjectName(name.getSerializedNameString());
1403                } catch (MalformedObjectNameException e) {
1404                    throw new IllegalArgumentException("Unexpected: " + e);
1405                    // can't happen
1406                }
1407            }
1408
1409            /**
1410             * Construct an object name from the given string.
1411             *
1412             * @param name  A string representation of the object name.
1413             *
1414             * @exception MalformedObjectNameException The string passed as a
1415             * parameter does not have the right format.
1416             * @exception NullPointerException The <code>name</code> parameter
1417             * is null.
1418             */
1419            public ObjectName(String name) throws MalformedObjectNameException,
1420                    NullPointerException {
1421                construct(name);
1422            }
1423
1424            /**
1425             * Construct an object name with exactly one key property.
1426             *
1427             * @param domain  The domain part of the object name.
1428             * @param key  The attribute in the key property of the object name.
1429             * @param value The value in the key property of the object name.
1430             *
1431             * @exception MalformedObjectNameException The
1432             * <code>domain</code>, <code>key</code>, or <code>value</code>
1433             * contains an illegal character, or <code>value</code> does not
1434             * follow the rules for quoting.
1435             * @exception NullPointerException One of the parameters is null.
1436             */
1437            public ObjectName(String domain, String key, String value)
1438                    throws MalformedObjectNameException, NullPointerException {
1439                // If key or value are null a NullPointerException
1440                // will be thrown by the put method in Hashtable.
1441                //
1442                Map<String, String> table = Collections
1443                        .singletonMap(key, value);
1444                construct(domain, table);
1445            }
1446
1447            /**
1448             * Construct an object name with several key properties from a Hashtable.
1449             *
1450             * @param domain  The domain part of the object name.
1451             * @param table A hash table containing one or more key
1452             * properties.  The key of each entry in the table is the key of a
1453             * key property in the object name.  The associated value in the
1454             * table is the associated value in the object name.
1455             *
1456             * @exception MalformedObjectNameException The <code>domain</code>
1457             * contains an illegal character, or one of the keys or values in
1458             * <code>table</code> contains an illegal character, or one of the
1459             * values in <code>table</code> does not follow the rules for
1460             * quoting.
1461             * @exception NullPointerException One of the parameters is null.
1462             */
1463            public ObjectName(String domain, Hashtable<String, String> table)
1464                    throws MalformedObjectNameException, NullPointerException {
1465                construct(domain, table);
1466                /* The exception for when a key or value in the table is not a
1467                   String is now ClassCastException rather than
1468                   MalformedObjectNameException.  This was not previously
1469                   specified.  */
1470            }
1471
1472            // Category : ObjectName Construction <==============================
1473
1474            // Category : Getter methods ------------------------------>
1475
1476            /**
1477             * Checks whether the object name is a pattern.
1478             * <p>
1479             * An object name is a pattern if its domain contains a
1480             * wildcard or if the object name is a property pattern.
1481             *
1482             * @return  True if the name is a pattern, otherwise false.
1483             */
1484            public boolean isPattern() {
1485                return (_domain_pattern || _property_list_pattern || _property_value_pattern);
1486            }
1487
1488            /**
1489             * Checks whether the object name is a pattern on the domain part.
1490             *
1491             * @return  True if the name is a domain pattern, otherwise false.
1492             *
1493             */
1494            public boolean isDomainPattern() {
1495                return _domain_pattern;
1496            }
1497
1498            /**
1499             * Checks whether the object name is a pattern on the key properties.
1500             * <p>
1501             * An object name is a pattern on the key properties if it is a
1502             * pattern on the key property list (e.g. "d:k=v,*") or on the
1503             * property values (e.g. "d:k=*") or on both (e.g. "d:k=*,*").
1504             *
1505             * @return  True if the name is a property pattern, otherwise false.
1506             */
1507            public boolean isPropertyPattern() {
1508                return _property_list_pattern || _property_value_pattern;
1509            }
1510
1511            /**
1512             * Checks whether the object name is a pattern on the key property list.
1513             * <p>
1514             * For example, "d:k=v,*" and "d:k=*,*" are key property list patterns
1515             * whereas "d:k=*" is not.
1516             *
1517             * @return  True if the name is a property list pattern, otherwise false.
1518             *
1519             * @since 1.6
1520             */
1521            public boolean isPropertyListPattern() {
1522                return _property_list_pattern;
1523            }
1524
1525            /**
1526             * Checks whether the object name is a pattern on the value part
1527             * of at least one of the key properties.
1528             * <p>
1529             * For example, "d:k=*" and "d:k=*,*" are property value patterns
1530             * whereas "d:k=v,*" is not.
1531             *
1532             * @return  True if the name is a property value pattern, otherwise false.
1533             *
1534             * @since 1.6
1535             */
1536            public boolean isPropertyValuePattern() {
1537                return _property_value_pattern;
1538            }
1539
1540            /**
1541             * Checks whether the value associated with a key in a key
1542             * property is a pattern.
1543             *
1544             * @param property The property whose value is to be checked.
1545             *
1546             * @return True if the value associated with the given key property
1547             * is a pattern, otherwise false.
1548             *
1549             * @exception NullPointerException If <code>property</code> is null.
1550             * @exception IllegalArgumentException If <code>property</code> is not
1551             * a valid key property for this ObjectName.
1552             *
1553             * @since 1.6
1554             */
1555            public boolean isPropertyValuePattern(String property)
1556                    throws NullPointerException, IllegalArgumentException {
1557                if (property == null)
1558                    throw new NullPointerException("key property can't be null");
1559                for (int i = 0; i < _ca_array.length; i++) {
1560                    Property prop = _ca_array[i];
1561                    String key = prop.getKeyString(_canonicalName);
1562                    if (key.equals(property))
1563                        return (prop instanceof  PatternProperty);
1564                }
1565                throw new IllegalArgumentException("key property not found");
1566            }
1567
1568            /**
1569             * <p>Returns the canonical form of the name; that is, a string
1570             * representation where the properties are sorted in lexical
1571             * order.</p>
1572             *
1573             * <p>More precisely, the canonical form of the name is a String
1574             * consisting of the <em>domain part</em>, a colon
1575             * (<code>:</code>), the <em>canonical key property list</em>, and
1576             * a <em>pattern indication</em>.</p>
1577             *
1578             * <p>The <em>canonical key property list</em> is the same string
1579             * as described for {@link #getCanonicalKeyPropertyListString()}.</p>
1580             *
1581             * <p>The <em>pattern indication</em> is:
1582             * <ul>
1583             * <li>empty for an ObjectName
1584             * that is not a property list pattern;
1585             * <li>an asterisk for an ObjectName
1586             * that is a property list pattern with no keys; or
1587             * <li>a comma and an
1588             * asterisk (<code>,*</code>) for an ObjectName that is a property
1589             * list pattern with at least one key.
1590             * </ul></p>
1591             *
1592             * @return The canonical form of the name.
1593             */
1594            public String getCanonicalName() {
1595                return _canonicalName;
1596            }
1597
1598            /**
1599             * Returns the domain part.
1600             *
1601             * @return The domain.
1602             */
1603            public String getDomain() {
1604                return _canonicalName.substring(0, _domain_length);
1605            }
1606
1607            /**
1608             * Obtains the value associated with a key in a key property.
1609             *
1610             * @param property The property whose value is to be obtained.
1611             *
1612             * @return The value of the property, or null if there is no such
1613             * property in this ObjectName.
1614             *
1615             * @exception NullPointerException If <code>property</code> is null.
1616             */
1617            public String getKeyProperty(String property)
1618                    throws NullPointerException {
1619                return _getKeyPropertyList().get(property);
1620            }
1621
1622            /**
1623             * <p>Returns the key properties as a Map.  The returned
1624             * value is a Map in which each key is a key in the
1625             * ObjectName's key property list and each value is the associated
1626             * value.</p>
1627             *
1628             * <p>The returned value must not be modified.</p>
1629             *
1630             * @return The table of key properties.
1631             */
1632            private Map<String, String> _getKeyPropertyList() {
1633                synchronized (this ) {
1634                    if (_propertyList == null) {
1635                        // build (lazy eval) the property list from the canonical
1636                        // properties array
1637                        _propertyList = new HashMap<String, String>();
1638                        int len = _ca_array.length;
1639                        Property prop;
1640                        for (int i = len - 1; i >= 0; i--) {
1641                            prop = _ca_array[i];
1642                            _propertyList.put(
1643                                    prop.getKeyString(_canonicalName), prop
1644                                            .getValueString(_canonicalName));
1645                        }
1646                    }
1647                }
1648                return _propertyList;
1649            }
1650
1651            /**
1652             * <p>Returns the key properties as a Hashtable.  The returned
1653             * value is a Hashtable in which each key is a key in the
1654             * ObjectName's key property list and each value is the associated
1655             * value.</p>
1656             *
1657             * <p>The returned value may be unmodifiable.  If it is
1658             * modifiable, changing it has no effect on this ObjectName.</p>
1659             *
1660             * @return The table of key properties.
1661             */
1662            // CR 6441274 depends on the modification property defined above
1663            public Hashtable<String, String> getKeyPropertyList() {
1664                return new Hashtable<String, String>(_getKeyPropertyList());
1665            }
1666
1667            /**
1668             * <p>Returns a string representation of the list of key
1669             * properties specified at creation time.  If this ObjectName was
1670             * constructed with the constructor {@link #ObjectName(String)},
1671             * the key properties in the returned String will be in the same
1672             * order as in the argument to the constructor.</p>
1673             *
1674             * @return The key property list string.  This string is
1675             * independent of whether the ObjectName is a pattern.
1676             */
1677            public String getKeyPropertyListString() {
1678                // BEWARE : we rebuild the propertyliststring at each call !!
1679                if (_kp_array.length == 0)
1680                    return "";
1681
1682                // the size of the string is the canonical one minus domain
1683                // part and pattern part
1684                final int total_size = _canonicalName.length() - _domain_length
1685                        - 1 - (_property_list_pattern ? 2 : 0);
1686
1687                final char[] dest_chars = new char[total_size];
1688                final char[] value = _canonicalName.toCharArray();
1689                writeKeyPropertyListString(value, dest_chars, 0);
1690                return new String(dest_chars);
1691            }
1692
1693            /**
1694             * <p>Returns the serialized string of the ObjectName.
1695             * properties specified at creation time.  If this ObjectName was
1696             * constructed with the constructor {@link #ObjectName(String)},
1697             * the key properties in the returned String will be in the same
1698             * order as in the argument to the constructor.</p>
1699             *
1700             * @return The key property list string.  This string is
1701             * independent of whether the ObjectName is a pattern.
1702             */
1703            private String getSerializedNameString() {
1704
1705                // the size of the string is the canonical one
1706                final int total_size = _canonicalName.length();
1707                final char[] dest_chars = new char[total_size];
1708                final char[] value = _canonicalName.toCharArray();
1709                final int offset = _domain_length + 1;
1710
1711                // copy "domain:" into dest_chars
1712                //
1713                System.arraycopy(value, 0, dest_chars, 0, offset);
1714
1715                // Add property list string
1716                final int end = writeKeyPropertyListString(value, dest_chars,
1717                        offset);
1718
1719                // Add ",*" if necessary
1720                if (_property_list_pattern) {
1721                    if (end == offset) {
1722                        // Property list string is empty.
1723                        dest_chars[end] = '*';
1724                    } else {
1725                        // Property list string is not empty.
1726                        dest_chars[end] = ',';
1727                        dest_chars[end + 1] = '*';
1728                    }
1729                }
1730
1731                return new String(dest_chars);
1732            }
1733
1734            /**
1735             * <p>Write a string representation of the list of key
1736             * properties specified at creation time in the given array, starting
1737             * at the specified offset.  If this ObjectName was
1738             * constructed with the constructor {@link #ObjectName(String)},
1739             * the key properties in the returned String will be in the same
1740             * order as in the argument to the constructor.</p>
1741             *
1742             * @return offset + #of chars written
1743             */
1744            private int writeKeyPropertyListString(char[] canonicalChars,
1745                    char[] data, int offset) {
1746                if (_kp_array.length == 0)
1747                    return offset;
1748
1749                final char[] dest_chars = data;
1750                final char[] value = _canonicalName.toCharArray();
1751
1752                int index = offset;
1753                final int len = _kp_array.length;
1754                final int last = len - 1;
1755                for (int i = 0; i < len; i++) {
1756                    final Property prop = _kp_array[i];
1757                    final int prop_len = prop._key_length + prop._value_length
1758                            + 1;
1759                    System.arraycopy(value, prop._key_index, dest_chars, index,
1760                            prop_len);
1761                    index += prop_len;
1762                    if (i < last)
1763                        dest_chars[index++] = ',';
1764                }
1765                return index;
1766            }
1767
1768            /**
1769             * Returns a string representation of the list of key properties,
1770             * in which the key properties are sorted in lexical order. This
1771             * is used in lexicographic comparisons performed in order to
1772             * select MBeans based on their key property list.  Lexical order
1773             * is the order implied by {@link String#compareTo(String)
1774             * String.compareTo(String)}.
1775             *
1776             * @return The canonical key property list string.  This string is
1777             * independent of whether the ObjectName is a pattern.
1778             */
1779            public String getCanonicalKeyPropertyListString() {
1780                if (_ca_array.length == 0)
1781                    return "";
1782
1783                int len = _canonicalName.length();
1784                if (_property_list_pattern)
1785                    len -= 2;
1786                return _canonicalName.substring(_domain_length + 1, len);
1787            }
1788
1789            // Category : Getter methods <===================================
1790
1791            // Category : Utilities ---------------------------------------->
1792
1793            /**
1794             * <p>Returns a string representation of the object name.  The
1795             * format of this string is not specified, but users can expect
1796             * that two ObjectNames return the same string if and only if they
1797             * are equal.</p>
1798             *
1799             * @return a string representation of this object name.
1800             */
1801            public String toString() {
1802                return getSerializedNameString();
1803            }
1804
1805            /**
1806             * Compares the current object name with another object name.  Two
1807             * ObjectName instances are equal if and only if their canonical
1808             * forms are equal.  The canonical form is the string described
1809             * for {@link #getCanonicalName()}.
1810             *
1811             * @param object  The object name that the current object name is to be
1812             *        compared with.
1813             *
1814             * @return True if <code>object</code> is an ObjectName whose
1815             * canonical form is equal to that of this ObjectName.
1816             */
1817            public boolean equals(Object object) {
1818
1819                // same object case
1820                if (this  == object)
1821                    return true;
1822
1823                // object is not an object name case
1824                if (!(object instanceof  ObjectName))
1825                    return false;
1826
1827                // equality when canonical names are the same
1828                // (because usage of intern())
1829                ObjectName on = (ObjectName) object;
1830                String on_string = on._canonicalName;
1831                if (_canonicalName == on_string)
1832                    return true;
1833
1834                // Because we are sharing canonical form between object names,
1835                // we have finished the comparison at this stage ==> unequal
1836                return false;
1837            }
1838
1839            /**
1840             * Returns a hash code for this object name.
1841             *
1842             */
1843            public int hashCode() {
1844                return _canonicalName.hashCode();
1845            }
1846
1847            /**
1848             * <p>Returns a quoted form of the given String, suitable for
1849             * inclusion in an ObjectName.  The returned value can be used as
1850             * the value associated with a key in an ObjectName.  The String
1851             * <code>s</code> may contain any character.  Appropriate quoting
1852             * ensures that the returned value is legal in an ObjectName.</p>
1853             *
1854             * <p>The returned value consists of a quote ('"'), a sequence of
1855             * characters corresponding to the characters of <code>s</code>,
1856             * and another quote.  Characters in <code>s</code> appear
1857             * unchanged within the returned value except:</p>
1858             *
1859             * <ul>
1860             * <li>A quote ('"') is replaced by a backslash (\) followed by a quote.</li>
1861             * <li>An asterisk ('*') is replaced by a backslash (\) followed by an
1862             * asterisk.</li>
1863             * <li>A question mark ('?') is replaced by a backslash (\) followed by
1864             * a question mark.</li>
1865             * <li>A backslash ('\') is replaced by two backslashes.</li>
1866             * <li>A newline character (the character '\n' in Java) is replaced
1867             * by a backslash followed by the character '\n'.</li>
1868             * </ul>
1869             *
1870             * @param s the String to be quoted.
1871             *
1872             * @return the quoted String.
1873             *
1874             * @exception NullPointerException if <code>s</code> is null.
1875             *
1876             */
1877            public static String quote(String s) throws NullPointerException {
1878                final StringBuilder buf = new StringBuilder("\"");
1879                final int len = s.length();
1880                for (int i = 0; i < len; i++) {
1881                    char c = s.charAt(i);
1882                    switch (c) {
1883                    case '\n':
1884                        c = 'n';
1885                        buf.append('\\');
1886                        break;
1887                    case '\\':
1888                    case '\"':
1889                    case '*':
1890                    case '?':
1891                        buf.append('\\');
1892                        break;
1893                    }
1894                    buf.append(c);
1895                }
1896                buf.append('"');
1897                return buf.toString();
1898            }
1899
1900            /**
1901             * <p>Returns an unquoted form of the given String.  If
1902             * <code>q</code> is a String returned by {@link #quote quote(s)},
1903             * then <code>unquote(q).equals(s)</code>.  If there is no String
1904             * <code>s</code> for which <code>quote(s).equals(q)</code>, then
1905             * unquote(q) throws an IllegalArgumentException.</p>
1906             *
1907             * <p>These rules imply that there is a one-to-one mapping between
1908             * quoted and unquoted forms.</p>
1909             *
1910             * @param q the String to be unquoted.
1911             *
1912             * @return the unquoted String.
1913             *
1914             * @exception IllegalArgumentException if <code>q</code> could not
1915             * have been returned by the {@link #quote} method, for instance
1916             * if it does not begin and end with a quote (").
1917             *
1918             * @exception NullPointerException if <code>q</code> is null.
1919             *
1920             */
1921            public static String unquote(String q)
1922                    throws IllegalArgumentException, NullPointerException {
1923                final StringBuilder buf = new StringBuilder();
1924                final int len = q.length();
1925                if (len < 2 || q.charAt(0) != '"' || q.charAt(len - 1) != '"')
1926                    throw new IllegalArgumentException("Argument not quoted");
1927                for (int i = 1; i < len - 1; i++) {
1928                    char c = q.charAt(i);
1929                    if (c == '\\') {
1930                        if (i == len - 2)
1931                            throw new IllegalArgumentException(
1932                                    "Trailing backslash");
1933                        c = q.charAt(++i);
1934                        switch (c) {
1935                        case 'n':
1936                            c = '\n';
1937                            break;
1938                        case '\\':
1939                        case '\"':
1940                        case '*':
1941                        case '?':
1942                            break;
1943                        default:
1944                            throw new IllegalArgumentException(
1945                                    "Bad character '" + c + "' after backslash");
1946                        }
1947                    } else {
1948                        switch (c) {
1949                        case '*':
1950                        case '?':
1951                        case '\"':
1952                        case '\n':
1953                            throw new IllegalArgumentException(
1954                                    "Invalid unescaped character '" + c
1955                                            + "' in the string to unquote");
1956                        }
1957                    }
1958                    buf.append(c);
1959                }
1960                return buf.toString();
1961            }
1962
1963            /**
1964             * Defines the wildcard "*:*" ObjectName.
1965             *
1966             * @since 1.6
1967             */
1968            public static final ObjectName WILDCARD;
1969            static {
1970                try {
1971                    WILDCARD = new ObjectName("*:*");
1972                } catch (MalformedObjectNameException e) {
1973                    throw new Error("Can't initialize wildcard name", e);
1974                }
1975            }
1976
1977            // Category : Utilities <===================================
1978
1979            // Category : QueryExp Interface ---------------------------------------->
1980
1981            /**
1982             * <p>Test whether this ObjectName, which may be a pattern,
1983             * matches another ObjectName.  If <code>name</code> is a pattern,
1984             * the result is false.  If this ObjectName is a pattern, the
1985             * result is true if and only if <code>name</code> matches the
1986             * pattern.  If neither this ObjectName nor <code>name</code> is
1987             * a pattern, the result is true if and only if the two
1988             * ObjectNames are equal as described for the {@link
1989             * #equals(Object)} method.</p>
1990             *
1991             * @param name The name of the MBean to compare to.
1992             *
1993             * @return True if <code>name</code> matches this ObjectName.
1994             *
1995             * @exception NullPointerException if <code>name</code> is null.
1996             *
1997             */
1998            public boolean apply(ObjectName name) throws NullPointerException {
1999
2000                if (name == null)
2001                    throw new NullPointerException();
2002
2003                if (name._domain_pattern || name._property_list_pattern
2004                        || name._property_value_pattern)
2005                    return false;
2006
2007                // No pattern
2008                if (!_domain_pattern && !_property_list_pattern
2009                        && !_property_value_pattern)
2010                    return _canonicalName.equals(name._canonicalName);
2011
2012                return matchDomains(name) && matchKeys(name);
2013            }
2014
2015            private final boolean matchDomains(ObjectName name) {
2016                if (_domain_pattern) {
2017                    // wildmatch domains
2018                    final char[] dom_pattern = getDomain().toCharArray();
2019                    final char[] dom_string = name.getDomain().toCharArray();
2020                    return wildmatch(dom_string, dom_pattern, 0, 0);
2021                }
2022                return getDomain().equals(name.getDomain());
2023            }
2024
2025            private final boolean matchKeys(ObjectName name) {
2026                // If key property value pattern but not key property list
2027                // pattern, then the number of key properties must be equal
2028                //
2029                if (_property_value_pattern && !_property_list_pattern
2030                        && (name._ca_array.length != _ca_array.length))
2031                    return false;
2032
2033                // If key property value pattern or key property list pattern,
2034                // then every property inside pattern should exist in name
2035                //
2036                if (_property_value_pattern || _property_list_pattern) {
2037                    final Map<String, String> nameProps = name
2038                            ._getKeyPropertyList();
2039                    final Property[] props = _ca_array;
2040                    final String cn = _canonicalName;
2041                    for (int i = props.length - 1; i >= 0; i--) {
2042                        // Find value in given object name for key at current
2043                        // index in receiver
2044                        //
2045                        final Property p = props[i];
2046                        final String k = p.getKeyString(cn);
2047                        final String v = nameProps.get(k);
2048                        // Did we find a value for this key ?
2049                        //
2050                        if (v == null)
2051                            return false;
2052                        // If this property is ok (same key, same value), go to next
2053                        //
2054                        if (_property_value_pattern
2055                                && (p instanceof  PatternProperty)) {
2056                            // wildmatch key property values
2057                            final char[] val_pattern = p.getValueString(cn)
2058                                    .toCharArray();
2059                            final char[] val_string = v.toCharArray();
2060                            if (wildmatch(val_string, val_pattern, 0, 0))
2061                                continue;
2062                            else
2063                                return false;
2064                        }
2065                        if (v.equals(p.getValueString(cn)))
2066                            continue;
2067                        return false;
2068                    }
2069                    return true;
2070                }
2071
2072                // If no pattern, then canonical names must be equal
2073                //
2074                final String p1 = name.getCanonicalKeyPropertyListString();
2075                final String p2 = getCanonicalKeyPropertyListString();
2076                return (p1.equals(p2));
2077            }
2078
2079            /* Method inherited from QueryExp, no implementation needed here
2080               because ObjectName is not relative to an MBeanServer and does
2081               not contain a subquery.
2082             */
2083            public void setMBeanServer(MBeanServer mbs) {
2084            }
2085
2086            // Category : QueryExp Interface <=========================
2087
2088            // Category : Comparable Interface ---------------------------------------->
2089
2090            /**
2091             * <p>Compares two ObjectName instances. The ordering relation between
2092             * ObjectNames is not completely specified but is intended to be such
2093             * that a sorted list of ObjectNames will appear in an order that is
2094             * convenient for a person to read.</p>
2095             *
2096             * <p>In particular, if the two ObjectName instances have different
2097             * domains then their order is the lexicographical order of the domains.
2098             * The ordering of the key property list remains unspecified.</p>
2099             *
2100             * <p>For example, the ObjectName instances below:</p>
2101             * <ul>
2102             * <li>Shapes:type=Square,name=3</li>
2103             * <li>Colors:type=Red,name=2</li>
2104             * <li>Shapes:type=Triangle,side=isosceles,name=2</li>
2105             * <li>Colors:type=Red,name=1</li>
2106             * <li>Shapes:type=Square,name=1</li>
2107             * <li>Colors:type=Blue,name=1</li>
2108             * <li>Shapes:type=Square,name=2</li>
2109             * <li>JMImplementation:type=MBeanServerDelegate</li>
2110             * <li>Shapes:type=Triangle,side=scalene,name=1</li>
2111             * </ul>
2112             * <p>could be ordered as follows:</p>
2113             * <ul>
2114             * <li>Colors:type=Blue,name=1</li>
2115             * <li>Colors:type=Red,name=1</li>
2116             * <li>Colors:type=Red,name=2</li>
2117             * <li>JMImplementation:type=MBeanServerDelegate</li>
2118             * <li>Shapes:type=Square,name=1</li>
2119             * <li>Shapes:type=Square,name=2</li>
2120             * <li>Shapes:type=Square,name=3</li>
2121             * <li>Shapes:type=Triangle,side=scalene,name=1</li>
2122             * <li>Shapes:type=Triangle,side=isosceles,name=2</li>
2123             * </ul>
2124             *
2125             * @param name the ObjectName to be compared.
2126             *
2127             * @return a negative integer, zero, or a positive integer as this
2128             *         ObjectName is less than, equal to, or greater than the
2129             *         specified ObjectName.
2130             *
2131             * @since 1.6
2132             */
2133            public int compareTo(ObjectName name) {
2134                // (1) Compare domains
2135                //
2136                int domainValue = this .getDomain().compareTo(name.getDomain());
2137                if (domainValue != 0)
2138                    return domainValue;
2139
2140                // (2) Compare "type=" keys
2141                //
2142                // Within a given domain, all names with missing or empty "type="
2143                // come before all names with non-empty type.
2144                //
2145                // When both types are missing or empty, canonical-name ordering
2146                // applies which is a total order.
2147                //
2148                String this TypeKey = this .getKeyProperty("type");
2149                String anotherTypeKey = name.getKeyProperty("type");
2150                if (this TypeKey == null)
2151                    this TypeKey = "";
2152                if (anotherTypeKey == null)
2153                    anotherTypeKey = "";
2154                int typeKeyValue = this TypeKey.compareTo(anotherTypeKey);
2155                if (typeKeyValue != 0)
2156                    return typeKeyValue;
2157
2158                // (3) Compare canonical names
2159                //
2160                return this .getCanonicalName().compareTo(
2161                        name.getCanonicalName());
2162            }
2163
2164            // Category : Comparable Interface <=========================
2165
2166            // Public methods <========================================
2167
2168        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.