src/share/classes/java/util/logging/FileHandler.java

Print this page

        

@@ -23,14 +23,23 @@
  * questions.
  */
 
 package java.util.logging;
 
-import java.io.*;
+import static java.nio.file.StandardOpenOption.CREATE_NEW;
+import static java.nio.file.StandardOpenOption.WRITE;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
 import java.nio.channels.FileChannel;
-import java.nio.channels.FileLock;
-import java.security.*;
+import java.nio.file.FileAlreadyExistsException;
+import java.nio.file.Paths;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 
 /**
  * Simple file logging <tt>Handler</tt>.
  * <p>
  * The <tt>FileHandler</tt> can either write to a specified file,

@@ -135,18 +144,20 @@
     private boolean append;
     private int limit;       // zero => no limit.
     private int count;
     private String pattern;
     private String lockFileName;
-    private FileOutputStream lockStream;
+    private FileChannel lockFileChannel;
     private File files[];
     private static final int MAX_LOCKS = 100;
     private static java.util.HashMap<String, String> locks = new java.util.HashMap<>();
 
-    // A metered stream is a subclass of OutputStream that
-    //   (a) forwards all its output to a target stream
-    //   (b) keeps track of how many bytes have been written
+    /**
+     * A metered stream is a subclass of OutputStream that
+     * (a) forwards all its output to a target stream
+     * (b) keeps track of how many bytes have been written
+     */
     private class MeteredStream extends OutputStream {
         OutputStream out;
         int written;
 
         MeteredStream(OutputStream out, int written) {

@@ -187,13 +198,14 @@
         BufferedOutputStream bout = new BufferedOutputStream(fout);
         meter = new MeteredStream(bout, len);
         setOutputStream(meter);
     }
 
-    // Private method to configure a FileHandler from LogManager
-    // properties and/or default values as specified in the class
-    // javadoc.
+    /**
+     * Configure a FileHandler from LogManager properties and/or default values
+     * as specified in the class javadoc.
+     */
     private void configure() {
         LogManager manager = LogManager.getLogManager();
 
         String cname = getClass().getName();
 

@@ -285,11 +297,12 @@
      * @exception  IOException if there are IO problems opening the files.
      * @exception  SecurityException  if a security manager exists and if
      *             the caller does not have <tt>LoggingPermission("control")</tt>.
      * @exception  IllegalArgumentException if pattern is an empty string
      */
-    public FileHandler(String pattern, boolean append) throws IOException, SecurityException {
+    public FileHandler(String pattern, boolean append) throws IOException,
+            SecurityException {
         if (pattern.length() < 1 ) {
             throw new IllegalArgumentException();
         }
         checkPermission();
         configure();

@@ -374,12 +387,14 @@
         this.count = count;
         this.append = append;
         openFiles();
     }
 
-    // Private method to open the set of output files, based on the
-    // configured instance variables.
+    /**
+     * Open the set of output files, based on the configured
+     * instance variables.
+     */
     private void openFiles() throws IOException {
         LogManager manager = LogManager.getLogManager();
         manager.checkPermission();
         if (count < 1) {
            throw new IllegalArgumentException("file count = " + count);

@@ -411,22 +426,22 @@
                 if (locks.get(lockFileName) != null) {
                     // We already own this lock, for a different FileHandler
                     // object.  Try again.
                     continue;
                 }
-                FileChannel fc;
+
                 try {
-                    lockStream = new FileOutputStream(lockFileName);
-                    fc = lockStream.getChannel();
-                } catch (IOException ix) {
-                    // We got an IOException while trying to open the file.
-                    // Try the next file.
+                    lockFileChannel = FileChannel.open(Paths.get(lockFileName),
+                            CREATE_NEW, WRITE);
+                } catch (FileAlreadyExistsException ix) {
+                    // try the next lock file name in the sequence
                     continue;
                 }
+
                 boolean available;
                 try {
-                    available = fc.tryLock() != null;
+                    available = lockFileChannel.tryLock() != null;
                     // We got the lock OK.
                 } catch (IOException ix) {
                     // We got an IOException while trying to get the lock.
                     // This normally indicates that locking is not supported
                     // on the target directory.  We have to proceed without

@@ -438,11 +453,11 @@
                     locks.put(lockFileName, lockFileName);
                     break;
                 }
 
                 // We failed to get the lock.  Try next file.
-                fc.close();
+                lockFileChannel.close();
             }
         }
 
         files = new File[count];
         for (int i = 0; i < count; i++) {

@@ -470,12 +485,21 @@
 
         // Install the normal default ErrorManager.
         setErrorManager(new ErrorManager());
     }
 
-    // Generate a filename from a pattern.
-    private File generate(String pattern, int generation, int unique) throws IOException {
+    /**
+     * Generate a file based on a user-supplied pattern, generation number,
+     * and an integer uniqueness suffix
+     * @param pattern the pattern for naming the output file
+     * @param generation the generation number to distinguish rotated logs
+     * @param unique a unique number to resolve conflicts
+     * @return the generated File
+     * @throws IOException
+     */
+    private File generate(String pattern, int generation, int unique)
+            throws IOException {
         File file = null;
         String word = "";
         int ix = 0;
         boolean sawg = false;
         boolean sawu = false;

@@ -546,11 +570,13 @@
             }
         }
         return file;
     }
 
-    // Rotate the set of output files
+    /**
+     * Rotate the set of output files
+     */
     private synchronized void rotate() {
         Level oldLevel = getLevel();
         setLevel(Level.OFF);
 
         super.close();

@@ -613,29 +639,30 @@
         // Unlock any lock file.
         if (lockFileName == null) {
             return;
         }
         try {
-            // Closing the lock file's FileOutputStream will close
-            // the underlying channel and free any locks.
-            lockStream.close();
+            // Close the lock file channel (which also will free any locks)
+            lockFileChannel.close();
         } catch (Exception ex) {
             // Problems closing the stream.  Punt.
         }
         synchronized(locks) {
             locks.remove(lockFileName);
         }
         new File(lockFileName).delete();
         lockFileName = null;
-        lockStream = null;
+        lockFileChannel = null;
     }
 
     private static class InitializationErrorManager extends ErrorManager {
         Exception lastException;
         public void error(String msg, Exception ex, int code) {
             lastException = ex;
         }
     }
 
-    // Private native method to check if we are in a set UID program.
+    /**
+     * check if we are in a set UID program.
+     */
     private static native boolean isSetUID();
 }