jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/monitor/VmIdentifier.java
changeset 43662 6b16a26de895
parent 43661 c3f1a529d829
parent 43593 06bce0388880
child 43663 4416065868c1
equal deleted inserted replaced
43661:c3f1a529d829 43662:6b16a26de895
     1 /*
       
     2  * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package sun.jvmstat.monitor;
       
    27 
       
    28 import java.net.*;
       
    29 
       
    30 /**
       
    31  * An abstraction that identifies a target Java Virtual Machine.
       
    32  * The VmIdentifier, or vmid, provides a convenient string representation
       
    33  * of the information needed to locate and communicate with a target
       
    34  * Java Virtual Machine. The string, based on a {@link URI}, may specify
       
    35  * the communications protocol, host name, local vm identifier, and protocol
       
    36  * specific information for a target Java Virtual Machine. The format for
       
    37  * a VmIdentifier string is:
       
    38  * <pre>
       
    39  *      [<I>protocol</I>:][<I>//</I>]<I><B>lvmid</B></I>[<I>@hostname</I>][<I>:port</I>][<I>/servername</I>]
       
    40  * </pre>
       
    41  * The only required component of this string is the Local Virtual Machine
       
    42  * Identifier, or {@code lvmid}, which uniquely identifies the target
       
    43  * Java Virtual Machine on a host. The optional components of the VmIdentifier
       
    44  * include:
       
    45  * <ul>
       
    46  *   <li>{@code protocol} - The communications protocol. A VmIdentifier
       
    47  *       omitting the protocol must be resolved against a HostIdentifier
       
    48  *       using {@link HostIdentifier#resolve}.
       
    49  *       </li>
       
    50  *   <li>{@code hostname} - A hostname or IP address indicating the target
       
    51  *       host. A VmIdentifier omitting the protocol must be resolved
       
    52  *       against a HostIdentifier using {@link HostIdentifier#resolve}.
       
    53  *       </li>
       
    54  *   <li>{@code port} - The port for the communications protocol.
       
    55  *       Treatment of the {@code port} parameter is implementation
       
    56  *       (protocol) specific. A VmIdentifier omitting the protocol should
       
    57  *       be resolved against a HostIdentifier using
       
    58  *       {@link HostIdentifier#resolve}.
       
    59  *       </li>
       
    60  *   <li>{@code servername} - The treatment of the Path, Query, and
       
    61  *       Fragment components of the VmIdentifier are implementation
       
    62  *       (protocol) dependent. A VmIdentifier omitting the protocol should
       
    63  *       be resolved against a HostIdentifier using
       
    64  *       {@link HostIdentifier#resolve}.
       
    65  *       </li>
       
    66  * </ul>
       
    67  * <p>
       
    68  * All VmIdentifier instances are constructed as absolute, hierarchical URIs.
       
    69  * The constructors will accept relative (and even some malformed,
       
    70  * though convenient) URI strings. Such strings are transformed into
       
    71  * legitimate, absolute URI strings.
       
    72  * <p>
       
    73  * With the exception of <em>file:</em> based VmIdentifier strings, all
       
    74  * VmIdentifier strings must include a {@code lvmid}. Attempting to construct
       
    75  * a non-file based VmIdentifier that doesn't include a {@code lvmid}
       
    76  * component will result in a {@code MonitorException}.
       
    77  * <p>
       
    78  * Here are some examples of VmIdentifier strings.
       
    79  * <ul>
       
    80  *    <li>Relative URIs
       
    81  *      <ul>
       
    82  *         <li><em>1234</em> - Specifies the Java Virtual Machine
       
    83  *             identified by lvmid <em>1234</em> on an unnamed host.
       
    84  *             This string is transformed into the absolute form
       
    85  *             <em>//1234</em>, which must be resolved against a
       
    86  *             HostIdentifier.
       
    87  *         </li>
       
    88  *         <li><em>1234@hostname</em> - Specifies the Java Virtual
       
    89  *             Machine identified by lvmid <em>1234</em> on host
       
    90  *             <em>hostname</em> with an unnamed protocol.
       
    91  *             This string is transformed into the absolute form
       
    92  *             <em>//1234@hostname</em>, which must be resolved against
       
    93  *             a HostIdentifier.
       
    94  *         </li>
       
    95  *         <li><em>1234@hostname:2099</em> - Specifies the Java Virtual
       
    96  *             Machine identified by lvmid <em>1234</em> on host
       
    97  *             <em>hostname</em> with an unnamed protocol, but with
       
    98  *             port <em>2099</em>. This string is transformed into
       
    99  *             the absolute form <em>//1234@hostname:2099</em>, which
       
   100  *             must be resolved against a HostIdentifier.
       
   101  *         </li>
       
   102  *      </ul>
       
   103  *    </li>
       
   104  *    <li>Absolute URIs
       
   105  *      <ul>
       
   106  *         <li><em>rmi://1234@hostname:2099/remoteobjectname</em> -
       
   107  *             Specifies the Java Virtual Machine identified by lvmid
       
   108  *             <em>1234</em> on host <em>hostname</em> accessed
       
   109  *             using the <em>rmi:</em> protocol through the rmi remote
       
   110  *             object named <em>remoteobjectname</em> as registered with
       
   111  *             the <em>rmiserver</em> on port <em>2099</em> on host
       
   112  *             <em>hostname</em>.
       
   113  *         </li>
       
   114  *         <li><em>file:/path/file</em> - Identifies a Java Virtual Machine
       
   115  *             through accessing a special file based protocol to use as
       
   116  *             the communications mechanism.
       
   117  *         </li>
       
   118  *      </ul>
       
   119  *    </li>
       
   120  * </ul>
       
   121  *
       
   122  * @see URI
       
   123  * @see HostIdentifier
       
   124  * @author Brian Doherty
       
   125  * @since 1.5
       
   126  */
       
   127 public class VmIdentifier {
       
   128     private URI uri;
       
   129 
       
   130     /**
       
   131      * creates a canonical representation of the uriString. This method
       
   132      * performs certain translations depending on the type of URI generated
       
   133      * by the string.
       
   134      */
       
   135     private URI canonicalize(String uriString) throws URISyntaxException {
       
   136         if (uriString == null) {
       
   137             uriString = "local://0@localhost";
       
   138             return new URI(uriString);
       
   139         }
       
   140 
       
   141         URI u = new URI(uriString);
       
   142 
       
   143         if (u.isAbsolute()) {
       
   144             if (u.isOpaque()) {
       
   145                 /*
       
   146                  * rmi:1234@hostname/path#fragment converted to
       
   147                  * rmi://1234@hostname/path#fragment
       
   148                  */
       
   149                 u = new URI(u.getScheme(), "//" + u.getSchemeSpecificPart(),
       
   150                             u.getFragment());
       
   151             }
       
   152         } else {
       
   153             /*
       
   154              * make the uri absolute, if possible. A relative URI doesn't
       
   155              * specify the scheme part, so it's safe to prepend a "//" and
       
   156              * try again.
       
   157              */
       
   158             if (!uriString.startsWith("//")) {
       
   159                 if (u.getFragment() == null) {
       
   160                     u = new URI("//" + u.getSchemeSpecificPart());
       
   161                 } else {
       
   162                     u = new URI("//" + u.getSchemeSpecificPart() + "#"
       
   163                                 + u.getFragment());
       
   164                 }
       
   165             }
       
   166         }
       
   167         return u;
       
   168     }
       
   169 
       
   170     /**
       
   171      * check that the VmIdentifier includes a unique numerical identifier
       
   172      * for the target JVM.
       
   173      */
       
   174     private void validate() throws URISyntaxException {
       
   175         // file:// uri, which is a special case where the lvmid is not required.
       
   176         String s = getScheme();
       
   177         if ((s != null) && (s.compareTo("file") == 0)) {
       
   178             return;
       
   179         }
       
   180         if (getLocalVmId() == -1) {
       
   181             throw new URISyntaxException(uri.toString(), "Local vmid required");
       
   182         }
       
   183     }
       
   184 
       
   185     /**
       
   186      * Create a VmIdentifier instance from a string value.
       
   187      *
       
   188      * @param uriString a string representing a target Java Virtual Machine.
       
   189      *                  The syntax of the string must conforms to the rules
       
   190      *                  specified in the class documentation.
       
   191      * @throws URISyntaxException Thrown when the uriString or its canonical
       
   192      *                            form is poorly formed.
       
   193      */
       
   194     public VmIdentifier(String uriString) throws URISyntaxException {
       
   195         URI u;
       
   196         try {
       
   197             u = canonicalize(uriString);
       
   198         } catch (URISyntaxException e) {
       
   199             /*
       
   200              * a vmid of the form 1234@hostname:1098 causes an exception,
       
   201              * so try again with a leading "//"
       
   202              */
       
   203             if (uriString.startsWith("//")) {
       
   204                 throw e;
       
   205             }
       
   206             u = canonicalize("//"+uriString);
       
   207         }
       
   208 
       
   209         uri = u;
       
   210 
       
   211         // verify that we have a valid lvmid
       
   212         validate();
       
   213     }
       
   214 
       
   215     /**
       
   216      * Create a VmIdentifier instance from a URI object.
       
   217      *
       
   218      * @param uri a well formed, absolute URI indicating the
       
   219      *            target Java Virtual Machine.
       
   220      * @throws URISyntaxException Thrown if the URI is missing some
       
   221      *                            required component.
       
   222      */
       
   223     public VmIdentifier(URI uri) throws URISyntaxException {
       
   224         this.uri = uri;
       
   225         validate();
       
   226     }
       
   227 
       
   228     /**
       
   229      * Return the corresponding HostIdentifier for this VmIdentifier.
       
   230      * <p>
       
   231      * This method constructs a HostIdentifier object from the VmIdentifier.
       
   232      * If the VmIdentifier is not specific about the protocol or other
       
   233      * components of the URI, then the resulting HostIdentifier will
       
   234      * be constructed based on this missing information. Typically, the
       
   235      * missing components will have result in the HostIdentifier assigning
       
   236      * assumed defaults that allow the VmIdentifier to be resolved according
       
   237      * to those defaults.
       
   238      * <p>
       
   239      * For example, a VmIdentifier that specifies only a {@code lvmid}
       
   240      * will result in a HostIdentifier for <em>localhost</em> utilizing
       
   241      * the default local protocol, <em>local:</em>. A VmIdentifier that
       
   242      * specifies both a {@code vmid} and a {@code hostname} will result
       
   243      * in a HostIdentifier for the specified host with the default remote
       
   244      * protocol, <em>rmi:</em>, using the protocol defaults for the
       
   245      * {@code port} and {@code servername} components.
       
   246      *
       
   247      * @return HostIdentifier - the host identifier for the host containing
       
   248      *                          the Java Virtual Machine represented by this
       
   249      *                          VmIdentifier.
       
   250      * @throws URISyntaxException Thrown if a bad host URI is constructed.
       
   251      *                            This exception may get encapsulated into
       
   252      *                            a MonitorException in a future version.
       
   253      */
       
   254     public HostIdentifier getHostIdentifier() throws URISyntaxException {
       
   255         StringBuilder sb = new StringBuilder();
       
   256         if (getScheme() != null) {
       
   257             sb.append(getScheme()).append(":");
       
   258         }
       
   259         sb.append("//").append(getHost());
       
   260         if (getPort() != -1) {
       
   261             sb.append(":").append(getPort());
       
   262         }
       
   263         if (getPath() != null) {
       
   264             sb.append(getPath());
       
   265         }
       
   266         return new HostIdentifier(sb.toString());
       
   267     }
       
   268 
       
   269     /**
       
   270      * Return the Scheme, or protocol, portion of this VmIdentifier.
       
   271      *
       
   272      * @return String - the scheme for this VmIdentifier.
       
   273      * @see URI#getScheme()
       
   274      */
       
   275     public String getScheme() {
       
   276         return uri.getScheme();
       
   277     }
       
   278 
       
   279     /**
       
   280      * Return the Scheme Specific Part of this VmIdentifier.
       
   281      *
       
   282      * @return String - the Scheme Specific Part for this VmIdentifier.
       
   283      * @see URI#getSchemeSpecificPart()
       
   284      */
       
   285     public String getSchemeSpecificPart() {
       
   286         return uri.getSchemeSpecificPart();
       
   287     }
       
   288 
       
   289     /**
       
   290      * Return the UserInfo part of this VmIdentifier.
       
   291      *
       
   292      * @return String - the UserInfo part for this VmIdentifier.
       
   293      * @see URI#getUserInfo()
       
   294      */
       
   295     public String getUserInfo() {
       
   296         return uri.getUserInfo();
       
   297     }
       
   298 
       
   299     /**
       
   300      * Return the Host part of this VmIdentifier.
       
   301      *
       
   302      * @return String - the Host part for this VmIdentifier.
       
   303      * @see URI#getHost()
       
   304      */
       
   305     public String getHost() {
       
   306         return uri.getHost();
       
   307     }
       
   308 
       
   309     /**
       
   310      * Return the Port part of this VmIdentifier.
       
   311      *
       
   312      * @return int - the Port part for this VmIdentifier.
       
   313      * @see URI#getPort()
       
   314      */
       
   315     public int getPort() {
       
   316         return uri.getPort();
       
   317     }
       
   318 
       
   319     /**
       
   320      * Return the Authority part of this VmIdentifier.
       
   321      *
       
   322      * @return String - the Authority part for this VmIdentifier.
       
   323      * @see URI#getAuthority()
       
   324      */
       
   325     public String getAuthority() {
       
   326         return uri.getAuthority();
       
   327     }
       
   328 
       
   329     /**
       
   330      * Return the Path part of this VmIdentifier.
       
   331      *
       
   332      * @return String - the Path part for this VmIdentifier.
       
   333      * @see URI#getPath()
       
   334      */
       
   335     public String getPath() {
       
   336         return uri.getPath();
       
   337     }
       
   338 
       
   339     /**
       
   340      * Return the Query part of this VmIdentifier.
       
   341      *
       
   342      * @return String - the Query part for this VmIdentifier.
       
   343      * @see URI#getQuery()
       
   344      */
       
   345     public String getQuery() {
       
   346         return uri.getQuery();
       
   347     }
       
   348 
       
   349     /**
       
   350      * Return the Fragment part of this VmIdentifier.
       
   351      *
       
   352      * @return String - the Fragment part for this VmIdentifier.
       
   353      * @see URI#getFragment()
       
   354      */
       
   355     public String getFragment() {
       
   356         return uri.getFragment();
       
   357     }
       
   358 
       
   359     /**
       
   360      * Return the Local Virtual Machine Identifier for this VmIdentifier.
       
   361      * The Local Virtual Machine Identifier is also known as the
       
   362      * <em>lvmid</em>.
       
   363      *
       
   364      * @return int - the lvmid for this VmIdentifier.
       
   365      */
       
   366     public int getLocalVmId() {
       
   367         int result = -1;
       
   368         try {
       
   369             if (uri.getUserInfo() == null) {
       
   370                 result = Integer.parseInt(uri.getAuthority());
       
   371             } else {
       
   372                 result = Integer.parseInt(uri.getUserInfo());
       
   373             }
       
   374         } catch (NumberFormatException e) { }
       
   375         return result;
       
   376     }
       
   377 
       
   378     /**
       
   379      * Return the mode indicated in this VmIdentifier.
       
   380      *
       
   381      * @return String - the mode string. If no mode is specified, then "r"
       
   382      *                  is returned. otherwise, the specified mode is returned.
       
   383      */
       
   384     public String getMode() {
       
   385         String query = getQuery();
       
   386         if (query != null) {
       
   387             String[] queryArgs = query.split("\\+");
       
   388             for (int i = 0; i < queryArgs.length; i++) {
       
   389                 if (queryArgs[i].startsWith("mode=")) {
       
   390                     int index = queryArgs[i].indexOf('=');
       
   391                     return queryArgs[i].substring(index+1);
       
   392                 }
       
   393             }
       
   394         }
       
   395         return "r";
       
   396     }
       
   397 
       
   398     /**
       
   399      * Return the URI associated with the VmIdentifier.
       
   400      *
       
   401      * @return URI - the URI.
       
   402      * @see URI
       
   403      */
       
   404     public URI getURI() {
       
   405         return uri;
       
   406     }
       
   407 
       
   408     /**
       
   409      * Return the hash code for this VmIdentifier. The hash code is
       
   410      * identical to the hash code for the contained URI.
       
   411      *
       
   412      * @return int - the hashcode.
       
   413      * @see URI#hashCode()
       
   414      */
       
   415     public int hashCode() {
       
   416         return uri.hashCode();
       
   417     }
       
   418 
       
   419     /**
       
   420      * Test for quality with other objects.
       
   421      *
       
   422      * @param object the object to be test for equality.
       
   423      * @return boolean - returns true if the given object is of type
       
   424      *                   VmIdentifier and its URI field is equal to
       
   425      *                   this object's URI field. Otherwise, return false.
       
   426      *
       
   427      * @see URI#equals(Object)
       
   428      */
       
   429     public boolean equals(Object object) {
       
   430         if (object == this) {
       
   431             return true;
       
   432         }
       
   433         if (!(object instanceof VmIdentifier)) {
       
   434             return false;
       
   435         }
       
   436         return uri.equals(((VmIdentifier)object).uri);
       
   437     }
       
   438 
       
   439     /**
       
   440      * Convert to a string representation. Conversion is identical to
       
   441      * calling getURI().toString(). This may change in a future release.
       
   442      *
       
   443      * @return String - a String representation of the VmIdentifier.
       
   444      *
       
   445      * @see URI#toString()
       
   446      */
       
   447     public String toString() {
       
   448         return uri.toString();
       
   449     }
       
   450 }