/*******************************************************************************
 * Copyright (c) 2001, 2004 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.24 $ $Date: 2005/05/18 23:11:26 $
 */
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.getString("ProxyRemoteNoLaunchKey"), null, 0); //$NON-NLS-1$

		// 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.getString("ProxyRemoteVMName"), new Object[] { project != null ? project.getProject().getName() : "" }); //$NON-NLS-1$ //$NON-NLS-2$
		else
			name = MessageFormat.format(ProxyRemoteMessages.getString("ProxyRemoteVMNameWithComment"), new Object[] { project != null ? project.getProject().getName() : "", name }); //$NON-NLS-1$ //$NON-NLS-2$

		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.getString("ProxyRemoteLaunchVM"), new Object[] { name })); //$NON-NLS-1$
		// check for cancellation
		if (pm.isCanceled())
			return;

		IVMInstall vm = verifyVMInstall(configuration);

		IVMRunner runner = vm.getVMRunner(mode);
		if (runner == null) {
			abort(MessageFormat.format(ProxyRemoteMessages.getString("Proxy_NoRunner_ERROR_"), new Object[] { name }), null, 0); //$NON-NLS-1$
		}

		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;
				Platform.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);

		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();
//TODO: this is a temporary solution for the fact that spaces
//      are not allowed in the libPath
		for (int i = 0; i < evmArgs.length; i++) {
			if (evmArgs[i].startsWith("-Djava.library.path")) { //$NON-NLS-1$
				StringBuffer b = new StringBuffer(evmArgs[i]);
				int idx=b.indexOf("%20"); //$NON-NLS-1$
				while (idx>=0) {
					b.replace(idx,idx+3," "); //$NON-NLS-1$
					idx=b.indexOf("%20"); //$NON-NLS-1$
				}
				evmArgs[i]=b.toString();
			}			
		}
		
		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.getString(ProxyRemoteMessages.VM_TERMINATED));
			w.println(ProxyRemoteMessages.getString(ProxyRemoteMessages.VM_TERMINATED_LINE1));
			w.println(stProxy.getErrorStreamMonitor().getContents());
			w.println(ProxyRemoteMessages.getString(ProxyRemoteMessages.VM_TERMINATED_LINE2));
			w.println(stProxy.getOutputStreamMonitor().getContents());
			w.println(ProxyRemoteMessages.getString(ProxyRemoteMessages.VM_TERMINATED_LINE3));
			w.close();

			String msg = MessageFormat.format(ProxyRemoteMessages.getString("Proxy_Terminated_too_soon_ERROR_"), new Object[] { name }); //$NON-NLS-1$
			dh.displayErrorMessage(ProxyRemoteMessages.getString("Proxy_Error_Title"), msg); //$NON-NLS-1$
			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.getString("LocalProxyLaunchDelegate.Monitor.PrintRemoteTrace.Text"), 1); //$NON-NLS-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
	 * @throws CoreException
	 * 
	 * @since 1.0.2
	 */
	private void addInFragmentLibraries(IConfigurationContributionController controller) throws CoreException {
		IPDEContributeClasspath instance = IPDEContributeClasspath.INSTANCE;
		if (instance != null) {
			instance.getPDEContributions(controller);
		}
	}

	// 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;
	}
	

}
