1 /* 2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 6244047 27 * @author Jim Gish 28 * @summary throw more precise IOException when pattern specifies invalid directory 29 * 30 * @run main/othervm CheckLockLocationTest 31 */ 32 import java.io.File; 33 import java.io.FileOutputStream; 34 import java.io.IOException; 35 import java.io.OutputStream; 36 import java.nio.file.AccessDeniedException; 37 import java.nio.file.FileSystemException; 38 import java.nio.file.Files; 39 import java.nio.file.NoSuchFileException; 40 import java.nio.file.Path; 41 import java.nio.file.attribute.UserPrincipal; 42 import java.util.UUID; 43 import java.util.logging.FileHandler; 44 public class CheckLockLocationTest { 45 46 private static final String NON_WRITABLE_DIR = "non-writable-dir"; 47 private static final String NOT_A_DIR = "not-a-dir"; 48 private static final String WRITABLE_DIR = "writable-dir"; 49 private static final String NON_EXISTENT_DIR = "non-existent-dir"; 50 private static boolean runNonWritableDirTest; 51 main(String... args)52 public static void main(String... args) throws IOException { 53 // we'll base all file creation attempts on the system temp directory, 54 // %t and also try specifying non-existent directories and plain files 55 // that should be directories, and non-writable directories, 56 // to exercise all code paths of checking the lock location 57 // Note that on platforms like Windows that don't support 58 // setWritable() on a directory, we'll skip the non-writable 59 // directory test if setWritable(false) returns false. 60 // 61 File writableDir = setup(); 62 // we now have three files/directories to work with: 63 // writableDir 64 // notAdir 65 // nonWritableDir (may not be possible on some platforms) 66 // nonExistentDir (which doesn't exist) 67 runTests(writableDir); 68 } 69 70 /** 71 * @param writableDir in which log and lock file are created 72 * @throws SecurityException 73 * @throws RuntimeException 74 * @throws IOException 75 */ runTests(File writableDir)76 private static void runTests(File writableDir) throws SecurityException, 77 RuntimeException, IOException { 78 // Test 1: make sure we can create FileHandler in writable directory 79 try { 80 new FileHandler("%t/" + WRITABLE_DIR + "/log.log"); 81 } catch (IOException ex) { 82 throw new RuntimeException("Test failed: should have been able" 83 + " to create FileHandler for " + "%t/" + WRITABLE_DIR 84 + "/log.log in writable directory" 85 + (!writableDir.canRead() // concurrent tests running or user conf issue? 86 ? ": directory not readable.\n\tPlease check your " 87 + "environment and machine configuration." 88 : "."), ex); 89 } finally { 90 // the above test leaves files in the directory. Get rid of the 91 // files created and the directory 92 delete(writableDir); 93 } 94 95 // Test 2: creating FileHandler in non-writable directory should fail 96 if (runNonWritableDirTest) { 97 try { 98 new FileHandler("%t/" + NON_WRITABLE_DIR + "/log.log"); 99 throw new RuntimeException("Test failed: should not have been able" 100 + " to create FileHandler for " + "%t/" + NON_WRITABLE_DIR 101 + "/log.log in non-writable directory."); 102 } catch (AccessDeniedException ex) { 103 // the right exception was thrown, so continue. 104 } catch (IOException ex) { 105 throw new RuntimeException( 106 "Test failed: Expected exception was not an " 107 + "AccessDeniedException", ex); 108 } 109 } 110 111 // Test 3: creating FileHandler in non-directory should fail 112 try { 113 new FileHandler("%t/" + NOT_A_DIR + "/log.log"); 114 throw new RuntimeException("Test failed: should not have been able" 115 + " to create FileHandler for " + "%t/" + NOT_A_DIR 116 + "/log.log in non-directory."); 117 } catch (FileSystemException ex) { 118 // the right exception was thrown, so continue. 119 } catch (IOException ex) { 120 throw new RuntimeException("Test failed: exception thrown was not a " 121 + "FileSystemException", ex); 122 } 123 124 // Test 4: make sure we can't create a FileHandler in a non-existent dir 125 try { 126 new FileHandler("%t/" + NON_EXISTENT_DIR + "/log.log"); 127 throw new RuntimeException("Test failed: should not have been able" 128 + " to create FileHandler for " + "%t/" + NON_EXISTENT_DIR 129 + "/log.log in a non-existent directory."); 130 } catch (NoSuchFileException ex) { 131 // the right exception was thrown, so continue. 132 } catch (IOException ex) { 133 throw new RuntimeException("Test failed: Expected exception " 134 + "was not a NoSuchFileException", ex); 135 } 136 } 137 138 /** 139 * Setup all the files and directories needed for the tests 140 * 141 * @return writable directory created that needs to be deleted when done 142 * @throws RuntimeException 143 */ setup()144 private static File setup() throws RuntimeException { 145 // First do some setup in the temporary directory (using same logic as 146 // FileHandler for %t pattern) 147 String tmpDir = System.getProperty("java.io.tmpdir"); // i.e. %t 148 if (tmpDir == null) { 149 tmpDir = System.getProperty("user.home"); 150 } 151 File tmpOrHomeDir = new File(tmpDir); 152 // Create a writable directory here (%t/writable-dir) 153 File writableDir = new File(tmpOrHomeDir, WRITABLE_DIR); 154 if (!createFile(writableDir, true)) { 155 throw new RuntimeException("Test setup failed: unable to create" 156 + " writable working directory " 157 + writableDir.getAbsolutePath() ); 158 } 159 160 if (!writableDir.canRead()) { 161 throw new RuntimeException("Test setup failed: can't read " 162 + " writable working directory " 163 + writableDir.getAbsolutePath() ); 164 } 165 166 // writableDirectory and its contents will be deleted after the test 167 // that uses it. 168 169 // check that we can write in the new writable dir. 170 File dummyFile = new File(writableDir, UUID.randomUUID().toString() + ".txt" ); 171 try { 172 if (!dummyFile.createNewFile()) { 173 throw new RuntimeException("Test setup failed: can't create " 174 + " dummy file in writable working directory " 175 + dummyFile.getAbsolutePath() ); 176 } 177 try (OutputStream os = new FileOutputStream(dummyFile)) { 178 os.write('A'); 179 } finally { 180 dummyFile.delete(); 181 } 182 if (dummyFile.canRead()) { 183 throw new RuntimeException("Test setup failed: can't delete " 184 + " dummy file in writable working directory " 185 + dummyFile.getAbsolutePath() ); 186 } 187 System.out.println("Successfully created and deleted dummy file: " + 188 dummyFile.getAbsolutePath()); 189 } catch(IOException x) { 190 throw new RuntimeException("Test setup failed: can't write " 191 + " or delete dummy file in writable working directory " 192 + dummyFile.getAbsolutePath(), x); 193 } 194 195 // Create a plain file which we will attempt to use as a directory 196 // (%t/not-a-dir) 197 File notAdir = new File(tmpOrHomeDir, NOT_A_DIR); 198 if (!createFile(notAdir, false)) { 199 throw new RuntimeException("Test setup failed: unable to a plain" 200 + " working file " + notAdir.getAbsolutePath() ); 201 } 202 notAdir.deleteOnExit(); 203 204 // Create a non-writable directory (%t/non-writable-dir) 205 File nonWritableDir = new File(tmpOrHomeDir, NON_WRITABLE_DIR); 206 if (!createFile(nonWritableDir, true)) { 207 throw new RuntimeException("Test setup failed: unable to create" 208 + " a non-" 209 + "writable working directory " 210 + nonWritableDir.getAbsolutePath() ); 211 } 212 nonWritableDir.deleteOnExit(); 213 214 // make it non-writable 215 Path path = nonWritableDir.toPath(); 216 final boolean nonWritable = nonWritableDir.setWritable(false); 217 final boolean isWritable = Files.isWritable(path); 218 if (nonWritable && !isWritable) { 219 runNonWritableDirTest = true; 220 System.out.println("Created non writable dir for " 221 + getOwner(path) + " at: " + path.toString()); 222 } else { 223 runNonWritableDirTest = false; 224 System.out.println( "Test Setup WARNING: unable to make" 225 + " working directory " + nonWritableDir.getAbsolutePath() 226 + "\n\t non-writable for " + getOwner(path) 227 + " on platform " + System.getProperty("os.name")); 228 } 229 230 // make sure non-existent directory really doesn't exist 231 File nonExistentDir = new File(tmpOrHomeDir, NON_EXISTENT_DIR); 232 if (nonExistentDir.exists()) { 233 nonExistentDir.delete(); 234 } 235 System.out.println("Setup completed - writableDir is: " + writableDir.getPath()); 236 return writableDir; 237 } 238 getOwner(Path path)239 private static String getOwner(Path path) { 240 UserPrincipal user = null; 241 try { 242 user = Files.getOwner(path); 243 } catch (Exception x) { 244 System.err.println("Failed to get owner of: " + path); 245 System.err.println("\terror is: " + x); 246 } 247 return user == null ? "???" : user.getName(); 248 } 249 250 /** 251 * @param newFile 252 * @return true if file already exists or creation succeeded 253 */ createFile(File newFile, boolean makeDirectory)254 private static boolean createFile(File newFile, boolean makeDirectory) { 255 if (newFile.exists()) { 256 return true; 257 } 258 if (makeDirectory) { 259 return newFile.mkdir(); 260 } else { 261 try { 262 return newFile.createNewFile(); 263 } catch (IOException ioex) { 264 ioex.printStackTrace(); 265 return false; 266 } 267 } 268 } 269 270 /* 271 * Recursively delete all files starting at specified file 272 */ delete(File f)273 private static void delete(File f) { 274 if (f != null && f.isDirectory()) { 275 for (File c : f.listFiles()) 276 delete(c); 277 } 278 if (!f.delete()) 279 System.err.println( 280 "WARNING: unable to delete/cleanup writable test directory: " 281 + f ); 282 } 283 } 284