Waiting for debugger.
authorTomas Zezula <tzezula@netbeans.org>
Thu, 30 Jan 2014 19:08:30 +0100
changeset 181425611fb53aab4
parent 18140 1e1a5bccbb84
child 18143 c51357ce5b6f
Waiting for debugger.
dew4nb/src/org/netbeans/modules/dew4nb/services/debugger/ActiveSessions.java
dew4nb/src/org/netbeans/modules/dew4nb/services/debugger/AttachHandler.java
     1.1 --- a/dew4nb/src/org/netbeans/modules/dew4nb/services/debugger/ActiveSessions.java	Thu Jan 30 16:50:49 2014 +0100
     1.2 +++ b/dew4nb/src/org/netbeans/modules/dew4nb/services/debugger/ActiveSessions.java	Thu Jan 30 19:08:30 2014 +0100
     1.3 @@ -50,15 +50,22 @@
     1.4  import java.util.List;
     1.5  import java.util.concurrent.ConcurrentHashMap;
     1.6  import java.util.concurrent.ConcurrentMap;
     1.7 +import java.util.concurrent.TimeUnit;
     1.8  import java.util.concurrent.atomic.AtomicInteger;
     1.9 +import java.util.concurrent.locks.Condition;
    1.10 +import java.util.concurrent.locks.Lock;
    1.11 +import java.util.concurrent.locks.ReentrantLock;
    1.12  import java.util.logging.Level;
    1.13  import java.util.logging.Logger;
    1.14  import org.netbeans.api.annotations.common.CheckForNull;
    1.15  import org.netbeans.api.annotations.common.NonNull;
    1.16  import org.netbeans.api.annotations.common.NullAllowed;
    1.17  import org.netbeans.api.debugger.DebuggerManager;
    1.18 +import org.netbeans.api.debugger.DebuggerManagerAdapter;
    1.19 +import org.netbeans.api.debugger.DebuggerManagerListener;
    1.20  import org.netbeans.api.debugger.Session;
    1.21  import org.netbeans.api.debugger.jpda.CallStackFrame;
    1.22 +import org.netbeans.api.debugger.jpda.DebuggerStartException;
    1.23  import org.netbeans.api.debugger.jpda.JPDADebugger;
    1.24  import org.netbeans.api.debugger.jpda.JPDAThread;
    1.25  import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl;
    1.26 @@ -69,6 +76,7 @@
    1.27  import org.openide.filesystems.FileObject;
    1.28  import org.openide.filesystems.FileUtil;
    1.29  import org.openide.filesystems.URLMapper;
    1.30 +import org.openide.util.Exceptions;
    1.31  import org.openide.util.Lookup;
    1.32  import org.openide.util.Parameters;
    1.33  
    1.34 @@ -98,18 +106,22 @@
    1.35          Parameters.notNull("context", context); //NOI18N
    1.36          Parameters.notNull("env", env); //NOI18N
    1.37          final int id = sequencer.incrementAndGet();
    1.38 -        for (int i = 0; i < 10; i++) {
    1.39 -            final Session session = DebuggerManager.getDebuggerManager().getCurrentSession();
    1.40 -            if (session != null) {
    1.41 -                if (active.putIfAbsent(id, new Data(id, context, env, session)) != null) {
    1.42 -                    throw new IllegalStateException("Trying to reuse active session");  //NOI18N
    1.43 -                }
    1.44 -                return id;
    1.45 +        final Session session = findSession();
    1.46 +        if (session != null) {
    1.47 +            if (active.putIfAbsent(id, new Data(id, context, env, session)) != null) {
    1.48 +                throw new IllegalStateException("Trying to reuse active session");  //NOI18N
    1.49 +            }
    1.50 +            final JPDADebugger jpda = session.lookupFirst(null, JPDADebugger.class);
    1.51 +            if (!(jpda instanceof JPDADebuggerImpl)) {
    1.52 +                throw new IllegalStateException("Wrong debugger service.");    //NOI18N
    1.53              }
    1.54              try {
    1.55 -                Thread.sleep(2000);
    1.56 -            } catch (InterruptedException ex) {}
    1.57 -        }
    1.58 +                jpda.waitRunning();
    1.59 +            } catch (DebuggerStartException ex) {
    1.60 +                return -1;
    1.61 +            }
    1.62 +            return id;
    1.63 +        }            
    1.64          return -1;
    1.65      }
    1.66  
    1.67 @@ -140,6 +152,24 @@
    1.68          return instance;
    1.69      }
    1.70  
    1.71 +    /**
    1.72 +     * Finds debuggers session.
    1.73 +     * Todo: debugger API does not pair sessions with projects,
    1.74 +     * no way to find out correct session.
    1.75 +     * @return
    1.76 +     */
    1.77 +    @CheckForNull
    1.78 +    private Session findSession () {
    1.79 +        final DebuggerManager dm = DebuggerManager.getDebuggerManager();
    1.80 +        final DML dml = new DML(dm);
    1.81 +        dm.addDebuggerListener(dml);
    1.82 +        try {
    1.83 +            return dml.getCurrentSession();
    1.84 +        }finally {
    1.85 +            dm.removeDebuggerListener(dml);
    1.86 +        }
    1.87 +    }
    1.88 +
    1.89      private static final class Data implements PropertyChangeListener {
    1.90          final int id;
    1.91          final WorkspaceResolver.Context ctx;
    1.92 @@ -273,4 +303,52 @@
    1.93          }
    1.94      }
    1.95  
    1.96 +    private static final class DML extends DebuggerManagerAdapter {
    1.97 +
    1.98 +        private final DebuggerManager dm;
    1.99 +        private final Lock lock;
   1.100 +        private final Condition cond;
   1.101 +        //GuardedBy("lock")
   1.102 +        private Session session;
   1.103 +
   1.104 +        DML(@NonNull final DebuggerManager dm) {
   1.105 +            Parameters.notNull("dm", dm);   //NOI18N
   1.106 +            this.dm = dm;
   1.107 +            this.lock = new ReentrantLock();
   1.108 +            this.cond = lock.newCondition();
   1.109 +        }
   1.110 +
   1.111 +        @Override
   1.112 +        public void sessionAdded(@NonNull Session session) {
   1.113 +            lock.lock();
   1.114 +            try {
   1.115 +                this.session = session;
   1.116 +                cond.signalAll();
   1.117 +            } finally {
   1.118 +                lock.unlock();
   1.119 +            }
   1.120 +        }
   1.121 +
   1.122 +        Session getCurrentSession() {
   1.123 +            Session res = dm.getCurrentSession();
   1.124 +            if (res != null) {
   1.125 +                return res;
   1.126 +            }
   1.127 +            lock.lock();
   1.128 +            try {
   1.129 +                while (this.session == null) {
   1.130 +                    try {
   1.131 +                        if (!cond.await(20, TimeUnit.SECONDS)) {
   1.132 +                            break;
   1.133 +                        }
   1.134 +                    } catch (InterruptedException e) {
   1.135 +                        return null;
   1.136 +                    }
   1.137 +                }
   1.138 +                return this.session;
   1.139 +            } finally {
   1.140 +                lock.unlock();
   1.141 +            }
   1.142 +        }
   1.143 +    }
   1.144  }
   1.145 \ No newline at end of file
     2.1 --- a/dew4nb/src/org/netbeans/modules/dew4nb/services/debugger/AttachHandler.java	Thu Jan 30 16:50:49 2014 +0100
     2.2 +++ b/dew4nb/src/org/netbeans/modules/dew4nb/services/debugger/AttachHandler.java	Thu Jan 30 19:08:30 2014 +0100
     2.3 @@ -42,6 +42,7 @@
     2.4  
     2.5  package org.netbeans.modules.dew4nb.services.debugger;
     2.6  
     2.7 +import java.util.concurrent.Executor;
     2.8  import org.netbeans.api.annotations.common.NonNull;
     2.9  import org.netbeans.modules.dew4nb.endpoint.AsyncRequestHandler;
    2.10  import org.netbeans.modules.dew4nb.endpoint.EndPoint;
    2.11 @@ -49,6 +50,7 @@
    2.12  import org.netbeans.modules.dew4nb.endpoint.Status;
    2.13  import org.netbeans.modules.dew4nb.spi.WorkspaceResolver;
    2.14  import org.openide.filesystems.FileObject;
    2.15 +import org.openide.util.RequestProcessor;
    2.16  import org.openide.util.lookup.ServiceProvider;
    2.17  
    2.18  /**
    2.19 @@ -58,6 +60,7 @@
    2.20  @ServiceProvider(service = RequestHandler.class)
    2.21  public class AttachHandler extends AsyncRequestHandler<DebugAction, DebugMessageType> {
    2.22  
    2.23 +    private static final Executor WORKER = new RequestProcessor(AttachHandler.class);
    2.24  
    2.25      public AttachHandler() {
    2.26          super(DebugerModels.END_POINT, DebugMessageType.attach, DebugAction.class);
    2.27 @@ -87,21 +90,25 @@
    2.28             ctx.getWorkspace(),
    2.29             ""   //NOI18N
    2.30          );
    2.31 -        Status status = Status.not_found;
    2.32 -        int id = -1;
    2.33 +        Status status = Status.not_found;        
    2.34          final FileObject workspace = resolver.resolveFile(serverCtx);                
    2.35          if (workspace != null) {
    2.36 -            id = ActiveSessions.getInstance().createSession(serverCtx, env);
    2.37 +            status = Status.accepted;
    2.38 +            WORKER.execute(new Runnable() {
    2.39 +                @Override
    2.40 +                public void run() {
    2.41 +                    int id = ActiveSessions.getInstance().createSession(serverCtx, env);
    2.42 +                    final AttachResult attachResult = new AttachResult();
    2.43 +                    attachResult.setId(id);
    2.44 +                    attachResult.setType(type);
    2.45 +                    attachResult.setState(state);
    2.46 +                    attachResult.setStatus(id < 0 ?
    2.47 +                        Status.not_found :
    2.48 +                        Status.done);
    2.49 +                    env.sendObject(attachResult);
    2.50 +                }
    2.51 +            });
    2.52          }
    2.53 -        if (id >= 0) {
    2.54 -            status = Status.done;
    2.55 -        }
    2.56 -        final AttachResult attachResult = new AttachResult();
    2.57 -        attachResult.setId(id);
    2.58 -        attachResult.setType(type);
    2.59 -        attachResult.setState(state);
    2.60 -        attachResult.setStatus(status);
    2.61 -        env.sendObject(attachResult);
    2.62 -        return Status.accepted;
    2.63 +        return status;
    2.64      }
    2.65  }