KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > scripting > php > dbginterface > DbgDebuggerImpl


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-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.scripting.php.dbginterface;
21
22 import java.io.IOException JavaDoc;
23 import java.net.ConnectException JavaDoc;
24 import java.net.ServerSocket JavaDoc;
25 import java.net.Socket JavaDoc;
26 import java.net.SocketException JavaDoc;
27 import java.net.SocketTimeoutException JavaDoc;
28 import java.util.HashSet JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.List JavaDoc;
31 import java.util.Map JavaDoc;
32 import java.util.Set JavaDoc;
33 import java.util.concurrent.ConcurrentHashMap JavaDoc;
34 import org.netbeans.api.debugger.ActionsManager;
35 import org.netbeans.api.debugger.DebuggerManager;
36 import org.netbeans.modules.scripting.php.dbginterface.api.DbgSourceMap;
37 import org.netbeans.modules.scripting.php.dbginterface.api.DebuggerStartException;
38 import org.netbeans.modules.scripting.php.dbginterface.api.VariableNode;
39 import org.netbeans.modules.scripting.php.dbginterface.breakpoints.BreakpointModel;
40 import org.netbeans.modules.scripting.php.dbginterface.models.CallStackModel;
41 import org.netbeans.modules.scripting.php.dbginterface.models.DebugFrame;
42 import org.netbeans.modules.scripting.php.dbginterface.models.ThreadsModel;
43 import org.netbeans.modules.scripting.php.dbginterface.models.Variable;
44 import org.netbeans.modules.scripting.php.dbginterface.models.VariablesModel;
45 import org.netbeans.modules.scripting.php.dbginterface.models.WatchesModel;
46 import org.netbeans.spi.debugger.ActionsProviderSupport;
47 import org.netbeans.spi.debugger.ContextProvider;
48 import org.netbeans.spi.debugger.DebuggerEngineProvider;
49 import org.netbeans.spi.viewmodel.TableModel;
50 import org.netbeans.spi.viewmodel.TreeModel;
51 import org.openide.ErrorManager;
52 import org.openide.loaders.DataObject;
53 import org.openide.util.RequestProcessor;
54
55 /**
56  *
57  * @author marcow
58  */

59 public class DbgDebuggerImpl extends ActionsProviderSupport {
60     public static final String JavaDoc BREAKPOINTS_VIEW_NAME = "BreakpointsView";
61     public static final String JavaDoc CALLSTACK_VIEW_NAME = "CallStackView";
62     public static final String JavaDoc LOCALS_VIEW_NAME = "LocalsView";
63     public static final String JavaDoc SESSIONS_VIEW_NAME = "SessionsView";
64     public static final String JavaDoc THREADS_VIEW_NAME = "ThreadsView";
65     public static final String JavaDoc WATCHES_VIEW_NAME = "WatchesView";
66
67     private static final int DBG_DEFAULT_PORT = 7869;
68     
69     private ContextProvider contextProvider;
70     private ServerSocket JavaDoc server = null;
71     private int port;
72     private DbgServerLoop dbgServerLoop;
73     private DbgServerHandler currentScriptContext;
74     private Boolean JavaDoc finished = Boolean.FALSE;
75     
76     /** Creates a new instance of DbgDebuggerImpl */
77     // XXX probably a ref back to the project/source file beeing debugged!
78
public DbgDebuggerImpl(ContextProvider contextProvider) {
79         this.contextProvider = contextProvider;
80     }
81     
82     public void start() {
83         createServerSocket();
84     
85        
86         if (dbgServerLoop == null) {
87             dbgServerLoop = new DbgServerLoop();
88         }
89         
90         RequestProcessor.getDefault().post(dbgServerLoop);
91     }
92
93     
94     public void stop() {
95         synchronized (finished) {
96             if (finished.booleanValue()) {
97                 return;
98             }
99             
100             finished = Boolean.TRUE;
101         }
102         
103         if (dbgServerLoop != null) {
104             dbgServerLoop.setStop();
105             dbgServerLoop.notifyWait();
106             
107             dbgServerLoop = null;
108         }
109         
110         ((DbgEngineProvider)contextProvider.lookupFirst(null, DebuggerEngineProvider.class)).getDestructor().killEngine();
111     }
112     
113     
114    public void closeServerSocket() throws IOException JavaDoc {
115         if (server != null) {
116             stop();
117             server = null;
118         }
119     }
120     
121     public int getPort() {
122         return port;
123     }
124
125     public void waitRunning() throws DebuggerStartException {
126         start();
127     }
128
129     public String JavaDoc getHost() {
130         // XXX For now
131
return "localhost";
132     }
133
134     public CallStackModel getCallStackModel() {
135         return (CallStackModel)contextProvider.lookupFirst(CALLSTACK_VIEW_NAME, TreeModel.class);
136     }
137
138     public ThreadsModel getThreadsModel() {
139         return (ThreadsModel)contextProvider.lookupFirst(THREADS_VIEW_NAME, TreeModel.class);
140     }
141     
142     public VariablesModel getVariablesModel() {
143         return (VariablesModel)contextProvider.lookupFirst(LOCALS_VIEW_NAME, TreeModel.class);
144     }
145
146     public WatchesModel getWatchesModel() {
147         return (WatchesModel)contextProvider.lookupFirst(WATCHES_VIEW_NAME, TreeModel.class);
148     }
149     
150     public BreakpointModel getBreakpointModel() {
151         Iterator JavaDoc it = DebuggerManager.getDebuggerManager().lookup(BREAKPOINTS_VIEW_NAME, TableModel.class).iterator();
152
153         while(it.hasNext()) {
154             TableModel model = (TableModel)it.next();
155             if (model instanceof BreakpointModel) {
156                 return (BreakpointModel) model;
157             }
158         }
159
160         return null;
161     }
162     
163     public VariableNode evaluateExpr(DebugFrame frame, String JavaDoc expr) {
164         Context c = getCurrentScriptContext();
165         
166         if (c == null) {
167             return null;
168         }
169         
170         return c.evaluateExpr(frame, expr);
171     }
172     
173     public DataObject getDataObject(String JavaDoc sourceFile) {
174         DbgSourceMap sourceMap = (DbgSourceMap)contextProvider.lookupFirst(null, DbgSourceMap.class);
175         
176         if (sourceMap == null) {
177             return null;
178         }
179         
180         return sourceMap.mapToSourceFileDataObject(sourceFile);
181     }
182     
183     ////////////////////////////////////////////////////////////////////////////
184
////////////////////////////// ActionProvider //////////////////////////////
185
////////////////////////////////////////////////////////////////////////////
186

187     public void setEnableContActions(boolean s) {
188         setEnabled(ActionsManager.ACTION_CONTINUE, s);
189         setEnabled(ActionsManager.ACTION_STEP_INTO, s);
190         setEnabled(ActionsManager.ACTION_STEP_OVER, s);
191         setEnabled(ActionsManager.ACTION_STEP_OUT, s);
192     }
193     
194     private static final Set JavaDoc<Object JavaDoc> ACTIONS = new HashSet JavaDoc<Object JavaDoc>();
195
196     static {
197         ACTIONS.add(ActionsManager.ACTION_KILL);
198         ACTIONS.add(ActionsManager.ACTION_CONTINUE);
199         ACTIONS.add(ActionsManager.ACTION_START);
200         ACTIONS.add(ActionsManager.ACTION_STEP_INTO);
201         ACTIONS.add(ActionsManager.ACTION_STEP_OVER);
202         ACTIONS.add(ActionsManager.ACTION_STEP_OUT);
203         // ACTIONS.add(ActionsManager.ACTION_RUN_TO_CURSOR);
204
}
205
206     public Set JavaDoc getActions() {
207         return ACTIONS;
208     }
209
210     public void doAction(Object JavaDoc action) {
211         System.err.println("mw DbgDebuggerImpl.doAction(" + action + ")");
212         if (action == ActionsManager.ACTION_KILL) {
213             stop();
214         }
215         else {
216             DbgDebuggerImpl.Context context = getCurrentScriptContext();
217
218             System.err.println("mw DbgDebuggerImpl.doAction() context= " + context);
219             
220             if(context == null) {
221                 return;
222             }
223
224             if (action == ActionsManager.ACTION_CONTINUE) {
225                 getVariablesModel().clearModel();
226                 getWatchesModel().setStackFrame(null);
227                 context.resume();
228             }
229             else if (action == ActionsManager.ACTION_STEP_INTO) {
230                 context.stepInto();
231             }
232             else if (action == ActionsManager.ACTION_STEP_OUT) {
233                 context.stepOut();
234             }
235             else if (action == ActionsManager.ACTION_STEP_OVER) {
236                 context.stepOver();
237             }
238             /*
239             else if (action == ActionsManager.ACTION_RUN_TO_CURSOR) {
240                 try {
241                     Node[] nodes = TopComponent.getRegistry().getActivatedNodes();
242
243                     if (null == nodes || nodes.length == 0) {
244                         return;
245                     }
246                     
247                     DataObject doCookie = (DataObject)nodes[0].getCookie(DataObject.class);
248                     String logicalPath = getApplicationPath(doCookie.getPrimaryFile());
249
250                     Step step = createStepToCursor(logicalPath);
251                     if(null != step) {
252                         context.setCurrentStep(step);
253                         context.resume();
254                     }
255                 } catch(Exception e) {
256                     Debug.debugNotify(e);
257                 }
258             }
259              */

260         }
261     }
262
263     public Context[] getScriptContexts() {
264         Set JavaDoc<DbgServerHandler> set = dbgServerLoop.getHandlerSet().keySet();
265         
266         return set.toArray(new Context[set.size()]);
267     }
268     
269     public void closeScriptContext(Context context) {
270         DbgServerHandler handler = (DbgServerHandler)context;
271         
272         handler.stop();
273         dbgServerLoop.getHandlerSet().remove(handler);
274         
275         
276         if (currentScriptContext == handler) {
277             DbgServerHandler replacement = null;
278             
279             if (!dbgServerLoop.getHandlerSet().isEmpty()) {
280                 replacement = (DbgServerHandler)dbgServerLoop.getHandlerSet().keySet().toArray()[0];
281                 setCurrentScriptContext(replacement);
282             }
283             else {
284                 stop();
285                 
286                 return;
287             }
288         }
289         else {
290             getThreadsModel().setNeedsRefresh();
291         }
292
293         // Update threads model immediately because the thread view should update
294
// visually even when application is runnning.
295
getThreadsModel().refresh(false);
296     }
297
298
299     public Context getCurrentScriptContext() {
300         return currentScriptContext;
301     }
302
303     public void setCurrentScriptContext(Context context) {
304         if(currentScriptContext == context) {
305             return;
306         }
307
308         if(currentScriptContext != null) {
309             currentScriptContext.hideCurrentLine();
310         }
311
312         currentScriptContext = (DbgServerHandler)context;
313
314         if(currentScriptContext != null) {
315             currentScriptContext.handleCurrentLine();
316             setEnabled(ActionsManager.ACTION_KILL, true);
317         }
318
319         getThreadsModel().setNeedsRefresh();
320         getCallStackModel().setNeedsRefresh();
321     }
322     
323     public DbgSourceMap getSourceMap() {
324         return (DbgSourceMap)contextProvider.lookupFirst(null, DbgSourceMap.class);
325     }
326     
327     public static abstract class Context {
328         private DbgDebuggerImpl server;
329         
330         protected Context(DbgDebuggerImpl impl) {
331             this.server = impl;
332         }
333         
334         public DbgDebuggerImpl getServer() {
335             return server;
336         }
337         
338         public abstract boolean isSuspended();
339         
340         public abstract List JavaDoc<DebugFrame> getCallStack();
341         
342         public abstract Variable getScopeVariables(DebugFrame frame);
343
344         public abstract void setVariableValue(DebugFrame frame, Variable v, Object JavaDoc value);
345         
346         public abstract Variable evaluateExpr(DebugFrame frame, String JavaDoc expr);
347         public abstract void resume();
348         
349         public abstract void stepInto();
350         
351         public abstract void stepOut();
352         
353         public abstract void stepOver();
354         
355         public boolean isCurrent() {
356             return server.getCurrentScriptContext() == this;
357         }
358     }
359     
360     private void createServerSocket() {
361         if (server == null) {
362             port = findFreePort();
363
364             if (port == -1) {
365                 ErrorManager.getDefault().
366                         log(ErrorManager.WARNING, "DbgServer.createServerSocket(): could not find free port!");
367             
368                 return;
369             }
370         
371             try {
372                 server = new ServerSocket JavaDoc(port);
373                 server.setSoTimeout(60000); // Just set this to a 1 minute timeout.
374
}
375             catch (IOException JavaDoc ioe) {
376                 ErrorManager.getDefault().
377                         log(ErrorManager.WARNING, "DbgServer.createServerSocket(): could not create server socket!");
378                 ErrorManager.getDefault().
379                         notify(ErrorManager.WARNING, ioe);
380             
381                 stop();
382             }
383         }
384     }
385     
386
387     private int findFreePort() {
388         for (int port = DBG_DEFAULT_PORT; port < DBG_DEFAULT_PORT + 100; port++) {
389             Socket JavaDoc testClient = null;
390             
391             try {
392                 testClient = new Socket JavaDoc("localhost", port); // NOI18N
393
}
394             catch (ConnectException JavaDoc ce) {
395                 return port;
396             }
397             catch (IOException JavaDoc ioe) {
398                 ioe.printStackTrace(System.err);
399                 // Something else went wrong, we don't care.
400
}
401             finally {
402                 if (testClient != null) {
403                     // something listenend on that socket. It's not useful for us.
404
try {
405                         testClient.close();
406                     }
407                     catch (IOException JavaDoc ioe) {
408                         // We don't care here.
409
}
410                 }
411             }
412         }
413
414         return -1;
415     }
416     
417     
418     private class DbgServerLoop implements Runnable JavaDoc {
419         private boolean stop;
420         private Map JavaDoc<DbgServerHandler, Boolean JavaDoc> handlerSet = new ConcurrentHashMap JavaDoc<DbgServerHandler, Boolean JavaDoc>();
421
422         public DbgServerLoop() {
423             stop = false;
424         }
425         
426         public Map JavaDoc<DbgServerHandler, Boolean JavaDoc> getHandlerSet() {
427             return handlerSet;
428         }
429         
430         public synchronized void setStop() {
431             stop = true;
432             
433             // If the server socket is blocked in the accept()!
434
try {
435                 server.close();
436             }
437             catch (IOException JavaDoc ioe) {
438                 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ioe);
439             }
440         }
441         
442         public synchronized void notifyWait() {
443             notify();
444         }
445         
446         public void run() {
447             try {
448                 // The Server main loop
449
while (!stop && !server.isClosed()) {
450                     Socket JavaDoc handlerSocket = null;
451                 
452                     try {
453                         handlerSocket = server.accept();
454                         System.err.println("DbgServerLoop.run().Accepted! : " + handlerSocket.toString());
455                     }
456                     catch (SocketTimeoutException JavaDoc ste) {
457                         // That's OK, we wake up periodically
458
}
459                     catch (SocketException JavaDoc se) {
460                         // That probably means we are about to be stopped.
461
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, se);
462                         
463                         return;
464                     }
465                     catch (IOException JavaDoc ioe) {
466                         ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ioe);
467
468                         return;
469                     }
470                     
471                     if (handlerSocket != null) {
472                         // XXX Needs some info about the project etc!
473
DbgServerHandler h = new DbgServerHandler(DbgDebuggerImpl.this, handlerSocket);
474                         
475                         handlerSet.put(h, Boolean.TRUE);
476                         RequestProcessor.getDefault().post(h);
477                         DbgDebuggerImpl.this.setCurrentScriptContext(h);
478                     }
479                 }
480             }
481             catch (Exception JavaDoc ex) {
482                 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
483             } finally {
484                 try {
485                     for (DbgServerHandler h : handlerSet.keySet()) {
486                         h.stop();
487                     }
488                     
489                     server.close();
490                 }
491                 catch (IOException JavaDoc ioe) {
492                     ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ioe);
493                     
494                     return;
495                 }
496                 
497                 //System.out.println("Socket loop finished.");
498
}
499         }
500     }
501 }
502
Popular Tags