/*******************************************************************************
 * Copyright (c) 2000, 2019 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Alex Smirnoff   - Bug 289916
 *******************************************************************************/
package org.eclipse.jdt.internal.launching;


import java.io.File;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.IStatusHandler;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.IStreamsProxy;
import org.eclipse.jdi.Bootstrap;
import org.eclipse.jdt.debug.core.JDIDebugModel;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.IVMInstall2;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.launching.SocketUtil;
import org.eclipse.jdt.launching.VMRunnerConfiguration;

import com.sun.jdi.VirtualMachine;
import com.sun.jdi.connect.Connector;
import com.sun.jdi.connect.IllegalConnectorArgumentsException;
import com.sun.jdi.connect.ListeningConnector;

/**
 * A launcher for debugging Java main classes. Uses JDI to launch a VM in debug
 * mode.
 */
public class StandardVMDebugger extends StandardVMRunner {


	/**
	 * @since 3.3 OSX environment variable specifying JRE to use
	 */
	protected static final String JAVA_JVM_VERSION = "JAVA_JVM_VERSION"; //$NON-NLS-1$

	/**
	 * JRE path segment descriptor
	 *
	 * String equals the word: <code>jre</code>
	 *
	 * @since 3.3.1
	 */
	protected static final String JRE = "jre"; //$NON-NLS-1$

	/**
	 * Bin path segment descriptor
	 *
	 * String equals the word: <code>bin</code>
	 *
	 * @since 3.3.1
	 */
	protected static final String BIN = "bin"; //$NON-NLS-1$

	/**
	 * Used to attach to a VM in a separate thread, to allow for cancellation
	 * and detect that the associated System process died before the connect
	 * occurred.
	 */
	class ConnectRunnable implements Runnable {

		private VirtualMachine fVirtualMachine = null;
		private ListeningConnector fConnector = null;
		private Map<String, Connector.Argument> fConnectionMap = null;
		private Exception fException = null;

		/**
		 * Constructs a runnable to connect to a VM via the given connector
		 * with the given connection arguments.
		 *
		 * @param connector the connector to use
		 * @param map the argument map
		 */
		public ConnectRunnable(ListeningConnector connector, Map<String, Connector.Argument> map) {
			fConnector = connector;
			fConnectionMap = map;
		}

		@Override
		public void run() {
			try {
				fVirtualMachine = fConnector.accept(fConnectionMap);
			} catch (IOException e) {
				fException = e;
			} catch (IllegalConnectorArgumentsException e) {
				fException = e;
			}
		}

		/**
		 * Returns the VM that was attached to, or <code>null</code> if none.
		 *
		 * @return the VM that was attached to, or <code>null</code> if none
		 */
		public VirtualMachine getVirtualMachine() {
			return fVirtualMachine;
		}

		/**
		 * Returns any exception that occurred while attaching, or <code>null</code>.
		 *
		 * @return IOException or IllegalConnectorArgumentsException
		 */
		public Exception getException() {
			return fException;
		}
	}

	/**
	 * Creates a new launcher
	 * @param vmInstance the backing {@link IVMInstall} to launch
	 */
	public StandardVMDebugger(IVMInstall vmInstance) {
		super(vmInstance);
	}

	@Override
	public String showCommandLine(VMRunnerConfiguration configuration, ILaunch launch, IProgressMonitor monitor) throws CoreException {
		SubMonitor subMonitor = SubMonitor.convert(monitor);

		CommandDetails cmd = getCommandLine(configuration, launch, subMonitor);
		if (subMonitor.isCanceled()) {
			return ""; //$NON-NLS-1$
		}
		String[] cmdLine = cmd.getCommandLine();
		cmdLine = quoteWindowsArgs(cmdLine);
		return getCmdLineAsString(cmdLine);
	}

	private CommandDetails getCommandLine(VMRunnerConfiguration config, ILaunch launch, IProgressMonitor monitor) throws CoreException {
		IProgressMonitor subMonitor = SubMonitor.convert(monitor, 1);

		// check for cancellation
		if (subMonitor.isCanceled()) {
			return null;
		}

		subMonitor.subTask(LaunchingMessages.StandardVMDebugger_Finding_free_socket____2);

		int port= SocketUtil.findFreePort();
		if (port == -1) {
			abort(LaunchingMessages.StandardVMDebugger_Could_not_find_a_free_socket_for_the_debugger_1, null, IJavaLaunchConfigurationConstants.ERR_NO_SOCKET_AVAILABLE);
		}

		subMonitor.worked(1);

		// check for cancellation
		if (subMonitor.isCanceled()) {
			return null;
		}

		subMonitor.subTask(LaunchingMessages.StandardVMDebugger_Constructing_command_line____3);

		String program= constructProgramString(config);

		List<String> arguments= new ArrayList<>(12);

		arguments.add(program);

		if (fVMInstance instanceof StandardVM && ((StandardVM)fVMInstance).getDebugArgs() != null){
			String debugArgString = ((StandardVM)fVMInstance).getDebugArgs().replaceAll("\\Q" + StandardVM.VAR_PORT + "\\E", Integer.toString(port));  //$NON-NLS-1$ //$NON-NLS-2$
			String[] debugArgs = DebugPlugin.parseArguments(debugArgString);
			for (int i = 0; i < debugArgs.length; i++) {
				arguments.add(debugArgs[i]);
			}
		} else {
			// VM arguments are the first thing after the java program so that users can specify
			// options like '-client' & '-server' which are required to be the first options
			double version = getJavaVersion();
			if (version < 1.5) {
				arguments.add("-Xdebug"); //$NON-NLS-1$
				arguments.add("-Xnoagent"); //$NON-NLS-1$
			}

			//check if java 1.4 or greater
			if (version < 1.4) {
				arguments.add("-Djava.compiler=NONE"); //$NON-NLS-1$
			}
			if (version < 1.5) {
				arguments.add("-Xrunjdwp:transport=dt_socket,suspend=y,address=localhost:" + port); //$NON-NLS-1$
			} else {
				arguments.add("-agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:" + port); //$NON-NLS-1$
			}

		}

		String[] allVMArgs = combineVmArgs(config, fVMInstance);
		addArguments(ensureEncoding(launch, allVMArgs), arguments);
		addBootClassPathArguments(arguments, config);

		String[] mp = config.getModulepath();
		if (mp != null && mp.length > 0) { // There can be scenarios like junit where launched class is in classpath
											// with modular path entries
			arguments.add("-p"); //$NON-NLS-1$
			arguments.add(convertClassPath(mp));
		}

		String[] cp= config.getClassPath();
		if (cp.length > 0) {
			arguments.add("-classpath"); //$NON-NLS-1$
			arguments.add(convertClassPath(cp));
		}

		// https://openjdk.java.net/jeps/12
		if (config.isPreviewEnabled()) {
			arguments.add("--enable-preview"); //$NON-NLS-1$
		}

		String dependencies = config.getOverrideDependencies();
		if (dependencies != null && dependencies.length() > 0) {
			String[] parseArguments = DebugPlugin.parseArguments(dependencies);
			for (String string : parseArguments) {
				arguments.add(string);
			}

		}

		if (isModular(config, fVMInstance)) {
			arguments.add("-m"); //$NON-NLS-1$
			arguments.add(config.getModuleDescription() + "/" + config.getClassToLaunch()); //$NON-NLS-1$
		} else {
			arguments.add(config.getClassToLaunch());
		}
		int lastVMArgumentIndex = arguments.size() - 1;
		/*
		 * String[] cp= config.getClassPath(); int cpidx = -1; if (cp.length > 0) { cpidx = arguments.size(); arguments.add("-classpath");
		 * //$NON-NLS-1$ arguments.add(convertClassPath(cp)); }
		 *
		 * arguments.add(config.getClassToLaunch());
		 */
		addArguments(config.getProgramArguments(), arguments);

		//With the newer VMs and no backwards compatibility we have to always prepend the current env path (only the runtime one)
		//with a 'corrected' path that points to the location to load the debug dlls from, this location is of the standard JDK installation
		//format: <jdk path>/jre/bin
		String[] envp = prependJREPath(config.getEnvironment(), new Path(program));

		String[] cmdLine= new String[arguments.size()];
		arguments.toArray(cmdLine);

		// check for cancellation
		if (subMonitor.isCanceled()) {
			return null;
		}
		File workingDir = getWorkingDir(config);
		ClasspathShortener classpathShortener = new ClasspathShortener(fVMInstance, launch, cmdLine, lastVMArgumentIndex, workingDir, envp);
		if (classpathShortener.shortenCommandLineIfNecessary()) {
			cmdLine = classpathShortener.getCmdLine();
			envp = classpathShortener.getEnvp();
		}

		String[] newCmdLine = validateCommandLine(launch.getLaunchConfiguration(), cmdLine);
		if (newCmdLine != null) {
			cmdLine = newCmdLine;
		}
		subMonitor.worked(1);

		CommandDetails cmd = new CommandDetails();
		cmd.setCommandLine(cmdLine);
		cmd.setEnvp(envp);
		cmd.setWorkingDir(workingDir);
		cmd.setClasspathShortener(classpathShortener);
		cmd.setPort(port);
		return cmd;

	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.launching.IVMRunner#run(org.eclipse.jdt.launching.VMRunnerConfiguration, org.eclipse.debug.core.ILaunch,
	 * org.eclipse.core.runtime.IProgressMonitor)
	 */
	@Override
	public void run(VMRunnerConfiguration config, ILaunch launch, IProgressMonitor monitor) throws CoreException {
		IProgressMonitor subMonitor = SubMonitor.convert(monitor, 1);
		CommandDetails cmdDetails = getCommandLine(config, launch, subMonitor);

		// check for cancellation
		if (subMonitor.isCanceled() || cmdDetails == null) {
			return;
		}
		String[] cmdLine = cmdDetails.getCommandLine();

		subMonitor.beginTask(LaunchingMessages.StandardVMDebugger_Launching_VM____1, 4);
		subMonitor.subTask(LaunchingMessages.StandardVMDebugger_Starting_virtual_machine____4);
		ListeningConnector connector= getConnector();
		if (connector == null) {
			abort(LaunchingMessages.StandardVMDebugger_Couldn__t_find_an_appropriate_debug_connector_2, null, IJavaLaunchConfigurationConstants.ERR_CONNECTOR_NOT_AVAILABLE);
		}
		Map<String, Connector.Argument> map= connector.defaultArguments();

		specifyArguments(map, cmdDetails.getPort());
		Process p= null;
		try {
			try {
				// check for cancellation
				if (subMonitor.isCanceled()) {
					return;
				}

				connector.startListening(map);

				p = exec(cmdLine, cmdDetails.getWorkingDir(), cmdDetails.getEnvp(), config.isMergeOutput());
				if (p == null) {
					return;
				}

				// check for cancellation
				if (subMonitor.isCanceled()) {
					p.destroy();
					return;
				}
				String timestamp = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM).format(new Date(System.currentTimeMillis()));
				IProcess process= newProcess(launch, p, renderProcessLabel(cmdLine, timestamp), getDefaultProcessMap());
				process.setAttribute(DebugPlugin.ATTR_PATH, cmdLine[0]);
				process.setAttribute(IProcess.ATTR_CMDLINE, renderCommandLine(cmdLine));
				String ltime = launch.getAttribute(DebugPlugin.ATTR_LAUNCH_TIMESTAMP);
				process.setAttribute(DebugPlugin.ATTR_LAUNCH_TIMESTAMP, ltime != null ? ltime : timestamp);
				if (cmdDetails.getWorkingDir() != null) {
					process.setAttribute(DebugPlugin.ATTR_WORKING_DIRECTORY, cmdDetails.getWorkingDir().getAbsolutePath());
				}
				if (cmdDetails.getEnvp() != null) {
					Arrays.sort(cmdDetails.getEnvp());
					StringBuilder buff = new StringBuilder();
					for (int i = 0; i < cmdDetails.getEnvp().length; i++) {
						buff.append(cmdDetails.getEnvp()[i]);
						if (i < cmdDetails.getEnvp().length - 1) {
							buff.append('\n');
						}
					}
					process.setAttribute(DebugPlugin.ATTR_ENVIRONMENT, buff.toString());
				}
				if (!cmdDetails.getClasspathShortener().getProcessTempFiles().isEmpty()) {
					String tempFiles = cmdDetails.getClasspathShortener().getProcessTempFiles().stream().map(file -> file.getAbsolutePath()).collect(Collectors.joining(File.pathSeparator));
					process.setAttribute(LaunchingPlugin.ATTR_LAUNCH_TEMP_FILES, tempFiles);
				}
				subMonitor.worked(1);
				subMonitor.subTask(LaunchingMessages.StandardVMDebugger_Establishing_debug_connection____5);
				int retryCount = 0;
				boolean retry= false;
				do  {
					try {

						ConnectRunnable runnable = new ConnectRunnable(connector, map);
						Thread connectThread = new Thread(runnable, "Listening Connector"); //$NON-NLS-1$
                        connectThread.setDaemon(true);
						connectThread.start();
						while (connectThread.isAlive()) {
							if (subMonitor.isCanceled()) {
                                try {
                                    connector.stopListening(map);
                                } catch (IOException ioe) {
                                    //expected
                                }
								p.destroy();
								return;
							}
							try {
								p.exitValue();
								// process has terminated - stop waiting for a connection
								try {
									connector.stopListening(map);
								} catch (IOException e) {
									// expected
								}
								checkErrorMessage(process);
							} catch (IllegalThreadStateException e) {
								// expected while process is alive
							}
							try {
								Thread.sleep(100);
							} catch (InterruptedException e) {
							}
						}

						Exception ex = runnable.getException();
						if (ex instanceof IllegalConnectorArgumentsException) {
							throw (IllegalConnectorArgumentsException)ex;
						}
						if (ex instanceof InterruptedIOException) {
							throw (InterruptedIOException)ex;
						}
						if (ex instanceof IOException) {
							throw (IOException)ex;
						}

						VirtualMachine vm= runnable.getVirtualMachine();
						if (vm != null) {
							createDebugTarget(config, launch, cmdDetails.getPort(), process, vm);
							subMonitor.worked(1);
							subMonitor.done();
						}
						return;
					} catch (InterruptedIOException e) {
						checkErrorMessage(process);

						// timeout, consult status handler if there is one
						IStatus status = new Status(IStatus.ERROR, LaunchingPlugin.getUniqueIdentifier(), IJavaLaunchConfigurationConstants.ERR_VM_CONNECT_TIMEOUT, "", e); //$NON-NLS-1$
						IStatusHandler handler = DebugPlugin.getDefault().getStatusHandler(status);

						retry= false;
						if (handler == null) {
							// if there is no handler, throw the exception
							throw new CoreException(status);
						}
						Object result = handler.handleStatus(status, this);
						if (result instanceof Boolean) {
							retry = ((Boolean)result).booleanValue();
						}
						if (!retry && retryCount < 5) {
							retry = true;
							retryCount++;
							LaunchingPlugin.log("Retrying count: " + retryCount); //$NON-NLS-1$

						}
					}
				} while (retry);
			} finally {
				connector.stopListening(map);
			}
		} catch (IOException e) {
			abort(LaunchingMessages.StandardVMDebugger_Couldn__t_connect_to_VM_4, e, IJavaLaunchConfigurationConstants.ERR_CONNECTION_FAILED);
		} catch (IllegalConnectorArgumentsException e) {
			abort(LaunchingMessages.StandardVMDebugger_Couldn__t_connect_to_VM_5, e, IJavaLaunchConfigurationConstants.ERR_CONNECTION_FAILED);
		}
		if (p != null) {
			p.destroy();
		}
	}

	/**
	 * This method performs platform specific operations to modify the runtime path for JREs prior to launching.
	 * Nothing is written back to the original system path.
	 *
	 * <p>
	 * For Windows:
	 * Prepends the location of the JRE bin directory for the given JDK path to the PATH variable in Windows.
	 * This method assumes that the JRE is located within the JDK install directory
	 * in: <code><JDK install dir>/jre/bin/</code> where the JRE itself would be located
	 * in: <code><JDK install dir>/bin/</code>  where the JDK itself is located
	 * </p>
	 * <p>
	 * For Mac OS:
	 * Searches for and sets the correct state of the JAVA_VM_VERSION environment variable to ensure it matches
	 * the currently chosen VM of the launch config
	 * </p>
	 *
	 * @param env the current array of environment variables to run with
	 * @param jdkpath the path to the executable (javaw).
	 * @return the altered JRE path
	 * @since 3.3
	 */
	protected String[] prependJREPath(String[] env, IPath jdkpath) {
		if(Platform.OS_WIN32.equals(Platform.getOS())) {
			IPath jrepath = jdkpath.removeLastSegments(1);
			if(jrepath.lastSegment().equals(BIN)) {
				int count = jrepath.segmentCount();
				if(count > 1 && !jrepath.segment(count-2).equalsIgnoreCase(JRE)) {
					jrepath = jrepath.removeLastSegments(1).append(JRE).append(BIN);
				}
			}
			else {
				jrepath = jrepath.append(JRE).append(BIN);
			}
			if(jrepath.toFile().exists()) {
				String jrestr = jrepath.toOSString();
				if(env == null){
					Map<String, String> map = DebugPlugin.getDefault().getLaunchManager().getNativeEnvironment();
					env = new String[map.size()];
					String var = null;
					int index = 0;
					for(Iterator<String> iter = map.keySet().iterator(); iter.hasNext();) {
						var = iter.next();
						String value = map.get(var);
						if (value == null) {
							value = ""; //$NON-NLS-1$
						}
						if (var.equalsIgnoreCase("path")) { //$NON-NLS-1$
							if(value.indexOf(jrestr) == -1) {
								value = jrestr+';'+value;
							}
						}
						env[index] = var+"="+value; //$NON-NLS-1$
						index++;
					}
				} else {
					String var = null;
					int esign = -1;
					for(int i = 0; i < env.length; i++) {
						esign = env[i].indexOf('=');
						if(esign > -1) {
							var = env[i].substring(0, esign);
							if(var != null && var.equalsIgnoreCase("path")) { //$NON-NLS-1$
								if(env[i].indexOf(jrestr) == -1) {
									env[i] = var + "="+jrestr+';'+(esign == env[i].length() ? "" : env[i].substring(esign+1)); //$NON-NLS-1$ //$NON-NLS-2$
									break;
								}
							}
						}
					}
				}
			}
		}
		return super.prependJREPath(env);
	}

	/**
	 * Creates a new debug target for the given virtual machine and system process
	 * that is connected on the specified port for the given launch.
	 *
	 * @param config run configuration used to launch the VM
	 * @param launch launch to add the target to
	 * @param port port the VM is connected to
	 * @param process associated system process
	 * @param vm JDI virtual machine
	 * @return the {@link IDebugTarget}
	 */
	protected IDebugTarget createDebugTarget(VMRunnerConfiguration config, ILaunch launch, int port, IProcess process, VirtualMachine vm) {
		return JDIDebugModel.newDebugTarget(launch, vm, renderDebugTarget(config.getClassToLaunch(), port), process, true, false, config.isResumeOnStartup());
	}

	/**
	 * Returns the version of the current VM in use
	 * @return the VM version
	 */
	private double getJavaVersion() {
		String version = null;
		if (fVMInstance instanceof IVMInstall2) {
			version = ((IVMInstall2)fVMInstance).getJavaVersion();
		} else {
			LibraryInfo libInfo = LaunchingPlugin.getLibraryInfo(fVMInstance.getInstallLocation().getAbsolutePath());
			if (libInfo == null) {
			    return 0D;
			}
			version = libInfo.getVersion();
		}
		if (version == null) {
			// unknown version
			return 0D;
		}
		int index = version.indexOf("."); //$NON-NLS-1$
		int nextIndex = version.indexOf(".", index+1); //$NON-NLS-1$
		try {
			if (index > 0 && nextIndex>index) {
				return Double.parseDouble(version.substring(0,nextIndex));
			}
			return Double.parseDouble(version);
		} catch (NumberFormatException e) {
			return 0D;
		}

	}

	/**
	 * Checks and forwards an error from the specified process
	 * @param process the process to get the error message from
	 * @throws CoreException if a problem occurs
	 */
	protected void checkErrorMessage(IProcess process) throws CoreException {
		IStreamsProxy streamsProxy = process.getStreamsProxy();
		if (streamsProxy != null) {
			String errorMessage= streamsProxy.getErrorStreamMonitor().getContents();
			if (errorMessage.length() == 0) {
				errorMessage= streamsProxy.getOutputStreamMonitor().getContents();
			}
			if (errorMessage.length() != 0) {
				abort(errorMessage, null, IJavaLaunchConfigurationConstants.ERR_VM_LAUNCH_ERROR);
			}
		}
	}

	/**
	 * Allows arguments to be specified
	 * @param map argument map
	 * @param portNumber the port number
	 */
	protected void specifyArguments(Map<String, Connector.Argument> map, int portNumber) {
		// XXX: Revisit - allows us to put a quote (") around the classpath
		Connector.IntegerArgument port= (Connector.IntegerArgument) map.get("port"); //$NON-NLS-1$
		port.setValue(portNumber);

		Connector.IntegerArgument timeoutArg= (Connector.IntegerArgument) map.get("timeout"); //$NON-NLS-1$
		if (timeoutArg != null) {
			int timeout = Platform.getPreferencesService().getInt(
					LaunchingPlugin.ID_PLUGIN,
					JavaRuntime.PREF_CONNECT_TIMEOUT,
					JavaRuntime.DEF_CONNECT_TIMEOUT,
					null);
			timeoutArg.setValue(timeout);
		}
	}

	/**
	 * Returns the default 'com.sun.jdi.SocketListen' connector
	 * @return the {@link ListeningConnector}
	 */
	@SuppressWarnings("nls")
	protected ListeningConnector getConnector() {
		List<ListeningConnector> connectors= Bootstrap.virtualMachineManager().listeningConnectors();
		for (int i= 0; i < connectors.size(); i++) {
			ListeningConnector c= connectors.get(i);
			if ("com.sun.jdi.SocketListen".equals(c.name())) {
				return c;
			}
		}
		return null;
	}

}
