/*******************************************************************************
 * Copyright (c) 2001, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
/*
 * $RCSfile: LocalProxyLaunchDelegate.java,v $ $Revision: 1.35 $ $Date: 2006/05/23 15:43:03 $
 */
package org.eclipse.jem.internal.proxy.remote;

import java.io.File;
import java.io.IOException;
import java.net.*;
import java.text.MessageFormat;
import java.util.*;
import java.util.logging.Level;

import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.*;
import org.eclipse.debug.core.model.*;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.launching.*;

import org.eclipse.jem.internal.proxy.common.remote.ExpressionCommands;
import org.eclipse.jem.internal.proxy.core.*;
import org.eclipse.jem.internal.proxy.remote.awt.REMRegisterAWT;
import org.eclipse.jem.util.TimerTests;
import org.eclipse.jem.util.logger.proxy.Logger;


/**
 * Launch Delegate for launching Local (i.e. remote vm is on local system). Here "remote" means the
 * registry is not in the IDE but in a separate VM, and "local" means that is in on the local
 * physical machine and not on a separate machine.
 * 
 * @since 1.0.0
 */
public class LocalProxyLaunchDelegate extends AbstractJavaLaunchConfigurationDelegate {

	/*
	 * (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)
	 */
	public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor pm) throws CoreException {

		String launchKey = configuration.getAttribute(IProxyConstants.ATTRIBUTE_LAUNCH_KEY, (String) null);
		if (launchKey == null)
			abort(ProxyRemoteMessages.ProxyRemoteNoLaunchKey, null, 0); 

		// In Eclipse, even if private, a launch will show up in the debug process tree and in the console viewer.
		// To be absolutely private, we need to remove the launch which has already been added.
		if (ProxyLaunchSupport.ATTR_PRIVATE != null && configuration.getAttribute(ProxyLaunchSupport.ATTR_PRIVATE, false)) 
			DebugPlugin.getDefault().getLaunchManager().removeLaunch(launch);		
		if (pm == null) {
			pm = new NullProgressMonitor();
		}

		IJavaProject project = getJavaProject(configuration);
		String name = configuration.getAttribute(IProxyConstants.ATTRIBUTE_VM_TITLE, (String) null);
		if (name == null)
			name = MessageFormat.format(ProxyRemoteMessages.ProxyRemoteVMName, new Object[] { project != null ? project.getProject().getName() : "" });  //$NON-NLS-1$
		else
			name = MessageFormat.format(ProxyRemoteMessages.ProxyRemoteVMNameWithComment, new Object[] { project != null ? project.getProject().getName() : "", name });  //$NON-NLS-1$

		String stepId = "Launch VM ( " + name + " )"; //$NON-NLS-1$ //$NON-NLS-2$
		TimerTests.basicTest.startStep(stepId);
		// Problem with launch, can't have double-quotes in vmName.
		if (name.indexOf('"') != -1)
			name = name.replace('"', '\'');

		pm.beginTask("", 500); //$NON-NLS-1$
		pm.subTask(MessageFormat.format(ProxyRemoteMessages.ProxyRemoteLaunchVM, new Object[] { name })); 
		// check for cancellation
		if (pm.isCanceled())
			return;

		IVMInstall vm = verifyVMInstall(configuration);

		IVMRunner runner = vm.getVMRunner(mode);
		if (runner == null) {
			abort(MessageFormat.format(ProxyRemoteMessages.Proxy_NoRunner_ERROR_, new Object[] { name }), null, 0); 
		}

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

		// Environment variables
		String[] envp = DebugPlugin.getDefault().getLaunchManager().getEnvironment(configuration);

		// Program & VM args
		String pgmArgs = getProgramArguments(configuration);
		String vmArgs = getVMArguments(configuration);
		ExecutionArguments execArgs = new ExecutionArguments(vmArgs, pgmArgs);

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

		pm.worked(100);
		
		// Now let's get the classpaths created through the contributors.
		URL[] classpath = ProxyLaunchSupport.convertStringPathsToURL(getClasspath(configuration));
		String[][] bootpathInfoStrings = getBootpathExt(vmAttributesMap);
		URL[][] bootpathInfo = new URL[][]{
				ProxyLaunchSupport.convertStringPathsToURL(bootpathInfoStrings[0]),
				ProxyLaunchSupport.convertStringPathsToURL(bootpathInfoStrings[1]),
				ProxyLaunchSupport.convertStringPathsToURL(bootpathInfoStrings[2]),
		};
		ProxyLaunchSupport.LaunchInfo launchInfo = ProxyLaunchSupport.getInfo(launchKey);
		final IConfigurationContributor[] contributors = launchInfo.contributors;
		final LocalFileConfigurationContributorController controller =
			new LocalFileConfigurationContributorController(classpath, bootpathInfo, launchInfo);
		if (contributors != null) {		
			for (int i = 0; i < contributors.length; i++) {
				// Run in safe mode so that anything happens we don't go away.
				final int ii = i;
				SafeRunner.run(new ISafeRunnable() {
					public void handleException(Throwable exception) {
						// Don't need to do anything. Platform.run logs it for me.
					}

					public void run() throws Exception {
						contributors[ii].contributeClasspaths(controller);
					}
				});
			}
		}

		// Add in the required ones by the Proxy support. These are hard-coded since they are
		// required.
		ProxyRemoteUtil.updateClassPaths(controller);
		addInFragmentLibraries(controller, launchInfo.getConfigInfo());

		classpath = controller.getFinalClasspath();
		if (bootpathInfo[0] != controller.getFinalPrependBootpath()) {
		    if (vmAttributesMap == null)
		        vmAttributesMap = new HashMap(2);
		    vmAttributesMap.put(IJavaLaunchConfigurationConstants.ATTR_BOOTPATH_PREPEND, ProxyLaunchSupport.convertURLsToStrings(bootpathInfo[0]));
		}
		if (bootpathInfo[2] != controller.getFinalAppendBootpath()) {
		    if (vmAttributesMap == null)
		        vmAttributesMap = new HashMap(2);
		    vmAttributesMap.put(IJavaLaunchConfigurationConstants.ATTR_BOOTPATH_APPEND, ProxyLaunchSupport.convertURLsToStrings(bootpathInfo[2]));
		}

		// check for cancellation
		if (pm.isCanceled())
			return;
		pm.worked(100);

		// Create VM config
		VMRunnerConfiguration runConfig =
			new VMRunnerConfiguration("org.eclipse.jem.internal.proxy.vm.remote.RemoteVMApplication", ProxyLaunchSupport.convertURLsToStrings(classpath)); //$NON-NLS-1$

		REMProxyFactoryRegistry registry = new REMProxyFactoryRegistry(ProxyRemoteUtil.getRegistryController(), name);
		Integer registryKey = registry.getRegistryKey();

		Integer bufSize = Integer.getInteger("proxyvm.bufsize"); //$NON-NLS-1$
		if (bufSize == null)
			bufSize = new Integer(16000);

		int masterServerPort = ProxyRemoteUtil.getRegistryController().getMasterSocketPort();

		// See if debug mode is requested.
		DebugModeHelper dh = new DebugModeHelper();
		boolean debugMode = dh.debugMode(name);
		boolean useNoverify = ProxyPlugin.getPlugin().getPluginPreferences().getBoolean(ProxyPlugin.PREFERENCES_VM_NOVERIFY_KEY);

		String[] evmArgs = execArgs.getVMArgumentsArray();
		
		int extraArgs = 4;	// Number of extra standard args added (if number changes below, this must change)
		if (debugMode)
			extraArgs+=4;	// Number of extra args added for debug mode (if number changes below, this must change).
		if(useNoverify)
			extraArgs++; // An extra arg added for '-noverify' flag (if number changes below, this must change).
		
		boolean useExpressionTracing = "true".equalsIgnoreCase(Platform.getDebugOption(ProxyPlugin.getPlugin().getBundle().getSymbolicName() + ProxyLaunchSupport.EXPRESSION_TRACING)); //$NON-NLS-1$
		long expressionTracingThreshold = -1;
		if (useExpressionTracing) {
			extraArgs++;
			String thresholdString = Platform.getDebugOption(ProxyPlugin.getPlugin().getBundle().getSymbolicName() + ProxyLaunchSupport.EXPRESSION_TRACEING_TIMER_THRESHOLD);
			if (thresholdString != null) {
				try {
					expressionTracingThreshold = Long.valueOf(thresholdString).longValue();
					extraArgs++;
				} catch (NumberFormatException e) {
				}
			}
		}
		
		List javaLibPaths = controller.getFinalJavaLibraryPath();
		int existingLibpaths = -1;
		if (!javaLibPaths.isEmpty()) {
			// first need to see if java lib path also specified in standard args by someone configuring the configuration by hand.
			for (int i = 0; i < evmArgs.length; i++) {
				if (evmArgs[i].startsWith("-Djava.library.path")) { //$NON-NLS-1$
					// We found one already here, save the spot so we update it later.
					existingLibpaths = i;
					break;
				}
			}
			if (existingLibpaths == -1)
				++extraArgs;	// Need to have room for one more.
		}
		
		String[] cvmArgs = new String[evmArgs.length + extraArgs];
		System.arraycopy(evmArgs, 0, cvmArgs, extraArgs, evmArgs.length);	// Put existing into new list at the end.		
		
		int cvmArgsCount=0;
		cvmArgs[cvmArgsCount++] = "-Dproxyvm.registryKey=" + registryKey; //$NON-NLS-1$
		cvmArgs[cvmArgsCount++] = "-Dproxyvm.masterPort=" + String.valueOf(masterServerPort); //$NON-NLS-1$
		cvmArgs[cvmArgsCount++] = "-Dproxyvm.bufsize=" + bufSize; //$NON-NLS-1$
		cvmArgs[cvmArgsCount++] = "-Dproxyvm.servername=" + name; //$NON-NLS-1$
		
		if(useNoverify)
			cvmArgs[cvmArgsCount++] = "-noverify"; //$NON-NLS-1$
		
		if (useExpressionTracing) {
			cvmArgs[cvmArgsCount++] = "-D"+ExpressionCommands.EXPRESSIONTRACE+"=true"; //$NON-NLS-1$ //$NON-NLS-2$
			if (expressionTracingThreshold != -1)
				cvmArgs[cvmArgsCount++] = "-D"+ExpressionCommands.EXPRESSIONTRACE_TIMER_THRESHOLD+'='+String.valueOf(expressionTracingThreshold); //$NON-NLS-1$
		}

		// If in debug mode, we need to find a port for it to use.
		int dport = -1;
		if (debugMode) {
			dport = findUnusedLocalPort("localhost", 5000, 15000, new int[0]); //$NON-NLS-1$
			cvmArgs[cvmArgsCount++] = "-Djava.compiler=NONE"; //$NON-NLS-1$
			cvmArgs[cvmArgsCount++] = "-Xdebug"; //$NON-NLS-1$
			cvmArgs[cvmArgsCount++] = "-Xnoagent"; //$NON-NLS-1$
			cvmArgs[cvmArgsCount++] = "-Xrunjdwp:transport=dt_socket,server=y,address=" + dport; //$NON-NLS-1$
		}
		
		if (!javaLibPaths.isEmpty()) {
			StringBuffer appendTo = null;
			if (existingLibpaths != -1) {
				appendTo = new StringBuffer(evmArgs[existingLibpaths]); 
				appendTo.append(File.pathSeparatorChar);	// Plus a separator so we can append
			} else 
				appendTo = new StringBuffer("-Djava.library.path="); //$NON-NLS-1$
			String [] libPaths = ProxyLaunchSupport.convertURLsToStrings((URL[]) javaLibPaths.toArray(new URL[javaLibPaths.size()]));
			for (int i = 0; i < libPaths.length; i++) {
				if (i != 0)
					appendTo.append(File.pathSeparator);
				appendTo.append(libPaths[i]);
			}
			if (existingLibpaths != -1)
				cvmArgs[extraArgs+existingLibpaths] = appendTo.toString();
			else
				cvmArgs[extraArgs-1] = appendTo.toString();
		}

		runConfig.setProgramArguments(execArgs.getProgramArgumentsArray());
		runConfig.setEnvironment(envp);
		runConfig.setVMArguments(cvmArgs);
		runConfig.setWorkingDirectory(workingDirName);
		runConfig.setVMSpecificAttributesMap(vmAttributesMap);

		// Bootpath
		runConfig.setBootClassPath(getBootpath(configuration));

		// check for cancellation
		if (pm.isCanceled())
			return;
		pm.worked(100);

		// set the default source locator if required
		setDefaultSourceLocator(launch, configuration);

		// Launch the configuration - 1 unit of work
		runner.run(runConfig, launch, new SubProgressMonitor(pm, 100));

		// check for cancellation
		if (pm.isCanceled())
			return;

		IProcess[] processes = launch.getProcesses();
		IProcess process = processes[0]; // There is only one.
		// Check if it is already terminated. If it is, then there was a bad error, so just
		// print out the results from it.
		if (process.isTerminated()) {
			IStreamsProxy stProxy = process.getStreamsProxy();
			// Using a printWriter for println capability, but it needs to be on another
			// writer, which will be string
			java.io.StringWriter s = new java.io.StringWriter();
			java.io.PrintWriter w = new java.io.PrintWriter(s);

			w.println(ProxyRemoteMessages.VM_TERMINATED_INFO_); 
			w.println(ProxyRemoteMessages.VM_COMMAND_LINE);
			w.println(process.getAttribute(IProcess.ATTR_CMDLINE));
			w.println(ProxyRemoteMessages.VM_TERMINATED_LINE1); 
			w.println(stProxy.getErrorStreamMonitor().getContents());
			w.println(ProxyRemoteMessages.VM_TERMINATED_LINE2); 
			w.println(stProxy.getOutputStreamMonitor().getContents());
			w.println(ProxyRemoteMessages.VM_TERMINATED_LINE3); 
			w.close();

			String msg = MessageFormat.format(ProxyRemoteMessages.Proxy_Terminated_too_soon_ERROR_, new Object[] { name }); 
			dh.displayErrorMessage(ProxyRemoteMessages.Proxy_Error_Title, msg); 
			throw new CoreException(
				new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, s.toString(), null));
		} else {
			final String traceName = name;
			IStreamsProxy fStreamsProxy = process.getStreamsProxy();

			/**
			 * StreamListener. Should not be created if ProxyPlugin logger is not logging the requested level.
			 * 
			 * @since 1.1.0
			 */
			class StreamListener implements IStreamListener {
				String tracePrefix;
				Level level;
				Job printJob;	// Job to try to gather printing together.
				Logger logger;
				StringBuffer gatheredText = new StringBuffer(100);
				{
					logger = ProxyPlugin.getPlugin().getLogger();
					printJob = new Job("") { //$NON-NLS-1$

						protected IStatus run(IProgressMonitor monitor) {
							monitor.beginTask(ProxyRemoteMessages.LocalProxyLaunchDelegate_Monitor_PrintRemoteTrace_Text, 1); 
							while(true) {
								String output = null;
								synchronized (gatheredText) {
									if (gatheredText.length() <= tracePrefix.length())
										break;	// We've reached the end, no more to print.
									output = gatheredText.toString();
									gatheredText.setLength(tracePrefix.length());	// Reset the length to the prefix.
								}
								logger.log(output, level);
							}
							monitor.done();
							return Status.OK_STATUS;
						}
					};
					printJob.setPriority(Job.SHORT);
					printJob.setSystem(true);
				}
				
				public StreamListener(String type, Level level, Logger logger) {
					tracePrefix = traceName + ':' + type + '>' + System.getProperty("line.separator"); //$NON-NLS-1$
					gatheredText.append(tracePrefix);
					this.level = level;
					this.logger = logger;
				}

				public void streamAppended(String newText, IStreamMonitor monitor) {
					synchronized(gatheredText) {
						gatheredText.append(newText);
					}
					printJob.schedule(100L);	// Wait tenth of second to gather as much as can together.
				}
			};

			Logger logger = ProxyPlugin.getPlugin().getLogger();
			if (logger.isLoggingLevel(Level.WARNING)) {
				// Always listen to System.err output if we are at least logging warnings.
				IStreamMonitor monitor = fStreamsProxy.getErrorStreamMonitor();
				if (monitor != null)
					monitor.addListener(new StreamListener("err", Level.WARNING, logger)); //$NON-NLS-1$
			}

			// If debug trace is requested, then attach trace listener for System.out
			// Expression tracing requires debug trace too because it prints to sysout. However, it requesting expressionTracing, change logging level to INFO,
			// we want them to show if this true. It is confusing to also have to change logging level in .options file.
			if (useExpressionTracing)
				if (!logger.isLoggingLevel(Level.INFO))
					logger.setLevel(Level.INFO);
			if (useExpressionTracing || "true".equalsIgnoreCase(Platform.getDebugOption(ProxyPlugin.getPlugin().getBundle().getSymbolicName() + ProxyRemoteUtil.DEBUG_VM_TRACEOUT))) { //$NON-NLS-1$
				// Want to trace the output of the remote vm's. And we are logging at least level info.
				if (logger.isLoggingLevel(Level.INFO)) {
					IStreamMonitor monitor = fStreamsProxy.getOutputStreamMonitor();
					if (monitor != null)
						monitor.addListener(new StreamListener("out", Level.INFO, logger)); //$NON-NLS-1$							
				}							
			}
		}

		// If in debug mode, tester must start debugger before going on.
		if (debugMode) {
			if (!dh.promptPort(dport)) {
				process.terminate();
				throw new CoreException(
					new Status(
						IStatus.WARNING,
						ProxyPlugin.getPlugin().getBundle().getSymbolicName(),
						0,
						"Debugger attach canceled", //$NON-NLS-1$
						null));
			}
		}

		// Now set up the registry.
		registry.initializeRegistry(process);
		new REMStandardBeanTypeProxyFactory(registry);
		new REMStandardBeanProxyFactory(registry);
		new REMMethodProxyFactory(registry);

		if (debugMode || REMProxyFactoryRegistry.fGlobalNoTimeouts)
			registry.fNoTimeouts = true;
		if (configuration.getAttribute(IProxyConstants.ATTRIBUTE_AWT_SWING, true))
			REMRegisterAWT.registerAWT(registry);

		launchInfo.resultRegistry = registry;

		pm.done();
		TimerTests.basicTest.stopStep(stepId);
	}

	/**
	 * @param controller
	 * @param info 
	 * @throws CoreException
	 * 
	 * @since 1.0.2
	 */
	private void addInFragmentLibraries(IConfigurationContributionController controller, IConfigurationContributionInfo info) throws CoreException {
		IPDEContributeClasspath instance = IPDEContributeClasspath.INSTANCE;
		if (instance != null) {
			instance.getPDEContributions(controller, info);
		}
	}

	// Utilities to find the free port
	private static final Random fgRandom = new Random(System.currentTimeMillis());

	private static int findUnusedLocalPort(String host, int searchFrom, int searchTo, int[] exclude) {
		for (int i = 0; i < 10; i++) {
			int port = 0;
			newport : while (true) {
				port = getRandomPort(searchFrom, searchTo);
				if (exclude != null)
					for (int e = 0; e < exclude.length; e++)
						if (port == exclude[e])
							continue newport;
				break;
			}
			try {
				new Socket(host, port);
			} catch (ConnectException e) {
				return port;
			} catch (IOException e) {
			}
		}
		return -1;
	}

	private static int getRandomPort(int low, int high) {
		return (int) (fgRandom.nextFloat() * (high - low)) + low;
	}
	
	private String[][] getBootpathExt(Map vmMap) {
	    String[][] ext = new String[3][];
	    if (vmMap != null) {
		    ext[0] = (String[]) vmMap.get(IJavaLaunchConfigurationConstants.ATTR_BOOTPATH_PREPEND);
		    ext[1] = (String[]) vmMap.get(IJavaLaunchConfigurationConstants.ATTR_BOOTPATH);
		    ext[2] = (String[]) vmMap.get(IJavaLaunchConfigurationConstants.ATTR_BOOTPATH_APPEND);
	    }
	    return ext;
	}
	

}
