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.global.CommonConstants;
044:
045: /**
046: * A collection of utility classes and methods used exclusively by the client.
047: *
048: * @author Tomas Hurka
049: * @author Misha Dmitriev
050: * @author Adrian Mos
051: * @author Ian Formanek
052: */
053: public class ClientUtils implements CommonConstants {
054: //~ Inner Classes ------------------------------------------------------------------------------------------------------------
055:
056: public static class SourceCodeSelection implements Cloneable {
057: //~ Instance fields ------------------------------------------------------------------------------------------------------
058:
059: String className;
060: String methodName;
061: String methodSignature;
062: boolean isMarkerMethod;
063: int endLine;
064: int startLine;
065:
066: //~ Constructors ---------------------------------------------------------------------------------------------------------
067:
068: public SourceCodeSelection(String className, int startLine,
069: int endLine) {
070: this .className = (className != null) ? className : ""; // NULL might cause problems in JFluid - see eg. #95961
071: this .startLine = startLine;
072: this .endLine = endLine;
073:
074: // methodName and methodSignature are null in this case
075: }
076:
077: public SourceCodeSelection(String className, String methodName,
078: String methodSignature) {
079: this .className = (className != null) ? className : ""; // NULL might cause problems in JFluid - see eg. #95961
080: this .methodName = (methodName != null) ? methodName : ""; // NULL might cause problems in JFluid - see eg. #95961
081: this .methodSignature = (methodSignature != null) ? methodSignature
082: : ""; // NULL might cause problems in JFluid - see eg. #95961
083: startLine = endLine = -1;
084: }
085:
086: // Used for various special instrumentation kinds where no real method name/line are used
087: public SourceCodeSelection(int specialCode) {
088: if (specialCode == 1) {
089: // "Instrument all spawned threads" profiling mode. The "run()" method of all threads started after
090: // the "instrument" command is issued, is instrumented - but NOT the main() method. The intended usage
091: // of this mode is when JFluid is attached to an already running app. Otherwise, one should set the
092: // main method as a root, and call GlobalSettins.setInstrumentSpawnedThreads(true) explicitly.
093: className = NO_CLASS_NAME;
094: methodName = NO_METHOD_NAME;
095: methodSignature = NO_METHOD_SIGNATURE;
096: startLine = endLine = 0; // So that it's defined neither via source line nor via method name
097: }
098: }
099:
100: //~ Methods --------------------------------------------------------------------------------------------------------------
101:
102: public String getClassName() {
103: return className;
104: }
105:
106: public int getEndLine() {
107: return endLine;
108: }
109:
110: public void setMarkerMethod(boolean value) {
111: isMarkerMethod = value;
112: }
113:
114: public boolean isMarkerMethod() {
115: return isMarkerMethod;
116: }
117:
118: public String getMethodName() {
119: return methodName;
120: }
121:
122: public String getMethodSignature() {
123: return methodSignature;
124: }
125:
126: public int getStartLine() {
127: return startLine;
128: }
129:
130: public Object clone() throws CloneNotSupportedException {
131: SourceCodeSelection clone = (SourceCodeSelection) super
132: .clone();
133: clone.className = className;
134: clone.methodName = methodName;
135: clone.methodSignature = methodSignature;
136:
137: return clone;
138: }
139:
140: public boolean contains(
141: ClientUtils.SourceCodeSelection anotherSelection) {
142: if (definedViaSourceLines()) {
143: if (className.equals(anotherSelection.className)) {
144: return (startLine >= anotherSelection.startLine)
145: && (endLine <= anotherSelection.endLine);
146: }
147: } else {
148: String this Flattened = toFlattened().replace('.', '\\')
149: .replace('$', '\\')
150: + "\\"; //NOI18N
151: String anotherFlattened = anotherSelection
152: .toFlattened().replace('.', '\\').replace('$',
153: '\\'); //NOI18N
154:
155: return anotherFlattened.startsWith(this Flattened);
156: }
157:
158: return false;
159: }
160:
161: public boolean definedViaMethodName() {
162: return startLine == -1;
163: }
164:
165: public boolean definedViaSourceLines() {
166: return startLine > 0;
167: }
168:
169: public boolean equals(Object obj) {
170: if (obj == null) {
171: return false;
172: }
173:
174: if (!(obj instanceof SourceCodeSelection)) {
175: return false;
176: }
177:
178: SourceCodeSelection other = (SourceCodeSelection) obj;
179:
180: // if (this.isMarkerMethod != other.isMarkerMethod) return false;
181: // check start/end lines - they should be the same even in case they are not used
182: if ((this .startLine != other.startLine)
183: || (this .endLine != other.endLine)) {
184: return false;
185: }
186:
187: // length of classNames needs to be the same
188: if (!this .className.equals(other.className)) {
189: return false;
190: }
191:
192: if (this .methodName != null) {
193: if (!this .methodName.equals(other.methodName)) {
194: return false;
195: }
196: } else {
197: if (other.methodName != null) {
198: return false;
199: }
200: }
201:
202: if (this .methodSignature != null) {
203: if (!this .methodSignature.equals(other.methodSignature)) {
204: return false;
205: }
206: } else {
207: if (other.methodSignature != null) {
208: return false;
209: }
210: }
211:
212: return true;
213: }
214:
215: public int hashCode() {
216: int hashcode = 0;
217: hashcode += (startLine + endLine);
218: hashcode += className.hashCode();
219: hashcode += ((methodName != null) ? methodName.hashCode()
220: : 0);
221: hashcode += ((methodSignature != null) ? methodSignature
222: .hashCode() : 0);
223:
224: return hashcode;
225: }
226:
227: public String toFlattened() {
228: if ((className == null) || (className.length() == 0)) {
229: return "";
230: }
231:
232: StringBuffer flattenedBuf = new StringBuffer(className);
233:
234: if (flattenedBuf.charAt(flattenedBuf.length() - 1) != '*') { //NOI18N
235: flattenedBuf.append('.').append(methodName);
236: }
237:
238: if (flattenedBuf.charAt(flattenedBuf.length() - 1) != '*') { //NOI18N
239: flattenedBuf.append(methodSignature);
240: }
241:
242: return flattenedBuf.toString().replaceAll("\\.\\*", ""); //NOI18N
243: }
244:
245: public String toString() {
246: if (definedViaSourceLines()) {
247: return "Source Code defined via lines: [class: " // NOI18N
248: + className + ", start line: " // NOI18N
249: + startLine + ", end line: " // NOI18N
250: + endLine + "]"; // NOI18N
251: } else {
252: StringBuffer sb = new StringBuffer();
253: sb.append("Source Code defined via method: "); // NOI18N
254: sb.append("\n"); // NOI18N
255: sb.append(" class: "); // NOI18N
256: sb.append(className);
257: sb.append("\n "); // NOI18N
258:
259: if (methodName != null) {
260: sb.append(" method: "); // NOI18N
261: sb.append(methodName);
262: sb.append(" "); // NOI18N
263: sb.append(methodSignature);
264: sb.append("\n "); // NOI18N
265: }
266:
267: if (isMarkerMethod) {
268: sb.append("[Marker Method]\n"); //NOI18N
269: }
270:
271: return sb.toString();
272: }
273: }
274: }
275:
276: public static class TargetAppFailedToStart extends Exception {
277: //~ Instance fields ------------------------------------------------------------------------------------------------------
278:
279: private String origCause;
280:
281: //~ Constructors ---------------------------------------------------------------------------------------------------------
282:
283: public TargetAppFailedToStart(String errorMessage) {
284: this .origCause = errorMessage;
285: }
286:
287: //~ Methods --------------------------------------------------------------------------------------------------------------
288:
289: public String getOrigCause() {
290: return origCause;
291: }
292: }
293:
294: public static class TargetAppOrVMTerminated extends Exception {
295: //~ Static fields/initializers -------------------------------------------------------------------------------------------
296:
297: public static final int VM = 1;
298: public static final int APP = 2;
299:
300: //~ Instance fields ------------------------------------------------------------------------------------------------------
301:
302: int code;
303:
304: //~ Constructors ---------------------------------------------------------------------------------------------------------
305:
306: public TargetAppOrVMTerminated(int code) {
307: this .code = code;
308: }
309:
310: public TargetAppOrVMTerminated(int code, String message) {
311: super (message);
312: this .code = code;
313: }
314:
315: //~ Methods --------------------------------------------------------------------------------------------------------------
316:
317: public boolean isAppTerminated() {
318: return (code == APP);
319: }
320:
321: public String getMessage() {
322: if (super .getMessage() == null) {
323: return (code == VM) ? "Target JVM inactive"
324: : "Target JVM inactive"; // NOI18N
325: } else {
326: return super .getMessage();
327: }
328: }
329:
330: public boolean isVMTerminated() {
331: return (code == VM);
332: }
333: }
334:
335: //~ Static fields/initializers -----------------------------------------------------------------------------------------------
336:
337: public static final String LINES_PREFIX = "[lines]"; //NOI18N
338:
339: //~ Methods ------------------------------------------------------------------------------------------------------------------
340:
341: public static String selectionToString(
342: ClientUtils.SourceCodeSelection selection) {
343: if (selection == null) {
344: return ""; //NOI18N
345: }
346:
347: if (selection.definedViaSourceLines()) {
348: return LINES_PREFIX + selection.getClassName() + ","
349: + selection.getStartLine() + ","
350: + selection.getEndLine(); //NOI18N
351: } else {
352: if (selection.getMethodName() == null) {
353: return selection.getClassName(); //NOI18N
354: } else if (selection.getMethodSignature() == null) {
355: return selection.getClassName() + ","
356: + selection.getMethodName(); //NOI18N
357: } else {
358: return selection.getClassName() + ","
359: + selection.getMethodName() + ","
360: + selection.getMethodSignature(); //NOI18N
361: }
362: }
363: }
364:
365: public static ClientUtils.SourceCodeSelection stringToSelection(
366: String str) {
367: if ((str == null) || (str.length() == 0)) { // NOI18N
368:
369: return null;
370: }
371:
372: boolean viaLines = false;
373:
374: if (str.startsWith(LINES_PREFIX)) {
375: viaLines = true;
376: str = str.substring(LINES_PREFIX.length());
377: }
378:
379: String[] parts = str.split(","); //NOI18N
380:
381: if (viaLines) {
382: if (parts.length != 3) {
383: return null; // invalid
384: }
385:
386: try {
387: return new ClientUtils.SourceCodeSelection(parts[0],
388: Integer.parseInt(parts[1]), Integer
389: .parseInt(parts[2]));
390: } catch (NumberFormatException e) {
391: return null; // error in encoding of lines
392: }
393: } else {
394: String className = ""; // NOI18N
395:
396: if (parts.length > 0) {
397: className = parts[0];
398: }
399:
400: String methodName = ""; // NOI18N
401:
402: if (parts.length > 1) {
403: methodName = parts[1];
404: }
405:
406: String methodSig = ""; // NOI18N
407:
408: if (parts.length > 2) {
409: methodSig = parts[2];
410: }
411:
412: return new ClientUtils.SourceCodeSelection(className,
413: methodName, methodSig);
414: }
415: }
416: }
|