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: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.api.debugger.jpda;
043:
044: import java.util.Map;
045: import java.util.WeakHashMap;
046: import javax.swing.event.ChangeEvent;
047: import javax.swing.event.ChangeListener;
048: import org.netbeans.api.debugger.Breakpoint;
049:
050: /**
051: * Notifies about method entry events.
052: *
053: * <br><br>
054: * <b>How to use it:</b>
055: * <pre style="background-color: rgb(255, 255, 153);">
056: * DebuggerManager.addBreakpoint (MethodBreakpoint.create (
057: * "examples.texteditor.Ted*",
058: * "<init>
059: * ));</pre>
060: * This breakpoint stops when some initializer of class Ted or innercalsses is
061: * called.
062: *
063: * @author Jan Jancura
064: */
065: public class MethodBreakpoint extends JPDABreakpoint {
066:
067: /** Property name constant */
068: public static final String PROP_METHOD_NAME = "methodName"; // NOI18N
069: /** Property name constant */
070: public static final String PROP_METHOD_SIGNATURE = "signature"; // NOI18N
071: /** Property name constant. */
072: public static final String PROP_BREAKPOINT_TYPE = "breakpointtType"; // NOI18N
073: /** Property name constant. */
074: public static final String PROP_CONDITION = "condition"; // NOI18N
075: /** Property name constant */
076: public static final String PROP_CLASS_FILTERS = "classFilters"; // NOI18N
077: /** Property name constant */
078: public static final String PROP_CLASS_EXCLUSION_FILTERS = "classExclusionFilters"; // NOI18N
079: /** Property name constant */
080: public static final String PROP_INSTANCE_FILTERS = "instanceFilters"; // NOI18N
081: /** Property name constant */
082: public static final String PROP_THREAD_FILTERS = "threadFilters"; // NOI18N
083:
084: /** Breakpoint type property value constant. */
085: public static final int TYPE_METHOD_ENTRY = 1;
086: /** Breakpoint type property value constant. */
087: public static final int TYPE_METHOD_EXIT = 2;
088:
089: /** Property variable. */
090: private String[] classFilters = new String[0];
091: private String[] classExclusionFilters = new String[0];
092: private String methodName = "";
093: private String methodSignature;
094: private int breakpointType = TYPE_METHOD_ENTRY;
095: private String condition = "";
096: private Map<JPDADebugger, ObjectVariable[]> instanceFilters;
097: private Map<JPDADebugger, JPDAThread[]> threadFilters;
098:
099: private MethodBreakpoint() {
100: }
101:
102: /**
103: * Creates a new method breakpoint for given parameters.
104: *
105: * @param className a class name filter
106: * @param methodName a name of method
107: * @return a new breakpoint for given parameters
108: */
109: public static MethodBreakpoint create(String className,
110: String methodName) {
111: MethodBreakpoint b = new MethodBreakpointImpl();
112: b.setClassFilters(new String[] { className });
113: b.setMethodName(methodName);
114: return b;
115: }
116:
117: /**
118: * Creates a new method breakpoint.
119: *
120: * @return a new method breakpoint
121: */
122: public static MethodBreakpoint create() {
123: MethodBreakpoint b = new MethodBreakpointImpl();
124: return b;
125: }
126:
127: /**
128: * Get name of method to stop on.
129: *
130: * @return name of method to stop on
131: */
132: public String getMethodName() {
133: return methodName;
134: }
135:
136: /**
137: * Set name of method to stop on.
138: *
139: * @param mn a name of method to stop on
140: */
141: public void setMethodName(String mn) {
142: if (mn != null) {
143: mn = mn.trim();
144: }
145: if ((mn == methodName)
146: || ((mn != null) && (methodName != null) && methodName
147: .equals(mn)))
148: return;
149: String old = methodName;
150: methodName = mn;
151: firePropertyChange(PROP_METHOD_NAME, old, mn);
152: }
153:
154: /**
155: * Get the JNI-style signature of the method to stop on.
156: *
157: * @return JNI-style signature of the method to stop on
158: * @see com.sun.jdi.TypeComponent#signature
159: */
160: public String getMethodSignature() {
161: return methodSignature;
162: }
163:
164: /**
165: * Set JNI-style signature of the method to stop on.
166: *
167: * @param signature the JNI-style signature of the method to stop on
168: * @see com.sun.jdi.TypeComponent#signature
169: */
170: public void setMethodSignature(String signature) {
171: if (signature != null) {
172: signature = signature.trim();
173: }
174: if ((signature == methodSignature)
175: || ((signature != null) && signature
176: .equals(methodSignature))) {
177:
178: return;
179: }
180: String old = methodSignature;
181: methodSignature = signature;
182: firePropertyChange(PROP_METHOD_SIGNATURE, old, signature);
183: }
184:
185: /**
186: * Returns condition.
187: *
188: * @return cond a condition
189: */
190: public String getCondition() {
191: return condition;
192: }
193:
194: /**
195: * Sets condition.
196: *
197: * @param cond a c new condition
198: */
199: public void setCondition(String cond) {
200: if (cond != null) {
201: cond = cond.trim();
202: }
203: String old = condition;
204: condition = cond;
205: firePropertyChange(PROP_CONDITION, old, cond);
206: }
207:
208: /**
209: * Returns type of this breakpoint.
210: *
211: * @return type of this breakpoint
212: */
213: public int getBreakpointType() {
214: return breakpointType;
215: }
216:
217: /**
218: * Sets type of this breakpoint (TYPE_METHOD_ENTRY or TYPE_METHOD_EXIT).
219: *
220: * @param breakpointType a new value of breakpoint type property
221: */
222: public void setBreakpointType(int breakpointType) {
223: if (breakpointType == this .breakpointType)
224: return;
225: if ((breakpointType & (TYPE_METHOD_ENTRY | TYPE_METHOD_EXIT)) == 0)
226: throw new IllegalArgumentException();
227: int old = this .breakpointType;
228: this .breakpointType = breakpointType;
229: firePropertyChange(PROP_BREAKPOINT_TYPE, new Integer(old),
230: new Integer(breakpointType));
231: }
232:
233: /**
234: * Get list of class filters to stop on.
235: *
236: * @return list of class filters to stop on
237: */
238: public String[] getClassFilters() {
239: return classFilters;
240: }
241:
242: /**
243: * Set list of class filters to stop on.
244: *
245: * @param classFilters a new value of class filters property
246: */
247: public void setClassFilters(String[] classFilters) {
248: if (classFilters == this .classFilters)
249: return;
250: Object old = this .classFilters;
251: this .classFilters = classFilters;
252: firePropertyChange(PROP_CLASS_FILTERS, old, classFilters);
253: }
254:
255: /**
256: * Get list of class exclusion filters to stop on.
257: *
258: * @return list of class exclusion filters to stop on
259: */
260: public String[] getClassExclusionFilters() {
261: return classExclusionFilters;
262: }
263:
264: /**
265: * Set list of class exclusion filters to stop on.
266: *
267: * @param classExclusionFilters a new value of class exclusion filters property
268: */
269: public void setClassExclusionFilters(String[] classExclusionFilters) {
270: if (classExclusionFilters == this .classExclusionFilters)
271: return;
272: Object old = this .classExclusionFilters;
273: this .classExclusionFilters = classExclusionFilters;
274: firePropertyChange(PROP_CLASS_EXCLUSION_FILTERS, old,
275: classExclusionFilters);
276: }
277:
278: /**
279: * Get the instance filter for a specific debugger session.
280: * @return The instances or <code>null</code> when there is no instance restriction.
281: */
282: public ObjectVariable[] getInstanceFilters(JPDADebugger session) {
283: if (instanceFilters != null) {
284: return instanceFilters.get(session);
285: } else {
286: return null;
287: }
288: }
289:
290: /**
291: * Set the instance filter for a specific debugger session. This restricts
292: * the breakpoint to specific instances in that session.
293: * @param session the debugger session
294: * @param instances the object instances or <code>null</code> to unset the filter.
295: */
296: public void setInstanceFilters(JPDADebugger session,
297: ObjectVariable[] instances) {
298: if (instanceFilters == null) {
299: instanceFilters = new WeakHashMap<JPDADebugger, ObjectVariable[]>();
300: }
301: if (instances != null) {
302: instanceFilters.put(session, instances);
303: } else {
304: instanceFilters.remove(session);
305: }
306: firePropertyChange(PROP_INSTANCE_FILTERS, null,
307: instances != null ? new Object[] { session, instances }
308: : null);
309: }
310:
311: /**
312: * Get the thread filter for a specific debugger session.
313: * @return The thread or <code>null</code> when there is no thread restriction.
314: */
315: public JPDAThread[] getThreadFilters(JPDADebugger session) {
316: if (threadFilters != null) {
317: return threadFilters.get(session);
318: } else {
319: return null;
320: }
321: }
322:
323: /**
324: * Set the thread filter for a specific debugger session. This restricts
325: * the breakpoint to specific threads in that session.
326: * @param session the debugger session
327: * @param threads the threads or <code>null</code> to unset the filter.
328: */
329: public void setThreadFilters(JPDADebugger session,
330: JPDAThread[] threads) {
331: if (threadFilters == null) {
332: threadFilters = new WeakHashMap<JPDADebugger, JPDAThread[]>();
333: }
334: if (threads != null) {
335: threadFilters.put(session, threads);
336: } else {
337: threadFilters.remove(session);
338: }
339: firePropertyChange(PROP_THREAD_FILTERS, null,
340: threads != null ? new Object[] { session, threads }
341: : null);
342: }
343:
344: /**
345: * Returns a string representation of this object.
346: *
347: * @return a string representation of the object
348: */
349: public String toString() {
350: return "MethodBreakpoint "
351: + java.util.Arrays.asList(classFilters).toString()
352: + "."
353: + methodName
354: + ((methodSignature != null) ? " '" + methodSignature
355: + "'" : "");
356: }
357:
358: private static final class MethodBreakpointImpl extends
359: MethodBreakpoint implements ChangeListener {
360:
361: public void stateChanged(ChangeEvent chev) {
362: Object source = chev.getSource();
363: if (source instanceof Breakpoint.VALIDITY) {
364: setValidity((Breakpoint.VALIDITY) source, chev
365: .toString());
366: } else {
367: throw new UnsupportedOperationException(chev.toString());
368: }
369: }
370: }
371: }
|