1 /*
   2  * Copyright (c) 2012, 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.IOException;
  34 import java.nio.file.AccessDeniedException;
  35 import java.nio.file.FileSystemException;
  36 import java.nio.file.Files;
  37 import java.nio.file.NoSuchFileException;
  38 import java.nio.file.Path;
  39 import java.util.logging.FileHandler;
  40 public class CheckLockLocationTest {
  41 
  42     private static final String NON_WRITABLE_DIR = "non-writable-dir";
  43     private static final String NOT_A_DIR = "not-a-dir";
  44     private static final String WRITABLE_DIR = "writable-dir";
  45     private static final String NON_EXISTENT_DIR = "non-existent-dir";
  46     private static boolean runNonWritableDirTest;
  47 
  48     public static void main(String... args) throws IOException {
  49         // we'll base all file creation attempts on the system temp directory,
  50         // %t and also try specifying non-existent directories and plain files
  51         // that should be directories, and non-writable directories,
  52         // to exercise all code paths of checking the lock location
  53         // Note that on platforms like Windows that don't support
  54         // setWritable() on a directory, we'll skip the non-writable
  55         // directory test if setWritable(false) returns false.
  56         //
  57         File writableDir = setup();
  58         // we now have three files/directories to work with:
  59         //    writableDir
  60         //    notAdir
  61         //    nonWritableDir (may not be possible on some platforms)
  62         //    nonExistentDir (which doesn't exist)
  63         runTests(writableDir);
  64     }
  65 
  66     /**
  67      * @param writableDir in which log and lock file are created
  68      * @throws SecurityException
  69      * @throws RuntimeException
  70      * @throws IOException
  71      */
  72     private static void runTests(File writableDir) throws SecurityException,
  73             RuntimeException, IOException {
  74         // Test 1: make sure we can create FileHandler in writable directory
  75         try {
  76             new FileHandler("%t/" + WRITABLE_DIR + "/log.log");
  77         } catch (IOException ex) {
  78             throw new RuntimeException("Test failed: should have been able"
  79                     + " to create FileHandler for " + "%t/" + WRITABLE_DIR
  80                     + "/log.log in writable directory.", ex);
  81         } finally {
  82             // the above test leaves files in the directory.  Get rid of the
  83             // files created and the directory
  84             delete(writableDir);
  85         }
  86 
  87         // Test 2: creating FileHandler in non-writable directory should fail
  88         if (runNonWritableDirTest) {
  89             try {
  90                 new FileHandler("%t/" + NON_WRITABLE_DIR + "/log.log");
  91                 throw new RuntimeException("Test failed: should not have been able"
  92                         + " to create FileHandler for " + "%t/" + NON_WRITABLE_DIR
  93                         + "/log.log in non-writable directory.");
  94             } catch (AccessDeniedException ex) {
  95                 // the right exception was thrown, so continue.
  96             } catch (IOException ex) {
  97                 throw new RuntimeException(
  98                         "Test failed: Expected exception was not an "
  99                                 + "AccessDeniedException", ex);
 100             }
 101         }
 102 
 103         // Test 3: creating FileHandler in non-directory should fail
 104         try {
 105             new FileHandler("%t/" + NOT_A_DIR + "/log.log");
 106             throw new RuntimeException("Test failed: should not have been able"
 107                     + " to create FileHandler for " + "%t/" + NOT_A_DIR
 108                     + "/log.log in non-directory.");
 109         } catch (FileSystemException ex) {
 110             // the right exception was thrown, so continue.
 111         } catch (IOException ex) {
 112             throw new RuntimeException("Test failed: exception thrown was not a "
 113                     + "FileSystemException", ex);
 114         }
 115 
 116         // Test 4: make sure we can't create a FileHandler in a non-existent dir
 117         try {
 118             new FileHandler("%t/" + NON_EXISTENT_DIR + "/log.log");
 119             throw new RuntimeException("Test failed: should not have been able"
 120                     + " to create FileHandler for " + "%t/" + NON_EXISTENT_DIR
 121                     + "/log.log in a non-existent directory.");
 122         } catch (NoSuchFileException ex) {
 123             // the right exception was thrown, so continue.
 124         } catch (IOException ex) {
 125             throw new RuntimeException("Test failed: Expected exception "
 126                     + "was not a NoSuchFileException", ex);
 127         }
 128     }
 129 
 130     /**
 131      * Setup all the files and directories needed for the tests
 132      *
 133      * @return writable directory created that needs to be deleted when done
 134      * @throws RuntimeException
 135      */
 136     private static File setup() throws RuntimeException {
 137         // First do some setup in the temporary directory (using same logic as
 138         // FileHandler for %t pattern)
 139         String tmpDir = System.getProperty("java.io.tmpdir"); // i.e. %t
 140         if (tmpDir == null) {
 141             tmpDir = System.getProperty("user.home");
 142         }
 143         File tmpOrHomeDir = new File(tmpDir);
 144         // Create a writable directory here (%t/writable-dir)
 145         File writableDir = new File(tmpOrHomeDir, WRITABLE_DIR);
 146         if (!createFile(writableDir, true)) {
 147             throw new RuntimeException("Test setup failed: unable to create"
 148                     + " writable working directory "
 149                     + writableDir.getAbsolutePath() );
 150         }
 151         // writableDirectory and its contents will be deleted after the test
 152         // that uses it
 153 
 154         // Create a plain file which we will attempt to use as a directory
 155         // (%t/not-a-dir)
 156         File notAdir = new File(tmpOrHomeDir, NOT_A_DIR);
 157         if (!createFile(notAdir, false)) {
 158             throw new RuntimeException("Test setup failed: unable to a plain"
 159                     + " working file " + notAdir.getAbsolutePath() );
 160         }
 161         notAdir.deleteOnExit();
 162 
 163         // Create a non-writable directory (%t/non-writable-dir)
 164         File nonWritableDir = new File(tmpOrHomeDir, NON_WRITABLE_DIR);
 165         if (!createFile(nonWritableDir, true)) {
 166             throw new RuntimeException("Test setup failed: unable to create"
 167                     + " a non-"
 168                     + "writable working directory "
 169                     + nonWritableDir.getAbsolutePath() );
 170         }
 171         nonWritableDir.deleteOnExit();
 172 
 173         // make it non-writable
 174         Path path = nonWritableDir.toPath();
 175         final boolean nonWritable = nonWritableDir.setWritable(false);
 176         final boolean isWritable = Files.isWritable(path);
 177         if (nonWritable && !isWritable) {
 178             runNonWritableDirTest = true;
 179             System.out.println("Created non writable dir at: " + path.toString());
 180         } else {
 181             runNonWritableDirTest = false;
 182             System.out.println( "Test Setup WARNING: unable to make"
 183                     + " working directory " + nonWritableDir.getAbsolutePath()
 184                     + " non-writable on platform " + System.getProperty("os.name"));
 185 
 186         }
 187 
 188         // make sure non-existent directory really doesn't exist
 189         File nonExistentDir = new File(tmpOrHomeDir, NON_EXISTENT_DIR);
 190         if (nonExistentDir.exists()) {
 191             nonExistentDir.delete();
 192         }
 193         System.out.println("Setup completed - writableDir is: " + writableDir.getPath());
 194         return writableDir;
 195     }
 196 
 197     /**
 198      * @param newFile
 199      * @return true if file already exists or creation succeeded
 200      */
 201     private static boolean createFile(File newFile, boolean makeDirectory) {
 202         if (newFile.exists()) {
 203             return true;
 204         }
 205         if (makeDirectory) {
 206             return newFile.mkdir();
 207         } else {
 208             try {
 209                 return newFile.createNewFile();
 210             } catch (IOException ioex) {
 211                 ioex.printStackTrace();
 212                 return false;
 213             }
 214         }
 215     }
 216 
 217     /*
 218      * Recursively delete all files starting at specified file
 219      */
 220     private static void delete(File f) {
 221         if (f != null && f.isDirectory()) {
 222             for (File c : f.listFiles())
 223                 delete(c);
 224         }
 225         if (!f.delete())
 226             System.err.println(
 227                     "WARNING: unable to delete/cleanup writable test directory: "
 228                     + f );
 229         }
 230 }