2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
42
package org.netbeans.modules.scripting.php.dbginterface;
44
import java.io.BufferedInputStream;
45
import java.io.IOException;
46
import java.io.InputStream;
47
import java.net.Socket;
48
import java.util.ArrayList;
49
import java.util.HashMap;
50
import java.util.HashSet;
51
import java.util.List;
54
import javax.swing.SwingUtilities;
55
import org.netbeans.api.debugger.Breakpoint;
56
import org.netbeans.api.debugger.DebuggerManager;
57
import org.netbeans.modules.scripting.php.dbginterface.api.DbgSourceMap;
58
import org.netbeans.modules.scripting.php.dbginterface.breakpoints.PhpBreakpoint;
59
import org.netbeans.modules.scripting.php.dbginterface.models.DebugError;
60
import org.netbeans.modules.scripting.php.dbginterface.models.DebugFrame;
61
import org.netbeans.modules.scripting.php.dbginterface.models.Variable;
62
import org.openide.ErrorManager;
63
import org.openide.filesystems.FileObject;
64
import org.openide.text.Line;
65
import org.openide.util.Utilities;
71
public class DbgServerHandler extends DbgDebuggerImpl.Context implements Runnable {
72
private Socket socket;
73
private InputStream in;
76
private List<DbgPacket> packetsToSend = new ArrayList<DbgPacket>();
77
private Thread handlerThread;
78
private String sessionId;
79
private DbgSourceMap sourceMap;
80
private DebuggerAnnotation currentLineAnnotation;
81
private Line currentLine;
82
private Set<DebuggerAnnotation> errorAnnotations = new HashSet<DebuggerAnnotation>();
83
private boolean suspended;
84
private List<DebugFrame> callStack;
86
private Map<Integer, String> sourceFileMap = new HashMap<Integer, String>();
88
public DbgServerHandler(DbgDebuggerImpl impl, Socket socket) {
90
sourceMap = impl.getSourceMap();
95
in = new BufferedInputStream(socket.getInputStream());
97
catch (IOException ioe) {
98
ErrorManager.getDefault().notify(ErrorManager.WARNING, ioe);
102
public void sendPacket(DbgPacket packet) {
103
if (handlerThread == null) {
107
synchronized (packetsToSend) {
108
packetsToSend.add(packet);
111
handlerThread.interrupt();
116
synchronized (this) {
119
if (handlerThread != null) {
120
handlerThread.interrupt();
126
System.err.println("mw DbgServerHandler.run() started!");
128
synchronized (this) {
129
handlerThread = Thread.currentThread();
132
while (!stop && !socket.isClosed()) {
134
List<DbgPacket> toSend = null;
136
synchronized (packetsToSend) {
137
if (packetsToSend != null && packetsToSend.size() > 0) {
138
toSend = new ArrayList<DbgPacket>(packetsToSend);
139
packetsToSend.clear();
143
if (toSend != null) {
144
for (DbgPacket p : toSend) {
146
// Are there packets from the debuggee to handle first?
147
handleIncomingPackets(false);
150
p.send(socket.getOutputStream());
153
// Wait for the acknowledgement packet
154
handleIncomingPackets(true);
159
handleIncomingPackets(false);
161
catch (IOException ioe) {
162
ErrorManager.getDefault().notify(ErrorManager.WARNING, ioe);
166
// Wake up every 100 milliseconds and see if the debuggee has something to say.
167
// The IDE side can interrupt the sleep to send new packets to the
171
catch (InterruptedException ie) {
172
// OK, run the look again.
176
if (!socket.isClosed()) {
179
} catch (IOException ioe) {
180
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ioe);
184
synchronized (this) {
185
handlerThread = null;
189
getServer().getCallStackModel().refresh(true);
190
getServer().getVariablesModel().clearModel();
193
for (DebuggerAnnotation a : errorAnnotations) {
198
public boolean isSuspended() {
202
public void setSuspended(boolean s) {
205
getServer().setEnableContActions(s);
208
public void setCurrentLine(Line line) {
212
public void finish() {
213
getServer().closeScriptContext(this);
216
public DbgSourceMap getSourceMap() {
220
public void addError(DebugError e) {
223
aType = DebuggerAnnotation.ERROR_ANNOTATION_TYPE;
225
else if (e.isNotice()) {
226
aType = DebuggerAnnotation.NOTICE_ANNOTATION_TYPE;
228
else if (e.isWarning()) {
229
aType = DebuggerAnnotation.WARNING_ANNOTATION_TYPE;
232
errorAnnotations.add(new DebuggerAnnotation(aType, e.getLine(), e.getString()));
235
public void hideCurrentLine() {
236
if (currentLineAnnotation != null) {
237
currentLineAnnotation.detach();
238
currentLineAnnotation = null;
242
public void handleCurrentLine() {
243
if (currentLineAnnotation != null) {
244
currentLineAnnotation.detach();
247
if (currentLine != null) {
248
final Line line = currentLine;
250
currentLineAnnotation = new DebuggerAnnotation(DebuggerAnnotation.CURRENT_LINE_ANNOTATION_TYPE,
253
SwingUtilities.invokeLater(new Runnable() {
255
line.show(Line.SHOW_GOTO);
261
public void setCallStack(List<DebugFrame> list) {
263
getServer().getCallStackModel().setNeedsRefresh();
264
getServer().getVariablesModel().setStackFrame(callStack.get(0));
265
getServer().getWatchesModel().setStackFrame(callStack.get(0));
268
public List<DebugFrame> getCallStack() {
272
public void addSourceFileInfo(int modNo, String filename) {
273
sourceFileMap.put(new Integer(modNo), filename);
276
public String getSourceFileInfo(int modNo) {
277
return sourceFileMap.get(new Integer(modNo));
280
public Variable getScopeVariables(DebugFrame frame) {
281
// Initialize the $this if the scope has one.
282
// That's done by asking for it?!
283
DbgPacket packet = new DbgPacket(DbgConstants.DBGA_REQUEST);
285
packet.setFlags(DbgConstants.DBGF_WAITACK);
286
DbgPacket.FrameRawdata f = new DbgPacket.FrameRawdata(packet, "$this");
289
packet.addFrame(new DbgPacket.FrameEval(f.getRawId(), frame.getScope()));
292
packet.send(socket.getOutputStream());
293
// Wait for the response
294
packet = DbgPacket.receive(in);
297
catch (IOException ioe) {
298
ErrorManager.getDefault().notify(ErrorManager.WARNING, ioe);
301
// OK, now get the scope variables;-)
302
packet = new DbgPacket(DbgConstants.DBGA_REQUEST);
304
packet.setFlags(DbgConstants.DBGF_WAITACK);
305
packet.addFrame(new DbgPacket.FrameEval(0, frame.getScope()));
308
packet.send(socket.getOutputStream());
309
// Wait for the response
310
packet = DbgPacket.receive(in);
313
catch (IOException ioe) {
314
ErrorManager.getDefault().notify(ErrorManager.WARNING, ioe);
317
List<Variable> vars = packet.getEvalValue();
326
public void setVariableValue(DebugFrame frame, Variable v, Object value) {
327
DbgPacket packet = new DbgPacket(DbgConstants.DBGA_REQUEST);
329
packet.setFlags(DbgConstants.DBGF_WAITACK);
330
DbgPacket.FrameRawdata f = new DbgPacket.FrameRawdata(packet, v.getDisplayName() +
334
packet.addFrame(new DbgPacket.FrameEval(f.getRawId(), frame.getScope()));
337
packet.send(socket.getOutputStream());
338
// Wait for the response
339
packet = DbgPacket.receive(in);
342
catch (IOException ioe) {
343
ErrorManager.getDefault().notify(ErrorManager.WARNING, ioe);
348
public Variable evaluateExpr(DebugFrame frame, String expr) {
353
DbgPacket packet = new DbgPacket(DbgConstants.DBGA_REQUEST);
355
packet.setFlags(DbgConstants.DBGF_WAITACK);
356
DbgPacket.FrameRawdata f = new DbgPacket.FrameRawdata(packet, expr);
359
packet.addFrame(new DbgPacket.FrameEval(f.getRawId(), frame.getScope()));
362
packet.send(socket.getOutputStream());
363
// Wait for the response
364
packet = DbgPacket.receive(in);
367
catch (IOException ioe) {
368
ErrorManager.getDefault().notify(ErrorManager.WARNING, ioe);
371
List<Variable> vars = packet.getEvalValue();
380
public void setSessionId(String sId) {
384
public void setBreakpoints() {
385
Breakpoint[] breakpoints = DebuggerManager.getDebuggerManager().getBreakpoints();
387
for (int i = 0; i < breakpoints.length; i++) {
388
System.err.println("mw DbgServerHandler.setBreakpoints() breakpoints[" + i + "]= " + breakpoints[i]);
390
if (breakpoints[i] instanceof PhpBreakpoint) {
391
PhpBreakpoint b = (PhpBreakpoint)breakpoints[i];
393
Line line = b.getLine();
394
FileObject sourceFile = line.getLookup().lookup(FileObject.class);
395
String targetFile = sourceMap.mapToServerPath(sourceFile);
397
if (targetFile != null) {
399
System.err.println("mw addBP! line= " + sourceFile + ":" + (line.getLineNumber() + 1));
400
System.err.println("mw targetFile= " + targetFile);
402
DbgPacket packet = new DbgPacket(DbgConstants.DBGA_REQUEST);
404
packet.setFlags(DbgConstants.DBGF_WAITACK);
406
DbgPacket.FrameRawdata mod_name = new DbgPacket.FrameRawdata(packet, targetFile);
407
packet.addFrame(mod_name);
408
DbgPacket.FrameRawdata condition = new DbgPacket.FrameRawdata(packet, b.getCondition());
409
packet.addFrame(condition);
411
packet.addFrame(new DbgPacket.FrameBps(0, line.getLineNumber() + 1, 0, mod_name.getRawId(),
412
condition.getRawId(), b.isTemp(), 0,
413
(b.isEnabled() ? DbgConstants.BPS_ENABLED : DbgConstants.BPS_DISABLED)));
416
packet.send(socket.getOutputStream());
417
// Wait for the response
418
packet = DbgPacket.receive(in);
419
DbgPacket.FrameBpl f = (DbgPacket.FrameBpl)packet.getFirstFrame();
420
b.setBpNo(f.getBpNo());
422
catch (IOException ioe) {
423
ErrorManager.getDefault().notify(ErrorManager.WARNING, ioe);
430
public void updateSourceTree() {
431
DbgPacket packet = new DbgPacket(DbgConstants.DBGA_REQUEST);
433
packet.setFlags(DbgConstants.DBGF_WAITACK);
435
DbgPacket.FrameSrcTree f = new DbgPacket.FrameSrcTree();
439
packet.send(socket.getOutputStream());
440
// Wait for the response
441
packet = DbgPacket.receive(in);
445
catch (IOException ioe) {
446
ErrorManager.getDefault().notify(ErrorManager.WARNING, ioe);
450
public void resume() {
452
getServer().getCallStackModel().setNeedsRefresh();
453
getServer().getVariablesModel().clearModel();
455
cont(DbgConstants.DBGA_CONTINUE);
458
public void stepInto() {
459
cont(DbgConstants.DBGA_STEPINTO);
462
public void stepOut() {
463
cont(DbgConstants.DBGA_STEPOUT);
466
public void stepOver() {
467
cont(DbgConstants.DBGA_STEPOVER);
470
private void cont(int step) {
474
System.err.println("mw DbgServerHandler.cont(" + step + ")");
476
sendPacket(new DbgPacket(step));
480
private void handleIncomingPackets(boolean block) throws IOException {
481
while (block || in.available() > 0) {
482
DbgPacket packet = DbgPacket.receive(in);
489
public DebuggerAnnotation getCurrentLineAnnotation() {
490
return currentLineAnnotation;
493
public void setCurrentLineAnnotation(DebuggerAnnotation annotation) {
494
this.currentLineAnnotation = annotation;
497
packet = new DbgPacket(DbgConstants.DBGA_REQUEST);
498
packet.addFrame(new DbgPacket.FrameVer());
499
packet.setFlags(flags | DbgConstants.DBGF_WAITACK);
500
System.err.println("mw packet to send= " + packet);
502
packet.send(socket.getOutputStream());
504
packet = DbgPacket.receive(in);
506
System.err.println("mw packet returned= " + packet);
508
packet = new DbgPacket(DbgConstants.DBGA_REQUEST);
509
packet.setFlags(flags | DbgConstants.DBGF_WAITACK);
510
packet.addFrame(new DbgPacket.FrameSrcTree());
512
System.err.println("mw packet to send= " + packet);
513
packet.send(socket.getOutputStream());
515
packet = DbgPacket.receive(in);
517
System.err.println("mw packet returned= " + packet);
519
packet = new DbgPacket(DbgConstants.DBGA_REQUEST);
520
packet.setFlags(flags | DbgConstants.DBGF_WAITACK);
521
packet.addFrame(new DbgPacket.FrameSrcLinesInfo(1));
523
System.err.println("mw packet to send= " + packet);
524
packet.send(socket.getOutputStream());
526
packet = DbgPacket.receive(in);
528
System.err.println("mw packet returned= " + packet);
530
packet = new DbgPacket(DbgConstants.DBGA_REQUEST);
531
packet.setFlags(flags | DbgConstants.DBGF_WAITACK);
532
packet.addFrame(new DbgPacket.FrameSrcCtxInfo(1));
534
System.err.println("mw packet to send= " + packet);
535
packet.send(socket.getOutputStream());
537
packet = DbgPacket.receive(in);
539
System.err.println("mw packet returned= " + packet);
541
packet = new DbgPacket(DbgConstants.DBGA_REQUEST);
542
packet.setFlags(flags | DbgConstants.DBGF_WAITACK);
543
packet.addFrame(new DbgPacket.FrameSource(1, 10));
545
System.err.println("mw packet to send= " + packet);
546
packet.send(socket.getOutputStream());
548
packet = DbgPacket.receive(in);
550
System.err.println("mw packet returned= " + packet);
552
packet = new DbgPacket(DbgConstants.DBGA_CONTINUE);
553
System.err.println("mw packet to send= " + packet);
554
packet.send(socket.getOutputStream());
559
catch (InterruptedException ie) {
563
while (in.available() > 0) {
564
packet = DbgPacket.receive(in);
566
System.err.println("mw packet returned= " + packet);
569
packet = new DbgPacket(DbgConstants.DBGA_REQUEST);
570
packet.setFlags(flags | DbgConstants.DBGF_WAITACK);
571
packet.addFrame(new DbgPacket.FrameStack());
573
System.err.println("mw packet to send= " + packet);
574
packet.send(socket.getOutputStream());
576
packet = DbgPacket.receive(in);
578
System.err.println("mw packet returned= " + packet);
580
packet = new DbgPacket(DbgConstants.DBGA_REQUEST);
581
packet.setFlags(flags | DbgConstants.DBGF_WAITACK);
582
DbgPacket.FrameRawdata f = new DbgPacket.FrameRawdata(packet, "$i");
584
packet.addFrame(new DbgPacket.FrameEval(f.getRawId(), 1));
586
System.err.println("mw packet to send= " + packet);
587
packet.send(socket.getOutputStream());
589
packet = DbgPacket.receive(in);
591
System.err.println("mw packet returned= " + packet);
593
packet = new DbgPacket(DbgConstants.DBGA_REQUEST);
594
packet.setFlags(flags | DbgConstants.DBGF_WAITACK);
595
f = new DbgPacket.FrameRawdata(packet, "$GLOBALS");
597
packet.addFrame(new DbgPacket.FrameEval(f.getRawId(), 1));
599
System.err.println("mw packet to send= " + packet);
600
packet.send(socket.getOutputStream());
602
packet = DbgPacket.receive(in);
604
System.err.println("mw packet returned= " + packet);
606
packet = new DbgPacket(DbgConstants.DBGA_REQUEST);
607
packet.setFlags(flags | DbgConstants.DBGF_WAITACK);
608
f = new DbgPacket.FrameRawdata(packet, "");
610
packet.addFrame(new DbgPacket.FrameEval(f.getRawId(), 1));
612
System.err.println("mw packet to send= " + packet);
613
packet.send(socket.getOutputStream());
615
packet = DbgPacket.receive(in);
617
System.err.println("mw packet returned= " + packet);