### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core.tests.compiler Index: src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java,v retrieving revision 1.59 diff -u -r1.59 BatchCompilerTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java 21 Apr 2006 18:48:16 -0000 1.59 +++ src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java 15 May 2006 08:24:25 -0000 @@ -2914,8 +2914,88 @@ + " -1.5 -g -preserveAllLocals" + " -d \"" + OUTPUT_DIR + File.separator + "X.java\"", "", - "No .class file created for file X.class in ---OUTPUT_DIR_PLACEHOLDER---/X.java because of an IOException: The output directory is a file : ---OUTPUT_DIR_PLACEHOLDER---/X.java\n", - true); + "No .class file created for file X.class in ---OUTPUT_DIR_PLACEHOLDER" + + "---/X.java because of an IOException: Regular file " + + "---OUTPUT_DIR_PLACEHOLDER---/X.java cannot be used " + + "as output directory\n", + true); +} +// suggested by https://bugs.eclipse.org/bugs/show_bug.cgi?id=141522 +// only checking messages (the bug itself involves concurrent access to +// the file system and a true test case would call for instrumented +// code) +public void test054(){ + this.runConformTest( + new String[] { + "X.java", + "public class X {}", + "f", // create simple file f + "" + }, + "\"" + OUTPUT_DIR + File.separator + "X.java\"" + + " -1.5 -g -preserveAllLocals" + + " -d \"" + OUTPUT_DIR + "/f/out\"", + "", + "No .class file created for file X.class in ---OUTPUT_DIR_PLACEHOLDER" + + "---/f/out because of an IOException: " + + "Could not create output directory ---OUTPUT_DIR_PLACEHOLDER---/f/out\n", + true); +} +// suggested by https://bugs.eclipse.org/bugs/show_bug.cgi?id=141522 +// only checking messages (the bug itself involves concurrent access to +// the file system and a true test case would call for instrumented +// code) +// this test only works on appropriate file systems +public void test055(){ + if (File.separatorChar == '/') { + String tentativeOutputDirNameTail = + File.separator + "out"; + File outputDirectory = new File(OUTPUT_DIR + tentativeOutputDirNameTail); + outputDirectory.mkdirs(); + outputDirectory.setReadOnly(); + // read-only directories do not prevent file creation + // on under-gifted file systems + this.runConformTest( + new String[] { + "p/X.java", + "package p;\n" + + "public class X {}", + }, + "\"" + OUTPUT_DIR + File.separator + "p/X.java\"" + + " -1.5 -g -preserveAllLocals" + + " -d \"" + OUTPUT_DIR + "/out\"", + "", + "No .class file created for file p/X.class in " + + "---OUTPUT_DIR_PLACEHOLDER---/out because of " + + "an IOException: Could not create subdirectory p into output directory " + + "---OUTPUT_DIR_PLACEHOLDER---/out\n", + false /* do not flush output directory */); + } +} +// suggested by https://bugs.eclipse.org/bugs/show_bug.cgi?id=141522 +// only checking messages (the bug itself involves concurrent access to +// the file system and a true test case would call for instrumented +// code) +public void test056(){ + String tentativeOutputDirNameTail = + File.separator + "out"; + this.runConformTest( + new String[] { + "p/X.java", + "package p;\n" + + "public class X {}", + "out/p", // create simple file out/p + "" + }, + "\"" + OUTPUT_DIR + File.separator + "p/X.java\"" + + " -1.5 -g -preserveAllLocals" + + " -d \"" + OUTPUT_DIR + tentativeOutputDirNameTail + "\"", + "", + "No .class file created for file p/X.class in " + + "---OUTPUT_DIR_PLACEHOLDER---/out" + + " because of an IOException: Regular file ---OUTPUT_DIR_PLACEHOLDER---" + + "/out/p cannot be used as output directory\n", + true); } public static Class testClass() { return BatchCompilerTest.class; #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/internal/compiler/messages.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/messages.properties,v retrieving revision 1.6 diff -u -r1.6 messages.properties --- compiler/org/eclipse/jdt/internal/compiler/messages.properties 18 Apr 2006 19:08:15 -0000 1.6 +++ compiler/org/eclipse/jdt/internal/compiler/messages.properties 15 May 2006 08:24:30 -0000 @@ -23,9 +23,9 @@ compilation_internalError = Internal compiler error ### output -output_isFile = The output directory is a file : {0} -output_notValidAll = The output directory {0} is not a valid directory name. All the directories cannot be created -output_notValid = The output directory ''{0}'' is not a valid directory name. The directory cannot be created +output_isFile = Regular file {0} cannot be used as output directory +output_notValidAll = Could not create output directory {0} +output_notValid = Could not create subdirectory {0} into output directory {1} ### problem problem_noSourceInformation = Index: compiler/org/eclipse/jdt/internal/compiler/ClassFile.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java,v retrieving revision 1.137 diff -u -r1.137 ClassFile.java --- compiler/org/eclipse/jdt/internal/compiler/ClassFile.java 18 Apr 2006 19:08:15 -0000 1.137 +++ compiler/org/eclipse/jdt/internal/compiler/ClassFile.java 15 May 2006 08:24:30 -0000 @@ -117,18 +117,28 @@ outputPath = outputPath.substring(0, outputPath.length() - 1); } f = new File(outputPath); + boolean checkFileType = false; if (f.exists()) { - if (!f.isDirectory()) { - final String message = Messages.bind(Messages.output_isFile, f.getAbsolutePath()); - throw new IOException(message); - } + checkFileType = true; // pre-existed } else { // we have to create that directory if (!f.mkdirs()) { - final String message = Messages.bind(Messages.output_notValidAll, f.getAbsolutePath()); - throw new IOException(message); + if (f.exists()) { + // someone else created f -- need to check its type + checkFileType = true; + } else { + // no one could create f -- complain + throw new IOException(Messages.bind( + Messages.output_notValidAll, f.getAbsolutePath())); + } } } + if (checkFileType) { + if (!f.isDirectory()) { + throw new IOException(Messages.bind( + Messages.output_isFile, f.getAbsolutePath())); + } + } StringBuffer outDir = new StringBuffer(outputPath); outDir.append(fileSeparator); StringTokenizer tokenizer = @@ -136,15 +146,32 @@ String token = tokenizer.nextToken(); while (tokenizer.hasMoreTokens()) { f = new File(outDir.append(token).append(fileSeparator).toString()); + checkFileType = false; // reset if (f.exists()) { - // The outDir already exists, so we proceed the next entry - // System.out.println("outDir: " + outDir + " already exists."); + checkFileType = true; // this is suboptimal, but it catches corner cases + // in which a regular file pre-exists } else { - // Need to add the outDir - if (!f.mkdir()) { - throw new IOException(Messages.bind(Messages.output_notValid, f.getName())); - } - } + // we have to create that directory + if (!f.mkdir()) { + if (f.exists()) { + // someone else created f -- need to check its type + checkFileType = true; + } else { + // no one could create f -- complain + throw new IOException(Messages.bind( + Messages.output_notValid, + outDir.substring(outputPath.length() + 1, + outDir.length() - 1), + outputPath)); + } + } + } + if (checkFileType) { + if (!f.isDirectory()) { + throw new IOException(Messages.bind( + Messages.output_isFile, f.getAbsolutePath())); + } + } token = tokenizer.nextToken(); } // token contains the last one