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
Probe(ProbeDescription probeDescription, ProbeInfo probeInfo)95     Probe(ProbeDescription probeDescription, ProbeInfo probeInfo)
96     {
97 	description = probeDescription;
98 	info = probeInfo;
99 	validate();
100     }
101 
102     private final void
validate()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
getDescription()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
getInfo()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
equals(Object o)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
hashCode()162     hashCode()
163     {
164 	return description.hashCode();
165     }
166 
167     private void
readObject(ObjectInputStream s)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
toString()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