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