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