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 */
28package org.opensolaris.os.dtrace;
29
30import java.util.*;
31import java.io.*;
32import java.beans.*;
33
34/**
35 * Probe stability information.  Does not identify a probe, but gives
36 * information about a single probe identified by a {@link
37 * ProbeDescription}.  A {@code ProbeDescription} can match multiple
38 * probes using pattern syntax (globbing) and wildcarding (field
39 * omission), but it does not normally make sense to associate a {@code
40 * ProbeInfo} with a {@code ProbeDescription} unless that description
41 * matches exactly one probe on the system.  A {@link Probe} pairs a
42 * {@code ProbeDescription} with information about the DTrace probe it
43 * identifies.
44 * <p>
45 * Immutable.  Supports persistence using {@link java.beans.XMLEncoder}.
46 *
47 * @see Consumer#listProbeDetail(ProbeDescription filter)
48 * @see Consumer#listProgramProbeDetail(Program program)
49 *
50 * @author Tom Erickson
51 */
52public final class ProbeInfo implements Serializable {
53    static final long serialVersionUID = 1057402669978245904L;
54
55    static {
56	try {
57	    BeanInfo info = Introspector.getBeanInfo(ProbeInfo.class);
58	    PersistenceDelegate persistenceDelegate =
59		    new DefaultPersistenceDelegate(
60		    new String[] {"probeAttributes",
61		    "argumentAttributes"})
62	    {
63		/*
64		 * Need to prevent DefaultPersistenceDelegate from using
65		 * overridden equals() method, resulting in a
66		 * StackOverFlowError.  Revert to PersistenceDelegate
67		 * implementation.  See
68		 * http://forum.java.sun.com/thread.jspa?threadID=
69		 * 477019&tstart=135
70		 */
71		protected boolean
72		mutatesTo(Object oldInstance, Object newInstance)
73		{
74		    return (newInstance != null && oldInstance != null &&
75			    oldInstance.getClass() == newInstance.getClass());
76		}
77	    };
78	    BeanDescriptor d = info.getBeanDescriptor();
79	    d.setValue("persistenceDelegate", persistenceDelegate);
80	} catch (IntrospectionException e) {
81	    System.out.println(e);
82	}
83    }
84
85    /** @serial */
86    private final InterfaceAttributes probeAttributes;
87    /** @serial */
88    private final InterfaceAttributes argumentAttributes;
89
90    /**
91     * Creates a {@code ProbeInfo} instance from the given attributes.
92     * Supports XML persistence.
93     *
94     * @throws NullPointerException if any parameter is null
95     */
96    public
97    ProbeInfo(InterfaceAttributes singleProbeAttributes,
98	    InterfaceAttributes argAttributes)
99    {
100	probeAttributes = singleProbeAttributes;
101	argumentAttributes = argAttributes;
102	validate();
103    }
104
105    private final void
106    validate()
107    {
108	if (probeAttributes == null) {
109	    throw new NullPointerException("probeAttributes is null");
110	}
111	if (argumentAttributes == null) {
112	    throw new NullPointerException("argumentAttributes is null");
113	}
114    }
115
116    /**
117     * Gets the interface attributes of a probe.
118     *
119     * @return non-null attributes including stability levels and
120     * dependency class
121     */
122    public InterfaceAttributes
123    getProbeAttributes()
124    {
125	return probeAttributes;
126    }
127
128    /**
129     * Gets the interface attributes of the arguments to a probe.
130     *
131     * @return non-null attributes including stability levels and
132     * dependency class of the arguments to a probe
133     */
134    public InterfaceAttributes
135    getArgumentAttributes()
136    {
137	return argumentAttributes;
138    }
139
140    /**
141     * Compares the specified object with this {@code ProbeInfo}
142     * instance for equality.  Defines equality as having equal probe
143     * attributes and equal argument attributes.
144     *
145     * @return {@code true} if and only if the specified object is also
146     * a {@code ProbeInfo} and both instances have the same attributes
147     */
148    @Override
149    public boolean
150    equals(Object o)
151    {
152	if (o instanceof ProbeInfo) {
153	    ProbeInfo i = (ProbeInfo)o;
154	    return (probeAttributes.equals(i.probeAttributes) &&
155		    argumentAttributes.equals(i.argumentAttributes));
156	}
157	return false;
158    }
159
160    /**
161     * Overridden to ensure that equal instances have equal hash codes.
162     */
163    @Override
164    public int
165    hashCode()
166    {
167	int hash = 17;
168	hash = (37 * hash) + probeAttributes.hashCode();
169	hash = (37 * hash) + argumentAttributes.hashCode();
170	return hash;
171    }
172
173    private void
174    readObject(ObjectInputStream s)
175            throws IOException, ClassNotFoundException
176    {
177	s.defaultReadObject();
178	// Must copy before checking class invariants
179	try {
180	    validate();
181	} catch (Exception e) {
182	    InvalidObjectException x = new InvalidObjectException(
183		    e.getMessage());
184	    x.initCause(e);
185	    throw x;
186	}
187    }
188
189    /**
190     * Gets a string representation of this {@code ProbeInfo} useful for
191     * logging and not intended for display.  The exact details of the
192     * representation are unspecified and subject to change, but the
193     * following format may be regarded as typical:
194     * <pre><code>
195     * class-name[property1 = value1, property2 = value2]
196     * </code></pre>
197     */
198    public String
199    toString()
200    {
201	StringBuilder buf = new StringBuilder();
202	buf.append(ProbeInfo.class.getName());
203	buf.append("[probeAttributes = ");
204	buf.append(probeAttributes);
205	buf.append(", argumentAttributes = ");
206	buf.append(argumentAttributes);
207	buf.append(']');
208	return buf.toString();
209    }
210}
211