Java Tutorial/File/FilterOutputStream
Версия от 17:44, 31 мая 2010; (обсуждение)
Содержание
- 1 Adds extra dot if dot occurs in message body at beginning of line (according to RFC1939)
- 2 Apply a ASCII Hex encoding to the stream
- 3 Capture System.out into a JFrame
- 4 Count the number of bytes written to the output stream.
- 5 extends FilterOutputStream
- 6 extends FilterOutputStream for printable characters
- 7 Provide a debug trace of the stuff thats being written out into the DataOutputStream
- 8 Rollover FileOutputStream
Adds extra dot if dot occurs in message body at beginning of line (according to RFC1939)
/****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one *
* or more contributor license agreements. See the NOTICE file *
* distributed with this work for additional information *
* regarding copyright ownership. The ASF licenses this file *
* to you under the Apache License, Version 2.0 (the *
* "License"); you may not use this file except in compliance *
* with the License. You may obtain a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, *
* software distributed under the License is distributed on an *
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
****************************************************************/
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* Adds extra dot if dot occurs in message body at beginning of line (according to RFC1939)
* Compare also org.apache.james.smtpserver.SMTPInputStream
*/
public class ExtraDotOutputStream extends FilterOutputStream {
/*
static public void main(String[] args) throws IOException
{
String data = ".This is a test\r\nof the thing.\r\nWe should not have much trouble.\r\n.doubled?\r\nor not?\n.doubled\nor not?\r\n\r\n\n\n\r\r\r\n";
OutputStream os = new ExtraDotOutputStream(System.out);
os.write(data.getBytes());
}
*/
/**
* Counter for number of last (0A or 0D).
*/
protected int countLast0A0D;
/**
* Constructor that wraps an OutputStream.
*
* @param out the OutputStream to be wrapped
*/
public ExtraDotOutputStream(OutputStream out) {
super(out);
countLast0A0D = 2; // we already assume a CRLF at beginning (otherwise TOP would not work correctly !)
}
/**
* Writes a byte to the stream, adding dots where appropriate.
* Also fixes any naked CR or LF to the RFC 2821 mandated CFLF
* pairing.
*
* @param b the byte to write
*
* @throws IOException if an error occurs writing the byte
*/
public void write(int b) throws IOException {
switch (b) {
case ".":
if (countLast0A0D == 2) {
// add extra dot (the first of the pair)
out.write(".");
}
countLast0A0D = 0;
break;
case "\r":
if (countLast0A0D == 1) out.write("\n"); // two CR in a row, so insert an LF first
countLast0A0D = 1;
break;
case "\n":
/* RFC 2821 #2.3.7 mandates that line termination is
* CRLF, and that CR and LF must not be transmitted
* except in that pairing. If we get a naked LF,
* convert to CRLF.
*/
if (countLast0A0D != 1) out.write("\r");
countLast0A0D = 2;
break;
default:
// we"re no longer at the start of a line
countLast0A0D = 0;
break;
}
out.write(b);
}
/**
* Ensure that the stream is CRLF terminated.
*
* @throws IOException if an error occurs writing the byte
*/
public void checkCRLFTerminator() throws IOException {
if (countLast0A0D != 2) {
write("\n");
}
}
}
//////////////////////////////
/****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one *
* or more contributor license agreements. See the NOTICE file *
* distributed with this work for additional information *
* regarding copyright ownership. The ASF licenses this file *
* to you under the Apache License, Version 2.0 (the *
* "License"); you may not use this file except in compliance *
* with the License. You may obtain a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, *
* software distributed under the License is distributed on an *
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
****************************************************************/
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import junit.framework.TestCase;
/**
* Tests for the ExtraDotOutputStream
*/
public class ExtraDotOutputStreamTest extends TestCase {
public void testMain() throws IOException {
String data = ".This is a test\r\nof the thing.\r\nWe should not have much trouble.\r\n.doubled?\r\nor not?\n.doubled\nor not?\r\n\r\n\n\n\r\r\r\n";
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
OutputStream os = new ExtraDotOutputStream(bOut);
os.write(data.getBytes());
os.flush();
String expected = "..This is a test\r\nof the thing.\r\nWe should not have much trouble.\r\n..doubled?\r\nor not?\r\n..doubled\r\nor not?\r\n\r\n\r\n\r\n\r\n\r\n\r\n";
assertEquals(expected,bOut.toString());
}
/*
* Test method for "org.apache.james.util.ExtraDotOutputStream.checkCRLFTerminator()"
*/
public void testCheckCRLFTerminator() throws IOException {
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
ExtraDotOutputStream os = new ExtraDotOutputStream(bOut);
// if the stream is empty then we should not add the CRLF.
os.checkCRLFTerminator();
os.flush();
assertEquals("",bOut.toString());
os.write("Test".getBytes());
os.flush();
assertEquals("Test",bOut.toString());
os.checkCRLFTerminator();
os.flush();
assertEquals("Test\r\n",bOut.toString());
// if the stream ends with \r we should simply add the \n
os.write("A line with incomplete ending\r".getBytes());
os.flush();
assertEquals("Test\r\nA line with incomplete ending\r",bOut.toString());
os.checkCRLFTerminator();
os.flush();
assertEquals("Test\r\nA line with incomplete ending\r\n",bOut.toString());
// already correctly terminated, should leave the output untouched
os.checkCRLFTerminator();
os.flush();
assertEquals("Test\r\nA line with incomplete ending\r\n",bOut.toString());
}
}
Apply a ASCII Hex encoding to the stream
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* $Id: ASCIIHexOutputStream.java 426584 2006-07-28 16:01:47Z jeremias $ */
import java.io.OutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
/**
* This class applies a ASCII Hex encoding to the stream.
*
* @version $Id: ASCIIHexOutputStream.java 426584 2006-07-28 16:01:47Z jeremias $
*/
public class ASCIIHexOutputStream extends FilterOutputStream
{
private static final int EOL = 0x0A; //"\n"
private static final int EOD = 0x3E; //">"
private static final int ZERO = 0x30; //"0"
private static final int NINE = 0x39; //"9"
private static final int A = 0x41; //"A"
private static final int ADIFF = A - NINE - 1;
private int posinline = 0;
/** @see java.io.FilterOutputStream **/
public ASCIIHexOutputStream(OutputStream out) {
super(out);
}
/** @see java.io.FilterOutputStream **/
public void write(int b) throws IOException {
b &= 0xFF;
int digit1 = ((b & 0xF0) >> 4) + ZERO;
if (digit1 > NINE) {
digit1 += ADIFF;
}
out.write(digit1);
int digit2 = (b & 0x0F) + ZERO;
if (digit2 > NINE) {
digit2 += ADIFF;
}
out.write(digit2);
posinline++;
checkLineWrap();
}
private void checkLineWrap() throws IOException {
//Maximum line length is 80 characters
if (posinline >= 40) {
out.write(EOL);
posinline = 0;
}
}
/** @see Finalizable **/
public void finalizeStream() throws IOException {
checkLineWrap();
//Write closing character ">"
super.write(EOD);
flush();
}
/** @see java.io.FilterOutputStream **/
public void close() throws IOException {
finalizeStream();
super.close();
}
}
Capture System.out into a JFrame
import java.io.ByteArrayOutputStream;
import java.io.FileWriter;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class Main extends JFrame {
JTextArea aTextArea = new JTextArea();
PrintStream aPrintStream = new PrintStream(new FilteredStream(new ByteArrayOutputStream()));
public Main() {
setSize(300, 300);
add("Center", new JScrollPane(aTextArea));
setVisible(true);
System.setOut(aPrintStream); // catches System.out messages
System.setErr(aPrintStream); // catches error messages
}
class FilteredStream extends FilterOutputStream {
public FilteredStream(OutputStream aStream) {
super(aStream);
}
public void write(byte b[]) throws IOException {
String aString = new String(b);
aTextArea.append(aString);
}
public void write(byte b[], int off, int len) throws IOException {
String aString = new String(b, off, len);
aTextArea.append(aString);
FileWriter aWriter = new FileWriter("a.log", true);
aWriter.write(aString);
aWriter.close();
}
}
}
Count the number of bytes written to the output stream.
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//Revised from Apache cocoon
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* This class is like the {@link java.io.BufferedOutputStream} but it
* extends it with a logic to count the number of bytes written to
* the output stream.
*
* @version $Id: BufferedOutputStream.java 587751 2007-10-24 02:41:36Z vgritsenko $
* @since 2.1
*/
public final class BufferedOutputStream extends FilterOutputStream {
protected byte buf[];
protected int count;
/**
* Creates a new buffered output stream to write data to the
* specified underlying output stream with a default 8192-byte
* buffer size.
*
* @param out the underlying output stream.
*/
public BufferedOutputStream(OutputStream out) {
this(out, 8192);
}
/**
* Creates a new buffered output stream to write data to the
* specified underlying output stream with the specified buffer
* size.
*
* @param out the underlying output stream.
* @param size the buffer size.
* @exception IllegalArgumentException if size <= 0.
*/
public BufferedOutputStream(OutputStream out, int size) {
super(out);
if (size <= 0) {
throw new IllegalArgumentException("Buffer size <= 0");
}
this.buf = new byte[size];
}
/**
* Writes the specified byte to this buffered output stream.
*
* @param b the byte to be written.
* @exception IOException if an I/O error occurs.
*/
public void write(int b) throws IOException {
if (this.count >= this.buf.length) {
this.incBuffer();
}
this.buf[count++] = (byte)b;
}
/**
* Writes <code>len</code> bytes from the specified byte array
* starting at offset <code>off</code> to this buffered output stream.
*
* Ordinarily this method stores bytes from the given array into this
* stream"s buffer, flushing the buffer to the underlying output stream as
* needed. If the requested length is at least as large as this stream"s
* buffer, however, then this method will flush the buffer and write the
* bytes directly to the underlying output stream. Thus redundant
* <code>BufferedOutputStream</code>s will not copy data unnecessarily.
*
* @param b the data.
* @param off the start offset in the data.
* @param len the number of bytes to write.
* @exception IOException if an I/O error occurs.
*/
public void write(byte b[], int off, int len) throws IOException {
while (len > buf.length - count) {
this.incBuffer();
}
System.arraycopy(b, off, buf, count, len);
count += len;
}
/**
* Flushes this buffered output stream.
* We don"t flush here, flushing is done during closing.
*
* @exception IOException if an I/O error occurs.
*/
public void flush() throws IOException {
// nothing
}
/**
* Closes this buffered output stream.
* Flush before closing.
*
* @exception IOException if an I/O error occurs.
*/
public void close() throws IOException {
realFlush();
super.close ();
}
/**
* Flushes this buffered output stream.
*/
public void realFlush() throws IOException {
this.writeBuffer();
this.out.flush();
}
/**
* Write the buffer
*/
private void writeBuffer()
throws IOException {
if (this.count > 0) {
this.out.write(this.buf, 0, this.count);
this.clearBuffer();
}
}
/**
* Increment the buffer
*/
private void incBuffer() {
// currently we double the buffer size
// this is not so fast but is a very simple logic
byte[] newBuf = new byte[this.buf.length * 2];
System.arraycopy(this.buf, 0, newBuf, 0, this.buf.length);
this.buf = newBuf;
}
/**
* Clear/reset the buffer
*/
public void clearBuffer() {
this.count = 0;
}
/**
* Return the size of the current buffer
*/
public int getCount() {
return this.count;
}
}
extends FilterOutputStream
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class MainClass {
public static void main(String[] args) throws IOException {
if (args.length != 3) {
System.out.println("Usage: java TeeCopier infile outfile1 outfile2");
return;
}
FileInputStream fin = new FileInputStream(args[0]);
FileOutputStream fout1 = new FileOutputStream(args[1]);
FileOutputStream fout2 = new FileOutputStream(args[2]);
MyOutputStream tout = new MyOutputStream(fout1, fout2);
copy(fin, tout);
fin.close();
tout.close();
}
public static void copy(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
while (true) {
int bytesRead = in.read(buffer);
if (bytesRead == -1)
break;
out.write(buffer, 0, bytesRead);
}
}
}
class MyOutputStream extends FilterOutputStream {
private OutputStream out1;
private OutputStream out2;
public MyOutputStream(OutputStream stream1, OutputStream stream2) {
super(stream1);
out1 = stream1;
out2 = stream2;
}
public void write(int b) throws IOException {
out1.write(b);
out2.write(b);
}
public void write(byte[] data, int offset, int length) throws IOException {
out1.write(data, offset, length);
out2.write(data, offset, length);
}
public void flush() throws IOException {
out1.flush();
out2.flush();
}
public void close() throws IOException {
out1.close();
out2.close();
}
}
extends FilterOutputStream for printable characters
import java.io.FileInputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class MainClass {
public static void main(String[] args) throws Exception {
InputStream in = new FileInputStream("test.txt");
OutputStream out = System.out;
PrintableOutputStream pout = new PrintableOutputStream(out);
for (int c = in.read(); c != -1; c = in.read()) {
pout.write(c);
}
out.close();
}
}
class PrintableOutputStream extends FilterOutputStream {
public PrintableOutputStream(OutputStream out) {
super(out);
}
public void write(int b) throws IOException {
// carriage return, linefeed, and tab
if (b == "\n" || b == "\r" || b == "\t")
out.write(b);
// non-printing characters
else if (b < 32 || b > 126)
out.write("?");
// printing, ASCII characters
else
out.write(b);
}
public void write(byte[] data, int offset, int length) throws IOException {
for (int i = offset; i < offset + length; i++) {
this.write(data[i]);
}
}
}
Provide a debug trace of the stuff thats being written out into the DataOutputStream
/*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the "License"). You may not use this file except
* in compliance with the License.
*
* You can obtain a copy of the license at
* glassfish/bootstrap/legal/CDDLv1.0.txt or
* https://glassfish.dev.java.net/public/CDDLv1.0.html.
* See the License for the specific language governing
* permissions and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* HEADER in each file and include the License file at
* glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
* add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your
* own identifying information: Portions Copyright [yyyy]
* [name of copyright owner]
*/
/*
* @(#)TraceOutputStream.java 1.5 05/08/29
*
* Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
*/
// revised from sun mail util
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* This class is a subclass of DataOutputStream that copies the
* data being written into the DataOutputStream into another output
* stream. This class is used here to provide a debug trace of the
* stuff thats being written out into the DataOutputStream.
*
* @author John Mani
*/
public class TraceOutputStream extends FilterOutputStream {
private boolean trace = false;
private boolean quote = false;
private OutputStream traceOut;
/**
* Creates an output stream filter built on top of the specified
* underlying output stream.
*
* @param out the underlying output stream.
* @param traceOut the trace stream.
*/
public TraceOutputStream(OutputStream out, OutputStream traceOut) {
super(out);
this.traceOut = traceOut;
}
/**
* Set the trace mode.
*/
public void setTrace(boolean trace) {
this.trace = trace;
}
/**
* Set quote mode.
* @param quote the quote mode
*/
public void setQuote(boolean quote) {
this.quote = quote;
}
/**
* Writes the specified <code>byte</code> to this output stream.
* Writes out the byte into the trace stream if the trace mode
* is <code>true</code>
*/
public void write(int b) throws IOException {
if (trace) {
if (quote)
writeByte(b);
else
traceOut.write(b);
}
out.write(b);
}
/**
* Writes <code>b.length</code> bytes to this output stream.
* Writes out the bytes into the trace stream if the trace
* mode is <code>true</code>
*/
public void write(byte b[], int off, int len) throws IOException {
if (trace) {
if (quote) {
for (int i = 0; i < len; i++)
writeByte(b[off + i]);
} else
traceOut.write(b, off, len);
}
out.write(b, off, len);
}
/**
* Write a byte in a way that every byte value is printable ASCII.
*/
private final void writeByte(int b) throws IOException {
b &= 0xff;
if (b > 0x7f) {
traceOut.write("M");
traceOut.write("-");
b &= 0x7f;
}
if (b == "\r") {
traceOut.write("\\");
traceOut.write("r");
} else if (b == "\n") {
traceOut.write("\\");
traceOut.write("n");
traceOut.write("\n");
} else if (b == "\t") {
traceOut.write("\\");
traceOut.write("t");
} else if (b < " ") {
traceOut.write("^");
traceOut.write("@" + b);
} else {
traceOut.write(b);
}
}
}
Rollover FileOutputStream
//Copyright 2006 Mort Bay Consulting Pty. Ltd.
//------------------------------------------------------------------------
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//http://www.apache.org/licenses/LICENSE-2.0
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.Timer;
import java.util.TimerTask;
/**
* RolloverFileOutputStream
*
* @author Greg Wilkins
*/
public class RolloverFileOutputStream extends FilterOutputStream {
private static Timer __rollover;
final static String YYYY_MM_DD = "yyyy_mm_dd";
private RollTask _rollTask;
private SimpleDateFormat _fileBackupFormat = new SimpleDateFormat(System.getProperty(
"ROLLOVERFILE_BACKUP_FORMAT", "HHmmssSSS"));
private SimpleDateFormat _fileDateFormat = new SimpleDateFormat(System.getProperty(
"ROLLOVERFILE_DATE_FORMAT", "yyyy_MM_dd"));
private String _filename;
private File _file;
private boolean _append;
private int _retainDays;
/* ------------------------------------------------------------ */
public RolloverFileOutputStream(String filename) throws IOException {
this(filename, true, Integer.getInteger("ROLLOVERFILE_RETAIN_DAYS", 31).intValue());
}
/* ------------------------------------------------------------ */
public RolloverFileOutputStream(String filename, boolean append) throws IOException {
this(filename, append, Integer.getInteger("ROLLOVERFILE_RETAIN_DAYS", 31).intValue());
}
/* ------------------------------------------------------------ */
public RolloverFileOutputStream(String filename, boolean append, int retainDays)
throws IOException {
this(filename, append, retainDays, TimeZone.getDefault());
}
/* ------------------------------------------------------------ */
public RolloverFileOutputStream(String filename, boolean append, int retainDays, TimeZone zone)
throws IOException {
super(null);
_fileBackupFormat.setTimeZone(zone);
_fileDateFormat.setTimeZone(zone);
if (filename != null) {
filename = filename.trim();
if (filename.length() == 0)
filename = null;
}
if (filename == null)
throw new IllegalArgumentException("Invalid filename");
_filename = filename;
_append = append;
_retainDays = retainDays;
setFile();
synchronized (RolloverFileOutputStream.class) {
if (__rollover == null)
__rollover = new Timer();
_rollTask = new RollTask();
Calendar now = Calendar.getInstance();
now.setTimeZone(zone);
GregorianCalendar midnight = new GregorianCalendar(now.get(Calendar.YEAR), now
.get(Calendar.MONTH), now.get(Calendar.DAY_OF_MONTH), 23, 0);
midnight.setTimeZone(zone);
midnight.add(Calendar.HOUR, 1);
__rollover.scheduleAtFixedRate(_rollTask, midnight.getTime(), 1000L * 60 * 60 * 24);
}
}
/* ------------------------------------------------------------ */
public String getFilename() {
return _filename;
}
/* ------------------------------------------------------------ */
public String getDatedFilename() {
if (_file == null)
return null;
return _file.toString();
}
/* ------------------------------------------------------------ */
public int getRetainDays() {
return _retainDays;
}
/* ------------------------------------------------------------ */
private synchronized void setFile() throws IOException {
// Check directory
File file = new File(_filename);
_filename = file.getCanonicalPath();
file = new File(_filename);
File dir = new File(file.getParent());
if (!dir.isDirectory() || !dir.canWrite())
throw new IOException("Cannot write log directory " + dir);
Date now = new Date();
// Is this a rollover file?
String filename = file.getName();
int i = filename.toLowerCase().indexOf(YYYY_MM_DD);
if (i >= 0) {
file = new File(dir, filename.substring(0, i) + _fileDateFormat.format(now)
+ filename.substring(i + YYYY_MM_DD.length()));
}
if (file.exists() && !file.canWrite())
throw new IOException("Cannot write log file " + file);
// Do we need to change the output stream?
if (out == null || !file.equals(_file)) {
// Yep
_file = file;
if (!_append && file.exists())
file.renameTo(new File(file.toString() + "." + _fileBackupFormat.format(now)));
OutputStream oldOut = out;
out = new FileOutputStream(file.toString(), _append);
if (oldOut != null)
oldOut.close();
// if(log.isDebugEnabled())log.debug("Opened "+_file);
}
}
/* ------------------------------------------------------------ */
private void removeOldFiles() {
if (_retainDays > 0) {
Calendar retainDate = Calendar.getInstance();
retainDate.add(Calendar.DATE, -_retainDays);
int borderYear = retainDate.get(java.util.Calendar.YEAR);
int borderMonth = retainDate.get(java.util.Calendar.MONTH) + 1;
int borderDay = retainDate.get(java.util.Calendar.DAY_OF_MONTH);
File file = new File(_filename);
File dir = new File(file.getParent());
String fn = file.getName();
int s = fn.toLowerCase().indexOf(YYYY_MM_DD);
if (s < 0)
return;
String prefix = fn.substring(0, s);
String suffix = fn.substring(s + YYYY_MM_DD.length());
String[] logList = dir.list();
for (int i = 0; i < logList.length; i++) {
fn = logList[i];
if (fn.startsWith(prefix) && fn.indexOf(suffix, prefix.length()) >= 0) {
try {
StringTokenizer st = new StringTokenizer(fn.substring(prefix.length(), prefix.length()
+ YYYY_MM_DD.length()), "_.");
int nYear = Integer.parseInt(st.nextToken());
int nMonth = Integer.parseInt(st.nextToken());
int nDay = Integer.parseInt(st.nextToken());
if (nYear < borderYear || (nYear == borderYear && nMonth < borderMonth)
|| (nYear == borderYear && nMonth == borderMonth && nDay <= borderDay)) {
// log.info("Log age "+fn);
new File(dir, fn).delete();
}
} catch (Exception e) {
// if (log.isDebugEnabled())
e.printStackTrace();
}
}
}
}
}
/* ------------------------------------------------------------ */
public void write(byte[] buf) throws IOException {
out.write(buf);
}
/* ------------------------------------------------------------ */
public void write(byte[] buf, int off, int len) throws IOException {
out.write(buf, off, len);
}
/* ------------------------------------------------------------ */
/**
*/
public void close() throws IOException {
synchronized (RolloverFileOutputStream.class) {
try {
super.close();
} finally {
out = null;
_file = null;
}
_rollTask.cancel();
}
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
private class RollTask extends TimerTask {
public void run() {
try {
RolloverFileOutputStream.this.setFile();
RolloverFileOutputStream.this.removeOldFiles();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}