From a24b7af73c4e08e7b05935d30be10b1afd046dcc Mon Sep 17 00:00:00 2001 From: Mike Rennie Date: Tue, 17 Jul 2012 14:53:04 -0500 Subject: Bug 327193 - [patch] Launching command line exceeds the windows limit --- .../internal/launching/Standard11xVMRunner.java | 15 ++- .../jdt/internal/launching/StandardVMDebugger.java | 16 +++- .../jdt/internal/launching/StandardVMRunner.java | 104 ++++++++++++++++++++- 3 files changed, 123 insertions(+), 12 deletions(-) diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/Standard11xVMRunner.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/Standard11xVMRunner.java index dd967e2c2..1ea8b9d90 100644 --- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/Standard11xVMRunner.java +++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/Standard11xVMRunner.java @@ -44,11 +44,9 @@ public class Standard11xVMRunner extends StandardVMRunner { */ @Override public void run(VMRunnerConfiguration config, ILaunch launch, IProgressMonitor monitor) throws CoreException { - if (monitor == null) { monitor = new NullProgressMonitor(); } - IProgressMonitor subMonitor = new SubProgressMonitor(monitor, 1); subMonitor.beginTask(LaunchingMessages.StandardVMRunner_Launching_VM____1, 2); subMonitor.subTask(LaunchingMessages.StandardVMRunner_Constructing_command_line____2); // @@ -85,14 +83,23 @@ public class Standard11xVMRunner extends StandardVMRunner { combinedPath[offset] = classPath[i]; offset++; } - + int cpidx = -1; if (combinedPath.length > 0) { + cpidx = arguments.size(); arguments.add("-classpath"); //$NON-NLS-1$ arguments.add(convertClassPath(combinedPath)); } arguments.add(config.getClassToLaunch()); String[] programArgs= config.getProgramArguments(); + + String[] envp = prependJREPath(config.getEnvironment()); + String[] newenvp = checkClasspath(arguments, classPath, envp); + if(newenvp != null) { + envp = newenvp; + arguments.remove(cpidx); + arguments.remove(cpidx); + } addArguments(programArgs, arguments); String[] cmdLine= new String[arguments.size()]; @@ -108,7 +115,7 @@ public class Standard11xVMRunner extends StandardVMRunner { Process p= null; File workingDir = getWorkingDir(config); - p= exec(cmdLine, workingDir); + p= exec(cmdLine, workingDir, envp); if (p == null) { return; } diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMDebugger.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMDebugger.java index d29a76c10..2fe3fd104 100644 --- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMDebugger.java +++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMDebugger.java @@ -208,23 +208,31 @@ public class StandardVMDebugger extends StandardVMRunner { addBootClassPathArguments(arguments, config); 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); - String[] cmdLine= new String[arguments.size()]; - arguments.toArray(cmdLine); //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: /jre/bin String[] envp = prependJREPath(config.getEnvironment(), new Path(program)); + String[] newenvp = checkClasspath(arguments, cp, envp); + if(newenvp != null) { + envp = newenvp; + arguments.remove(cpidx); + arguments.remove(cpidx); + } + + String[] cmdLine= new String[arguments.size()]; + arguments.toArray(cmdLine); + // check for cancellation if (monitor.isCanceled()) { return; diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMRunner.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMRunner.java index 32103a832..a79b19f9f 100644 --- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMRunner.java +++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMRunner.java @@ -208,7 +208,6 @@ public class StandardVMRunner extends AbstractVMRunner { if (fileExists(exe)) { return exe.getAbsolutePath(); } - // not found abort(NLS.bind(LaunchingMessages.StandardVMRunner_Specified_executable__0__does_not_exist_for__1__4, new String[]{command, fVMInstance.getName()}), null, IJavaLaunchConfigurationConstants.ERR_INTERNAL_ERROR); @@ -282,7 +281,7 @@ public class StandardVMRunner extends AbstractVMRunner { IProgressMonitor subMonitor = new SubProgressMonitor(monitor, 1); subMonitor.beginTask(LaunchingMessages.StandardVMRunner_Launching_VM____1, 2); - subMonitor.subTask(LaunchingMessages.StandardVMRunner_Constructing_command_line____2); + subMonitor.subTask(LaunchingMessages.StandardVMRunner_Constructing_command_line____2); String program= constructProgramString(config); @@ -297,7 +296,9 @@ public class StandardVMRunner extends AbstractVMRunner { addBootClassPathArguments(arguments, config); String[] cp= config.getClassPath(); + int cpidx = -1; if (cp.length > 0) { + cpidx = arguments.size(); arguments.add("-classpath"); //$NON-NLS-1$ arguments.add(convertClassPath(cp)); } @@ -306,11 +307,18 @@ public class StandardVMRunner extends AbstractVMRunner { String[] programArgs= config.getProgramArguments(); addArguments(programArgs, arguments); + String[] envp = prependJREPath(config.getEnvironment()); + + String[] newenvp = checkClasspath(arguments, cp, envp); + if(newenvp != null) { + envp = newenvp; + arguments.remove(cpidx); + arguments.remove(cpidx); + } + String[] cmdLine= new String[arguments.size()]; arguments.toArray(cmdLine); - String[] envp = prependJREPath(config.getEnvironment()); - subMonitor.worked(1); // check for cancellation @@ -355,6 +363,94 @@ public class StandardVMRunner extends AbstractVMRunner { subMonitor.done(); } + /** + * Returns the index in the given array for the CLASSPATH variable + * @param env the environment array or null + * @return -1 or the index of the CLASSPATH variable + * @since 3.6.200 + */ + int getCPIndex(String[] env) { + if(env != null) { + for (int i = 0; i < env.length; i++) { + if(env[i].regionMatches(true, 0, "CLASSPATH=", 0, 10)) { //$NON-NLS-1$ + return i; + } + } + } + return -1; + } + + /** + * Checks to see if the command / classpath needs to be shortened for Windows. Returns the modified + * environment or null if no changes are needed. + * + * @param args the raw arguments from the runner + * @param cp the raw classpath from the runner configuration + * @param env the current environment + * @return the modified environment or null if no changes were made + * @sine 3.6.200 + */ + String[] checkClasspath(List args, String[] cp, String[] env) { + if(Platform.getOS().equals(Platform.OS_WIN32)) { + //count the complete command length + int size = 0; + for (String arg : args) { + if(arg != null) { + size += arg.length(); + } + } + //greater than 32767 is a no-go + //see http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx + if(size > 32767) { + StringBuffer newcp = new StringBuffer(); + for (int i = 0; i < cp.length; i++) { + newcp.append(cp[i]); + newcp.append(File.pathSeparatorChar); + } + String[] newenvp = null; + int index = -1; + if(env == null) { + Map nenv = DebugPlugin.getDefault().getLaunchManager().getNativeEnvironment(); + Entry entry = null; + newenvp = new String[nenv.size()]; + int idx = 0; + for (Iterator> i = nenv.entrySet().iterator(); i.hasNext();) { + entry = i.next(); + String value = entry.getValue(); + if(value == null) { + value = ""; //$NON-NLS-1$ + } + String key = entry.getKey(); + if(key.equalsIgnoreCase("CLASSPATH")) { //$NON-NLS-1$ + index = idx; + } + newenvp[idx] = key+'='+value+File.pathSeparatorChar; + idx++; + } + } + else { + newenvp = env; + index = getCPIndex(newenvp); + } + if(index < 0) { + newcp.insert(0, "CLASSPATH="); //$NON-NLS-1$ + String[] newenv = new String[newenvp.length+1]; + System.arraycopy(newenvp, 0, newenv, 0, newenvp.length); + newenv[newenvp.length] = newcp.toString(); + return newenv; + } + String oldcp = newenvp[index]; + if(!oldcp.endsWith(File.pathSeparator)) { + oldcp += File.pathSeparatorChar; + } + newcp.insert(0, oldcp); + newenvp[index] = newcp.toString(); + return newenvp; + } + } + return null; + } + /** * Prepends the correct java version variable state to the environment path for Mac VMs * -- cgit v1.2.3