001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: * The Original Software is NetBeans. The Initial Developer of the Original
026: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
027: * Microsystems, Inc. All Rights Reserved.
028: *
029: * If you wish your version of this file to be governed by only the CDDL
030: * or only the GPL Version 2, indicate your decision by adding
031: * "[Contributor] elects to include this software in this distribution
032: * under the [CDDL or GPL Version 2] license." If you do not indicate a
033: * single choice of license, a recipient has the option to distribute
034: * your version of this file under either the CDDL, the GPL Version 2 or
035: * to extend the choice of license to its licensees as provided above.
036: * However, if you add GPL Version 2 code and therefore, elected the GPL
037: * Version 2 license, then the option applies only if the new code is
038: * made subject to such option by the copyright holder.
039: */
040:
041: package org.netbeans.lib.profiler.client;
042:
043: import org.netbeans.lib.profiler.classfile.ClassInfo;
044: import org.netbeans.lib.profiler.classfile.ClassRepository;
045:
046: /**
047: * Represents a Profiling point.
048: * Its lifetime must not span across sessions.
049: *
050: * @author Tomas Hurka
051: * @author Maros Sandor
052: */
053: public class RuntimeProfilingPoint {
054: //~ Inner Classes ------------------------------------------------------------------------------------------------------------
055:
056: /**
057: * Encapsulates an event of hitting a profiling point.
058: */
059: public static class HitEvent {
060: //~ Instance fields ------------------------------------------------------------------------------------------------------
061:
062: private final int id;
063: private final int threadId;
064: private final long timestamp;
065:
066: //~ Constructors ---------------------------------------------------------------------------------------------------------
067:
068: public HitEvent(int id, long timestamp, int threadId) {
069: this .id = id;
070: this .timestamp = timestamp;
071: this .threadId = threadId;
072: }
073:
074: //~ Methods --------------------------------------------------------------------------------------------------------------
075:
076: public int getId() {
077: return id;
078: }
079:
080: public int getThreadId() {
081: return threadId;
082: }
083:
084: public long getTimestamp() {
085: return timestamp;
086: }
087:
088: public String toString() {
089: return "HitEvent [id=" + getId() + ", thread id="
090: + getThreadId() + ", timestamp=" + getTimestamp()
091: + "]"; //NOI18N
092: }
093: }
094:
095: //~ Instance fields ----------------------------------------------------------------------------------------------------------
096:
097: /**
098: * Name of the class where the profiling point resides in the form: package.Class.Inner
099: */
100: private final String className;
101:
102: /**
103: * Name of the method where this profiling point resides. This is mutually exclusive with the line field and means
104: * "beginning of a method".
105: */
106: private final String methodName;
107:
108: /**
109: * Signature of the method where this profiling point resides. This is mutually exclusive with the line field and
110: * supplements the methodName field. May be null to indicate 'the first method with the given name'.
111: */
112: private final String methodSignature;
113:
114: /**
115: * Handler for hit events.
116: */
117: private final String serverHandlerClass;
118:
119: /**
120: * Additional arbitrary info send to server
121: */
122: private final String serverInfo;
123:
124: /**
125: * ID identifies this profiling point in eventbuffer events.
126: */
127: private final int id;
128:
129: /**
130: * Line number where this profiling point resides. This is mutually exclusive with the method field.
131: */
132: private final int line;
133:
134: /**
135: * Line offset where this profiling point resides. This is mutually exclusive with the method field.
136: */
137: private final int offset;
138:
139: /**
140: * Bytecode index; filled at runtime when the class loads and we inject profile point hit methods.
141: */
142: private int bci;
143:
144: /**
145: * Method index; filled at runtime when the class loads and we inject profile point hit methods.
146: */
147: private int methodIdx = -1;
148:
149: //~ Constructors -------------------------------------------------------------------------------------------------------------
150:
151: /**
152: * Creates a new profiling point.
153: *
154: *
155: *
156: * @param id unique ID of this profiling point
157: * @param className name of the class where this profiling point is placed
158: * @param line profiling point location in the class. If line is positive, it is be inserted just before the line executes.
159: * If line is negative, it is inserted just after the line executes.
160: * @param offset line offset
161: * @param serverHandlerClass handles hits of this profiling point on server side (fully qualified class name)
162: */
163: public RuntimeProfilingPoint(int id, String className, int line,
164: int offset, String serverHandlerClass, String serverInfo) {
165: this (id, className, line, offset, null, null,
166: serverHandlerClass, serverInfo);
167: }
168:
169: /**
170: * Creates a new profiling point.
171: *
172: *
173: *
174: * @param id unique ID of this profiling point
175: * @param className name of the class where this profiling point is placed
176: * @param methodName name of the method where this profiling point is placed
177: * @param methodSignature signature of the method where this profiling point is placed
178: * @param serverHandlerClass handles hits of this profiling point on server side (fully qualified class name)
179: */
180: public RuntimeProfilingPoint(int id, String className,
181: String methodName, String methodSignature,
182: String serverHandlerClass, String serverInfo) {
183: this (id, className, -1, -1, methodName, methodSignature,
184: serverHandlerClass, serverInfo);
185: }
186:
187: private RuntimeProfilingPoint(int id, String className, int line,
188: int offset, String methodName, String methodSignature,
189: String serverHandlerClass, String serverInfo) {
190: this .id = id;
191: this .className = className;
192: this .line = line;
193: this .offset = offset;
194: this .methodName = methodName;
195: this .methodSignature = methodSignature;
196: this .serverHandlerClass = serverHandlerClass;
197: this .serverInfo = serverInfo;
198: }
199:
200: //~ Methods ------------------------------------------------------------------------------------------------------------------
201:
202: public int getBci() {
203: return bci;
204: }
205:
206: public String getClassName() {
207: return className;
208: }
209:
210: public int getId() {
211: return id;
212: }
213:
214: public int getMethodIdx() {
215: return methodIdx;
216: }
217:
218: public String getServerHandlerClass() {
219: return serverHandlerClass;
220: }
221:
222: public String getServerInfo() {
223: return serverInfo;
224: }
225:
226: public boolean resolve(ClassInfo classInfo) {
227: if (methodIdx != -1) {
228: return true;
229: }
230:
231: return (methodName != null) ? resolveMethodName(classInfo)
232: : resolveLineNumber(classInfo);
233: }
234:
235: public String toString() {
236: return "RuntimeProfilingPoint [id=" + id + ", classname="
237: + className + ", line=" + line + ", offset=" + offset
238: + ", server handler=" + serverHandlerClass + "]"; //NOI18N
239: }
240:
241: private boolean resolveLineNumber(ClassInfo classInfo) {
242: try {
243: // int ln = Math.abs(line);
244: ClassRepository.CodeRegionBCI crbci = ClassRepository
245: .getMethodForSourceRegion(classInfo, line, line);
246: methodIdx = classInfo.getMethodIndex(crbci.methodName,
247: crbci.methodSignature);
248: bci = (offset == Integer.MAX_VALUE) ? crbci.bci1
249: : crbci.bci0;
250:
251: return true;
252: } catch (Exception e) {
253: return false;
254: }
255: }
256:
257: private boolean resolveMethodName(ClassInfo classInfo) {
258: if (methodSignature != null) {
259: methodIdx = classInfo.getMethodIndex(methodName,
260: methodSignature);
261: } else {
262: String[] allNames = classInfo.getMethodNames();
263:
264: for (int i = 0; i < allNames.length; i++) {
265: if (methodName.equals(allNames[i])) {
266: methodIdx = i;
267:
268: break;
269: }
270: }
271: }
272:
273: if (methodIdx == -1) {
274: return false;
275: }
276:
277: bci = classInfo.getLineNumberTables().getStartPCs()[methodIdx][0];
278:
279: return true;
280: }
281: }
|