001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018: package org.apache.tools.ant.util;
019:
020: import java.io.File;
021: import java.io.FileOutputStream;
022: import java.io.IOException;
023: import java.io.OutputStream;
024:
025: /**
026: * Class that delays opening the output file until the first bytes
027: * shall be written or the method {@link #open open} has been invoked
028: * explicitly.
029: *
030: * @since Ant 1.6
031: */
032: public class LazyFileOutputStream extends OutputStream {
033:
034: private FileOutputStream fos;
035: private File file;
036: private boolean append;
037: private boolean alwaysCreate;
038: private boolean opened = false;
039: private boolean closed = false;
040:
041: /**
042: * Creates a stream that will eventually write to the file with
043: * the given name and replace it.
044: * @param name the filename.
045: */
046: public LazyFileOutputStream(String name) {
047: this (name, false);
048: }
049:
050: /**
051: * Creates a stream that will eventually write to the file with
052: * the given name and optionally append to instead of replacing
053: * it.
054: * @param name the filename.
055: * @param append if true append rather than replace.
056: */
057: public LazyFileOutputStream(String name, boolean append) {
058: this (new File(name), append);
059: }
060:
061: /**
062: * Creates a stream that will eventually write to the file with
063: * the given name and replace it.
064: * @param f the file to create.
065: */
066: public LazyFileOutputStream(File f) {
067: this (f, false);
068: }
069:
070: /**
071: * Creates a stream that will eventually write to the file with
072: * the given name and optionally append to instead of replacing
073: * it.
074: * @param file the file to create.
075: * @param append if true append rather than replace.
076: */
077: public LazyFileOutputStream(File file, boolean append) {
078: this (file, append, false);
079: }
080:
081: /**
082: * Creates a stream that will eventually write to the file with
083: * the given name, optionally append to instead of replacing
084: * it, and optionally always create a file (even if zero length).
085: * @param file the file to create.
086: * @param append if true append rather than replace.
087: * @param alwaysCreate if true create the file even if nothing to write.
088: */
089: public LazyFileOutputStream(File file, boolean append,
090: boolean alwaysCreate) {
091: this .file = file;
092: this .append = append;
093: this .alwaysCreate = alwaysCreate;
094: }
095:
096: /**
097: * Explicitly open the file for writing.
098: *
099: * <p>Returns silently if the file has already been opened.</p>
100: * @throws IOException if there is an error.
101: */
102: public void open() throws IOException {
103: ensureOpened();
104: }
105:
106: /**
107: * Close the file.
108: * @throws IOException if there is an error.
109: */
110: public synchronized void close() throws IOException {
111: if (alwaysCreate && !closed) {
112: ensureOpened();
113: }
114: if (opened) {
115: fos.close();
116: }
117: closed = true;
118: }
119:
120: /**
121: * Delegates to the three-arg version.
122: * @param b the bytearray to write.
123: * @throws IOException if there is a problem.
124: */
125: public void write(byte[] b) throws IOException {
126: write(b, 0, b.length);
127: }
128:
129: /**
130: * Write part of a byte array.
131: * @param b the byte array.
132: * @param offset write from this index.
133: * @param len the number of bytes to write.
134: * @throws IOException if there is a probem.
135: */
136: public synchronized void write(byte[] b, int offset, int len)
137: throws IOException {
138: ensureOpened();
139: fos.write(b, offset, len);
140: }
141:
142: /**
143: * Write a byte.
144: * @param b the byte to write.
145: * @throws IOException if there is a problem.
146: */
147: public synchronized void write(int b) throws IOException {
148: ensureOpened();
149: fos.write(b);
150: }
151:
152: private synchronized void ensureOpened() throws IOException {
153: if (closed) {
154: throw new IOException(file + " has already been closed.");
155: }
156:
157: if (!opened) {
158: fos = new FileOutputStream(file.getAbsolutePath(), append);
159: opened = true;
160: }
161: }
162: }
|