Package org.nodeclipse.debug.launch

Source Code of org.nodeclipse.debug.launch.LaunchConfigurationDelegate

package org.nodeclipse.debug.launch;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.chromium.debug.core.ChromiumDebugPlugin;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugException;
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;
import org.eclipse.debug.core.model.RuntimeProcess;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.nodeclipse.debug.util.Constants;
import org.nodeclipse.debug.util.NodeDebugUtil;
import org.nodeclipse.debug.util.VariablesUtil;
import org.nodeclipse.ui.Activator;
import org.nodeclipse.ui.preferences.Dialogs;
import org.nodeclipse.ui.preferences.PreferenceConstants;
import org.nodeclipse.ui.util.NodeclipseConsole;

/**
* launch() implements starting Node and passing all parameters.
* Node is launched as node, coffee, coffee -c, tsc or node-dev(or other monitors)
*
* @author Lamb, Tomoyuki, Pushkar, Paul Verest
*/
public class LaunchConfigurationDelegate implements
    ILaunchConfigurationDelegate {
  private static RuntimeProcess nodeProcess = null; //since 0.7 it should be debuggable instance
  //@since 0.7. contain all running Node thread, including under debug. Non Thread-safe, as it should be only in GUI thread
  //private static List<RuntimeProcess> nodeRunningProcesses = new LinkedList<RuntimeProcess>();
 
  private boolean warned = false;
 
  /*
   * (non-Javadoc)
   *
   * @see
   * org.eclipse.debug.core.model.ILaunchConfigurationDelegate#launch(org.
   * eclipse.debug.core.ILaunchConfiguration, java.lang.String,
   * org.eclipse.debug.core.ILaunch,
   * org.eclipse.core.runtime.IProgressMonitor)
   */
  @Override
  public void launch(ILaunchConfiguration configuration, String mode,
      ILaunch launch, IProgressMonitor monitor) throws CoreException {
   
    IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore();
    boolean allowedMany = preferenceStore.getBoolean(PreferenceConstants.NODE_ALLOW_MANY);//@since 0.7
    boolean isDebugMode = mode.equals(ILaunchManager.DEBUG_MODE);

    if (allowedMany){//@since 0.7
      if ( isDebugMode 
        && (nodeProcess != null && !nodeProcess.isTerminated()) ) {
        showErrorDialog("Only 1 node process can be debugged in 1 Eclipse instance!\n\n"+
        "Open other Eclipse/Enide Studio with different node debug port configurred. ");
        return;
      }
   
    }else
      if(nodeProcess != null && !nodeProcess.isTerminated()) {
        //throw new CoreException(new Status(IStatus.OK, ChromiumDebugPlugin.PLUGIN_ID, null, null));
        showErrorDialog("Other node process is running!");
        return;
        //TODO suggest to terminate and start new
     
    }

    
    // Using configuration to build command line 
    List<String> cmdLine = new ArrayList<String>();

    if (preferenceStore.getBoolean(PreferenceConstants.NODE_JUST_NODE)){
      cmdLine.add("node");
    }else{
      // old way: Application path should be stored in preference.
      String nodePath= preferenceStore.getString(PreferenceConstants.NODE_PATH);
      // Check if the node location is correctly configured
      File nodeFile = new File(nodePath);
      if(!nodeFile.exists()){
        // If the location is not valid than show a dialog which prompts the user to goto the preferences page
        Dialogs.showPreferencesDialog("Node.js runtime is not correctly configured.\n\n"
            + "Please goto Window -> Prefrences -> Nodeclipse and configure the correct location");
        return;
      }     
      cmdLine.add(nodePath);
    }
   
    if (isDebugMode) {
      // -brk says to Node runtime wait until Chromium Debugger starts and connects
      // that is causing "stop on first line" behavior,
      // otherwise small apps or first line can be undebuggable.
      String brk = "-brk" ; //default "-brk"
      if (preferenceStore.getBoolean(PreferenceConstants.NODE_DEBUG_NO_BREAK)) //default false
        brk = "";
      // done: flexible debugging port, instead of hard-coded 5858
      // #61 https://github.com/Nodeclipse/nodeclipse-1/issues/61
      int nodeDebugPort = preferenceStore.getInt(PreferenceConstants.NODE_DEBUG_PORT);
      if (nodeDebugPort==0) { nodeDebugPort=5858;};
      cmdLine.add("--debug"+brk+"="+nodeDebugPort); //--debug-brk=5858
    }
   
    //@since 0.9 from Preferences
    String nodeOptions= preferenceStore.getString(PreferenceConstants.NODE_OPTIONS);
    if(!nodeOptions.equals("")) {
      String[] sa = nodeOptions.split(" ");
      for(String s : sa) {
        cmdLine.add(s);
      }     
    }
   
    String nodeArgs = configuration.getAttribute(Constants.ATTR_NODE_ARGUMENTS, "");
    if(!nodeArgs.equals("")) {
      String[] sa = nodeArgs.split(" ");
      for(String s : sa) {
        cmdLine.add(s);
      }
    }
   
    String file = configuration.getAttribute(Constants.KEY_FILE_PATH,  Constants.BLANK_STRING);
    String extension = null;
    int i = file.lastIndexOf('.');
    if(i > 0) {
      extension = file.substring(i+1);
    } else {
      //      throw new CoreException(new Status(IStatus.OK, ChromiumDebugPlugin.PLUGIN_ID,
      //        "Target file does not have extension: " + file, null));
      // by default assume
      extension = "js";
    }
   
    // #57 running app.js with node-dev, forever, supervisor, nodemon etc
    // https://github.com/Nodeclipse/nodeclipse-1/issues/57
    String nodeMonitor = configuration.getAttribute(Constants.ATTR_NODE_MONITOR, "");
    if(!nodeMonitor.equals("")) { // any value
      //TODO support selection, now only one
     
      String nodeMonitorPath= preferenceStore.getString(PreferenceConstants.NODE_MONITOR_PATH);
     
      // Check if the node monitor location is correctly configured
      File nodeMonitorFile = new File(nodeMonitorPath);
      if(!nodeMonitorFile.exists()){
        // If the location is not valid than show a dialog which prompts the user to goto the preferences page
        Dialogs.showPreferencesDialog("Node.js monitor is not correctly configured.\n"
            + "Select path to installed util: forever, node-dev, nodemon or superviser.\n\n"
            + "Please goto Window -> Prefrences -> Nodeclipse and configure the correct location");
        return;
      }
      cmdLine.add(nodeMonitorPath);
    } else if ( ("coffee".equals(extension))||("litcoffee".equals(extension))||("md".equals(extension)) ) {
      //if (preferenceStore.getBoolean(PreferenceConstants.COFFEE_JUST_COFFEE)){
      //  cmdLine.add("coffee"); //TODO should be instead of node above
      //}else{
        cmdLine.add(preferenceStore.getString(PreferenceConstants.COFFEE_PATH));
      //}
      // coffee -c
      String coffeeCompile = configuration.getAttribute(Constants.ATTR_COFFEE_COMPILE, "");
      if(!coffeeCompile.equals("")) { // any value
        cmdLine.add("-c");
        String coffeeCompileOptions = preferenceStore.getString(PreferenceConstants.COFFEE_COMPILE_OPTIONS);
        if(!coffeeCompileOptions.equals("")) {
          cmdLine.add(coffeeCompileOptions);
        }
      }
    } else if ("ts".equals(extension)) {
      // the only thing we can do now with .ts is to compile, so no need to check if it was launched as tsc
      //String typescriptCompiler = configuration.getAttribute(Constants.ATTR_TYPESCRIPT_COMPILER, "");
      cmdLine.add(preferenceStore.getString(PreferenceConstants.TYPESCRIPT_COMPILER_PATH));
    }
   
    String filePath = ResourcesPlugin.getWorkspace().getRoot().findMember(file).getLocation().toOSString();
    // path is relative, so can not found it.
    cmdLine.add(filePath);

    //@since 0.9 from Preferences
    String nodeApplicationArguments = preferenceStore.getString(PreferenceConstants.NODE_APPLICATION_ARGUMENTS);
    if(!nodeApplicationArguments.equals("")) {
      String[] sa = nodeApplicationArguments.split(" ");
      for(String s : sa) {
        cmdLine.add(s);
      }
    }
   
    String programArgs = configuration.getAttribute(Constants.ATTR_PROGRAM_ARGUMENTS, "");
    if(!programArgs.equals("")) {
      String[] sa = programArgs.split(" ");
      for(String s : sa) {
        cmdLine.add(s);
      }
    }

    //TODO rename workingPath to workingDirectory, workingDirectory to workingDirectoryConfig
    //DONE propagate changes to .phantom,.mongo ...
    File workingPath = null;
    String workingDirectory = configuration.getAttribute(Constants.ATTR_WORKING_DIRECTORY, "");
    if(workingDirectory.length() > 0) {
      workingDirectory = VariablesUtil.resolveValue(workingDirectory);
      if(workingDirectory != null) {
        workingPath = new File(workingDirectory);
      }
    }
    if (workingPath == null){
      workingPath = (new File(filePath)).getParentFile();
    }
   
    //env
    String[] envp = getEnvironmentVariables(configuration);
   
    for(String s : cmdLine) NodeclipseConsole.write(s+" ");
    NodeclipseConsole.write("\n");
   
    String[] cmds = {};
    cmds = cmdLine.toArray(cmds);
    // Launch a process to run/debug. See also #71 (output is less or no output)
    Process p = DebugPlugin.exec(cmds, workingPath, envp);
    // no way to get private p.handle from java.lang.ProcessImpl
    RuntimeProcess process = (RuntimeProcess)DebugPlugin.newProcess(launch, p, Constants.PROCESS_MESSAGE);
    if (isDebugMode) {
      if(!process.isTerminated()) {
        int nodeDebugPort = preferenceStore.getInt(PreferenceConstants.NODE_DEBUG_PORT);
        NodeDebugUtil.launch(mode, launch, monitor, nodeDebugPort);
      }
    }
   
    if (allowedMany){ //@since 0.7
      if (isDebugMode){
        nodeProcess = process; 
      }
      //nodeRunningProcesses.add(process);
    }else{
      nodeProcess = process; 
    }
  }
 
  private String[] getEnvironmentVariables(ILaunchConfiguration configuration) throws CoreException {
    Map<String, String> envm = new HashMap<String, String>();
    envm = configuration.getAttribute(Constants.ATTR_ENVIRONMENT_VARIABLES, envm);
   
    int envmSizeDelta = 4;
    Map<String,String> all = null;
    IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore();
    boolean passAllEnvVars = preferenceStore.getBoolean(PreferenceConstants.NODE_PASS_ALL_ENVIRONMENT_VARIABLES);//@since 0.12
    if (passAllEnvVars){
      all = System.getenv();
      envmSizeDelta = all.size();
    }
   
    String[] envp = new String[envm.size()+envmSizeDelta]; // see below
    int idx = 0;
    for(String key : envm.keySet()) {
      String value = envm.get(key);
      envp[idx++] = key + "=" + value;
    }
   
    if (passAllEnvVars){
      for (Map.Entry<String, String> entry : all.entrySet())
      {
          //System.out.println(entry.getKey() + "/" + entry.getValue());
          envp[idx++] = entry.getKey() + "=" + entry.getValue();
      }
    }else{
      //+ #81
      envp[idx++] = getEnvVariableEqualsString("PATH");
      envp[idx++] = getEnvVariableEqualsString("TEMP");
      envp[idx++] = getEnvVariableEqualsString("TMP");
      envp[idx++] = getEnvVariableEqualsString("SystemDrive");
    }
    if (!warned ){
      NodeclipseConsole.write("  These environment variables will be applied automatically to every `node` launch.\n");
      StringBuilder sb = new StringBuilder(100);
      for(int i=0; i<envp.length; i++){
        sb.append("  ").append(envp[i]).append('\n')
      }
      NodeclipseConsole.write(sb.toString());
      warned = true;
    }
    return envp;
  }

  protected String getEnvVariableEqualsString(String envvarName){
    String envvarValue = System.getenv(envvarName);
    if (envvarValue==null) envvarValue = "";
    return envvarName + "=" + envvarValue;   
  }
 
  private void showErrorDialog(final String message) {
    Display.getDefault().syncExec(new Runnable() {
      public void run() {
        Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();

        MessageDialog dialog = new MessageDialog(shell, "Nodeclipse", null, message,
            MessageDialog.ERROR, new String[] { "OK" }, 0);
        dialog.open();
      }
    });
  }
 
  public static void terminateNodeProcess() {
    if(nodeProcess != null) {
      try {
        nodeProcess.terminate();
      } catch (DebugException e) {
        //e.printStackTrace();
        NodeclipseConsole.write(e.getLocalizedMessage()+"\n");
      }
      nodeProcess = null;
    }
  }
}
TOP

Related Classes of org.nodeclipse.debug.launch.LaunchConfigurationDelegate

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.