@SuppressWarnings("unchecked")
  public void launch(
      ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor)
      throws CoreException {

    try {

      GrailsVersion version = GrailsLaunchArgumentUtils.getGrailsVersion(configuration);
      IProgressMonitor subMonitor = new SubProgressMonitor(monitor, 5);
      checkCancelled(subMonitor);
      subMonitor.beginTask("Starting Grails", 5);
      subMonitor.worked(1);
      checkCancelled(subMonitor);
      subMonitor.subTask("Configuring launch parameters...");

      // FIXKDV FIXADE Copies of this code exist in
      // GrailsLaunchArgumentUtils.prepareClasspath()
      // and GrailsLaunchConfigurationDelegate.launch()
      // consider refactoring to combine

      IVMRunner runner;
      IVMInstall vm = verifyVMInstall(configuration);
      if (GrailsVersion.V_2_3_.compareTo(version) <= 0) {
        // We'll be debugging the forked process, not the run-app command.
        runner = vm.getVMRunner(ILaunchManager.RUN_MODE);
      } else {
        runner = vm.getVMRunner(mode);
      }
      if (runner == null) {
        runner = vm.getVMRunner(ILaunchManager.RUN_MODE);
      }

      String projectName =
          configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, "");
      IProject project = null;
      if (!"".equals(projectName)) {
        project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
      }

      String grailsHome = GrailsLaunchArgumentUtils.getGrailsHome(configuration);
      String baseDir =
          configuration.getAttribute(GrailsLaunchArgumentUtils.PROJECT_DIR_LAUNCH_ATTR, "");
      if (baseDir.equals("")) {
        baseDir = ResourcesPlugin.getWorkspace().getRoot().getLocation().toString();
      }
      String script = getScript(configuration);

      File workingDir = verifyWorkingDirectory(configuration);
      String workingDirName = null;
      if (workingDir != null) {
        workingDirName = workingDir.getAbsolutePath();
      } else {
        workingDirName = baseDir;
      }

      List<String> programArguments = new ArrayList<String>();
      programArguments.add("--conf");
      programArguments.add(grailsHome + "conf" + File.separatorChar + "groovy-starter.conf");
      programArguments.add("--main");
      programArguments.add("org.codehaus.groovy.grails.cli.GrailsScriptRunner");

      StringBuilder grailsCommand = new StringBuilder();
      String grailsWorkDir =
          configuration.getAttribute(GrailsLaunchArgumentUtils.GRAILS_WORK_DIR_LAUNCH_ATTR, "");
      if (!grailsWorkDir.equals("")) {
        grailsCommand.append("-Dgrails.work.dir=" + grailsWorkDir + " ");
      }
      grailsCommand.append(script + " ");
      programArguments.add(grailsCommand.toString().trim());

      List<String> vmArgs = new ArrayList<String>();
      // vmArgs.add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8123");

      // add manual configured vm options to the argument list
      String existingVmArgs = getVMArguments(configuration);
      boolean launchConfHasVMArgs = false;
      if (existingVmArgs != null && existingVmArgs.length() > 0) {
        launchConfHasVMArgs = true;
        StringTokenizer additionalArguments = new StringTokenizer(existingVmArgs, " ");
        while (additionalArguments.hasMoreTokens()) {
          vmArgs.add(additionalArguments.nextToken());
        }
      }

      Map<String, String> systemProps =
          GrailsCoreActivator.getDefault().getLaunchSystemProperties();
      GrailsLaunchArgumentUtils.setMaybe(systemProps, "base.dir", baseDir);
      GrailsLaunchArgumentUtils.setMaybe(systemProps, "grails.home", grailsHome);
      for (Map.Entry<String, String> prop : systemProps.entrySet()) {
        vmArgs.add("-D" + prop.getKey() + "=" + prop.getValue());
      }
      int forkedProcessDebugPort = addForkedModeDebuggingArgs(configuration, mode, vmArgs);
      ArrayList<Integer> killPorts = addKillPortArg(project, vmArgs);

      if (!launchConfHasVMArgs) {
        // If the user added their own vmargs to the launch config then the 'default' from global
        // prefs should
        // not be used.
        GrailsLaunchArgumentUtils.addUserDefinedJVMArgs(vmArgs);
      }
      // Grails uses some default memory settings that we want to use as well if no others have been
      // configured
      vmArgs = GrailsLaunchArgumentUtils.addMemorySettings(vmArgs);
      vmArgs = GrailsLaunchArgumentUtils.addSpringLoadedArgs(configuration, vmArgs);

      String[] envp = getEnvironment(configuration);
      Map<String, String> extra = new HashMap<String, String>();
      extra.put("JAVA_HOME", vm.getInstallLocation().getAbsolutePath());
      extra.put(
          "GROOVY_PAGE_ADD_LINE_NUMBERS", "true"); // Enables line number info for GSP debugging
      envp = GrailsLaunchArgumentUtils.addToEnvMaybe(envp, extra);

      Map<String, Object> vmAttributesMap = getVMSpecificAttributesMap(configuration);

      String[] classpath = getClasspath(configuration);
      String mainTypeName = verifyMainTypeName(configuration);

      VMRunnerConfiguration runConfiguration = new VMRunnerConfiguration(mainTypeName, classpath);
      runConfiguration.setProgramArguments(
          programArguments.toArray(new String[programArguments.size()]));
      runConfiguration.setVMArguments(vmArgs.toArray(new String[vmArgs.size()]));
      runConfiguration.setWorkingDirectory(workingDirName);
      runConfiguration.setEnvironment(envp);
      runConfiguration.setVMSpecificAttributesMap(vmAttributesMap);

      String[] bootpath = getBootpath(configuration);
      if (bootpath != null && bootpath.length > 0) {
        runConfiguration.setBootClassPath(bootpath);
      }

      subMonitor.worked(1);
      checkCancelled(subMonitor);

      subMonitor.subTask("Setting up source locator...");
      setDefaultSourceLocator(launch, configuration);
      subMonitor.worked(1);
      checkCancelled(subMonitor);

      subMonitor.worked(1);
      checkCancelled(subMonitor);

      subMonitor.subTask("Launching Grails...");

      if (ILaunchManager.DEBUG_MODE.equals(mode)) {
        launchRemote(forkedProcessDebugPort, configuration, mode, launch, subMonitor);
      }
      GrailsCoreActivator.getDefault().notifyCommandStart(project);
      runner.run(runConfiguration, launch, monitor);
      AbstractLaunchProcessListener listener = getLaunchListener(configuration);
      if (listener != null) {
        listener.init(launch.getProcesses()[0]);
      }
      DebugPlugin.getDefault()
          .addDebugEventListener(
              new GrailsProcessListener(launch.getProcesses(), project, killPorts));
      subMonitor.worked(1);
    } catch (Exception e) {
      GrailsCoreActivator.log(e);
    }
  }
  public void launch(
      ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor)
      throws CoreException {
    IServer server = ServerUtil.getServer(configuration);
    if (server == null) {
      Trace.trace(Trace.FINEST, "Launch configuration could not find server");
      // throw CoreException();
      return;
    }

    if (server.shouldPublish() && ServerCore.isAutoPublishing())
      server.publish(IServer.PUBLISH_INCREMENTAL, monitor);

    PreviewServerBehaviour previewServer =
        (PreviewServerBehaviour) server.loadAdapter(PreviewServerBehaviour.class, null);

    int size = REQUIRED_BUNDLE_IDS.length;
    String[] jars = new String[size];
    for (int i = 0; i < size; i++) {
      Bundle b = Platform.getBundle(REQUIRED_BUNDLE_IDS[i]);
      IPath path = null;
      if (b != null) path = PreviewRuntime.getJarredPluginPath(b);
      if (path == null)
        throw new CoreException(
            new Status(
                IStatus.ERROR,
                PreviewPlugin.PLUGIN_ID,
                "Could not find required bundle " + REQUIRED_BUNDLE_IDS[i]));
      jars[i] = path.toOSString();
    }

    // Appending the bin onto the classpath is to support running from the workbench
    // when org.eclipse.wst.server.preview is checked out
    Trace.trace(Trace.FINEST, jars[CLASSPATH_BIN_INDEX_PREVIEW_SERVER] + File.separator + "bin");
    if (new File(jars[CLASSPATH_BIN_INDEX_PREVIEW_SERVER] + File.separator + "bin").exists())
      jars[CLASSPATH_BIN_INDEX_PREVIEW_SERVER] =
          jars[CLASSPATH_BIN_INDEX_PREVIEW_SERVER] + File.separator + "bin";

    IVMInstall vm = verifyVMInstall(configuration);

    IVMRunner runner = vm.getVMRunner(mode);
    if (runner == null) runner = vm.getVMRunner(ILaunchManager.RUN_MODE);

    File workingDir = verifyWorkingDirectory(configuration);
    String workingDirName = null;
    if (workingDir != null) workingDirName = workingDir.getAbsolutePath();

    // Program & VM args
    String pgmArgs =
        "\"" + previewServer.getTempDirectory().append("preview.xml").toOSString() + "\"";
    // getProgramArguments(configuration);
    String vmArgs = getVMArguments(configuration);
    String[] envp = getEnvironment(configuration);

    ExecutionArguments execArgs = new ExecutionArguments(vmArgs, pgmArgs);

    // VM-specific attributes
    Map vmAttributesMap = getVMSpecificAttributesMap(configuration);

    // Classpath
    String[] classpath2 = getClasspath(configuration);
    String[] classpath = new String[classpath2.length + REQUIRED_BUNDLE_IDS.length];
    System.arraycopy(jars, 0, classpath, 0, REQUIRED_BUNDLE_IDS.length);
    System.arraycopy(classpath2, 0, classpath, REQUIRED_BUNDLE_IDS.length, classpath2.length);

    // Create VM config
    VMRunnerConfiguration runConfig = new VMRunnerConfiguration(MAIN_CLASS, classpath);
    runConfig.setProgramArguments(execArgs.getProgramArgumentsArray());
    runConfig.setVMArguments(execArgs.getVMArgumentsArray());
    runConfig.setWorkingDirectory(workingDirName);
    runConfig.setEnvironment(envp);
    runConfig.setVMSpecificAttributesMap(vmAttributesMap);

    // Bootpath
    String[] bootpath = getBootpath(configuration);
    if (bootpath != null && bootpath.length > 0) runConfig.setBootClassPath(bootpath);

    setDefaultSourceLocator(launch, configuration);

    // Launch the configuration
    previewServer.setupLaunch(launch, mode, monitor);

    if (ILaunchManager.PROFILE_MODE.equals(mode))
      ServerProfilerDelegate.configureProfiling(launch, vm, runConfig, monitor);

    try {
      runner.run(runConfig, launch, monitor);
      previewServer.addProcessListener(launch.getProcesses()[0]);
    } catch (Exception e) {
      // ignore - process failed
    }
  }