132 * Thus if three processes were all trying to log to fred%u.%g.txt then 133 * they might end up using fred0.0.txt, fred1.0.txt, fred2.0.txt as 134 * the first file in their rotating sequences. 135 * <p> 136 * Note that the use of unique ids to avoid conflicts is only guaranteed 137 * to work reliably when using a local disk file system. 138 * 139 * @since 1.4 140 */ 141 142 public class FileHandler extends StreamHandler { 143 private MeteredStream meter; 144 private boolean append; 145 private int limit; // zero => no limit. 146 private int count; 147 private String pattern; 148 private String lockFileName; 149 private FileChannel lockFileChannel; 150 private File files[]; 151 private static final int MAX_LOCKS = 100; 152 private static java.util.HashMap<String, String> locks = new java.util.HashMap<>(); 153 154 /** 155 * A metered stream is a subclass of OutputStream that 156 * (a) forwards all its output to a target stream 157 * (b) keeps track of how many bytes have been written 158 */ 159 private class MeteredStream extends OutputStream { 160 OutputStream out; 161 int written; 162 163 MeteredStream(OutputStream out, int written) { 164 this.out = out; 165 this.written = written; 166 } 167 168 public void write(int b) throws IOException { 169 out.write(b); 170 written++; 171 } 172 173 public void write(byte buff[]) throws IOException { 174 out.write(buff); 175 written += buff.length; 176 } 177 178 public void write(byte buff[], int off, int len) throws IOException { 179 out.write(buff,off,len); 180 written += len; 181 } 182 183 public void flush() throws IOException { 184 out.flush(); 185 } 186 187 public void close() throws IOException { 188 out.close(); 189 } 190 } 191 192 private void open(File fname, boolean append) throws IOException { 193 int len = 0; 194 if (append) { 195 len = (int)fname.length(); 196 } 197 FileOutputStream fout = new FileOutputStream(fname.toString(), append); 198 BufferedOutputStream bout = new BufferedOutputStream(fout); 199 meter = new MeteredStream(bout, len); 200 setOutputStream(meter); 201 } 202 203 /** 204 * Configure a FileHandler from LogManager properties and/or default values 205 * as specified in the class javadoc. 206 */ 590 f1.renameTo(f2); 591 } 592 } 593 try { 594 open(files[0], false); 595 } catch (IOException ix) { 596 // We don't want to throw an exception here, but we 597 // report the exception to any registered ErrorManager. 598 reportError(null, ix, ErrorManager.OPEN_FAILURE); 599 600 } 601 setLevel(oldLevel); 602 } 603 604 /** 605 * Format and publish a <tt>LogRecord</tt>. 606 * 607 * @param record description of the log event. A null record is 608 * silently ignored and is not published 609 */ 610 public synchronized void publish(LogRecord record) { 611 if (!isLoggable(record)) { 612 return; 613 } 614 super.publish(record); 615 flush(); 616 if (limit > 0 && meter.written >= limit) { 617 // We performed access checks in the "init" method to make sure 618 // we are only initialized from trusted code. So we assume 619 // it is OK to write the target files, even if we are 620 // currently being called from untrusted code. 621 // So it is safe to raise privilege here. 622 AccessController.doPrivileged(new PrivilegedAction<Object>() { 623 public Object run() { 624 rotate(); 625 return null; 626 } 627 }); 628 } 629 } 630 631 /** 632 * Close all the files. 633 * 634 * @exception SecurityException if a security manager exists and if 635 * the caller does not have <tt>LoggingPermission("control")</tt>. 636 */ 637 public synchronized void close() throws SecurityException { 638 super.close(); 639 // Unlock any lock file. 640 if (lockFileName == null) { 641 return; 642 } 643 try { 644 // Close the lock file channel (which also will free any locks) 645 lockFileChannel.close(); 646 } catch (Exception ex) { 647 // Problems closing the stream. Punt. 648 } 649 synchronized(locks) { 650 locks.remove(lockFileName); 651 } 652 new File(lockFileName).delete(); 653 lockFileName = null; 654 lockFileChannel = null; 655 } 656 657 private static class InitializationErrorManager extends ErrorManager { 658 Exception lastException; 659 public void error(String msg, Exception ex, int code) { 660 lastException = ex; 661 } 662 } 663 664 /** 665 * check if we are in a set UID program. 666 */ 667 private static native boolean isSetUID(); 668 } | 132 * Thus if three processes were all trying to log to fred%u.%g.txt then 133 * they might end up using fred0.0.txt, fred1.0.txt, fred2.0.txt as 134 * the first file in their rotating sequences. 135 * <p> 136 * Note that the use of unique ids to avoid conflicts is only guaranteed 137 * to work reliably when using a local disk file system. 138 * 139 * @since 1.4 140 */ 141 142 public class FileHandler extends StreamHandler { 143 private MeteredStream meter; 144 private boolean append; 145 private int limit; // zero => no limit. 146 private int count; 147 private String pattern; 148 private String lockFileName; 149 private FileChannel lockFileChannel; 150 private File files[]; 151 private static final int MAX_LOCKS = 100; 152 private static final java.util.HashMap<String, String> locks = new java.util.HashMap<>(); 153 154 /** 155 * A metered stream is a subclass of OutputStream that 156 * (a) forwards all its output to a target stream 157 * (b) keeps track of how many bytes have been written 158 */ 159 private class MeteredStream extends OutputStream { 160 final OutputStream out; 161 int written; 162 163 MeteredStream(OutputStream out, int written) { 164 this.out = out; 165 this.written = written; 166 } 167 168 @Override 169 public void write(int b) throws IOException { 170 out.write(b); 171 written++; 172 } 173 174 @Override 175 public void write(byte buff[]) throws IOException { 176 out.write(buff); 177 written += buff.length; 178 } 179 180 @Override 181 public void write(byte buff[], int off, int len) throws IOException { 182 out.write(buff,off,len); 183 written += len; 184 } 185 186 @Override 187 public void flush() throws IOException { 188 out.flush(); 189 } 190 191 @Override 192 public void close() throws IOException { 193 out.close(); 194 } 195 } 196 197 private void open(File fname, boolean append) throws IOException { 198 int len = 0; 199 if (append) { 200 len = (int)fname.length(); 201 } 202 FileOutputStream fout = new FileOutputStream(fname.toString(), append); 203 BufferedOutputStream bout = new BufferedOutputStream(fout); 204 meter = new MeteredStream(bout, len); 205 setOutputStream(meter); 206 } 207 208 /** 209 * Configure a FileHandler from LogManager properties and/or default values 210 * as specified in the class javadoc. 211 */ 595 f1.renameTo(f2); 596 } 597 } 598 try { 599 open(files[0], false); 600 } catch (IOException ix) { 601 // We don't want to throw an exception here, but we 602 // report the exception to any registered ErrorManager. 603 reportError(null, ix, ErrorManager.OPEN_FAILURE); 604 605 } 606 setLevel(oldLevel); 607 } 608 609 /** 610 * Format and publish a <tt>LogRecord</tt>. 611 * 612 * @param record description of the log event. A null record is 613 * silently ignored and is not published 614 */ 615 @Override 616 public synchronized void publish(LogRecord record) { 617 if (!isLoggable(record)) { 618 return; 619 } 620 super.publish(record); 621 flush(); 622 if (limit > 0 && meter.written >= limit) { 623 // We performed access checks in the "init" method to make sure 624 // we are only initialized from trusted code. So we assume 625 // it is OK to write the target files, even if we are 626 // currently being called from untrusted code. 627 // So it is safe to raise privilege here. 628 AccessController.doPrivileged(new PrivilegedAction<Object>() { 629 @Override 630 public Object run() { 631 rotate(); 632 return null; 633 } 634 }); 635 } 636 } 637 638 /** 639 * Close all the files. 640 * 641 * @exception SecurityException if a security manager exists and if 642 * the caller does not have <tt>LoggingPermission("control")</tt>. 643 */ 644 @Override 645 public synchronized void close() throws SecurityException { 646 super.close(); 647 // Unlock any lock file. 648 if (lockFileName == null) { 649 return; 650 } 651 try { 652 // Close the lock file channel (which also will free any locks) 653 lockFileChannel.close(); 654 } catch (Exception ex) { 655 // Problems closing the stream. Punt. 656 } 657 synchronized(locks) { 658 locks.remove(lockFileName); 659 } 660 new File(lockFileName).delete(); 661 lockFileName = null; 662 lockFileChannel = null; 663 } 664 665 private static class InitializationErrorManager extends ErrorManager { 666 Exception lastException; 667 @Override 668 public void error(String msg, Exception ex, int code) { 669 lastException = ex; 670 } 671 } 672 673 /** 674 * check if we are in a set UID program. 675 */ 676 private static native boolean isSetUID(); 677 } |