blob: 04bba417994e8dfd4d4c6c31edd76552b82706d6 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2004 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.jvmstat.monitor;
27
28import 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 <tt>lvmid</tt>, which uniquely identifies the target
43 * Java Virtual Machine on a host. The optional components of the VmIdentifier
44 * include:
45 * <ul>
46 * <li><p><tt>protocol</tt> - The communications protocol. A VmIdentifier
47 * omitting the protocol must be resolved against a HostIdentifier
48 * using {@link HostIdentifier#resolve}.
49 * </p></li>
50 * <li><p><tt>hostname</tt> - 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 * </p></li>
54 * <li><p><tt>port</tt> - The port for the communications protocol.
55 * Treatment of the <tt>port</tt> parameter is implementation
56 * (protocol) specific. A VmIdentifier omitting the protocol should
57 * be resolved against a HostIdentifier using
58 * {@link HostIdentifier#resolve}.
59 * </p></li>
60 * <li><p><tt>servername</tt> - 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 * </p></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 * <p>
74 * With the exception of <em>file:</em> based VmIdentifier strings, all
75 * VmIdentifier strings must include a <tt>lvmid</tt>. Attempting to construct
76 * a non-file based VmIdentifier that doesn't include a <tt>lvmid</tt>
77 * component will result in a <tt>MonitorException</tt>.
78 * </p>
79 * <p>
80 * Here are some examples of VmIdentifier strings.
81 * <ul>
82 * <li><p>Relative URIs</p></li>
83 * <ul>
84 * <li><p><em>1234</em> - Specifies the Java Virtual Machine
85 * identified by lvmid <em>1234</em> on an unnamed host.
86 * This string is transformed into the absolute form
87 * <em>//1234</em>, which must be resolved against a
88 * HostIdentifier.
89 * </p></li>
90 * <li><p><em>1234@hostname</em> - Specifies the Java Virtual
91 * Machine identified by lvmid <em>1234</em> on host
92 * <em>hostname</em> with an unnamed protocol.
93 * This string is transformed into the absolute form
94 * <em>//1234@hostname</em>, which must be resolved against
95 * a HostIdentifier.
96 * </p></li>
97 * <li><p><em>1234@hostname:2099</em> - Specifies the Java Virtual
98 * Machine identified by lvmid <em>1234</em> on host
99 * <em>hostname</em> with an unnamed protocol, but with
100 * port <em>2099</em>. This string is transformed into
101 * the absolute form <em>//1234@hostname:2099</em>, which
102 * must be resolved against a HostIdentifier.
103 * </p></li>
104 * </ul>
105 * <li><p>Absolute URIs</p></li>
106 * <ul>
107 * <li><p><em>rmi://1234@hostname:2099/remoteobjectname</em> -
108 * Specifies the Java Virtual Machine identified by lvmid
109 * <em>1234</em> on host <em>hostname</em> accessed
110 * using the <em>rmi:</em> protocol through the rmi remote
111 * object named <em>remoteobjectname</em> as registered with
112 * the <em>rmiserver</em> on port <em>2099</em> on host
113 * <em>hostname</em>.
114 * </p></li>
115 * <li><p><em>file:/path/file</em> - Identifies a Java Virtual Machine
116 * through accessing a special file based protocol to use as
117 * the communications mechanism.
118 * </p></li>
119 * </ul>
120 * </ul>
121 * </p>
122 *
123 * @see URI
124 * @see HostIdentifier
125 * @author Brian Doherty
126 * @since 1.5
127 */
128public class VmIdentifier {
129 private URI uri;
130
131 /**
132 * creates a canonical representation of the uriString. This method
133 * performs certain translations depending on the type of URI generated
134 * by the string.
135 */
136 private URI canonicalize(String uriString) throws URISyntaxException {
137 if (uriString == null) {
138 uriString = "local://0@localhost";
139 return new URI(uriString);
140 }
141
142 URI u = new URI(uriString);
143
144 if (u.isAbsolute()) {
145 if (u.isOpaque()) {
146 /*
147 * rmi:1234@hostname/path#fragment converted to
148 * rmi://1234@hostname/path#fragment
149 */
150 u = new URI(u.getScheme(), "//" + u.getSchemeSpecificPart(),
151 u.getFragment());
152 }
153 } else {
154 /*
155 * make the uri absolute, if possible. A relative URI doesn't
156 * specify the scheme part, so it's safe to prepend a "//" and
157 * try again.
158 */
159 if (!uriString.startsWith("//")) {
160 if (u.getFragment() == null) {
161 u = new URI("//" + u.getSchemeSpecificPart());
162 } else {
163 u = new URI("//" + u.getSchemeSpecificPart() + "#"
164 + u.getFragment());
165 }
166 }
167 }
168 return u;
169 }
170
171 /**
172 * check that the VmIdentifier includes a unique numerical identifier
173 * for the target JVM.
174 */
175 private void validate() throws URISyntaxException {
176 // file:// uri, which is a special case where the lvmid is not required.
177 String s = getScheme();
178 if ((s != null) && (s.compareTo("file") == 0)) {
179 return;
180 }
181 if (getLocalVmId() == -1) {
182 throw new URISyntaxException(uri.toString(), "Local vmid required");
183 }
184 }
185
186 /**
187 * Create a VmIdentifier instance from a string value.
188 *
189 * @param uriString a string representing a target Java Virtual Machine.
190 * The syntax of the string must conforms to the rules
191 * specified in the class documentation.
192 * @throws URISyntaxException Thrown when the uriString or its canonical
193 * form is poorly formed.
194 */
195 public VmIdentifier(String uriString) throws URISyntaxException {
196 URI u;
197 try {
198 u = canonicalize(uriString);
199 } catch (URISyntaxException e) {
200 /*
201 * a vmid of the form 1234@hostname:1098 causes an exception,
202 * so try again with a leading "//"
203 */
204 if (uriString.startsWith("//")) {
205 throw e;
206 }
207 u = canonicalize("//"+uriString);
208 }
209
210 uri = u;
211
212 // verify that we have a valid lvmid
213 validate();
214 }
215
216 /**
217 * Create a VmIdentifier instance from a URI object.
218 *
219 * @param uri a well formed, absolute URI indicating the
220 * target Java Virtual Machine.
221 * @throws URISyntaxException Thrown if the URI is missing some
222 * required component.
223 */
224 public VmIdentifier(URI uri) throws URISyntaxException {
225 this.uri = uri;
226 validate();
227 }
228
229 /**
230 * Return the corresponding HostIdentifier for this VmIdentifier.
231 * <p>
232 * This method constructs a HostIdentifier object from the VmIdentifier.
233 * If the VmIdentifier is not specific about the protocol or other
234 * components of the URI, then the resulting HostIdentifier will
235 * be constructed based on this missing information. Typically, the
236 * missing components will have result in the HostIdentifier assigning
237 * assumed defaults that allow the VmIdentifier to be resolved according
238 * to those defaults.
239 * </p>
240 * <p>
241 * For example, a VmIdentifier that specifies only a <tt>lvmid</tt>
242 * will result in a HostIdentifier for <em>localhost</em> utilizing
243 * the default local protocol, <em>local:</em>. A VmIdentifier that
244 * specifies both a <tt>vmid</tt> and a <tt>hostname</tt> will result
245 * in a HostIdentifier for the specified host with the default remote
246 * protocol, <em>rmi:</em>, using the protocol defaults for the
247 * <tt>port</tt> and <tt>servername</tt> components.
248 * </p>
249 *
250 * @return HostIdentifier - the host identifier for the host containing
251 * the Java Virtual Machine represented by this
252 * VmIdentifier.
253 * @throws URISyntaxException Thrown if a bad host URI is constructed.
254 * This exception may get encapsulated into
255 * a MonitorException in a future version.
256 */
257 public HostIdentifier getHostIdentifier() throws URISyntaxException {
258 StringBuffer sb = new StringBuffer();
259 if (getScheme() != null) {
260 sb.append(getScheme()).append(":");
261 }
262 sb.append("//").append(getHost());
263 if (getPort() != -1) {
264 sb.append(":").append(getPort());
265 }
266 if (getPath() != null) {
267 sb.append(getPath());
268 }
269 return new HostIdentifier(sb.toString());
270 }
271
272 /**
273 * Return the Scheme, or protocol, portion of this VmIdentifier.
274 *
275 * @return String - the scheme for this VmIdentifier.
276 * @see URI#getScheme()
277 */
278 public String getScheme() {
279 return uri.getScheme();
280 }
281
282 /**
283 * Return the Scheme Specific Part of this VmIdentifier.
284 *
285 * @return String - the Scheme Specific Part for this VmIdentifier.
286 * @see URI#getSchemeSpecificPart()
287 */
288 public String getSchemeSpecificPart() {
289 return uri.getSchemeSpecificPart();
290 }
291
292 /**
293 * Return the UserInfo part of this VmIdentifier.
294 *
295 * @return String - the UserInfo part for this VmIdentifier.
296 * @see URI#getUserInfo()
297 */
298 public String getUserInfo() {
299 return uri.getUserInfo();
300 }
301
302 /**
303 * Return the Host part of this VmIdentifier.
304 *
305 * @return String - the Host part for this VmIdentifier.
306 * @see URI#getHost()
307 */
308 public String getHost() {
309 return uri.getHost();
310 }
311
312 /**
313 * Return the Port part of this VmIdentifier.
314 *
315 * @return int - the Port part for this VmIdentifier.
316 * @see URI#getPort()
317 */
318 public int getPort() {
319 return uri.getPort();
320 }
321
322 /**
323 * Return the Authority part of this VmIdentifier.
324 *
325 * @return String - the Authority part for this VmIdentifier.
326 * @see URI#getAuthority()
327 */
328 public String getAuthority() {
329 return uri.getAuthority();
330 }
331
332 /**
333 * Return the Path part of this VmIdentifier.
334 *
335 * @return String - the Path part for this VmIdentifier.
336 * @see URI#getPath()
337 */
338 public String getPath() {
339 return uri.getPath();
340 }
341
342 /**
343 * Return the Query part of this VmIdentifier.
344 *
345 * @return String - the Query part for this VmIdentifier.
346 * @see URI#getQuery()
347 */
348 public String getQuery() {
349 return uri.getQuery();
350 }
351
352 /**
353 * Return the Fragment part of this VmIdentifier.
354 *
355 * @return String - the Fragment part for this VmIdentifier.
356 * @see URI#getFragment()
357 */
358 public String getFragment() {
359 return uri.getFragment();
360 }
361
362 /**
363 * Return the Local Virtual Machine Identifier for this VmIdentifier.
364 * The Local Virtual Machine Identifier is also known as the
365 * <em>lvmid</em>.
366 *
367 * @return int - the lvmid for this VmIdentifier.
368 */
369 public int getLocalVmId() {
370 int result = -1;
371 try {
372 if (uri.getUserInfo() == null) {
373 result = Integer.parseInt(uri.getAuthority());
374 } else {
375 result = Integer.parseInt(uri.getUserInfo());
376 }
377 } catch (NumberFormatException e) { }
378 return result;
379 }
380
381 /**
382 * Return the mode indicated in this VmIdentifier.
383 *
384 * @return String - the mode string. If no mode is specified, then "r"
385 * is returned. otherwise, the specified mode is returned.
386 */
387 public String getMode() {
388 String query = getQuery();
389 if (query != null) {
390 String[] queryArgs = query.split("\\+");
391 for (int i = 0; i < queryArgs.length; i++) {
392 if (queryArgs[i].startsWith("mode=")) {
393 int index = queryArgs[i].indexOf('=');
394 return queryArgs[i].substring(index+1);
395 }
396 }
397 }
398 return "r";
399 }
400
401 /**
402 * Return the URI associated with the VmIdentifier.
403 *
404 * @return URI - the URI.
405 * @see URI
406 */
407 public URI getURI() {
408 return uri;
409 }
410
411 /**
412 * Return the hash code for this VmIdentifier. The hash code is
413 * identical to the hash code for the contained URI.
414 *
415 * @return int - the hashcode.
416 * @see URI#hashCode()
417 */
418 public int hashCode() {
419 return uri.hashCode();
420 }
421
422 /**
423 * Test for quality with other objects.
424 *
425 * @param object the object to be test for equality.
426 * @return boolean - returns true if the given object is of type
427 * VmIdentifier and its URI field is equal to
428 * this object's URI field. Otherwise, return false.
429 *
430 * @see URI#equals(Object)
431 */
432 public boolean equals(Object object) {
433 if (object == this) {
434 return true;
435 }
436 if (!(object instanceof VmIdentifier)) {
437 return false;
438 }
439 return uri.equals(((VmIdentifier)object).uri);
440 }
441
442 /**
443 * Convert to a string representation. Conversion is identical to
444 * calling getURI().toString(). This may change in a future release.
445 *
446 * @return String - a String representation of the VmIdentifier.
447 *
448 * @see URI#toString()
449 */
450 public String toString() {
451 return uri.toString();
452 }
453}