PageRenderTime 25ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/php.dbgp/src/org/netbeans/modules/php/dbgp/DebugSession.java

https://github.com/mark-moseley/Netbeans
Java | 339 lines | 228 code | 43 blank | 68 comment | 24 complexity | 48cb5e83356eb8379f3340c467387f15 MD5 | raw file
Possible License(s): 0BSD
  1. /*
  2. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  3. *
  4. * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
  5. *
  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]"
  23. *
  24. * Contributor(s):
  25. *
  26. * The Original Software is NetBeans. The Initial Developer of the Original
  27. * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  28. * Microsystems, Inc. All Rights Reserved.
  29. *
  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.
  40. */
  41. package org.netbeans.modules.php.dbgp;
  42. import java.io.IOException;
  43. import java.net.Socket;
  44. import java.util.ArrayList;
  45. import java.util.LinkedList;
  46. import java.util.List;
  47. import java.util.concurrent.atomic.AtomicBoolean;
  48. import java.util.concurrent.atomic.AtomicInteger;
  49. import java.util.concurrent.atomic.AtomicReference;
  50. import java.util.logging.Level;
  51. import java.util.logging.Logger;
  52. import org.netbeans.api.debugger.DebuggerEngine;
  53. import org.netbeans.api.debugger.DebuggerManager;
  54. import org.netbeans.api.debugger.Session;
  55. import org.netbeans.modules.php.dbgp.api.SessionId;
  56. import org.netbeans.modules.php.dbgp.models.AbstractIDEBridge;
  57. import org.netbeans.modules.php.dbgp.packets.DbgpCommand;
  58. import org.netbeans.modules.php.dbgp.packets.DbgpMessage;
  59. import org.netbeans.modules.php.dbgp.packets.DbgpResponse;
  60. import org.netbeans.modules.php.dbgp.packets.InitMessage;
  61. /**
  62. * @author ads
  63. *
  64. */
  65. public class DebugSession implements Runnable {
  66. private static final int SLEEP_TIME = 100;
  67. DebugSession( Socket socket ){
  68. mySocket = socket;
  69. isStop = new AtomicBoolean( false );
  70. myCommands = new LinkedList<DbgpCommand>();
  71. mySessionId = new AtomicReference<SessionId>();
  72. myBridge = new IDESessionBridge();
  73. myFileName = new AtomicReference<String>();
  74. myEngine = new AtomicReference<DebuggerEngine>();
  75. }
  76. /* (non-Javadoc)
  77. * @see java.lang.Runnable#run()
  78. */
  79. public void run() {
  80. setSessionThread( Thread.currentThread() );
  81. boolean moreCommands = false;
  82. synchronized ( myCommands ){
  83. moreCommands = myCommands.size() > 0;
  84. }
  85. while( !isStop.get() || moreCommands ){
  86. try {
  87. sendCommands();
  88. receiveData();
  89. sleepTillNewCommand();
  90. }
  91. catch ( IOException e ){
  92. log( e );
  93. }
  94. }
  95. setSessionThread( null );
  96. try {
  97. getSocket().close();
  98. }
  99. catch (IOException e) {
  100. log( e);
  101. }
  102. }
  103. public void sendCommandLater( DbgpCommand command ){
  104. synchronized ( this ) {
  105. /*
  106. * Do not collect command before session is not initialized.
  107. * So any command before Init message will not be sent.
  108. * ( F.e. commands for getting watch values will be just ignored
  109. * if they was requested before Init message ).
  110. */
  111. if ( getSessionId() == null ){
  112. return;
  113. }
  114. if ( getSessionThread() == null ){
  115. return;
  116. }
  117. addCommand(command);
  118. getSessionThread().interrupt();
  119. }
  120. }
  121. public DbgpResponse sendSynchronCommand( DbgpCommand command ) {
  122. if ( getSessionThread() != Thread.currentThread() ) {
  123. throw new IllegalStateException("Method incorrect usage. " +
  124. "It should be called in handler thread only"); // NOI18N
  125. }
  126. try {
  127. command.send( getSocket().getOutputStream() );
  128. if ( command.wantAcknowledgment() ) {
  129. DbgpMessage message = receiveData( command );
  130. if ( message instanceof DbgpResponse ) {
  131. return (DbgpResponse) message;
  132. }
  133. }
  134. }
  135. catch (IOException e) {
  136. log(e);
  137. }
  138. return null;
  139. }
  140. public String getTransactionId() {
  141. return myTransactionId.getAndIncrement() +"";
  142. }
  143. public void setStop() {
  144. isStop.set( true );
  145. getBridge().setSuspended( false );
  146. getBridge().hideAnnotations();
  147. StartActionProviderImpl.getInstance().removeSession( this );
  148. getBridge().getBreakpointModel().setCurrentStack( null , this);
  149. getBridge().getCallStackModel().clearModel();
  150. getBridge().getThreadsModel().update();
  151. getBridge().getVariablesModel().clearModel();
  152. getBridge().getWatchesModel().clearModel();
  153. }
  154. public void setId( InitMessage message ) {
  155. setSessionFile( message.getFileUri() );
  156. String sessionId = message.getSessionId();
  157. DebuggerEngine[] engines =
  158. DebuggerManager.getDebuggerManager().getDebuggerEngines();
  159. for (DebuggerEngine engine : engines) {
  160. SessionId id = (SessionId)engine.lookupFirst( null , SessionId.class );
  161. if ( id.getId().equals( sessionId ) ) {
  162. mySessionId.set( id );
  163. id.setFileUri( message.getFileUri() );
  164. myEngine.set(engine);
  165. }
  166. }
  167. Session[] sessions = DebuggerManager.getDebuggerManager().getSessions();
  168. for (Session session : sessions) {
  169. SessionId id = (SessionId)session.lookupFirst( null , SessionId.class );
  170. if ( id.getId().equals( sessionId ) ) {
  171. StartActionProviderImpl.getInstance().attachDebugSession( session ,
  172. this );
  173. }
  174. }
  175. }
  176. public SessionId getSessionId() {
  177. return mySessionId.get();
  178. }
  179. public IDESessionBridge getBridge() {
  180. return myBridge;
  181. }
  182. public String getFileName() {
  183. return myFileName.get();
  184. }
  185. private void setSessionFile( String fileName ) {
  186. myFileName.set( fileName );
  187. }
  188. private void sleepTillNewCommand() {
  189. try {
  190. // Wake up every 100 milliseconds and see if the debuggee has something to say.
  191. // The IDE side can interrupt the sleep to send new packets to the
  192. // debugger.
  193. Thread.sleep(SLEEP_TIME);
  194. }
  195. catch (InterruptedException ie) {
  196. // OK, run the look again.
  197. }
  198. }
  199. private synchronized void setSessionThread( Thread thread ){
  200. mySessionThread = thread;
  201. }
  202. private void sendCommands() throws IOException {
  203. List<DbgpCommand> list;
  204. synchronized ( myCommands ) {
  205. list = new ArrayList<DbgpCommand>( myCommands );
  206. myCommands.clear();
  207. }
  208. for (DbgpCommand command : list) {
  209. command.send( getSocket().getOutputStream() );
  210. if ( command.wantAcknowledgment() ) {
  211. receiveData( command );
  212. }
  213. }
  214. }
  215. private void addCommand( DbgpCommand command ){
  216. synchronized ( myCommands ) {
  217. myCommands.add( command );
  218. }
  219. }
  220. private Thread getSessionThread(){
  221. return mySessionThread;
  222. }
  223. private void receiveData() throws IOException{
  224. receiveData( null );
  225. }
  226. private DbgpMessage receiveData( DbgpCommand command ) throws IOException{
  227. if ( command!= null || getSocket().getInputStream().available() > 0) {
  228. DbgpMessage message = DbgpMessage.create(
  229. getSocket().getInputStream() );
  230. handleMessage(command, message);
  231. return message;
  232. }
  233. return null;
  234. }
  235. private void handleMessage( DbgpCommand command, DbgpMessage message )
  236. throws IOException
  237. {
  238. if ( message == null ) {
  239. return;
  240. }
  241. if ( command == null ) {
  242. // this is case when we don't need achnowl-t
  243. message.process(this, null );
  244. return;
  245. }
  246. boolean awaited = false;
  247. if ( message instanceof DbgpResponse ) {
  248. DbgpResponse response = (DbgpResponse) message;
  249. String id = response.getTransactionId();
  250. if ( id.equals( command.getTransactionId())) {
  251. awaited = true;
  252. message.process(this, command);
  253. }
  254. }
  255. if ( !awaited ) {
  256. message.process(this, null );
  257. receiveData( command );
  258. }
  259. }
  260. private Socket getSocket(){
  261. return mySocket;
  262. }
  263. private void log( IOException e ) {
  264. Logger.getLogger( DebugSession.class.getName() ).log(
  265. Level.SEVERE, null, e );
  266. }
  267. /*
  268. * This class is associated with DebugSession but is intended for
  269. * cooperation with IDE UI.
  270. */
  271. public class IDESessionBridge extends AbstractIDEBridge {
  272. /* (non-Javadoc)
  273. * @see org.netbeans.modules.php.dbgp.models.AbstractIDEBridge#getEngine()
  274. */
  275. @Override
  276. protected DebuggerEngine getEngine()
  277. {
  278. return myEngine.get();
  279. }
  280. /* (non-Javadoc)
  281. * @see org.netbeans.modules.php.dbgp.models.AbstractIDEBridge#getDebugSession()
  282. */
  283. protected DebugSession getDebugSession(){
  284. return DebugSession.this;
  285. }
  286. }
  287. private Socket mySocket;
  288. private AtomicBoolean isStop;
  289. private Thread mySessionThread;
  290. private List<DbgpCommand> myCommands;
  291. private AtomicReference<SessionId> mySessionId;
  292. private AtomicReference<DebuggerEngine> myEngine;
  293. private static final AtomicInteger myTransactionId = new AtomicInteger( 0 );
  294. private final IDESessionBridge myBridge;
  295. private AtomicReference<String> myFileName;
  296. }