KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > debugger > jpda > breakpoints > BreakpointImpl


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.debugger.jpda.breakpoints;
21
22 import com.sun.jdi.IncompatibleThreadStateException;
23 import com.sun.jdi.ReferenceType;
24 import com.sun.jdi.StackFrame;
25 import com.sun.jdi.ThreadReference;
26 import com.sun.jdi.VMDisconnectedException;
27 import com.sun.jdi.Value;
28 import com.sun.jdi.VirtualMachine;
29 import com.sun.jdi.request.EventRequest;
30 import com.sun.jdi.request.EventRequestManager;
31 import java.util.ArrayList JavaDoc;
32 import java.util.LinkedList JavaDoc;
33 import java.util.List JavaDoc;
34 import java.beans.PropertyChangeListener JavaDoc;
35 import java.beans.PropertyChangeEvent JavaDoc;
36 import java.util.logging.Logger JavaDoc;
37 import javax.swing.event.ChangeEvent JavaDoc;
38 import javax.swing.event.ChangeListener JavaDoc;
39 import org.netbeans.api.debugger.Breakpoint;
40
41 import org.netbeans.api.debugger.jpda.InvalidExpressionException;
42 import org.netbeans.api.debugger.jpda.JPDABreakpoint;
43 import org.netbeans.api.debugger.jpda.MethodBreakpoint;
44 import org.netbeans.api.debugger.jpda.Variable;
45 import org.netbeans.api.debugger.jpda.event.JPDABreakpointEvent;
46 import org.netbeans.api.debugger.jpda.JPDADebugger;
47 import org.netbeans.api.debugger.Session;
48 import org.netbeans.api.debugger.DebuggerManager;
49
50 import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl;
51 import org.netbeans.modules.debugger.jpda.expr.Expression;
52 import org.netbeans.modules.debugger.jpda.expr.ParseException;
53 import org.netbeans.modules.debugger.jpda.models.JPDAThreadImpl;
54 import org.netbeans.modules.debugger.jpda.models.ReturnVariableImpl;
55 import org.netbeans.modules.debugger.jpda.util.Executor;
56 import org.openide.ErrorManager;
57
58
59 /**
60  *
61  * @author Jan Jancura
62  */

63 public abstract class BreakpointImpl implements Executor, PropertyChangeListener JavaDoc {
64     
65     private static Logger JavaDoc logger = Logger.getLogger("org.netbeans.modules.debugger.jpda.breakpoints"); // NOI18N
66

67     private JPDADebuggerImpl debugger;
68     private JPDABreakpoint breakpoint;
69     private BreakpointsReader reader;
70     private final Session session;
71     private Expression compiledCondition;
72     private List JavaDoc<EventRequest> requests = new ArrayList JavaDoc<EventRequest>();
73
74
75     protected BreakpointImpl (JPDABreakpoint p, BreakpointsReader reader, JPDADebuggerImpl debugger, Session session) {
76         this.debugger = debugger;
77         this.reader = reader;
78         breakpoint = p;
79         this.session = session;
80     }
81
82     /**
83      * Called from XXXBreakpointImpl constructor only.
84      */

85     final void set () {
86         breakpoint.addPropertyChangeListener (this);
87         update ();
88     }
89     
90     /**
91      * Called when Fix&Continue is invoked. Reqritten in LineBreakpointImpl.
92      */

93     void fixed () {
94         if (reader != null) {
95             reader.storeCachedClassName(breakpoint, null);
96         }
97         update ();
98     }
99     
100     /**
101      * Called from set () and propertyChanged.
102      */

103     final void update () {
104         if ( (getVirtualMachine () == null) ||
105              (getDebugger ().getState () == JPDADebugger.STATE_DISCONNECTED)
106         ) return;
107         removeAllEventRequests ();
108         if (breakpoint.isEnabled () && isEnabled()) {
109             setRequests ();
110         }
111     }
112     
113     protected boolean isEnabled() {
114         return true;
115     }
116     
117     protected final void setValidity(Breakpoint.VALIDITY validity, String JavaDoc reason) {
118         if (breakpoint instanceof ChangeListener JavaDoc) {
119             ((ChangeListener JavaDoc) breakpoint).stateChanged(new ValidityChangeEvent(validity, reason));
120         }
121     }
122
123     public void propertyChange (PropertyChangeEvent JavaDoc evt) {
124         String JavaDoc propertyName = evt.getPropertyName();
125         if (Breakpoint.PROP_DISPOSED.equals(propertyName)) {
126             remove();
127         } else if (!Breakpoint.PROP_VALIDITY.equals(propertyName)) {
128             if (reader != null) {
129                 reader.storeCachedClassName(breakpoint, null);
130             }
131             if (Breakpoint.PROP_ENABLED.equals(propertyName)) {
132                 update ();
133             }
134         }
135     }
136
137     protected abstract void setRequests ();
138     
139     protected final void remove () {
140         removeAllEventRequests ();
141         breakpoint.removePropertyChangeListener(this);
142         setValidity(Breakpoint.VALIDITY.UNKNOWN, null);
143     }
144
145     protected JPDABreakpoint getBreakpoint () {
146         return breakpoint;
147     }
148
149     protected JPDADebuggerImpl getDebugger () {
150         return debugger;
151     }
152
153     protected VirtualMachine getVirtualMachine () {
154         return getDebugger ().getVirtualMachine ();
155     }
156     
157     protected EventRequestManager getEventRequestManager () {
158         VirtualMachine vm = getVirtualMachine();
159         if (vm == null) {
160             // Already disconnected
161
throw new VMDisconnectedException();
162         }
163         return vm.eventRequestManager ();
164     }
165
166     synchronized protected void addEventRequest (EventRequest r) {
167         logger.fine("BreakpointImpl addEventRequest: " + r);
168         requests.add (r);
169         getDebugger ().getOperator ().register (r, this);
170        
171         // PATCH #48174
172
// if this is breakpoint with SUSPEND_NONE we stop EVENT_THREAD to print output line
173
if (getBreakpoint().getSuspend() == JPDABreakpoint.SUSPEND_ALL)
174             r.setSuspendPolicy (JPDABreakpoint.SUSPEND_ALL);
175         else
176             r.setSuspendPolicy (JPDABreakpoint.SUSPEND_EVENT_THREAD);
177         r.enable ();
178     }
179
180     synchronized private void removeAllEventRequests () {
181         if (requests.size () == 0) return;
182         VirtualMachine vm = getDebugger().getVirtualMachine();
183         if (vm == null) return;
184         int i, k = requests.size ();
185         try {
186             for (i = 0; i < k; i++) {
187                 EventRequest r = requests.get (i);
188                 logger.fine("BreakpointImpl removeEventRequest: " + r);
189                 vm.eventRequestManager().deleteEventRequest(r);
190                 getDebugger ().getOperator ().unregister (r);
191             }
192             
193         } catch (VMDisconnectedException e) {
194         } catch (com.sun.jdi.InternalException e) {
195         }
196         requests = new LinkedList JavaDoc<EventRequest>();
197     }
198
199     public boolean perform (
200         String JavaDoc condition,
201         ThreadReference thread,
202         ReferenceType referenceType,
203         Value value
204     ) {
205         //S ystem.out.println("BreakpointImpl.perform");
206
boolean resume;
207         
208         //PATCH 48174
209
try {
210             getDebugger().setAltCSF(thread.frame(0));
211         } catch (com.sun.jdi.IncompatibleThreadStateException e) {
212             ErrorManager.getDefault().notify(e);
213         } catch (java.lang.IndexOutOfBoundsException JavaDoc e) {
214             // No frame in case of Thread and "Main" class breakpoints, PATCH 56540
215
}
216         Variable variable = null;
217         if (getBreakpoint() instanceof MethodBreakpoint &&
218                 (((MethodBreakpoint) getBreakpoint()).getBreakpointType()
219                  & MethodBreakpoint.TYPE_METHOD_EXIT) != 0) {
220             JPDAThreadImpl jt = (JPDAThreadImpl) getDebugger().getThread(thread);
221             if (value != null) {
222                 ReturnVariableImpl retVariable = new ReturnVariableImpl(getDebugger(), value, "", jt.getMethodName());
223                 jt.setReturnVariable(retVariable);
224                 variable = retVariable;
225             }
226         }
227         if (variable == null) {
228             variable = debugger.getVariable(value);
229         }
230         
231         
232         if ((condition == null) || condition.equals ("")) {
233             JPDABreakpointEvent e = new JPDABreakpointEvent (
234                 getBreakpoint (),
235                 debugger,
236                 JPDABreakpointEvent.CONDITION_NONE,
237                 debugger.getThread (thread),
238                 referenceType,
239                 variable
240             );
241             getDebugger ().fireBreakpointEvent (
242                 getBreakpoint (),
243                 e
244             );
245             resume = getBreakpoint().getSuspend() == JPDABreakpoint.SUSPEND_NONE || e.getResume ();
246             logger.fine("BreakpointImpl: perform breakpoint (no condition): " + this + " resume: " + resume);
247         } else {
248             resume = evaluateCondition (
249                 condition,
250                 thread,
251                 referenceType,
252                 variable
253             );
254             //PATCH 48174
255
resume = getBreakpoint().getSuspend() == JPDABreakpoint.SUSPEND_NONE || resume;
256         }
257         getDebugger().setAltCSF(null);
258         if (!resume) {
259             DebuggerManager.getDebuggerManager().setCurrentSession(session);
260             getDebugger ().setStoppedState (thread);
261         }
262         //S ystem.out.println("BreakpointImpl.perform end");
263
return resume;
264     }
265
266     private boolean evaluateCondition (
267         String JavaDoc condition,
268         ThreadReference thread,
269         ReferenceType referenceType,
270         Variable variable
271     ) {
272         try {
273             try {
274                 boolean result;
275                 JPDABreakpointEvent ev;
276                 synchronized (debugger.LOCK) {
277                     StackFrame sf = thread.frame (0);
278                     result = evaluateConditionIn (condition, sf);
279                     ev = new JPDABreakpointEvent (
280                         getBreakpoint (),
281                         debugger,
282                         result ?
283                             JPDABreakpointEvent.CONDITION_TRUE :
284                             JPDABreakpointEvent.CONDITION_FALSE,
285                         debugger.getThread (thread),
286                         referenceType,
287                         variable
288                     );
289                 }
290                 getDebugger ().fireBreakpointEvent (
291                     getBreakpoint (),
292                     ev
293                 );
294                             
295                 // condition true => stop here (do not resume)
296
// condition false => resume
297
logger.fine("BreakpointImpl: perform breakpoint (condition = " + result + "): " + this + " resume: " + (!result || ev.getResume ()));
298                 return !result || ev.getResume ();
299             } catch (ParseException ex) {
300                 JPDABreakpointEvent ev = new JPDABreakpointEvent (
301                     getBreakpoint (),
302                     debugger,
303                     ex,
304                     debugger.getThread (thread),
305                     referenceType,
306                     variable
307                 );
308                 getDebugger ().fireBreakpointEvent (
309                     getBreakpoint (),
310                     ev
311                 );
312                 logger.fine("BreakpointImpl: perform breakpoint (bad condition): " + this + " resume: " + ev.getResume ());
313                 return ev.getResume ();
314             } catch (InvalidExpressionException ex) {
315                 JPDABreakpointEvent ev = new JPDABreakpointEvent (
316                     getBreakpoint (),
317                     debugger,
318                     ex,
319                     debugger.getThread (thread),
320                     referenceType,
321                     variable
322                 );
323                 getDebugger ().fireBreakpointEvent (
324                     getBreakpoint (),
325                     ev
326                 );
327                 logger.fine("BreakpointImpl: perform breakpoint (invalid condition): " + this + " resume: " + ev.getResume ());
328                 return ev.getResume ();
329             }
330         } catch (IncompatibleThreadStateException ex) {
331             // should not occurre
332
ex.printStackTrace ();
333         }
334         // some error occured during evaluation of expression => do not resume
335
return false; // do not resume
336
}
337
338     /**
339      * Evaluates given condition. Returns value of condition evaluation.
340      * Returns true othervise (bad expression).
341      */

342     private boolean evaluateConditionIn (
343         String JavaDoc condExpr,
344         StackFrame frame
345     ) throws ParseException, InvalidExpressionException {
346         // 1) compile expression
347
if ( compiledCondition == null ||
348              !compiledCondition.getExpression ().equals (condExpr)
349         )
350             compiledCondition = Expression.parse (
351                 condExpr,
352                 Expression.LANGUAGE_JAVA_1_5
353             );
354         
355         // 2) evaluate expression
356
// already synchronized (debugger.LOCK)
357
com.sun.jdi.Value value = getDebugger ().evaluateIn (
358             compiledCondition,
359             frame
360         );
361         try {
362             return ((com.sun.jdi.BooleanValue) value).booleanValue ();
363         } catch (ClassCastException JavaDoc e) {
364             throw new InvalidExpressionException (e);
365         }
366     }
367     
368     /**
369      * Support method for simple patterns.
370      */

371     static boolean match (String JavaDoc name, String JavaDoc pattern) {
372         if (pattern.startsWith ("*"))
373             return name.endsWith (pattern.substring (1));
374         else
375         if (pattern.endsWith ("*"))
376             return name.startsWith (
377                 pattern.substring (0, pattern.length () - 1)
378             );
379         return name.equals (pattern);
380     }
381     
382     private static final class ValidityChangeEvent extends ChangeEvent JavaDoc {
383         
384         private String JavaDoc reason;
385         
386         public ValidityChangeEvent(Breakpoint.VALIDITY validity, String JavaDoc reason) {
387             super(validity);
388             this.reason = reason;
389         }
390         
391         public String JavaDoc toString() {
392             return reason;
393         }
394     }
395 }
396
Popular Tags