Added
Link Here
|
1 |
<!-- |
2 |
- Sun Public License Notice |
3 |
- |
4 |
- The contents of this file are subject to the Sun Public License |
5 |
- Version 1.0 (the "License"). You may not use this file except in |
6 |
- compliance with the License. A copy of the License is available at |
7 |
- http://www.sun.com/ |
8 |
- |
9 |
- The Original Code is NetBeans. The Initial Developer of the Original |
10 |
- Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun |
11 |
- Microsystems, Inc. All Rights Reserved. |
12 |
--> |
13 |
|
14 |
<html> |
15 |
<head> |
16 |
<title>Debugger API</title> |
17 |
<link rel="Stylesheet" href="../../open-apis.css" type="text/css" title="NetBeans Open APIs Style"> |
18 |
</head> |
19 |
<body> |
20 |
|
21 |
<p align="right"><a href="../../../../overview-summary.html"><b>Overview</b></a></p> |
22 |
|
23 |
<h1>Javadoc</h1> |
24 |
|
25 |
The Javadoc resides in |
26 |
|
27 |
<a href="../package-summary.html"><code>org.openide.debugger</code></a>. |
28 |
|
29 |
<h1>Contents</h1> |
30 |
|
31 |
<ul> |
32 |
|
33 |
<li><a href="#create">Creating a Debugger</a> |
34 |
<ul> |
35 |
<li><a href="#break-watch">Special breakpoint & watch implementation</a> |
36 |
<li><a href="#module">Installation tips</a> |
37 |
</ul> |
38 |
|
39 |
<li><a href="#create-xtra">Creating Extra Debugger-Related Implementation</a> |
40 |
<ul> |
41 |
<li><a href="#curr-line">Handling the current line</a> |
42 |
<li><a href="#xtra-actions">Adding extra actions</a> |
43 |
<li><a href="#env-nodes">Adding nodes to "Runtime"</a> |
44 |
<li><a href="#windows">Adding a debugging workspace, windows, etc.</a> |
45 |
<li><a href="#sysop">Adding a system option</a> |
46 |
<li><a href="#persistence">Persisting debugger state</a> |
47 |
</ul> |
48 |
|
49 |
<li><a href="#createtype">Creating Debugger Types</a> |
50 |
|
51 |
<li><a href="#invoke">Invoking the Debugger</a> |
52 |
<ul> |
53 |
<li><a href="#hidden-watch">Using hidden watches</a> |
54 |
</ul> |
55 |
|
56 |
</ul> |
57 |
|
58 |
<h1>Debugger API</h1> |
59 |
|
60 |
The Debugger API provides a thin interface between the IDE and various |
61 |
possible debugger implementations, including the IDE's standard |
62 |
debugger. The API is designed to work with Java programs, although it |
63 |
could also be used for |
64 |
|
65 |
<a href="http://grunge.cs.tu-berlin.de/~tolk/vmlanguages.html">any language</a> |
66 |
|
67 |
compiled to the JVM. |
68 |
|
69 |
<p>Note that the API itself defines only the basic methods of |
70 |
communication, and does not specify a rich level of |
71 |
functionality. However, what it provides is sufficient to implement |
72 |
all of the connections between the standard debugger module and the |
73 |
debugging-related actions and UI components, including with the |
74 |
Editor. Real debuggers will very likely have more features than are |
75 |
specified here, but it is not difficult to make the |
76 |
|
77 |
<a href="#create-xtra">added functionality</a> |
78 |
|
79 |
visible to the user. |
80 |
|
81 |
<p>There are two different aspects to adding debugging capabilities to the IDE. |
82 |
One is to create the <a href="#create">debugger itself</a>, i.e. a set of implementations |
83 |
which specify how the debugger will be run, its current dynamic status, manipulation |
84 |
of breakpoints and watches, etc. The other half is to create <a href="#createtype">debugger types</a> |
85 |
which specify how the debugger should be <em>invoked</em> for particular types of objects - for |
86 |
example, applets need to be debugged by means of launching the AppletViewer pointing to the correct |
87 |
applet class or HTML page; but once the AppletViewer's main class has been launched with the correct |
88 |
arguments, the remaining implementation is entirely up to the debugger. These two halves can (and typically |
89 |
are) treated quite separately, so that the standard IDE debugger module installs a debugger as well as a |
90 |
couple of simple, generic debugger types, while modules providing support for more exotic data types such |
91 |
as applets or servlets provide their own specialized debugger types. |
92 |
|
93 |
<div class="nonnormative"> |
94 |
|
95 |
<p>In practice, the specification of debugger functionality in the |
96 |
Open APIs is insufficient for most projects to supply an integrated |
97 |
alternate debugger for NetBeans. Generally it is necessary to rely on |
98 |
additional SPIs contained in the Debugger Core module. These however |
99 |
may not have the same standards of API design, documentation, and |
100 |
compatibility as the Open APIs.</p> |
101 |
|
102 |
<p>The |
103 |
|
104 |
<a href="http://debuggercore.netbeans.org/">debugger module's home page</a> |
105 |
|
106 |
has a certain amount of documentation for how to use these extended |
107 |
SPIs, and a trivial example. As of this writing, the documentation is |
108 |
not sufficient to cover all aspects of the module's SPI, so additional |
109 |
help from the mailing lists and examination of NetBeans source code |
110 |
will likely be necessary.</p> |
111 |
|
112 |
</div> |
113 |
|
114 |
<h2><a name="create">Creating a Debugger</a></h2> |
115 |
|
116 |
To create a debugger, you must implement the |
117 |
|
118 |
<a href="../Debugger.html"><code>Debugger</code></a> |
119 |
|
120 |
abstract class. It must provide the following sets of features: |
121 |
|
122 |
<ol> |
123 |
|
124 |
<li>Access to, and control of, the debugger's basic state. The state should be queriable by means of |
125 |
|
126 |
<a href="../Debugger.html#getState()"><code>Debugger.getState()</code></a>. |
127 |
|
128 |
Initially, the debugger will be |
129 |
|
130 |
<a href="../Debugger.html#DEBUGGER_NOT_RUNNING"><code>Debugger.DEBUGGER_NOT_RUNNING</code></a> |
131 |
|
132 |
When some other part of the system starts it up with |
133 |
|
134 |
<a href="../Debugger.html#startDebugger(org.openide.debugger.DebuggerInfo)"><code>Debugger.startDebugger(...)</code></a>, |
135 |
|
136 |
it may indicate its state during the initialization phase as |
137 |
|
138 |
<a href="../Debugger.html#DEBUGGER_STARTING"><code>Debugger.DEBUGGER_STARTING</code></a>. |
139 |
|
140 |
When it is ready, it will be either |
141 |
|
142 |
<a href="../Debugger.html#DEBUGGER_RUNNING"><code>Debugger.DEBUGGER_RUNNING</code></a> |
143 |
|
144 |
(if actually executing user code at the time), |
145 |
|
146 |
or |
147 |
|
148 |
<a href="../Debugger.html#DEBUGGER_STOPPED"><code>Debugger.DEBUGGER_STOPPED</code></a> |
149 |
|
150 |
(if stopped at a breakpoint). |
151 |
|
152 |
<p>Once it is running, the debugger should respond to the basic commands |
153 |
|
154 |
<a href="../Debugger.html#traceInto()"><code>Debugger.traceInto()</code></a>, |
155 |
|
156 |
<a href="../Debugger.html#traceOver()"><code>Debugger.traceOver()</code></a>, |
157 |
|
158 |
and |
159 |
|
160 |
<a href="../Debugger.html#stepOut()"><code>Debugger.stepOut()</code></a>, |
161 |
|
162 |
all of which return it to the stopped state; and |
163 |
|
164 |
<a href="../Debugger.html#go()"><code>Debugger.go()</code></a>, |
165 |
|
166 |
putting it into the running state (unless a breakpoint is encountered). |
167 |
|
168 |
<a href="../Debugger.html#finishDebugger()"><code>Debugger.finishDebugger()</code></a> |
169 |
|
170 |
should stop the debugger as soon as possible (some cleanup may be |
171 |
required) and leave it in the not-running state. |
172 |
|
173 |
<p>The |
174 |
|
175 |
<a href="../DebuggerInfo.html"><code>DebuggerInfo</code></a> |
176 |
|
177 |
provides the basic information needed for the debugger to start - the |
178 |
name of the main class; a list of "command-line" parameters to pass to |
179 |
its <code>main(String[])</code> method, which may be empty; and |
180 |
(optionally) the name of a class to first stop execution on (as if |
181 |
there were breakpoints on all of its methods). |
182 |
|
183 |
<p>The debugger can look in the |
184 |
|
185 |
<a href="@OPENIDE@/org/openide/filesystems/Repository.html">repository</a> |
186 |
|
187 |
to find source code; and for a normal external |
188 |
debugger, determine how to prepare the classpath correctly, which |
189 |
generally involves scanning through |
190 |
|
191 |
<a href="@OPENIDE@/org/openide/filesystems/Repository.html#getFileSystems()">all filesystems</a>, |
192 |
|
193 |
asking each to |
194 |
|
195 |
<a href="@OPENIDE@/org/openide/filesystems/FileSystem.html#prepareEnvironment(org.openide.filesystems.FileSystem.Environment)">add information</a> |
196 |
|
197 |
to an object supplied by the debugger implementing |
198 |
|
199 |
<a href="@OPENIDE@/org/openide/filesystems/FileSystem.Environment.html"><code>FileSystem.Environment</code></a>. |
200 |
|
201 |
If classes should be compiled before being used in the debugger, the |
202 |
debugger should take care of that using the |
203 |
|
204 |
<a href="@OPENIDE/COMPILER@/org/openide/compiler/doc-files/api.html">Compiler API</a>. |
205 |
|
206 |
<li>The debugger should be able to create breakpoints and watches when |
207 |
requested by |
208 |
|
209 |
<a href="../Debugger.html#createBreakpoint(org.openide.text.Line)"><code>Debugger.createBreakpoint(...)</code></a> |
210 |
|
211 |
(and related methods) or |
212 |
|
213 |
<a href="../Debugger.html#createWatch(java.lang.String, boolean)"><code>Debugger.createWatch(...)</code></a>. |
214 |
|
215 |
The debugger must <a href="#break-watch">create</a> an implementation |
216 |
of these objects. |
217 |
|
218 |
<li>The debugger should |
219 |
|
220 |
<a href="../Debugger.html#addPropertyChangeListener(java.beans.PropertyChangeListener)">fire events</a> |
221 |
|
222 |
for a few properties, so that other parts of the system (such as the |
223 |
|
224 |
Trace Over |
225 |
|
226 |
action) can be sensitive to changes in the debugger's state. |
227 |
|
228 |
<li><a name="sysopt-note"></a>Most debuggers (including the standard module) will |
229 |
need to provide certain options not specified in the API, such as |
230 |
whether to compile automatically before debugging; extra class path |
231 |
elements to use; parameters to connect to an external debugger; |
232 |
etc. These should be handled by providing a |
233 |
|
234 |
<a href="@OPENIDE@/org/openide/options/doc-files/api.html#make-opt">system option</a> |
235 |
|
236 |
in the debugger's module. |
237 |
|
238 |
</ol> |
239 |
|
240 |
<h3><a name="break-watch">Special breakpoint & watch implementation</a></h3> |
241 |
|
242 |
<p>The debugger is not required to do anything for implementation of |
243 |
breakpoints and watches beyond the small interfaces specified in |
244 |
|
245 |
<a href="../Breakpoint.html"><code>Breakpoint</code></a> |
246 |
|
247 |
and |
248 |
|
249 |
<a href="../Watch.html"><code>Watch</code></a>, |
250 |
|
251 |
which essentially only specify abstract points in debugged code and |
252 |
request that listeners be notified of changes in these basic |
253 |
properties. These objects need only be created by the main debugger |
254 |
class, as mentioned above.</p> |
255 |
|
256 |
<div class="nonnormative"> |
257 |
|
258 |
<p>However, it is likely that the debugger implementation will want to |
259 |
provide additional functionality, possibly pertaining to these |
260 |
objects. For example: |
261 |
|
262 |
<ul> |
263 |
|
264 |
<li>Breakpoints could be made conditional, not absolute, based on some |
265 |
(possibly Java) expression to evaluate. |
266 |
|
267 |
<li>Threads and thread groups could be explicitly represented. |
268 |
|
269 |
<li>Inspection of objects in the debugged process could be provided. |
270 |
|
271 |
<li>Watches could be real expressions (say, a function call), not just |
272 |
the name of a variable. |
273 |
|
274 |
</ul> |
275 |
|
276 |
<p>None of this interferes with the use of the API - the only likely |
277 |
caveat is that the Editor might expect a watch to operate correctly |
278 |
when its expression is an unqualified (local or member) variable name, |
279 |
so this should be considered. (This most common usage of watches is |
280 |
the one that a user will expect anyway.)</p> |
281 |
|
282 |
</div> |
283 |
|
284 |
<p>Any additional functionality built onto the debugger itself, or |
285 |
onto its breakpoints or watches, ought to be exposed as JavaBeans |
286 |
properties, and events fired upon their change - this convention |
287 |
ensures that if such objects are used by any other part of the system |
288 |
(say, inspected in a property sheet, customized in some action...), |
289 |
that the extended functionality will be properly presented. |
290 |
See the section on |
291 |
|
292 |
<a href="#create-xtra">extra implementation</a> |
293 |
|
294 |
for ideas on how to present additional functionality. |
295 |
|
296 |
<h3><a name="module">Installation tips</a></h3> |
297 |
|
298 |
<p>Installation of the debugger itself is quite simple thanks to the |
299 |
|
300 |
<a href="@OPENIDE@/org/openide/doc-files/services-api.html#service-lookup">Services API</a> - |
301 |
|
302 |
you need only register an instance of it to lookup</p> |
303 |
|
304 |
<p class="nonnormative">A typical debugger implementation will, however, want to install |
305 |
some other components to support it, such as a system option |
306 |
(mentioned <a href="#sysopt-note">above</a>), or an environment node |
307 |
to represent the state of the running debugger, its breakpoints and |
308 |
watches, possibly threads, etc. - see the |
309 |
|
310 |
<a href="@OPENIDE@/org/openide/nodes/doc-files/api.html#create-mod">Nodes API</a> |
311 |
|
312 |
for instructions on doing this.</p> |
313 |
|
314 |
<h2><a name="create-xtra">Creating Extra Debugger-Related Implementation</a></h2> |
315 |
|
316 |
While the previous section described what is <em>required</em> of |
317 |
the debugger by the APIs, in practice a good debugger module will |
318 |
present more of a user interface than the APIs specify. By default, |
319 |
the implementation of the IDE does not do much with the debugger |
320 |
directly: |
321 |
|
322 |
<ol> |
323 |
|
324 |
<li><a href="../DebuggerType.Default.html"><code>DebuggerType.Default</code></a> |
325 |
|
326 |
is available as a bare-bones |
327 |
|
328 |
<a href="#createtype">debugger type</a> |
329 |
|
330 |
which just invokes the debugger via the public interface; you may |
331 |
want to write your own debugger types to complement it. |
332 |
|
333 |
</ol> |
334 |
|
335 |
<div class="nonnormative"> |
336 |
|
337 |
The following subsections describe things which the IDE |
338 |
implementation does <em>not</em> do automatically, and ideas on how |
339 |
to implement them suitably for your debugger. They are all optional |
340 |
for a compliant debugger implementation, since they affect the UI |
341 |
rather than the interactions of other parts of the IDE with the |
342 |
debugger; most are desirable nevertheless. |
343 |
|
344 |
<a href="#createtype">Writing debugger types</a> |
345 |
|
346 |
is also a good idea, but is described separately since it may also |
347 |
be done in modules outside of the debugger proper, as debugger |
348 |
types are specific to certain kinds of development support |
349 |
(e.g. RMI, servlet, etc.). |
350 |
|
351 |
<h3><a name="curr-line">Handling the current line</a></h3> |
352 |
|
353 |
It is desirable (though not strictly required) that a debugger update |
354 |
the Editor to track the current line as it moves through source code |
355 |
(if such movement can be tracked properly, and the current source is |
356 |
available). This is the debugger's responsibility, not the Editor's |
357 |
nor the system's. |
358 |
|
359 |
<p>Though different debuggers may of course vary in exactly how they |
360 |
wish to do this, the basic implementation is not difficult once you |
361 |
know where to look: |
362 |
|
363 |
<ol> |
364 |
|
365 |
<li>Keep track of the current line in a variable of type |
366 |
|
367 |
<a href="@OPENIDE@/org/openide/text/Line.html"><code>Line</code></a>, |
368 |
|
369 |
which is designed for exactly this sort of purpose. You may use |
370 |
|
371 |
<a href="@OPENIDE@/org/openide/text/Line.html#markCurrentLine()"><code>Line.markCurrentLine()</code></a> |
372 |
|
373 |
and |
374 |
|
375 |
<a href="@OPENIDE@/org/openide/text/Line.html#unmarkCurrentLine()"><code>Line.unmarkCurrentLine()</code></a> |
376 |
|
377 |
whenever control enters or exits this line. |
378 |
|
379 |
<li>To find the current source file based on the classname, |
380 |
|
381 |
<a href="@OPENIDE@/org/openide/filesystems/Repository.html#find(java.lang.String, java.lang.String, java.lang.String)"><code>Repository.find(...)</code></a> |
382 |
|
383 |
is easiest. You may instead wish to get all filesystems marked as |
384 |
supporting debugging via |
385 |
|
386 |
<a href="@OPENIDE@/org/openide/filesystems/FileSystemCapability.html#DEBUG"><code>FileSystemCapability.DEBUG</code></a> |
387 |
|
388 |
and then call |
389 |
|
390 |
<a href="@OPENIDE@/org/openide/filesystems/FileSystemCapability.html#find(java.lang.String, java.lang.String, java.lang.String)"><code>FileSystemCapability.find(...)</code></a> |
391 |
|
392 |
to find the source file within these filesystems only. |
393 |
|
394 |
<li>Knowing the file containing source, the lines in it are available |
395 |
by first getting the data object (with |
396 |
|
397 |
<a href="@OPENIDE@/org/openide/loaders/DataObject.html#find(org.openide.filesystems.FileObject)"><code>DataObject.find(...)</code></a>), |
398 |
|
399 |
then using |
400 |
|
401 |
<a href="@OPENIDE@/org/openide/loaders/DataObject.html#getCookie(java.lang.Class)"><code>DataObject.getCookie(...)</code></a> |
402 |
|
403 |
to look for a |
404 |
|
405 |
<a href="@OPENIDE@/org/openide/cookies/LineCookie.html"><code>LineCookie</code></a> |
406 |
|
407 |
(which ought to have been provided by, e.g., the |
408 |
|
409 |
<a href="@OPENIDE@/org/openide/text/EditorSupport.html"><code>EditorSupport</code></a> |
410 |
|
411 |
attached by the standard Java loader), |
412 |
|
413 |
and finally getting the desired line with |
414 |
|
415 |
<a href="@OPENIDE@/org/openide/cookies/LineCookie.html#getLineSet()"><code>LineCookie.getLineSet()</code></a> |
416 |
|
417 |
and |
418 |
|
419 |
<a href="@OPENIDE@/org/openide/text/Line.Set.html#getOriginal(int)"><code>Line.Set.getOriginal(int)</code></a> |
420 |
|
421 |
(which finds the line based on the original line numbering, even if |
422 |
the user has since edited the document). |
423 |
|
424 |
</ol> |
425 |
|
426 |
<h3><a name="xtra-actions">Adding extra actions</a></h3> |
427 |
|
428 |
Many debuggers will provide additional functionality as regards |
429 |
their running state over that specified in the APIs. For example, |
430 |
the standard IDE debugger supports suspending and resuming the |
431 |
debugger, which is not required by the APIs and not accessible via |
432 |
them. For this reason, you may want to create your own user-visible |
433 |
actions to support extended debugger manipulation using the |
434 |
|
435 |
<a href="@OPENIDE@/org/openide/actions/doc-files/api.html#create">Actions API</a>. |
436 |
|
437 |
<p>The IDE's default menu and toolbar configurations should include |
438 |
the basic (API-supplied) actions in sensible positions. If you do |
439 |
not agree with these positions, or wish to add your own special |
440 |
actions to the menus or toolbars, the Actions API again describes |
441 |
|
442 |
<a href="@OPENIDE@/org/openide/actions/doc-files/api.html#adv-install">how to do this</a>. |
443 |
|
444 |
<p>Finally, you may want to provide context-menu actions on |
445 |
|
446 |
<a href="#env-nodes">any nodes</a> |
447 |
|
448 |
which you create for your debugger; if so, please use the |
449 |
|
450 |
<a href="@OPENIDE@/org/openide/nodes/doc-files/api.html#create-cookie-act">Nodes API</a> |
451 |
|
452 |
for guidance. |
453 |
|
454 |
<h3><a name="env-nodes">Adding nodes to "Runtime"</a></h3> |
455 |
|
456 |
The standard debugger installs a new master node into the |
457 |
<b>Runtime</b> tab in the Explorer, containing lists of current |
458 |
breakpoints and watches, as well as extra functionality it has such |
459 |
as current threads (and thread groups), and debugging sessions in |
460 |
the case of a multiple-session debugger. Debugger implementors who |
461 |
wish to provide similar functionality should do so themselves; |
462 |
although there is no direct API support for this, in practice |
463 |
creating basic lists of objects is not difficult. |
464 |
|
465 |
<p>The basic idea is to use the |
466 |
|
467 |
<a href="@OPENIDE@/org/openide/nodes/doc-files/api.html#create">Nodes API</a> |
468 |
|
469 |
to create simple lists of all objects in your debugger's current |
470 |
state. For starters, you could create a master node (the one |
471 |
directly under <b>Runtime</b>) as an |
472 |
|
473 |
<a href="@OPENIDE@/org/openide/nodes/AbstractNode.html"><code>AbstractNode</code></a> |
474 |
|
475 |
using |
476 |
|
477 |
<a href="@OPENIDE@/org/openide/nodes/Children.Array.html"><code>Children.Array</code></a>: |
478 |
|
479 |
the children can just be listed as is, since you will want one |
480 |
child for each category (breakpoints, watches, etc.). |
481 |
|
482 |
<p>Now, each category node (e.g. list of all watches) can again be |
483 |
an <code>AbstractNode</code>, but this time using |
484 |
|
485 |
<a href="@OPENIDE@/org/openide/nodes/Children.Keys.html"><code>Children.Keys</code></a> |
486 |
|
487 |
so that its children are dynamically determined; in the |
488 |
|
489 |
<a href="@OPENIDE@/org/openide/nodes/Children.html#addNotify()"><code>Children.addNotify()</code></a> |
490 |
|
491 |
method, call |
492 |
|
493 |
<a href="@OPENIDE@/org/openide/nodes/Children.Keys.html#setKeys(java.util.Collection)"><code>Children.Keys.setKeys(Collection)</code></a> |
494 |
|
495 |
to update the list of keys. Probably you will want each key to just |
496 |
be one actual watch object from the debugger. Also, attach a |
497 |
listener to your debugger so that when the set of watches changes, |
498 |
<code>setKeys</code> will be called again with the new list of |
499 |
children to update the display. Note that if your implementation |
500 |
supports hidden breakpoints, as determined by |
501 |
|
502 |
<a href="../Breakpoint.html#isHidden()"><code>Breakpoint.isHidden()</code></a>, |
503 |
|
504 |
then these should of course be excluded from the visible list. |
505 |
|
506 |
<p>In the |
507 |
|
508 |
<a href="@OPENIDE@/org/openide/nodes/Children.Keys.html#createNodes(java.lang.Object)"><code>Children.Keys.createNodes(Object)</code></a> |
509 |
|
510 |
method, you know your key is a watch object, so just use |
511 |
|
512 |
<a href="@OPENIDE@/org/openide/nodes/BeanNode.html#BeanNode(java.lang.Object)"><code>new BeanNode(Object)</code></a> |
513 |
|
514 |
to represent it. Remember, watches and breakpoints should have |
515 |
bound properties and bean info just like any JavaBean, so using a |
516 |
<code>BeanNode</code> for them should provide all the right |
517 |
behavior automatically. You can also subclass <code>BeanNode</code> |
518 |
and implement |
519 |
|
520 |
<a href="@OPENIDE@/org/openide/nodes/BeanNode.html#canDestroy()"><code>BeanNode.canDestroy()</code></a> |
521 |
|
522 |
and |
523 |
|
524 |
<a href="@OPENIDE@/org/openide/nodes/BeanNode.html#destroy()"><code>BeanNode.destroy()</code></a> |
525 |
|
526 |
(etc.) to permit the user to delete watches from this view - the |
527 |
method should simply remove the watch from the debugger, and then |
528 |
the parent node will get routinely notified via its listener of the |
529 |
change and refresh the display. |
530 |
|
531 |
<p>Other types of objects such as threads and so on can also be |
532 |
represented in similar ways, but of course the details of how to |
533 |
set up the nodes will vary depending on how you represent such |
534 |
objects; refer to the Nodes API for this. |
535 |
|
536 |
<p>Finally, the master node can be installed by your module using the |
537 |
|
538 |
<a href="@OPENIDE@/org/openide/modules/doc-files/api.html#sec-environment">Modules API</a>. |
539 |
|
540 |
<h3><a name="windows">Adding a debugging workspace, windows, etc.</a></h3> |
541 |
|
542 |
You can check how the IDE looks without your debugger module (or |
543 |
the standard debugger module) installed and then decide if you need |
544 |
to customize workspaces, windows, and so on. If you wish, you can |
545 |
create your own customized workspaces and so on for the purpose of |
546 |
giving a characteristic feel and UI to a user's debugging sessions; |
547 |
refer to the |
548 |
|
549 |
<a href="@OPENIDE@/org/openide/windows/doc-files/api.html#xml-scenarios">Window System API</a> |
550 |
|
551 |
for all details. |
552 |
|
553 |
<p>If you wish to provide a window (possibly multitabbed) showing |
554 |
your debugging nodes, the way the standard module does, you can |
555 |
create |
556 |
|
557 |
<a href="@OPENIDE@/org/openide/explorer/ExplorerPanel.html"><code>ExplorerPanel</code></a>s |
558 |
|
559 |
to hold e.g. a |
560 |
|
561 |
<a href="@OPENIDE@/org/openide/explorer/view/BeanTreeView.html"><code>BeanTreeView</code></a> |
562 |
|
563 |
and a |
564 |
|
565 |
<a href="@OPENIDE@/org/openide/explorer/propertysheet/PropertySheetView.html"><code>PropertySheetView</code></a>, |
566 |
|
567 |
then assign the root node to such a window using |
568 |
|
569 |
<a href="@OPENIDE@/org/openide/explorer/ExplorerPanel.html#getExplorerManager()"><code>ExplorerPanel.getExplorerManager()</code></a> |
570 |
|
571 |
and |
572 |
|
573 |
<a href="@OPENIDE@/org/openide/explorer/ExplorerManager.html#setRootContext(org.openide.nodes.Node)"><code>ExplorerManager.setRootContext(Node)</code></a>. |
574 |
|
575 |
The multitabbed look can be achieved simply using |
576 |
|
577 |
<a href="@OPENIDE@/org/openide/windows/doc-files/api.html#xml-visual">window manager modes</a>. |
578 |
|
579 |
<h3><a name="sysop">Adding a system option</a></h3> |
580 |
|
581 |
You will probably want to add a |
582 |
|
583 |
<a href="@OPENIDE@/org/openide/options/doc-files/api.html#make-opt">system option</a> |
584 |
|
585 |
to the IDE representing general configuration of your debugger |
586 |
(specifics of how to debug particular files, such as the path to |
587 |
any required debugger executable, ought to be left to |
588 |
|
589 |
<a href="#createtype">debugger types</a>). |
590 |
|
591 |
<h3><a name="persistence">Persisting debugger state</a></h3> |
592 |
|
593 |
Finally, it is important for the user experience of the IDE that as |
594 |
much as possible of their environment persist across IDE |
595 |
restarts. This is generally done by storing various types of |
596 |
configurations in the project state. In the case of debuggers, |
597 |
conventionally at least the list of breakpoints and watches should |
598 |
be stored, so that a user does not need to set up their debugging |
599 |
environment afresh each time the IDE is restarted. Fortunately, |
600 |
implementing this is rather easy; it is suggested that you: |
601 |
|
602 |
<ol> |
603 |
|
604 |
<li>Make sure your watches and breakpoints are really safely |
605 |
serializable (as required by the API interfaces). |
606 |
|
607 |
<li>Create a bean holding the set of watches and breakpoints |
608 |
as properties. It should be serializable and fire property |
609 |
changes. |
610 |
|
611 |
<li><a href="@OPENIDE@/org/openide/doc-files/services-api.html#settings">Register</a> |
612 |
an instance of this bean to lookup. It need not have any visible |
613 |
representation. |
614 |
|
615 |
<li>You can now ask lookup for the instance of the bean, and changes |
616 |
should be saved to disk automatically. |
617 |
|
618 |
</ol> |
619 |
|
620 |
</div> |
621 |
|
622 |
<h2><a name="createtype">Creating a Debugger Type</a></h2> |
623 |
|
624 |
You may create <em>debugger types</em> in order to provide special |
625 |
support for debugging objects other than simple Java classes with |
626 |
<code>main</code> methods. For example, debugging applets may |
627 |
entail launching the debugger on the AppletViewer application, |
628 |
passing in the HTML URL for the applet to be debugged. (For classes |
629 |
with <code>main</code> methods, the standard default implementation |
630 |
|
631 |
<a href="../DebuggerType.Default.html"><code>DebuggerType.Default</code></a> |
632 |
|
633 |
suffices.) Thus, debugger types are the bridge between the specifics of how |
634 |
a file should be started (in this way resembling |
635 |
|
636 |
<a href="@OPENIDE/EXECUTION@/org/openide/execution/Executor.html"><code>Executor</code></a>s) |
637 |
|
638 |
and the debugger implementation (which assumes that it is being started |
639 |
on a class with a <code>main</code> method). |
640 |
|
641 |
<p>Creating and installing the debugger type with its associated |
642 |
configuration is a fairly uniform process, according to the |
643 |
|
644 |
<a href="@OPENIDE@/org/openide/doc-files/services-api.html">Services API</a>, since |
645 |
|
646 |
the required superclass |
647 |
|
648 |
<a href="../DebuggerType.html"><code>DebuggerType</code></a> |
649 |
|
650 |
is a variety of |
651 |
|
652 |
<a href="@OPENIDE@/org/openide/ServiceType.html"><code>ServiceType</code></a>. |
653 |
|
654 |
Only issues pertaining specifically to subclassing |
655 |
<code>DebuggerType</code> will be discussed here. |
656 |
|
657 |
<p>There is just one abstract method to implement: |
658 |
|
659 |
<a href="../DebuggerType.html#startDebugger(org.openide.execution.ExecInfo, boolean)"><code>DebuggerType.startDebugger(ExecInfo,boolean)</code></a>. |
660 |
|
661 |
When a user of debugger types (such as <code>ExecSupport</code>, |
662 |
see <a href="#invoke">below</a>) wishes to start debugging some |
663 |
object (say, an applet), it will call this method on the debugger |
664 |
type, passing it an |
665 |
|
666 |
<a href="@OPENIDE@/org/openide/loaders/DataObject.html"><code>DataObject</code></a> |
667 |
|
668 |
containing the class to be debugged; and a flag indicating whether the |
669 |
debugger should initially break on the "main class" of the object |
670 |
(however that should be interpreted).</p> |
671 |
|
672 |
<div class="nonnormative"> |
673 |
|
674 |
<p>Typically, the debugger type will do a few simple steps:</p> |
675 |
|
676 |
<ol> |
677 |
|
678 |
<li> Construct a |
679 |
|
680 |
<a href="../DebuggerInfo.html#DebuggerInfo(java.lang.String, java.lang.String[])"><code>new DebuggerInfo(...)</code></a> |
681 |
|
682 |
according to the information passed in the <code>ExecInfo</code>, |
683 |
as well as the specifics of the debugger type. For example, in the |
684 |
case of applets, the <code>DebuggerInfo</code> should specify the |
685 |
main class as being that of the AppletViewer application, and the |
686 |
class name of the applet should be used to look up an HTML page |
687 |
which can then be passed in the argument list along with other |
688 |
options. |
689 |
|
690 |
<li> Handle the stop-on-main flag appropriately. If the flag is |
691 |
clear, typically |
692 |
|
693 |
<pre> |
694 |
new DebuggerInfo (mainClass, arguments, null) |
695 |
</pre> |
696 |
|
697 |
should be used, to prevent the debugger from breaking except at |
698 |
user-specified points. If the flag is set, you may use the |
699 |
two-argument constructor, but this will break at the beginning of |
700 |
the real main class (e.g. AppletViewer); you may instead prefer to |
701 |
explicitly specify the class to break on, such as the applet class. |
702 |
|
703 |
<li> Actually launch the debugger with: |
704 |
|
705 |
<pre> |
706 |
TopManager.getDefault ().getDebugger ().startDebugger (myDebugInfo); |
707 |
</pre> |
708 |
|
709 |
</ol> |
710 |
|
711 |
</div> |
712 |
|
713 |
<p>Note that general problems occurring during this problem can be reported with a |
714 |
|
715 |
<a href="../DebuggerException.html"><code>DebuggerException</code></a>. |
716 |
|
717 |
<p>You have the option of what exactly to include in the |
718 |
<code>DebuggerInfo</code> option passed to the |
719 |
<code>startDebugger</code> method. If the debugger type is to be |
720 |
generic (work with any installed debugger), then you should only |
721 |
assume the API minimum and use an actual instance of |
722 |
<code>DebuggerInfo</code>. But, it is permissible to provide |
723 |
additional debugger-specific information, if that information can |
724 |
be used to good effect by the debugger implementation.</p> |
725 |
|
726 |
<p class="nonnormative">For example, the standard IDE debugger actually defines several |
727 |
additional subclasses of <code>DebuggerInfo</code> and provides a |
728 |
special API to these (outside of the Open APIs), such as an |
729 |
extended info which contains descriptions of the exact process name |
730 |
to be used to start the Java launcher in debug mode, special VM |
731 |
options, and so on. It also defines standard debugger-type |
732 |
superclasses which already have all of this configuration present |
733 |
as Bean properties. So, debugger types (such as those for applets) |
734 |
can specify an applet style of debugging, along with special VM |
735 |
characteristics for the user to configure. If the debugger is |
736 |
handed a plain <code>DebuggerInfo</code>, it simply uses default |
737 |
settings for all the specifics; conversely, an extended |
738 |
<code>DebuggerInfo</code> could be passed to an alternate debugger |
739 |
implementation without harm, as the alternate debugger would just |
740 |
not recognize the extra information in the subclass.</p> |
741 |
|
742 |
<div class="nonnormative"> |
743 |
|
744 |
<h2><a name="invoke">Invoking the Debugger</a></h2> |
745 |
|
746 |
There is little to say about how to invoke an existing debugger |
747 |
programmatically - the essential methods are all provided in the |
748 |
<code>Debugger</code> interface, and the debugger can be started with |
749 |
only a |
750 |
|
751 |
<a href="../DebuggerInfo.html#DebuggerInfo(java.lang.String, java.lang.String[], java.lang.String)">small amount</a> |
752 |
|
753 |
of information. The debugger instance itself should be obtained via |
754 |
|
755 |
<a href="@OPENIDE@/org/openide/util/Lookup.html"><code>lookup</code></a> |
756 |
|
757 |
(currently the system expects only one debugger to be installed at |
758 |
a time; the APIs permit the implementation to keep multiple |
759 |
debuggers loaded with only one active at a time, though currently |
760 |
the implementation does not do this). |
761 |
|
762 |
<p>You may also wish to start debugging a particular file by means |
763 |
of its |
764 |
|
765 |
<a href="../../cookies/DebuggerCookie.html"><code>DebuggerCookie</code></a>; |
766 |
|
767 |
most frequently this implementation is an |
768 |
|
769 |
<a href="../../loaders/ExecSupport.html"><code>ExecSupport</code></a> |
770 |
|
771 |
which will delegate the request to an associated debugger type, |
772 |
which then launches the system debugger with the correct |
773 |
arguments. This more natural method is that used by the standard |
774 |
debugger-launching actions. |
775 |
|
776 |
<p>The |
777 |
|
778 |
<a href="@OPENIDE@/org/openide/doc-files/services-api.html#use-find">Services API</a> |
779 |
|
780 |
also permits you to look for specific debugger types which could |
781 |
then be applied manually to a specific file. |
782 |
|
783 |
</div> |
784 |
|
785 |
<h3><a name="hidden-watch">Using hidden watches</a></h3> |
786 |
|
787 |
A sophisticated editor implementation, and potentially other |
788 |
components as well, may want to monitor the current value of a |
789 |
variable mentioned in source code (e.g.) while the debugger is in |
790 |
operation. This is possible using a <em>hidden watch</em>, which |
791 |
functions exactly like a regular watch but is not created by the user |
792 |
and not intended for direct display to the user. To create one, just |
793 |
get the debugger and call |
794 |
|
795 |
<a href="../Debugger.html#createWatch(java.lang.String, boolean)"><code>Debugger.createWatch(...)</code></a> |
796 |
|
797 |
(with the second argument <code>true</code>). Typically the watched |
798 |
expression will be an unqualified variable name, but of course this |
799 |
depends on the watch's use, and what the debugger implementation is |
800 |
capable of handling (only assume bare variable names are supported). |
801 |
|
802 |
<p>Now, the current display value of the watch is available with |
803 |
|
804 |
<a href="../Watch.html#getAsText()"><code>Watch.getAsText()</code></a>, |
805 |
|
806 |
and the |
807 |
|
808 |
<a href="../Watch.html#PROP_AS_TEXT">corresponding property</a> |
809 |
|
810 |
may be listened to in order to update some user-oriented display (such |
811 |
as a tool tip). |
812 |
|
813 |
<p>Remember to call |
814 |
|
815 |
<a href="../Watch.html#remove()"><code>Watch.remove()</code></a> |
816 |
|
817 |
as soon as the watch is no longer required, so as not to waste memory. |
818 |
|
819 |
<hr>@FOOTER@ |
820 |
</body> |
821 |
</html> |