JDK-7028657 : (process) Runtime.getRuntime().exec remove spaces from path and arguments
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 7
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS: windows_2003
  • CPU: x86
  • Submitted: 2011-03-17
  • Updated: 2013-03-04
  • Resolved: 2013-03-04
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
F:\asp\OFclient\Java_x64\jdk1.7.0\bin>java -version
java version "1.7.0-ea"
Java(TM) SE Runtime Environment (build 1.7.0-ea-b131)
Java HotSpot(TM) 64-Bit Server VM (build 21.0-b02, mixed mode)

FULL OS VERSION :
Microsoft Windows [Version 5.2.3790]

A DESCRIPTION OF THE PROBLEM :
when executing a command with "Runtime.getRuntime().exec" like this following command:
F:\\asp\\OFserver\\gs\\gs8.71\\bin\\gswin32c.exe @F:\\asp\\OFserver\\gs\\pdfwriter.rsp -sOutputFile="F:\\asp\\OFserver\\pdmw_pdf\\302234... -  TUBO.pdf" "F:\\asp\\OFserver\\docs\\Administrador\\302234... -  TUBO.pdf" -f

exec function remove one space from the name of pdf file


THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: Did not try

THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Did not try

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
import java.io.IOException;

public class Test {
	public static final void main(String[] args) {
		try {
			Process p = Runtime
					.getRuntime()
					.exec("F:\\asp\\OFserver\\gs\\gs8.71\\bin\\gswin32c.exe @F:\\asp\\OFserver\\gs\\pdfwriter.rsp -sOutputFile=\"F:\\asp\\OFserver\\docs\\Administrador\\302234... -  TUBO.pdf\" \"F:\\asp\\OFserver\\pdmw_pdf\\302234... -  TUBO.pdf\" -f");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

javac Test.java
java Test


EXPECTED VERSUS ACTUAL BEHAVIOR :
ghostscript generates a wrong file name pdf with blank contents
ERROR MESSAGES/STACK TRACES THAT OCCUR :
nothing

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.io.IOException;

public class Test {
	public static final void main(String[] args) {
		try {
			Process p = Runtime
					.getRuntime()
					.exec("F:\\asp\\OFserver\\gs\\gs8.71\\bin\\gswin32c.exe @F:\\asp\\OFserver\\gs\\pdfwriter.rsp -sOutputFile=\"F:\\asp\\OFserver\\docs\\Administrador\\302234... -  TUBO.pdf\" \"F:\\asp\\OFserver\\pdmw_pdf\\302234... -  TUBO.pdf\" -f");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
  To work arround this trouble I create a function that getShortName:
	/**
     * returns the short filename (8.3) for a file in Windows
     *
     * @param longFileName
     * @return a string with the short filename, or null if an error occurred or the
     *         file does not exist.
     */
    public String getShortName(String longFileName) {
	    String ShortName = "";
	    String FileName = "";
	    String strPath = "";
	    
	    for(int x=longFileName.length()-1; x>0; x--) {
	    	if(longFileName.charAt(x) == '\\') {
	    		strPath = longFileName.substring(0, x+1);
	    		break;
	    	}
	    }
	    
	    if(longFileName.indexOf(' ') > 0)
	    	FileName += '\"';
	    FileName += longFileName;
	    if(longFileName.indexOf(' ') > 0)
	    	FileName += '\"';
		try {
			
			File f = new File(longFileName);
			if(f.exists())
				System.out.println("Arquivo existe!");
			
			String[] cmd = {"cmd", "/c", "dir", "/x", FileName};
		    Runtime r = Runtime.getRuntime();
		    Process p = r.exec( cmd );
		    
			InputStreamReader isr = new InputStreamReader(p.getInputStream());
			BufferedReader br = new BufferedReader(isr);
			String line = null;

			boolean finished = false;  // Set to true when p is finished

		    while( !finished) {
				try {
					while ((line = br.readLine()) != null)
						ShortName += line;
				    // Ask the process for its exitValue.  If the process
				    // is not finished, an IllegalThreadStateException
				    // is thrown.  If it is finished, we fall through and
				    // the variable finished is set to true.
				    p.exitValue();
				    finished = true;
				    int i = ShortName.indexOf('~');
				    int j=i+1;
				    if(i < 0)
				    	return longFileName;
				    
				    for(;i>0 && ShortName.charAt(i) != ' '; i--);
				    for(;j<ShortName.length() && ShortName.charAt(j) != ' '; j++);
				    if(ShortName.charAt(i) == ' ')
				    	i++;
				    //if(ShortName.charAt(j) == ' ')
				    //	j--;
				    ShortName = ShortName.substring(i, j);
		        } catch (IllegalThreadStateException e) {
				    // Sleep a little to save on CPU cycles
				    Thread.currentThread().sleep(500);
				}
		    }
		} catch (Exception e) {
		    System.err.println( e);
		}
		return strPath + ShortName;
    }

and treated the spaces in the output file

Comments
To save arguments from primitive parsing in java.lang.Runtime.exec(java.lang.String) call the java.lang.Runtime.exec(java.lang.String[]) call need to be used. In accordance with spec java.lang.Runtime.exec(java.lang.String) call does not recognize ["] as argument value aggregator. Sequential spaces would be lost.
04-03-2013