/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.uima.ducc.agent.launcher;

import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.uima.ducc.agent.NodeAgent;
import org.apache.uima.ducc.common.IDuccUser;
import org.apache.uima.ducc.common.container.FlagsHelper;
import org.apache.uima.ducc.common.utils.DuccLogger;
import org.apache.uima.ducc.common.utils.TimeStamp;
import org.apache.uima.ducc.common.utils.Utils;
import org.apache.uima.ducc.common.utils.id.DuccId;
import org.apache.uima.ducc.transport.cmdline.ACommandLine;
import org.apache.uima.ducc.transport.cmdline.ICommandLine;
import org.apache.uima.ducc.transport.cmdline.JavaCommandLine;
import org.apache.uima.ducc.transport.cmdline.NonJavaCommandLine;
import org.apache.uima.ducc.transport.event.common.IDuccProcess;
import org.apache.uima.ducc.transport.event.common.IDuccProcess.ReasonForStoppingProcess;
import org.apache.uima.ducc.transport.event.common.IDuccProcessType.ProcessType;
import org.apache.uima.ducc.transport.event.common.IProcessState.ProcessState;
import org.apache.uima.ducc.transport.event.common.ITimeWindow;
import org.apache.uima.ducc.transport.event.common.TimeWindow;

public class DuccCommandExecutor extends CommandExecutor {
	DuccLogger logger = DuccLogger.getLogger(this.getClass(),
			NodeAgent.COMPONENT_NAME);
	@SuppressWarnings("unused")
	private static AtomicInteger nextPort = new AtomicInteger(30000);

	public DuccCommandExecutor(NodeAgent agent, ICommandLine cmdLine,
			String host, String ip, Process managedProcess) throws Exception {
		super(agent, cmdLine, host, ip, managedProcess);
	}

	public DuccCommandExecutor(ICommandLine cmdLine, String host, String ip,
			Process managedProcess) throws Exception {
		super(null, cmdLine, host, ip, managedProcess);
	}

	private boolean useDuccSpawn() {
		if (super.managedProcess.isAgentProcess() || Utils.isWindows()) {
			return false;
		}
		// On non-windows check if we should spawn the process via ducc_ling
		String useSpawn = System
				.getProperty("ducc.agent.launcher.use.ducc_spawn");
		if (useSpawn != null && useSpawn.toLowerCase().equals("true")) {
			return true;
		}
		// default
		return false;
	}

	private boolean createCGroupContainer(IDuccProcess duccProcess,
			String containerId, String owner) throws Exception {
		// create cgroups container and assign limits
		if (agent.cgroupsManager.createContainer(containerId, System.getProperty("user.name"),
				agent.cgroupsManager.getUserGroupName(System.getProperty("user.name")), useDuccSpawn())) {
			logger.info("createCGroupContainer", null,
					"Calculating CPU shares \nProcess Max Memory="
							+ duccProcess.getCGroup().getMaxMemoryLimit()
							+ "\nNode Memory Total="
							+ agent.getNodeInfo().getNodeMetrics()
									.getNodeMemory().getMemTotal());
			long cpuShares = duccProcess.getCGroup().getMaxMemoryLimit()
					/ agent.getNodeInfo().getNodeMetrics().getNodeMemory()
							.getMemTotal();
			logger.info("createCGroupContainer", null, "\nCalculated Shares="
					+ cpuShares);
			agent.cgroupsManager.setContainerCpuShares(containerId, owner,
					useDuccSpawn(), cpuShares);
			long swappiness = 10; //default
			if ( agent.configurationFactory.nodeSwappiness != null ) {
				swappiness = Long.valueOf(agent.configurationFactory.nodeSwappiness);
			}
			agent.cgroupsManager.setContainerSwappiness(containerId, owner,
					useDuccSpawn(), swappiness);

			return agent.cgroupsManager.setContainerMaxMemoryLimit(containerId,
					owner, useDuccSpawn(), duccProcess.getCGroup()
							.getMaxMemoryLimit());
		}
		return false;
	}

	private String getContainerId() {
		String containerId;
		if (((ManagedProcess) super.managedProcess).getDuccProcess()
				.getProcessType().equals(ProcessType.Service)) {
			containerId = String.valueOf(((ManagedProcess) managedProcess)
					.getDuccProcess().getCGroup().getId());
		} else {
			containerId = ((ManagedProcess) managedProcess).getWorkDuccId()
					.getFriendly()
					+ "."
					+ ((ManagedProcess) managedProcess).getDuccProcess()
							.getCGroup().getId();
		}
		return containerId;
	}

	public Process exec(ICommandLine cmdLine, Map<String, String> processEnv)
			throws Exception {
		String methodName = "exec";
		try {
			String[] cmd = getDeployableCommandLine(cmdLine, processEnv);
			if (isKillCommand(cmdLine)) {
				logger.info(methodName, null, "Killing process");
				stopProcess(cmdLine, cmd);
			} else {
				IDuccProcess duccProcess = ((ManagedProcess) managedProcess)
						.getDuccProcess();
				// If running a real agent on a node, collect swap info and
				// assign max swap usage threshold
				// for each process. In virtual mode, where there are multiple
				// agents per node, we dont
				// set nor enforce swap limits.
				if (!agent.virtualAgent) {
					// Calculate how much swap space the process is allowed to
					// use. The calculation is based on
					// the percentage of real memory the process is assigned.
					// The process is entitled the
					// same percentage of the swap.
					// Normalize node's total memory as it is expressed in KB.
					// The calculation below is based on bytes.
					double percentOfTotal = ((double) duccProcess.getCGroup()
							.getMaxMemoryLimit())
							/ (agent.getNodeInfo().getNodeMetrics()
									.getNodeMemory().getMemTotal() * 1024); // need
																			// bytes

					// substract 1Gig from total swap on this node to
					// accommodate OS needs for swapping. The
					// getSwapTotal() returns swap space in KBs so normalize
					// 1Gig
					long adjustedTotalSwapAvailable = agent.getNodeInfo()
							.getNodeMetrics().getNodeMemory().getSwapTotal() - 1048576;
					// calculate the portion (in bytes) of swap this process is
					// entitled to
					long maxProcessSwapUsage = (long) (adjustedTotalSwapAvailable * percentOfTotal) * 1024;
					// assigned how much swap this process is entitled to. If it
					// exceeds this number the Agent
					// will kill the process.
					((ManagedProcess) managedProcess)
							.setMaxSwapThreshold(maxProcessSwapUsage);
					logger.info(
							methodName,
							null,
							"---Process DuccId:"
									+ duccProcess.getDuccId()
									+ " CGroup.getMaxMemoryLimit():"
									+ ((duccProcess.getCGroup()
											.getMaxMemoryLimit() / 1024) / 1024)
									+ " MBs"
									+ " Node Memory Total:"
									+ (agent.getNodeInfo().getNodeMetrics()
											.getNodeMemory().getMemTotal() / 1024)
									+ " MBs" + " Percentage Of Real Memory:"
									+ percentOfTotal
									+ " Adjusted Total Swap Available On Node:"
									+ adjustedTotalSwapAvailable / 1024
									+ " MBs" + " Process Entitled To Max:"
									+ (maxProcessSwapUsage / 1024) / 1024
									+ " MBs of Swap");

					// logger.info(methodName, null,
					// "The Process With ID:"+duccProcess.getDuccId()+" is Entitled to the Max "+(
					// (maxProcessSwapUsage/1024)/1024)+" Megs of Swap Space");
					// if configured to use cgroups and the process is the
					// cgroup owner, create a cgroup
					// using Process DuccId as a name. Additional processes may
					// be injected into the
					// cgroup by declaring cgroup owner id.
					if (agent.useCgroups) {
						// JDs are of type Pop (Plain Old Process). JDs run in a
						// reservation. The cgroup container
						// is created for the reservation and we co-locate as
						// many JDs as we can fit in it.
						// String containerId = ((ManagedProcess)
						// managedProcess).getWorkDuccId()+"."+duccProcess.getCGroup().getId().getFriendly();
						String containerId = getContainerId();
						logger.info(methodName, null,
								"Checking for CGroup Existance with ID:"
										+ containerId);
						if (!agent.cgroupsManager
								.cgroupExists(agent.cgroupsManager
										.getDuccCGroupBaseDir()
										+ "/"
										+ containerId)) {
							logger.info(methodName, null, "No CGroup with ID:"
									+ containerId + " Found");
							boolean failed = false;
							// create cgroup container for JDs
							try {
								if (createCGroupContainer(duccProcess,
										containerId,
										((ManagedProcess) super.managedProcess)
												.getOwner())) {
									logger.info(
											methodName,
											null,
											"Created CGroup with ID:"
													+ containerId
													+ " With Memory Limit="
													+ ((ManagedProcess) super.managedProcess)
															.getDuccProcess()
															.getCGroup()
															.getMaxMemoryLimit()
													+ " Bytes");
								} else {
									logger.info(methodName, null,
											"Failed To Create CGroup with ID:"
													+ containerId);
									duccProcess
											.setProcessState(ProcessState.Failed);
									duccProcess
											.setReasonForStoppingProcess("CGroupCreationFailed");
									failed = true;
									//agent.stop();
								}
							} catch (Exception e) {
								logger.error(methodName, null, e);
								failed = true;
								duccProcess
								    .setProcessState(ProcessState.Failed);
						        duccProcess
								    .setReasonForStoppingProcess("CGroupCreationFailed");
								//agent.stop();
							}
							if (failed) {
								logger.error(methodName, null, new RuntimeException(
										"The Agent is Unable To Create A CGroup with Container ID: "
												+ containerId
												+ ". Rejecting Deployment of Process with ID:"
												+ duccProcess.getDuccId()));
								return managedProcess;
							}
						} else {
							logger.info(methodName, null,
									"CGroup Exists with ID:" + containerId);

						}

						String[] cgroupCmd = new String[cmd.length + 3];
						cgroupCmd[0] = agent.cgroupsManager
								.getCGroupsUtilsDir() + "/cgexec";
						cgroupCmd[1] = "-g";
						cgroupCmd[2] = agent.cgroupsManager.getSubsystems()
								+ ":ducc/" + containerId;
						int inx = 3;
						for (String cmdPart : cmd) {
							cgroupCmd[inx++] = cmdPart;
						}
						startProcess(cmdLine, cgroupCmd, processEnv);
					} else {
						// Not configured to use CGroups
						startProcess(cmdLine, cmd, processEnv);
					}
				} else {
					// dont use CGroups on virtual agents
					startProcess(cmdLine, cmd, processEnv);
				}

			}
			return managedProcess;
		} catch (Exception e) {
			if (((ManagedProcess) super.managedProcess).getDuccProcess() != null) {
				DuccId duccId = ((ManagedProcess) super.managedProcess)
						.getDuccId();
				logger.error(methodName, duccId,
						((ManagedProcess) super.managedProcess)
								.getDuccProcess().getDuccId(), e,
						new Object[] {});
			}
			throw e;
		}
	}

	private void stopProcess(ICommandLine cmdLine, String[] cmd)
			throws Exception {
		String methodName = "stopProcess";


		Future<?> future = ((ManagedProcess) managedProcess).getFuture();
		if (future == null) {
		    throw new Exception(
					"Future Object not Found. Unable to Stop Process with PID:"
					+ ((ManagedProcess) managedProcess).getPid());
		}
		// for stop to work, PID must be provided
		if (((ManagedProcess) managedProcess).getDuccProcess().getPID() == null
		    || ((ManagedProcess) managedProcess).getDuccProcess().getPID()
		    .trim().length() == 0) {
		    throw new Exception(
					"Process Stop Command Failed. PID not provided.");
		}
		long maxTimeToWaitForProcessToStop = 60000; // default 1 minute
		if (super.agent.configurationFactory.processStopTimeout != null) {
		    maxTimeToWaitForProcessToStop = Long
			.valueOf(super.agent.configurationFactory.processStopTimeout);
		}
		try {
		    // NEW Code
		    logger.info(methodName,
				((ManagedProcess) super.managedProcess).getDuccId(),
				">>>>>>>>>>>>>>> Stopping Process:"
				+ ((ManagedProcess) managedProcess).getPid());
		    ICommandLine cmdL;
		    if (Utils.isWindows()) {
			cmdL = new NonJavaCommandLine("taskkill");
			cmdL.addArgument("/PID");
		    } else {
			cmdL = new NonJavaCommandLine("/bin/kill");
			cmdL.addArgument("-15");
		    }
		    cmdL.addArgument(((ManagedProcess) managedProcess)
				     .getDuccProcess().getPID());

		    String[] sigTermCmdLine = getDeployableCommandLine(cmdL,
								       new HashMap<String, String>());
		    doExec(new ProcessBuilder(sigTermCmdLine), sigTermCmdLine,
			   true);

		    try {
			logger.info(methodName,
				    ((ManagedProcess) super.managedProcess)
				    .getDuccId(),
				    "------------ Agent Starting Killer Timer Task For Process with PID:"
				    + ((ManagedProcess) managedProcess)
				    .getDuccProcess().getPID()
				    + " Process State: "
				    + ((ManagedProcess) managedProcess)
				    .getDuccProcess()
				    .getProcessState());
			future.get(maxTimeToWaitForProcessToStop,
				   TimeUnit.MILLISECONDS);

		    } catch(TimeoutException te) {
			    
			    logger.info(
					methodName,
					((ManagedProcess) super.managedProcess)
					.getDuccId(),
					"------------ Agent Timed-out Waiting for Process with PID:"
					+ ((ManagedProcess) managedProcess)
					.getDuccProcess().getPID()
					+ " to Stop. Process State:"
					+ ((ManagedProcess) managedProcess)
					.getDuccProcess()
					.getProcessState()
					+ " .Process did not stop in allotted time of "
					+ maxTimeToWaitForProcessToStop
					+ " millis");
			    logger.info(methodName,
					((ManagedProcess) super.managedProcess)
					.getDuccId(),
					">>>>>>>>>>>>>>> Killing Process:"
					+ ((ManagedProcess) managedProcess)
					.getDuccProcess().getPID()
					+ " .Process State:"
					+ ((ManagedProcess) managedProcess)
					.getDuccProcess()
					.getProcessState());
			    doExec(new ProcessBuilder(cmd), cmd, true);

			}

		} catch (Exception e) { // InterruptedException, ExecutionException
		    logger.error(methodName,
				 ((ManagedProcess) super.managedProcess).getDuccId(), e,
				 new Object[] {});
		}

	}

	private void startProcess(ICommandLine cmdLine, String[] cmd,
			Map<String, String> processEnv) throws Exception {
		String methodName = "startProcess";

		String millis;
		millis = TimeStamp.getCurrentMillis();

		ProcessBuilder pb = new ProcessBuilder(cmd);

		if (((ManagedProcess) super.managedProcess).getDuccProcess()
				.getProcessType().equals(ProcessType.Pop)
				|| ((ManagedProcess) super.managedProcess).getDuccProcess()
						.getProcessType().equals(ProcessType.Service)) {
			ITimeWindow twi = new TimeWindow();
			((ManagedProcess) managedProcess).getDuccProcess()
					.setTimeWindowInit(twi);
			twi.setStart(millis);
			twi.setEnd(millis);

			ITimeWindow twr = new TimeWindow();
			((ManagedProcess) managedProcess).getDuccProcess()
					.setTimeWindowRun(twr);
			twr.setStart(millis);

		}

		Map<String, String> env = pb.environment();
		// Dont enherit agent's environment
		env.clear();
		// enrich Process environment
		env.putAll(processEnv);
		if (cmdLine instanceof ACommandLine) {
			// enrich Process environment with one from a given command line
			env.putAll(((ACommandLine) cmdLine).getEnvironment());
		}
		if (logger.isTrace()) {
			for (Entry<String, String> entry : env.entrySet()) {
				String message = "key:" + entry.getKey() + " " + "value:"
						+ entry.getValue();
				logger.trace(methodName,
						((ManagedProcess) super.managedProcess).getDuccId(),
						message);

			}
		}
		try {
			doExec(pb, cmd, isKillCommand(cmdLine));
		} catch (Exception e) {
			throw e;
		} finally {
			// millis = TimeStamp.getCurrentMillis();
			// twr.setEnd(millis);
		}
	}

	/**
	 * Checks if a given process is AP. The code checks if process type is POP
	 * and it is *not* JD
	 * 
	 * @param process
	 *            - process instance
	 * @return - true if AP, false otherwise
	 */
	private boolean isAP(ManagedProcess process) {
		if (!process.isJd()
				&& process.getDuccProcess().getProcessType()
						.equals(ProcessType.Pop)) {
			return true;
		} else {
			return false;
		}
	}

	private void doExec(ProcessBuilder pb, String[] cmd, boolean isKillCmd)
			throws Exception {
		String methodName = "doExec";
		int exitCode = 0;
		boolean failed = false;
		try {

			StringBuilder sb = new StringBuilder(
					(isKillCommand(cmdLine) ? "--->Killing Process "
							: "---> Launching Process:")
							+ " Using command line:");
			int inx = 0;
			for (String cmdPart : cmd) {
				sb.append("\n\t[")
						.append(inx++)
						.append("]")
						.append(Utils.resolvePlaceholderIfExists(cmdPart,
								System.getProperties()));
			}
			logger.info(methodName,
					((ManagedProcess) super.managedProcess).getDuccId(),
					sb.toString());

			
			java.lang.Process process = pb.start();
			// Drain process streams
			postExecStep(process, logger, isKillCmd);
			// block waiting for the process to terminate.
			exitCode = process.waitFor();
			if (!isKillCommand(cmdLine)) {
				logger.info(methodName, ((ManagedProcess) super.managedProcess)
						.getDuccId(), ">>>>>>>>>>>>> Process with PID:"
						+ ((ManagedProcess) super.managedProcess)
								.getDuccProcess().getPID()
						+ " Terminated. Exit Code:" + exitCode);
				// Process is dead, determine if the cgroup container should be
				// destroyed as well.
				if (agent.useCgroups) {
					String containerId = getContainerId();
					String userId = ((ManagedProcess) super.managedProcess)
					.getOwner();
					// before destroying the container the code checks if there
					// are processes still running in it. This could be true if
					// user code launched child processes. If there are child
					// processes still running, the code kills each one at a 
					// time and at the end the container is removed.
					agent.cgroupsManager.destroyContainer(containerId, userId, NodeAgent.SIGKILL);
					logger.info(methodName, null,
							"Removed CGroup Container with ID:" + containerId);
				}
			}

		} catch (NullPointerException ex) {
			((ManagedProcess) super.managedProcess).getDuccProcess()
					.setProcessState(ProcessState.Failed);
			StringBuffer sb = new StringBuffer();
			sb.setLength(0);
			sb.append("\n\tJava ProcessBuilder Failed to Launch Process due to NullPointerException. An Entry in the Command Array Must be Null. Look at Command Array Below:\n");
			for (String cmdPart : cmd) {
				if (cmdPart != null) {
					sb.append("\n\t").append(cmdPart);
				}
			}
			logger.info(methodName,
					((ManagedProcess) super.managedProcess).getDuccId(),
					sb.toString());
			((ManagedProcess) super.managedProcess).getDuccProcess()
					.setProcessState(ProcessState.Failed);
			throw ex;
		} catch (Exception ex) {
			((ManagedProcess) super.managedProcess).getDuccProcess()
					.setProcessState(ProcessState.LaunchFailed);

			((ManagedProcess) super.managedProcess).getDuccProcess().setProcessExitCode(-1);  // overwrite process exit code if stderr has a msg 

		        StringWriter stackTraceBuffer = new StringWriter();
			ex.printStackTrace(new PrintWriter(stackTraceBuffer));

			((ManagedProcess) managedProcess).getDuccProcess()
					    .setReasonForStoppingProcess(stackTraceBuffer.toString());
                        failed = true;
			logger.info(methodName, 
                                    ((ManagedProcess) super.managedProcess).getDuccId(),
                                    "Failed to launch Process - Reason:"+stackTraceBuffer.toString());
			
			throw ex;
		} finally {
		    if ( !failed ) {
			// associate exit code
			((ManagedProcess) managedProcess).getDuccProcess()
					.setProcessExitCode(exitCode);

		    } 

			// Per team discussion on Aug 31 2011, the process is stopped by an
			// agent when initialization
			// times out or initialization failed. Both Initialization_Timeout
			// and FailedIntialization imply
			// that the process is stopped. If the process is AP and it exited
			// it should be marked
			// as Stopped. If the exit was due to Ducc kill mark reason as
			// KilledByDucc otherwise we have
			// no way of knowing why the process exited and in such case reason
			// is Other.
			if ((isAP((ManagedProcess) super.managedProcess))) {

			    // if failed to execute the command line, the process state is already set to Failed
			    if ( !((ManagedProcess) super.managedProcess).getDuccProcess()
				 .getProcessState().equals(ProcessState.LaunchFailed)) {

				((ManagedProcess) managedProcess).getDuccProcess()
						.setProcessState(ProcessState.Stopped);
			    } 


				if (((ManagedProcess) super.managedProcess).doKill()) { // killed
																		// by
																		// agent/ducc
					((ManagedProcess) managedProcess).getDuccProcess()
							.setReasonForStoppingProcess(
									ReasonForStoppingProcess.KilledByDucc
											.toString());
				} else if ( !failed ) {

				    ((ManagedProcess) managedProcess).getDuccProcess()
							.setReasonForStoppingProcess(
									ReasonForStoppingProcess.Other.toString());
				}

			} else if ( !isKillCommand(cmdLine) &&
                                        !((ManagedProcess) managedProcess).getDuccProcess()
					.getProcessState()
					.equals(ProcessState.InitializationTimeout)
					&& !((ManagedProcess) managedProcess).getDuccProcess()
							.getProcessState()
							.equals(ProcessState.FailedInitialization)
					&& !((ManagedProcess) managedProcess).getDuccProcess()
							.getProcessState().equals(ProcessState.Failed)
					&& !((ManagedProcess) managedProcess).getDuccProcess()
							.getProcessState().equals(ProcessState.LaunchFailed)
					&& !((ManagedProcess) managedProcess).getDuccProcess()
							.getProcessState().equals(ProcessState.Killed)) {
				((ManagedProcess) managedProcess).getDuccProcess()
						.setProcessState(ProcessState.Stopped);
			}
		}

	}

	private String[] getDeployableCommandLine(ICommandLine cmdLine,
			Map<String, String> processEnv) throws Exception {
		// String methodName = "getDeployableCommandLine";
		String[] cmd = new String[0];

		try {
			// lock using Agent single permit semaphore. The
			// Utils.concatAllArrays()
			// uses native call (for efficiency) which appears not thread safe.
			NodeAgent.lock();
			// Use ducc_ling (c code) as a launcher for the actual process. The
			// ducc_ling
			// allows the process to run as a specified user in order to write
			// out logs in
			// user's space as oppose to ducc space.
			String c_launcher_path = Utils.resolvePlaceholderIfExists(
					System.getProperty("ducc.agent.launcher.ducc_spawn_path"),
					System.getProperties());

			// if the command line is kill, don't provide any logging info to
			// the ducc_ling. Otherwise,
			// ducc_ling creates and empty log for each time we are killing a
			// process
			if (isKillCommand(cmdLine)) {
				// Duccling, with no logging, always run by ducc, no need for
				// workingdir
				String[] duccling_nolog = new String[] { c_launcher_path, "-u",
						((ManagedProcess) super.managedProcess).getOwner(),
						"--" };
				if (useDuccSpawn()) {
					cmd = Utils.concatAllArrays(duccling_nolog,
							new String[] { cmdLine.getExecutable() },
							cmdLine.getCommandLine());
				} else {
					cmd = Utils.concatAllArrays(
							new String[] { cmdLine.getExecutable() },
							cmdLine.getCommandLine());
				}
				
			} else {
				String processType = "-UIMA-";
				// If Java then may run many JPs from the same cmdLine so make a local copy that we can modify
				if (cmdLine instanceof JavaCommandLine) {
				  cmdLine = ((JavaCommandLine)cmdLine).copy();
				}
				switch (((ManagedProcess) super.managedProcess)
						.getDuccProcess().getProcessType()) {
				case Pop:
					// Both JD and POP arbitrary process are POPs. Assume this
					// is an arbitrary process
					processType = "-POP-";
					if (cmdLine instanceof JavaCommandLine) {
						for (String option : cmdLine.getOptions()) {
							// Both services and JD have processType=POP.
							// However, only the JD
							// will have -Dducc.deploy.components option set.
							if (option.startsWith("-Dducc.deploy.components=")) {
								processType = "-JD-";
								((ManagedProcess) super.managedProcess)
										.setIsJD(); // mark this process as JD
								break;
							}
						}
					}
					break;
				case Service:
					// processType = "-AP-";
					break;
				case Job_Uima_AS_Process:
					processType = "-UIMA-";
					boolean isDucc20JpProcess = false;
					boolean isDucc20ServiceProcess = false;
					// determine if we are launching Ducc2.0 or Ducc1.+ JP
					List<String> options = cmdLine.getOptions();
					for( String option : options ) {
						if (option.indexOf(FlagsHelper.Name.JpType.pname()) > -1) {
							isDucc20JpProcess = true;
						}
						if (option.indexOf("ducc.deploy.components=service") > -1) {
							isDucc20ServiceProcess = true;
						}
					}
					
					// Add main class and component type to the command line
					if (isDucc20JpProcess) {
						if (!isDucc20ServiceProcess) {
						  cmdLine.addOption("-Dducc.deploy.components=job-process");
						}
						((JavaCommandLine)cmdLine).setClassName("org.apache.uima.ducc.user.common.main.DuccJobService");
					} else {
					  cmdLine.addOption("-Dducc.deploy.components=uima-as");
					  ((JavaCommandLine)cmdLine).setClassName("org.apache.uima.ducc.common.main.DuccService");
					}
					break;
				}
				String processLogDir = ((ManagedProcess) super.managedProcess)
						.getProcessInfo().getLogDirectory()
						+ (((ManagedProcess) super.managedProcess)
								.getProcessInfo().getLogDirectory()
								.endsWith(File.separator) ? "" : File.separator)
						+ ((ManagedProcess) super.managedProcess)
								.getWorkDuccId() + File.separator;
				String processLogFile = ((ManagedProcess) super.managedProcess)
						.getWorkDuccId() + processType + host;
				String workingDir = ((ManagedProcess) super.managedProcess)
						.getProcessInfo().getWorkingDirectory();
				if (workingDir == null) {
					workingDir = "NONE";
				}

				// Duccling, with logging
				String[] duccling = new String[] { c_launcher_path, "-f",
						processLogDir + processLogFile, "-w", workingDir, "-u",
						((ManagedProcess) super.managedProcess).getOwner(),
						"--" };

				String executable = cmdLine.getExecutable();
				// Check if user specified which java to use to launch the
				// process. If not provided,
				// use the same java that the agent is running with
				if (executable == null || executable.trim().length() == 0) {
					executable = System.getProperty("java.home")
							+ File.separator + "bin" + File.separator + "java";
				}

				if (cmdLine instanceof JavaCommandLine) {
					String duccHomePath = Utils.findDuccHome();
					cmdLine.addOption("-DDUCC_HOME=" + duccHomePath);
					cmdLine.addOption("-Dducc.deploy.configuration="
								+ System.getProperty("ducc.deploy.configuration"));
					// UIMA-4935 Following moved from CommandExecutor to avoid duplications in the shared cmdLine
					cmdLine.addOption("-Dducc.deploy.JpUniqueId="
					        + ((ManagedProcess) managedProcess).getDuccId().getUnique());
					
          if (System.getProperties().containsKey("ducc.agent.managed.process.state.update.endpoint.type")) {
            String type = System.getProperty("ducc.agent.managed.process.state.update.endpoint.type");
            if (type != null && type.equalsIgnoreCase("socket")) {
              cmdLine.addOption("-D" + NodeAgent.ProcessStateUpdatePort + "="
                      + System.getProperty(NodeAgent.ProcessStateUpdatePort));
            }
          }
					// NOTE - These are redundant since the information is also
					// in the environment for both Java and non-Java processes
					cmdLine.addOption("-Dducc.process.log.dir="	+ processLogDir);
					cmdLine.addOption("-Dducc.process.log.basename=" + processLogFile); 
					cmdLine.addOption("-Dducc.job.id=" + ((ManagedProcess) super.managedProcess).getWorkDuccId());
				}
				
				if (useDuccSpawn()) {
					cmd = Utils.concatAllArrays(duccling,
							new String[] { executable },
							cmdLine.getCommandLine());
				} else {
					cmd = Utils.concatAllArrays(new String[] { executable },
							cmdLine.getCommandLine());
				}
				// add JobId and the log prefix to the env so additional
				// similarly-named log files can be created
				processEnv.put(IDuccUser.EnvironmentVariable.DUCC_ID_JOB.value(), String
						.valueOf(((ManagedProcess) super.managedProcess)
								.getWorkDuccId().getFriendly()));
				processEnv.put(IDuccUser.EnvironmentVariable.DUCC_LOG_PREFIX.value(), processLogDir
						+ processLogFile);
			}
			return cmd;
		} catch (Exception ex) {
			((ManagedProcess) super.managedProcess).getDuccProcess()
					.setProcessState(ProcessState.Failed);
			throw ex;
		} finally {
			NodeAgent.unlock();
		}

	}

	public void stop() {
	}
}
