org.chromium.debug.ui/src/org/chromium/debug/ui/launcher/LaunchTypeBase.java
changeset 2 e4420d2515f1
child 52 f577ea64429e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.chromium.debug.ui/src/org/chromium/debug/ui/launcher/LaunchTypeBase.java	Wed Dec 23 17:13:18 2009 -0800
@@ -0,0 +1,152 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.debug.ui.launcher;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.chromium.debug.core.model.ConnectionLoggerImpl;
+import org.chromium.debug.core.model.ConsolePseudoProcess;
+import org.chromium.debug.core.model.DebugTargetImpl;
+import org.chromium.debug.core.model.Destructable;
+import org.chromium.debug.core.model.DestructingGuard;
+import org.chromium.debug.core.model.JavascriptVmEmbedder;
+import org.chromium.debug.core.model.NamedConnectionLoggerFactory;
+import org.chromium.debug.ui.PluginUtil;
+import org.chromium.sdk.ConnectionLogger;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.model.ILaunchConfigurationDelegate;
+
+/**
+ * A launch configuration delegate for the JavaScript debugging.
+ */
+public abstract class LaunchTypeBase implements ILaunchConfigurationDelegate {
+
+  /** Launch configuration attribute (debug port). */
+  public static final String CHROMIUM_DEBUG_PORT = "debug_port"; //$NON-NLS-1$
+
+  public static final String ADD_NETWORK_CONSOLE = "add_network_console"; //$NON-NLS-1$
+
+  public void launch(ILaunchConfiguration config, String mode, final ILaunch launch,
+      IProgressMonitor monitor) throws CoreException {
+    if (!mode.equals(ILaunchManager.DEBUG_MODE)) {
+      // Chromium JavaScript launch is only supported for debugging.
+      return;
+    } 
+    
+    int port =
+        config.getAttribute(LaunchTypeBase.CHROMIUM_DEBUG_PORT,
+            PluginVariablesUtil.getValueAsInt(PluginVariablesUtil.DEFAULT_PORT));
+
+    boolean addNetworkConsole = config.getAttribute(LaunchTypeBase.ADD_NETWORK_CONSOLE, false);
+  
+    JavascriptVmEmbedder.ConnectionToRemote remoteServer =
+        createConnectionToRemote(port, launch, addNetworkConsole);
+    try {
+  
+      String projectNameBase = config.getName();
+  
+      DestructingGuard destructingGuard = new DestructingGuard();
+      try {
+        Destructable lauchDestructor = new Destructable() {
+          public void destruct() {
+            if (!launch.hasChildren()) {
+              DebugPlugin.getDefault().getLaunchManager().removeLaunch(launch);
+            }
+          }
+        };
+  
+        destructingGuard.addValue(lauchDestructor);
+  
+        final DebugTargetImpl target = new DebugTargetImpl(launch);
+  
+        Destructable targetDestructor = new Destructable() {
+          public void destruct() {
+            terminateTarget(target);
+          }
+        };
+        destructingGuard.addValue(targetDestructor);
+        boolean attached = target.attach(
+            projectNameBase, remoteServer, destructingGuard,
+            new Runnable() {
+              public void run() {
+                PluginUtil.openProjectExplorerView();
+              }
+            },
+            monitor);
+        if (!attached) {
+          // Error
+          return;
+        }
+  
+        launch.setSourceLocator(target.getSourceLocator());
+  
+        launch.addDebugTarget(target);
+        monitor.done();
+  
+        // All OK
+        destructingGuard.discharge();
+      } finally {
+        destructingGuard.doFinally();
+      }
+  
+    } finally {
+      remoteServer.disposeConnection();
+    }
+  }
+
+  protected abstract JavascriptVmEmbedder.ConnectionToRemote createConnectionToRemote(int port,
+      ILaunch launch, boolean addConsoleLogger) throws CoreException;
+
+  private static void terminateTarget(DebugTargetImpl target) {
+    target.setDisconnected(true);
+    target.fireTerminateEvent();
+  }
+
+  static ConnectionLogger createConsoleAndLogger(final ILaunch launch,
+      final boolean addLaunchToManager, final String title) {
+    final ConsolePseudoProcess.Retransmitter consoleRetransmitter =
+        new ConsolePseudoProcess.Retransmitter();
+
+    // This controller is responsible for creating ConsolePseudoProcess only on
+    // logStarted call. Before this ConnectionLoggerImpl with all it fields should stay
+    // garbage-collectible, because connection may not even start.
+    ConnectionLoggerImpl.LogLifecycleListener consoleController =
+        new ConnectionLoggerImpl.LogLifecycleListener() {
+      private final AtomicBoolean alreadyStarted = new AtomicBoolean(false);
+
+      public void logClosed() {
+        consoleRetransmitter.processClosed();
+      }
+
+      public void logStarted(ConnectionLoggerImpl connectionLogger) {
+        boolean res = alreadyStarted.compareAndSet(false, true);
+        if (!res) {
+          throw new IllegalStateException();
+        }
+        ConsolePseudoProcess consolePseudoProcess = new ConsolePseudoProcess(launch, title,
+            consoleRetransmitter, connectionLogger.getConnectionTerminate());
+        consoleRetransmitter.startFlushing();
+        if (addLaunchToManager) {
+          // Active the launch (again if it has already been removed)
+          DebugPlugin.getDefault().getLaunchManager().addLaunch(launch);
+       }
+      }
+    };
+
+    return new ConnectionLoggerImpl(consoleRetransmitter, consoleController);
+  }
+
+  static final NamedConnectionLoggerFactory NO_CONNECTION_LOGGER_FACTORY =
+      new NamedConnectionLoggerFactory() {
+    public ConnectionLogger createLogger(String title) {
+      return null;
+    }
+  };
+}
\ No newline at end of file