Search this blog ...

Thursday, February 10, 2011

javac – file not found – wildcards and spaces in directory names

Calling the javac command from Windows XP with the source files argument containing a wildcard in quotes – e.g. javac "*.java" will result in the error:

javac: file not found:

Whereas with no quotes – e.g.  javac *.java , no error is produced.

Consider a source files argument containing both a path and wildcard combined  – e.g. javac C:\temp\*.java , this is perfectly fine and no error is produced.

The following however will fail –e.g. javac "C:\my documents\*.java" , due to the wildcard in quotes issue above.

Some may argue that this is perfectly reasonable, given that java does not allow spaces in package names.  But what if the java files above in the “my documents” folder are top-level classes without  package qualification – such as the file below:

e.g.

class Test
{
  public static void main(String[] args)
  {
    System.out.println("Hello World!");
  }
}

Consider a simple java kit that you deliver to folks with the following structure:-

MyApplication\

  bin\compile.bat
  lib\utilities.jar
  lib\resources.jar
  src\com\acme\myapp\Main.java
  src\com\acme\myapp\utils\Utils.java

If the kit above is extracted to some folder/directory without spaces, it should be pretty easy to compile from the command-line. Whereas if it were extracted to the standard Windows desktop location as shown below, more care must be taken:

C:\Documents and Settings\Administrator\Desktop\MyApplication\

  bin\compile.bat
  lib\utilities.jar
  lib\resources.jar
  src\com\acme\myapp\Main.java
  src\com\acme\myapp\utils\Utils.java

One will not be able to run javac "C:\Documents and Settings\Administrator\Desktop\MyApplication\src\com\acme\myapp\*.java" .  They must instead change directory to an appropriate location whereby the javac source files argument can be supplied without including quotes.  For example:

cd /D "C:\Documents and Settings\Administrator\Desktop\MyApplication"
javac src\com\acme\myapp\*.java

Below is a sample windows java compile batch script that I’ve created that should work with the application structure above regardless of what destination directory the kit is extracted to:-

compile.bat

@ECHO off

REM Changes made to an Environment Variable after SETLOCAL has been issued are local to the batch file.
REM Issuing an ENDLOCAL command will restore the previous environment variables.
SETLOCAL

REM Commands
SET JAVACMPCMD=%JAVA_HOME%\bin\javac.exe
SET JARCMD=%JAVA_HOME%\bin\jar.exe

REM library files and source location
SET PROJECT_LIB=%~dp0..\lib
SET PROJECT_SRC=%~dp0..\src
REM source base package path
SET BASE_PKG_PATH=%PROJECT_SRC%\com\acme\myapp

REM classes directory
SET PROJECT_CLASSES=%~dp0..\classes

REM generated library destination path and file
SET DEST_JAR_FILE=%~dp0..\myapp.jar

REM classpath for compilation
SET CP=%PROJECT_LIB%\utilities.jar;%PROJECT_LIB%\resources.jar

REM ************
REM MAIN PROGRAM
REM ************

REM Verify whether required variables are set
IF "%JAVA_HOME%x"=="x" GOTO errjava

REM Preparation ...
IF EXIST "%DEST_JAR_FILE%" DEL /q "%DEST_JAR_FILE%"
IF EXIST "%PROJECT_CLASSES%" RMDIR /s /q "%PROJECT_CLASSES%"
MKDIR "%PROJECT_CLASSES%"

ECHO.
ECHO Compiling code ...

PUSHD "%BASE_PKG_PATH%"
"%JAVACMPCMD%" -target 1.6 -classpath "%CP%" -d "%PROJECT_CLASSES%" *.java utils\*.java
SET ERR=%ERRORLEVEL%
POPD
IF NOT "%ERR%"=="0" GOTO errcomp

ECHO.
ECHO Creating jar file ...

"%JARCMD%" cfM "%DEST_JAR_FILE%" -C "%PROJECT_CLASSES%/" .
IF NOT "%ERRORLEVEL%"=="0" GOTO errjar

REM Cleanup ...
RMDIR /s /q "%PROJECT_CLASSES%"
GOTO end

REM JAVA_HOME is not set
:errjava
ECHO.
ECHO Set the following environment variables:
ECHO.
ECHO JAVA_HOME          (Absolute path to jdk directory)
GOTO end

:errcomp
ECHO.
ECHO Compilation did not succeed.
ECHO Note: If receiving read errors, ensure folder path does not contain whitespace.
GOTO end

:errjar
ECHO.
ECHO Jar creation did not succeed.
GOTO end

:end
ECHO.