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.io.*;
31 import java.beans.*;
32 
33 /**
34  * A single stack frame in a {@link StackValueRecord}.
35  * <p>
36  * Immutable.  Supports persistence using {@link java.beans.XMLEncoder}.
37  *
38  * @author Tom Erickson
39  */
40 public final class StackFrame implements Serializable {
41     static final long serialVersionUID = 8617210929132692711L;
42 
43     static {
44 	try {
45 	    BeanInfo info = Introspector.getBeanInfo(StackFrame.class);
46 	    PersistenceDelegate persistenceDelegate =
47 		    new DefaultPersistenceDelegate(
48 		    new String[] {"frame"})
49 	    {
50 		/*
51 		 * Need to prevent DefaultPersistenceDelegate from using
52 		 * overridden equals() method, resulting in a
53 		 * StackOverFlowError.  Revert to PersistenceDelegate
54 		 * implementation.  See
55 		 * http://forum.java.sun.com/thread.jspa?threadID=
56 		 * 477019&tstart=135
57 		 */
58 		protected boolean
59 		mutatesTo(Object oldInstance, Object newInstance)
60 		{
61 		    return (newInstance != null && oldInstance != null &&
62 			    oldInstance.getClass() == newInstance.getClass());
63 		}
64 	    };
65 	    BeanDescriptor d = info.getBeanDescriptor();
66 	    d.setValue("persistenceDelegate", persistenceDelegate);
67 	} catch (IntrospectionException e) {
68 	    System.out.println(e);
69 	}
70     }
71 
72     /** @serial */
73     private final String frame;
74 
75     /**
76      * Creates a single stack frame.  Supports XML persistence.
77      *
78      * @param f human-readable string representation of this stack frame
79      * @throws NullPointerException if the given string representation
80      * is {@code null}
81      */
82     public
StackFrame(String f)83     StackFrame(String f)
84     {
85 	frame = f;
86 	validate();
87     }
88 
89     private final void
validate()90     validate()
91     {
92 	if (frame == null) {
93 	    throw new NullPointerException("frame is null");
94 	}
95     }
96 
97     /**
98      * Gets the human-readable string representation of this stack
99      * frame.  Supports XML persistence.
100      *
101      * @return the human-readable string representation of this stack frame.
102      */
103     public String
getFrame()104     getFrame()
105     {
106 	return frame;
107     }
108 
109     /**
110      * Compares the specified object with this {@code StackFrame} for
111      * equality.  Returns {@code true} if and only if the specified
112      * object is also a {@code StackFrame} and both instances have the
113      * same human-readable string representation.
114      *
115      * @return {@code true} if and only if the specified object is also
116      * a {@code StackFrame} and both instances have the same
117      * human-readable string representation
118      */
119     @Override
120     public boolean
equals(Object o)121     equals(Object o)
122     {
123 	if (o instanceof StackFrame) {
124 	    StackFrame s = (StackFrame)o;
125 	    return frame.equals(s.frame);
126 	}
127 	return false;
128     }
129 
130     /**
131      * Overridden to ensure that equal instances have equal hash codes.
132      */
133     @Override
134     public int
hashCode()135     hashCode()
136     {
137 	return frame.hashCode();
138     }
139 
140     private void
readObject(ObjectInputStream s)141     readObject(ObjectInputStream s)
142             throws IOException, ClassNotFoundException
143     {
144 	s.defaultReadObject();
145 	// check class invariants
146 	try {
147 	    validate();
148 	} catch (Exception e) {
149 	    InvalidObjectException x = new InvalidObjectException(
150 		    e.getMessage());
151 	    x.initCause(e);
152 	    throw x;
153 	}
154     }
155 
156     /**
157      * Gets the string representation of this stack frame, in this case
158      * the same value returned by {@link #getFrame()}.
159      */
160     public String
toString()161     toString()
162     {
163 	return frame;
164     }
165 }
166