1fb3fb4f3Stomee /*
2fb3fb4f3Stomee  * CDDL HEADER START
3fb3fb4f3Stomee  *
4fb3fb4f3Stomee  * The contents of this file are subject to the terms of the
5fb3fb4f3Stomee  * Common Development and Distribution License (the "License").
6fb3fb4f3Stomee  * You may not use this file except in compliance with the License.
7fb3fb4f3Stomee  *
8fb3fb4f3Stomee  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fb3fb4f3Stomee  * or http://www.opensolaris.org/os/licensing.
10fb3fb4f3Stomee  * See the License for the specific language governing permissions
11fb3fb4f3Stomee  * and limitations under the License.
12fb3fb4f3Stomee  *
13fb3fb4f3Stomee  * When distributing Covered Code, include this CDDL HEADER in each
14fb3fb4f3Stomee  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fb3fb4f3Stomee  * If applicable, add the following below this CDDL HEADER, with the
16fb3fb4f3Stomee  * fields enclosed by brackets "[]" replaced with your own identifying
17fb3fb4f3Stomee  * information: Portions Copyright [yyyy] [name of copyright owner]
18fb3fb4f3Stomee  *
19fb3fb4f3Stomee  * CDDL HEADER END
20fb3fb4f3Stomee  */
21fb3fb4f3Stomee 
22fb3fb4f3Stomee /*
2381621461Stomee  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24fb3fb4f3Stomee  * Use is subject to license terms.
25fb3fb4f3Stomee  *
26fb3fb4f3Stomee  * ident	"%Z%%M%	%I%	%E% SMI"
27fb3fb4f3Stomee  */
28fb3fb4f3Stomee package org.opensolaris.os.dtrace;
29fb3fb4f3Stomee 
30fb3fb4f3Stomee import java.util.*;
31fb3fb4f3Stomee import java.text.ParseException;
32fb3fb4f3Stomee import java.io.*;
33fb3fb4f3Stomee import java.beans.*;
34fb3fb4f3Stomee 
35fb3fb4f3Stomee /**
36fb3fb4f3Stomee  * A DTrace probe description consists of provider, module, function,
37fb3fb4f3Stomee  * and name.  A single probe description may identify a single DTrace
38fb3fb4f3Stomee  * probe or match multiple probes.  Any field may be wildcarded by
39fb3fb4f3Stomee  * omission (set to null) or set to a glob-style pattern:
40fb3fb4f3Stomee  * <pre>
41fb3fb4f3Stomee  *    *		Matches any string, including the null string
42fb3fb4f3Stomee  *    ?		Matches any single character
43fb3fb4f3Stomee  *    [ ... ]	Matches any one of the enclosed characters. A pair of
44fb3fb4f3Stomee  *    			characters separated by - matches any character
45fb3fb4f3Stomee  *    			between the pair, inclusive. If the first
46fb3fb4f3Stomee  *    			character after the [ is !, any character not
47fb3fb4f3Stomee  *    			enclosed in the set is matched.
48fb3fb4f3Stomee  *    \		Interpret the next character as itself, without any
49fb3fb4f3Stomee  *    			special meaning
50fb3fb4f3Stomee  * </pre>
51fb3fb4f3Stomee  * Immutable.  Supports persistence using {@link java.beans.XMLEncoder}.
52fb3fb4f3Stomee  *
53fb3fb4f3Stomee  * @see Consumer#listProbes(ProbeDescription filter)
54fb3fb4f3Stomee  *
55fb3fb4f3Stomee  * @author Tom Erickson
56fb3fb4f3Stomee  */
57fb3fb4f3Stomee public final class ProbeDescription implements Serializable,
58fb3fb4f3Stomee         Comparable <ProbeDescription>
59fb3fb4f3Stomee {
60fb3fb4f3Stomee     static final long serialVersionUID = 5978023304364513667L;
61fb3fb4f3Stomee 
62fb3fb4f3Stomee     /**
63fb3fb4f3Stomee      * Instance with empty provider, module, function, and name fields
64fb3fb4f3Stomee      * matches all DTrace probes on a system.
65fb3fb4f3Stomee      */
66fb3fb4f3Stomee     public static final ProbeDescription EMPTY =
67fb3fb4f3Stomee 	    new ProbeDescription(null, null, null, null);
68fb3fb4f3Stomee 
69fb3fb4f3Stomee     private static final int ID_NONE = -1;
70fb3fb4f3Stomee 
71fb3fb4f3Stomee     /**
72fb3fb4f3Stomee      * Enumerates the provider, module, function, and name fields of a
73fb3fb4f3Stomee      * probe description.
74fb3fb4f3Stomee      */
75fb3fb4f3Stomee     public enum Spec {
76fb3fb4f3Stomee 	/** Probe provider */
77fb3fb4f3Stomee 	PROVIDER,
78fb3fb4f3Stomee 	/** Probe module */
79fb3fb4f3Stomee 	MODULE,
80fb3fb4f3Stomee 	/** Probe function */
81fb3fb4f3Stomee 	FUNCTION,
82fb3fb4f3Stomee 	/** Probe name (unqualified) */
83fb3fb4f3Stomee 	NAME
84fb3fb4f3Stomee     };
85fb3fb4f3Stomee 
86fb3fb4f3Stomee     static {
87fb3fb4f3Stomee 	try {
88fb3fb4f3Stomee 	    BeanInfo info = Introspector.getBeanInfo(ProbeDescription.class);
89fb3fb4f3Stomee 	    PersistenceDelegate persistenceDelegate =
90fb3fb4f3Stomee 		    new DefaultPersistenceDelegate(
9181621461Stomee 		    new String[] {"ID", "provider", "module",
92fb3fb4f3Stomee 		    "function", "name"});
93fb3fb4f3Stomee 	    BeanDescriptor d = info.getBeanDescriptor();
94fb3fb4f3Stomee 	    d.setValue("persistenceDelegate", persistenceDelegate);
95fb3fb4f3Stomee 	} catch (IntrospectionException e) {
96fb3fb4f3Stomee 	    System.out.println(e);
97fb3fb4f3Stomee 	}
98fb3fb4f3Stomee     }
99fb3fb4f3Stomee 
100fb3fb4f3Stomee     /** @serial */
101fb3fb4f3Stomee     private int id = ID_NONE; // set by native code
102fb3fb4f3Stomee 
103fb3fb4f3Stomee     /** @serial */
104fb3fb4f3Stomee     private final String provider;
105fb3fb4f3Stomee     /** @serial */
106fb3fb4f3Stomee     private final String module;
107fb3fb4f3Stomee     /** @serial */
108fb3fb4f3Stomee     private final String function;
109fb3fb4f3Stomee     /** @serial */
110fb3fb4f3Stomee     private final String name;
111fb3fb4f3Stomee 
112fb3fb4f3Stomee     /**
11352aacb45Stomee      * Creates a fully qualified probe description from the name given
11452aacb45Stomee      * in the format <i>{@code provider:module:function:name}</i> or
11552aacb45Stomee      * else a probe description that specifies only the unqualified
116fb3fb4f3Stomee      * probe name.
117fb3fb4f3Stomee      *
11852aacb45Stomee      * @param probeName either the fully qualified name in the format
11952aacb45Stomee      * <i>{@code provider:module:function:name}</i> or else (if no colon
12052aacb45Stomee      * is present) the unqualified name interpreted as {@code
12152aacb45Stomee      * :::probeName}
122fb3fb4f3Stomee      * @see ProbeDescription#ProbeDescription(String probeProvider,
123fb3fb4f3Stomee      * String probeModule, String probeFunction, String probeName)
12452aacb45Stomee      * @see ProbeDescription#parse(String s)
125fb3fb4f3Stomee      */
126fb3fb4f3Stomee     public
ProbeDescription(String probeName)127fb3fb4f3Stomee     ProbeDescription(String probeName)
128fb3fb4f3Stomee     {
12952aacb45Stomee 	if ((probeName != null) && (probeName.indexOf(':') >= 0)) {
13052aacb45Stomee 	    ProbeDescription p;
13152aacb45Stomee 	    try {
13252aacb45Stomee 		p = ProbeDescription.parse(probeName);
13352aacb45Stomee 	    } catch (ParseException e) {
13452aacb45Stomee 		p = null;
13552aacb45Stomee 	    }
13652aacb45Stomee 
13752aacb45Stomee 	    if (p == null) {
13852aacb45Stomee 		provider = "";
13952aacb45Stomee 		module = "";
14052aacb45Stomee 		function = "";
14152aacb45Stomee 		name = ((probeName == null) ? "" : probeName);
14252aacb45Stomee 	    } else {
14352aacb45Stomee 		provider = p.provider;
14452aacb45Stomee 		module = p.module;
14552aacb45Stomee 		function = p.function;
14652aacb45Stomee 		name = p.name;
14752aacb45Stomee 	    }
14852aacb45Stomee 	} else {
14952aacb45Stomee 	    provider = "";
15052aacb45Stomee 	    module = "";
15152aacb45Stomee 	    function = "";
15252aacb45Stomee 	    name = ((probeName == null) ? "" : probeName);
15352aacb45Stomee 	}
154fb3fb4f3Stomee     }
155fb3fb4f3Stomee 
156fb3fb4f3Stomee     /**
157fb3fb4f3Stomee      * Creates a probe description that specifies the probe name
158fb3fb4f3Stomee      * qualified only by the function name.
159fb3fb4f3Stomee      *
160fb3fb4f3Stomee      * @see ProbeDescription#ProbeDescription(String probeProvider,
161fb3fb4f3Stomee      * String probeModule, String probeFunction, String probeName)
162fb3fb4f3Stomee      */
163fb3fb4f3Stomee     public
ProbeDescription(String probeFunction, String probeName)164fb3fb4f3Stomee     ProbeDescription(String probeFunction, String probeName)
165fb3fb4f3Stomee     {
166fb3fb4f3Stomee 	this(null, null, probeFunction, probeName);
167fb3fb4f3Stomee     }
168fb3fb4f3Stomee 
169fb3fb4f3Stomee     /**
170fb3fb4f3Stomee      * Creates a probe description that specifies the probe name
171fb3fb4f3Stomee      * qualified by the function name and module name.
172fb3fb4f3Stomee      *
173fb3fb4f3Stomee      * @see ProbeDescription#ProbeDescription(String probeProvider,
174fb3fb4f3Stomee      * String probeModule, String probeFunction, String probeName)
175fb3fb4f3Stomee      */
176fb3fb4f3Stomee     public
ProbeDescription(String probeModule, String probeFunction, String probeName)177fb3fb4f3Stomee     ProbeDescription(String probeModule, String probeFunction,
178fb3fb4f3Stomee 	    String probeName)
179fb3fb4f3Stomee     {
180fb3fb4f3Stomee 	this(null, probeModule, probeFunction, probeName);
181fb3fb4f3Stomee     }
182fb3fb4f3Stomee 
183fb3fb4f3Stomee     /**
184fb3fb4f3Stomee      * Creates a fully qualified probe description.  If no pattern
185fb3fb4f3Stomee      * syntax is used and no field is omitted, the resulting description
186fb3fb4f3Stomee      * matches at most one DTrace probe.
187fb3fb4f3Stomee      *
188fb3fb4f3Stomee      * @param probeProvider provider name, may be null or empty to match
189fb3fb4f3Stomee      * all providers or use pattern syntax to match multiple providers
190fb3fb4f3Stomee      * @param probeModule module name, may be null or empty to match all
191fb3fb4f3Stomee      * modules or use pattern syntax to match multiple modules
192fb3fb4f3Stomee      * @param probeFunction function name, may be null or empty to match
193fb3fb4f3Stomee      * all functions or use pattern syntax to match multiple functions
194fb3fb4f3Stomee      * @param probeName unqualified probe name, may be null or empty to
195fb3fb4f3Stomee      * match all names or use pattern syntax to match multiple names
196fb3fb4f3Stomee      */
197fb3fb4f3Stomee     public
ProbeDescription(String probeProvider, String probeModule, String probeFunction, String probeName)198fb3fb4f3Stomee     ProbeDescription(String probeProvider,
199fb3fb4f3Stomee 	    String probeModule,
200fb3fb4f3Stomee 	    String probeFunction,
201fb3fb4f3Stomee 	    String probeName)
202fb3fb4f3Stomee     {
203fb3fb4f3Stomee 	provider = ((probeProvider == null) ? "" : probeProvider);
204fb3fb4f3Stomee 	module = ((probeModule == null) ? "" : probeModule);
205fb3fb4f3Stomee 	function = ((probeFunction == null) ? "" : probeFunction);
206fb3fb4f3Stomee 	name = ((probeName == null) ? "" : probeName);
207fb3fb4f3Stomee     }
208fb3fb4f3Stomee 
209fb3fb4f3Stomee     /**
210fb3fb4f3Stomee      * Supports XML persistence.
211fb3fb4f3Stomee      */
212fb3fb4f3Stomee     public
ProbeDescription(int probeID, String probeProvider, String probeModule, String probeFunction, String probeName)213fb3fb4f3Stomee     ProbeDescription(int probeID,
214fb3fb4f3Stomee 	    String probeProvider,
215fb3fb4f3Stomee 	    String probeModule,
216fb3fb4f3Stomee 	    String probeFunction,
217fb3fb4f3Stomee 	    String probeName)
218fb3fb4f3Stomee     {
219fb3fb4f3Stomee 	this(probeProvider, probeModule, probeFunction, probeName);
220fb3fb4f3Stomee 	id = probeID;
221fb3fb4f3Stomee     }
222fb3fb4f3Stomee 
223fb3fb4f3Stomee     /**
224fb3fb4f3Stomee      * Generates a probe description from a string in the same format
225fb3fb4f3Stomee      * returned by {@link #toString()}.  Parses the string from right to
226fb3fb4f3Stomee      * left.
227fb3fb4f3Stomee      * <pre><code>
228fb3fb4f3Stomee      * <i>provider:module:function:name</i>
229fb3fb4f3Stomee      * </code></pre>
230fb3fb4f3Stomee      *
231fb3fb4f3Stomee      * @return non-null probe description
232fb3fb4f3Stomee      * @throws ParseException if {@code s} does not have the expected
233fb3fb4f3Stomee      * format.  The error offset is the index of the first unexpected
234fb3fb4f3Stomee      * character encountered starting from the last character and
235fb3fb4f3Stomee      * reading backwards.
236fb3fb4f3Stomee      * @throws NullPointerException if the given string is {@code null}
237fb3fb4f3Stomee      */
238fb3fb4f3Stomee     public static ProbeDescription
parse(String s)239fb3fb4f3Stomee     parse(String s) throws ParseException
240fb3fb4f3Stomee     {
241fb3fb4f3Stomee 	ProbeDescription p;
242fb3fb4f3Stomee 
243fb3fb4f3Stomee 	// StringTokenizer and String.split() do not correctly handle
244fb3fb4f3Stomee 	// the case of consecutive delimiters
245fb3fb4f3Stomee 	List <String> list = new ArrayList <String> ();
246fb3fb4f3Stomee 	int len = s.length();
247fb3fb4f3Stomee 	int npos = len;
248fb3fb4f3Stomee 	char ch;
249fb3fb4f3Stomee 	for (int i = (len - 1); i >= 0; --i) {
250fb3fb4f3Stomee 	    ch = s.charAt(i);
251fb3fb4f3Stomee 	    if (ch == ':') {
252fb3fb4f3Stomee 		list.add(0, s.substring((i + 1), npos));
253fb3fb4f3Stomee 		npos = i;
254fb3fb4f3Stomee 	    }
255fb3fb4f3Stomee 	}
256fb3fb4f3Stomee 	list.add(0, s.substring(0, npos));
257fb3fb4f3Stomee 
258fb3fb4f3Stomee 	switch (list.size()) {
259fb3fb4f3Stomee 	    case 0:
260fb3fb4f3Stomee 		p = EMPTY;
261fb3fb4f3Stomee 		break;
262fb3fb4f3Stomee 	    case 1:
263fb3fb4f3Stomee 		p = new ProbeDescription(list.get(0));
264fb3fb4f3Stomee 		break;
265fb3fb4f3Stomee 	    case 2:
266fb3fb4f3Stomee 		p = new ProbeDescription(list.get(0), list.get(1));
267fb3fb4f3Stomee 		break;
268fb3fb4f3Stomee 	    case 3:
269fb3fb4f3Stomee 		p = new ProbeDescription(list.get(0), list.get(1),
270fb3fb4f3Stomee 			list.get(2));
271fb3fb4f3Stomee 		break;
272fb3fb4f3Stomee 	    case 4:
273fb3fb4f3Stomee 		p = new ProbeDescription(list.get(0), list.get(1),
274fb3fb4f3Stomee 			list.get(2), list.get(3));
275fb3fb4f3Stomee 		break;
276fb3fb4f3Stomee 	    default:
277fb3fb4f3Stomee 		// get error offset (parsing right-to-left)
278fb3fb4f3Stomee 		int offset = (s.length() - 4);
279fb3fb4f3Stomee 		len = list.size();
280fb3fb4f3Stomee 		for (int i = (len - 1); i >= (len - 4); --i) {
281fb3fb4f3Stomee 		    offset -= list.get(i).length();
282fb3fb4f3Stomee 		}
283fb3fb4f3Stomee 		throw new ParseException("Overspecified probe " +
284fb3fb4f3Stomee 			"description: \"" + s + "\"", offset);
285fb3fb4f3Stomee 	}
286fb3fb4f3Stomee 	return p;
287fb3fb4f3Stomee     }
288fb3fb4f3Stomee 
289fb3fb4f3Stomee     /**
290fb3fb4f3Stomee      * Gets the probe ID.
291fb3fb4f3Stomee      *
292fb3fb4f3Stomee      * @return ID generated from a sequence by the native DTrace
293fb3fb4f3Stomee      * library, identifies the probe among all probes on the system
294fb3fb4f3Stomee      */
295fb3fb4f3Stomee     public int
getID()296fb3fb4f3Stomee     getID()
297fb3fb4f3Stomee     {
298fb3fb4f3Stomee 	return id;
299fb3fb4f3Stomee     }
300fb3fb4f3Stomee 
301fb3fb4f3Stomee     /**
302fb3fb4f3Stomee      * Gets the provider name.
303fb3fb4f3Stomee      *
304fb3fb4f3Stomee      * @return non-null provider name, may be an empty string to
305fb3fb4f3Stomee      * indicate omission
306fb3fb4f3Stomee      */
307fb3fb4f3Stomee     public String
getProvider()308fb3fb4f3Stomee     getProvider()
309fb3fb4f3Stomee     {
310fb3fb4f3Stomee 	return provider;
311fb3fb4f3Stomee     }
312fb3fb4f3Stomee 
313fb3fb4f3Stomee     /**
314fb3fb4f3Stomee      * Gets the module name.
315fb3fb4f3Stomee      *
316fb3fb4f3Stomee      * @return non-null module name, may be an empty string to indicate
317fb3fb4f3Stomee      * omission
318fb3fb4f3Stomee      */
319fb3fb4f3Stomee     public String
getModule()320fb3fb4f3Stomee     getModule()
321fb3fb4f3Stomee     {
322fb3fb4f3Stomee 	return module;
323fb3fb4f3Stomee     }
324fb3fb4f3Stomee 
325fb3fb4f3Stomee     /**
326fb3fb4f3Stomee      * Gets the function name.
327fb3fb4f3Stomee      *
328fb3fb4f3Stomee      * @return non-null function name, may be an empty string to
329fb3fb4f3Stomee      * indicate omission
330fb3fb4f3Stomee      */
331fb3fb4f3Stomee     public String
getFunction()332fb3fb4f3Stomee     getFunction()
333fb3fb4f3Stomee     {
334fb3fb4f3Stomee 	return function;
335fb3fb4f3Stomee     }
336fb3fb4f3Stomee 
337fb3fb4f3Stomee     /**
338fb3fb4f3Stomee      * Gets the unqualified probe name.
339fb3fb4f3Stomee      *
340fb3fb4f3Stomee      * @return non-null probe name, may be an empty string to indicate
341fb3fb4f3Stomee      * omission
342fb3fb4f3Stomee      */
343fb3fb4f3Stomee     public String
getName()344fb3fb4f3Stomee     getName()
345fb3fb4f3Stomee     {
346fb3fb4f3Stomee 	return name;
347fb3fb4f3Stomee     }
348fb3fb4f3Stomee 
349fb3fb4f3Stomee     /**
350fb3fb4f3Stomee      * Returns {@code true} if provider, module, function, and name are
351fb3fb4f3Stomee      * all omitted.  An empty probe description matches all DTrace
352fb3fb4f3Stomee      * probes on a system.
353fb3fb4f3Stomee      *
354fb3fb4f3Stomee      * @return {@code true} if all probe fields are omitted, {@code
355fb3fb4f3Stomee      * false} otherwise
356fb3fb4f3Stomee      */
357fb3fb4f3Stomee     public boolean
isEmpty()358fb3fb4f3Stomee     isEmpty()
359fb3fb4f3Stomee     {
360fb3fb4f3Stomee 	if (provider.length() > 0) {
361fb3fb4f3Stomee 	    return false;
362fb3fb4f3Stomee 	}
363fb3fb4f3Stomee 	if (module.length() > 0) {
364fb3fb4f3Stomee 	    return false;
365fb3fb4f3Stomee 	}
366fb3fb4f3Stomee 	if (function.length() > 0) {
367fb3fb4f3Stomee 	    return false;
368fb3fb4f3Stomee 	}
369fb3fb4f3Stomee 	if (name.length() > 0) {
370fb3fb4f3Stomee 	    return false;
371fb3fb4f3Stomee 	}
372fb3fb4f3Stomee 	return true;
373fb3fb4f3Stomee     }
374fb3fb4f3Stomee 
375fb3fb4f3Stomee     /**
376fb3fb4f3Stomee      * Compares the specified object with this probe description for
377fb3fb4f3Stomee      * equality.  Defines equality as having the same fields.  Omitted
378fb3fb4f3Stomee      * fields must be omitted in both instances in order for them to be
379fb3fb4f3Stomee      * equal, but it makes no difference whether {@code null} or empty
380fb3fb4f3Stomee      * string was used to indicate omission.
381fb3fb4f3Stomee      *
382fb3fb4f3Stomee      * @return {@code true} if and only if all corresponding fields of
383fb3fb4f3Stomee      * both probe descriptions are either both omitted (null or empty)
384fb3fb4f3Stomee      * or else equal as defined by {@link String#equals(Object o)
385fb3fb4f3Stomee      * String.equals()}
386fb3fb4f3Stomee      */
387fb3fb4f3Stomee     public boolean
equals(Object o)388fb3fb4f3Stomee     equals(Object o)
389fb3fb4f3Stomee     {
390fb3fb4f3Stomee 	if (o instanceof ProbeDescription) {
391fb3fb4f3Stomee 	    ProbeDescription p = (ProbeDescription)o;
392fb3fb4f3Stomee 	    if ((id == ID_NONE) || (p.id == ID_NONE)) {
393fb3fb4f3Stomee 		return (compareTo(p) == 0);
394fb3fb4f3Stomee 	    } else {
395fb3fb4f3Stomee 		return (id == p.id);
396fb3fb4f3Stomee 	    }
397fb3fb4f3Stomee 	}
398fb3fb4f3Stomee 
399fb3fb4f3Stomee 	return false;
400fb3fb4f3Stomee     }
401fb3fb4f3Stomee 
402fb3fb4f3Stomee     /**
403fb3fb4f3Stomee      * Defines the natural ordering of probe descriptions.  Returns the
404fb3fb4f3Stomee      * natural ordering of the first unequal pair of corresponding
405fb3fb4f3Stomee      * fields (starting with the provider and continuing to the
406fb3fb4f3Stomee      * unqualified name only if all other fields are equal).
407fb3fb4f3Stomee      * Corresponding fields are equal if they are both omitted or both
408fb3fb4f3Stomee      * equal as defined by {@link String#equals(Object o)
409fb3fb4f3Stomee      * String.equals()}.  It makes no difference if {@code null} or
410fb3fb4f3Stomee      * empty string is used to indicate omission.  The behavior is
411fb3fb4f3Stomee      * consistent with the {@link #equals(Object o) equals()} method.
412fb3fb4f3Stomee      *
413fb3fb4f3Stomee      * @return -1, 0, or 1 as this probe description is less than, equal
414fb3fb4f3Stomee      * to, or greater than the given probe description
415fb3fb4f3Stomee      */
416fb3fb4f3Stomee     public int
compareTo(ProbeDescription p)417fb3fb4f3Stomee     compareTo(ProbeDescription p)
418fb3fb4f3Stomee     {
419fb3fb4f3Stomee 	int cmp = 0;
420fb3fb4f3Stomee 	cmp = provider.compareTo(p.provider);
421fb3fb4f3Stomee 	if (cmp == 0) {
422fb3fb4f3Stomee 	    cmp = module.compareTo(p.module);
423fb3fb4f3Stomee 	    if (cmp == 0) {
424fb3fb4f3Stomee 		cmp = function.compareTo(p.function);
425fb3fb4f3Stomee 		if (cmp == 0) {
426fb3fb4f3Stomee 		    cmp = name.compareTo(p.name);
427fb3fb4f3Stomee 		}
428fb3fb4f3Stomee 	    }
429fb3fb4f3Stomee 	}
430fb3fb4f3Stomee 	return (cmp);
431fb3fb4f3Stomee     }
432fb3fb4f3Stomee 
433fb3fb4f3Stomee     /**
434fb3fb4f3Stomee      * Overridden to ensure that equal probe descriptions have equal
435fb3fb4f3Stomee      * hashcodes.
436fb3fb4f3Stomee      */
437fb3fb4f3Stomee     @Override
438fb3fb4f3Stomee     public int
hashCode()439fb3fb4f3Stomee     hashCode()
440fb3fb4f3Stomee     {
441fb3fb4f3Stomee 	int hash = id;
442fb3fb4f3Stomee 	if (hash != ID_NONE) {
443fb3fb4f3Stomee 	    return hash;
444fb3fb4f3Stomee 	}
445fb3fb4f3Stomee 
446fb3fb4f3Stomee 	hash = 17;
447fb3fb4f3Stomee 	hash = (37 * hash) + provider.hashCode();
448fb3fb4f3Stomee 	hash = (37 * hash) + module.hashCode();
449fb3fb4f3Stomee 	hash = (37 * hash) + function.hashCode();
450fb3fb4f3Stomee 	hash = (37 * hash) + name.hashCode();
451fb3fb4f3Stomee 	return hash;
452fb3fb4f3Stomee     }
453fb3fb4f3Stomee 
454fb3fb4f3Stomee     private void
readObject(ObjectInputStream s)455fb3fb4f3Stomee     readObject(ObjectInputStream s)
456fb3fb4f3Stomee             throws IOException, ClassNotFoundException
457fb3fb4f3Stomee     {
458fb3fb4f3Stomee 	s.defaultReadObject();
459fb3fb4f3Stomee 	// check invariants
460fb3fb4f3Stomee 	if (provider == null) {
461fb3fb4f3Stomee 	    throw new InvalidObjectException("provider is null");
462fb3fb4f3Stomee 	}
463fb3fb4f3Stomee 	if (module == null) {
464fb3fb4f3Stomee 	    throw new InvalidObjectException("module is null");
465fb3fb4f3Stomee 	}
466fb3fb4f3Stomee 	if (function == null) {
467fb3fb4f3Stomee 	    throw new InvalidObjectException("function is null");
468fb3fb4f3Stomee 	}
469fb3fb4f3Stomee 	if (name == null) {
470fb3fb4f3Stomee 	    throw new InvalidObjectException("name is null");
471fb3fb4f3Stomee 	}
472fb3fb4f3Stomee     }
473fb3fb4f3Stomee 
474fb3fb4f3Stomee     /**
475fb3fb4f3Stomee      * Gets the string representation of this probe description.  The
476fb3fb4f3Stomee      * format is as follows:
477fb3fb4f3Stomee      * <pre><code>
478fb3fb4f3Stomee      * <i>provider:module:function:name</i>
479fb3fb4f3Stomee      * </code></pre>
480fb3fb4f3Stomee      * Individual fields may be empty, but none of the three delimiting
481fb3fb4f3Stomee      * colons is ever omitted.  If this instance uses pattern matching
482fb3fb4f3Stomee      * syntax to match multiple probes, that syntax is preserved in the
483fb3fb4f3Stomee      * string representation.
484fb3fb4f3Stomee      */
485fb3fb4f3Stomee     public String
toString()486fb3fb4f3Stomee     toString()
487fb3fb4f3Stomee     {
488*4ae67516Stomee 	StringBuilder buf = new StringBuilder();
489fb3fb4f3Stomee 	buf.append(provider);
490fb3fb4f3Stomee 	buf.append(':');
491fb3fb4f3Stomee 	buf.append(module);
492fb3fb4f3Stomee 	buf.append(':');
493fb3fb4f3Stomee 	buf.append(function);
494fb3fb4f3Stomee 	buf.append(':');
495fb3fb4f3Stomee 	buf.append(name);
496fb3fb4f3Stomee 	return buf.toString();
497fb3fb4f3Stomee     }
498fb3fb4f3Stomee }
499