1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * ident "%Z%%M% %I% %E% SMI" 27 */ 28 package org.opensolaris.os.dtrace; 29 30 import java.util.*; 31 import java.io.*; 32 import java.beans.*; 33 34 /** 35 * A {@link ProbeDescription} identifying a single probe combined with 36 * information about the identified probe. 37 * <p> 38 * Immutable. Supports persistence using {@link java.beans.XMLEncoder}. 39 * 40 * @see Consumer#listProbes(ProbeDescription filter) 41 * @see Consumer#listProgramProbes(Program program) 42 * 43 * @author Tom Erickson 44 */ 45 public final class Probe implements Serializable { 46 static final long serialVersionUID = 8917481979541675727L; 47 48 static { 49 try { 50 BeanInfo info = Introspector.getBeanInfo(Probe.class); 51 PersistenceDelegate persistenceDelegate = 52 new DefaultPersistenceDelegate( 53 new String[] {"description", "info"}) 54 { 55 /* 56 * Need to prevent DefaultPersistenceDelegate from using 57 * overridden equals() method, resulting in a 58 * StackOverFlowError. Revert to PersistenceDelegate 59 * implementation. See 60 * http://forum.java.sun.com/thread.jspa?threadID= 61 * 477019&tstart=135 62 */ 63 protected boolean 64 mutatesTo(Object oldInstance, Object newInstance) 65 { 66 return (newInstance != null && oldInstance != null && 67 oldInstance.getClass() == newInstance.getClass()); 68 } 69 }; 70 BeanDescriptor d = info.getBeanDescriptor(); 71 d.setValue("persistenceDelegate", persistenceDelegate); 72 } catch (IntrospectionException e) { 73 System.out.println(e); 74 } 75 } 76 77 /** @serial */ 78 private final ProbeDescription description; 79 /** @serial */ 80 private final ProbeInfo info; 81 82 /** 83 * Creates a {@code Probe} instance with the given identifying 84 * description and associated probe information. Supports XML 85 * persistence. 86 * 87 * @param probeDescription probe description that identifies a 88 * single DTrace probe 89 * @param probeInfo information about the identified probe, {@code 90 * null} indicating that the information could not be obtained 91 * @throws NullPointerException if the given probe description is 92 * {@code null} 93 */ 94 public 95 Probe(ProbeDescription probeDescription, ProbeInfo probeInfo) 96 { 97 description = probeDescription; 98 info = probeInfo; 99 validate(); 100 } 101 102 private final void 103 validate() 104 { 105 if (description == null) { 106 throw new NullPointerException("description is null"); 107 } 108 } 109 110 /** 111 * Gets the probe description identifying a single probe described 112 * by this instance. 113 * 114 * @return non-null probe description matching a single probe on the 115 * system 116 */ 117 public ProbeDescription 118 getDescription() 119 { 120 return description; 121 } 122 123 /** 124 * Gets information including attributes and argument types of the 125 * probe identified by {@link #getDescription()}. 126 * 127 * @return information about the probe identified by {@link 128 * #getDescription()}, or {@code null} if that information could not 129 * be obtained for any reason 130 */ 131 public ProbeInfo 132 getInfo() 133 { 134 return info; 135 } 136 137 /** 138 * Compares the specified object with this {@code Probe} instance 139 * for equality. Defines equality as having the same probe 140 * description. 141 * 142 * @return {@code true} if and only if the specified object is also 143 * a {@code Probe} and both instances return equal values from 144 * {@link #getDescription()}. 145 */ 146 @Override 147 public boolean 148 equals(Object o) 149 { 150 if (o instanceof Probe) { 151 Probe p = (Probe)o; 152 return description.equals(p.description); 153 } 154 return false; 155 } 156 157 /** 158 * Overridden to ensure that equal instances have equal hash codes. 159 */ 160 @Override 161 public int 162 hashCode() 163 { 164 return description.hashCode(); 165 } 166 167 private void 168 readObject(ObjectInputStream s) 169 throws IOException, ClassNotFoundException 170 { 171 s.defaultReadObject(); 172 // Check class invariants 173 try { 174 validate(); 175 } catch (Exception e) { 176 InvalidObjectException x = new InvalidObjectException( 177 e.getMessage()); 178 x.initCause(e); 179 throw x; 180 } 181 } 182 183 /** 184 * Returns a string representation of this {@code Probe} useful for 185 * logging and not intended for display. The exact details of the 186 * representation are unspecified and subject to change, but the 187 * following format may be regarded as typical: 188 * <pre><code> 189 * class-name[property1 = value1, property2 = value2] 190 * </code></pre> 191 */ 192 public String 193 toString() 194 { 195 StringBuilder buf = new StringBuilder(); 196 buf.append(Probe.class.getName()); 197 buf.append("[description = "); 198 buf.append(description); 199 buf.append(", info = "); 200 buf.append(info); 201 buf.append(']'); 202 return buf.toString(); 203 } 204 } 205