Bug 491174 - Last stack entry in Debug view missing

We have (at least) two jobs started during the proxy initialization:
AbstractModelProxy.initialize() and JavaDebugTargetProxy.installed().
Both of them must complete before we can send the "suspended" event,
otherwise the "installed" event sent by proxy could override the
"suspended" event, which should be logically the last one.

ThreadEventHandler waits now for proxy initialization jobs before
sending "suspended" event.

To fix bug 491174, a second change in jdt.debug is needed (the job in
JavaDebugTargetProxy must also properly implement belongsTo()).

Change-Id: Ie9a966a14f0f7235612c6c50cd2a9c70a09dac35
Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/provisional/AbstractModelProxy.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/provisional/AbstractModelProxy.java
index e70f23d..5160d45 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/provisional/AbstractModelProxy.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/provisional/AbstractModelProxy.java
@@ -160,12 +160,12 @@
                     return Status.OK_STATUS;
                 }
 
-                /*
-                 * (non-Javadoc)
-                 *
-                 * @see org.eclipse.core.runtime.jobs.Job#shouldRun()
-                 */
                 @Override
+				public boolean belongsTo(Object family) {
+					return AbstractModelProxy.this == family;
+				}
+
+				@Override
 				public boolean shouldRun() {
                     return !isDisposed();
                 }
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/update/ThreadEventHandler.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/update/ThreadEventHandler.java
index 7936998..9afed36 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/update/ThreadEventHandler.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/update/ThreadEventHandler.java
@@ -15,6 +15,7 @@
 import java.util.Map;
 import java.util.Set;
 
+import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.debug.core.DebugEvent;
 import org.eclipse.debug.core.DebugException;
 import org.eclipse.debug.core.DebugPlugin;
@@ -99,10 +100,32 @@
 				default:
 					break;
             }
+
+			// wait until initialization is completed before sending suspend
+			// event, see bug 491174 comment 1
+			waitForProxyInitialization();
+
         	fireDeltaUpdatingSelectedFrame(thread, IModelDelta.NO_CHANGE | extras, event);
         }
 	}
 
+	private void waitForProxyInitialization() {
+		AbstractModelProxy modelProxy = getModelProxy();
+		if (modelProxy == null) {
+			return;
+		}
+		Job[] proxyInitJobs = Job.getJobManager().find(modelProxy);
+		while (proxyInitJobs.length > 0) {
+			try {
+				Thread.sleep(10);
+			} catch (InterruptedException e) {
+				// cancel waiting, something bad is happened
+				break;
+			}
+			proxyInitJobs = Job.getJobManager().find(modelProxy);
+		}
+	}
+
 	private boolean isEqual(Object o1, Object o2) {
 		if (o1 == o2) {
 			return true;