1. /*
  2. * Copyright 2003-2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. package org.apache.tools.ant.util;
  18. import java.io.File;
  19. import java.io.FileOutputStream;
  20. import java.io.IOException;
  21. import java.io.OutputStream;
  22. /**
  23. * Class that delays opening the output file until the first bytes
  24. * shall be written or the method {@link #open open} has been invoked
  25. * explicitly.
  26. *
  27. * @since Ant 1.6
  28. */
  29. public class LazyFileOutputStream extends OutputStream {
  30. private FileOutputStream fos;
  31. private File file;
  32. private boolean append;
  33. private boolean alwaysCreate;
  34. private boolean opened = false;
  35. private boolean closed = false;
  36. /**
  37. * Creates a stream that will eventually write to the file with
  38. * the given name and replace it.
  39. */
  40. public LazyFileOutputStream(String name) {
  41. this(name, false);
  42. }
  43. /**
  44. * Creates a stream that will eventually write to the file with
  45. * the given name and optionally append to instead of replacing
  46. * it.
  47. */
  48. public LazyFileOutputStream(String name, boolean append) {
  49. this(new File(name), append);
  50. }
  51. /**
  52. * Creates a stream that will eventually write to the file with
  53. * the given name and replace it.
  54. */
  55. public LazyFileOutputStream(File f) {
  56. this(f, false);
  57. }
  58. /**
  59. * Creates a stream that will eventually write to the file with
  60. * the given name and optionally append to instead of replacing
  61. * it.
  62. */
  63. public LazyFileOutputStream(File file, boolean append) {
  64. this(file, append, false);
  65. }
  66. /**
  67. * Creates a stream that will eventually write to the file with
  68. * the given name, optionally append to instead of replacing
  69. * it, and optionally always create a file (even if zero length).
  70. */
  71. public LazyFileOutputStream(File file, boolean append,
  72. boolean alwaysCreate) {
  73. this.file = file;
  74. this.append = append;
  75. this.alwaysCreate = alwaysCreate;
  76. }
  77. /**
  78. * Explicitly open the file for writing.
  79. *
  80. * <p>Returns silently if the file has already been opened.</p>
  81. */
  82. public void open() throws IOException {
  83. ensureOpened();
  84. }
  85. public synchronized void close() throws IOException {
  86. if (alwaysCreate && !closed) {
  87. ensureOpened();
  88. }
  89. if (opened) {
  90. fos.close();
  91. }
  92. closed = true;
  93. }
  94. /**
  95. * Delegates to the three arg version.
  96. */
  97. public void write(byte[] b) throws IOException {
  98. write(b, 0, b.length);
  99. }
  100. public synchronized void write(byte[] b, int offset, int len)
  101. throws IOException {
  102. ensureOpened();
  103. fos.write(b, offset, len);
  104. }
  105. public synchronized void write(int b) throws IOException {
  106. ensureOpened();
  107. fos.write(b);
  108. }
  109. private synchronized void ensureOpened() throws IOException {
  110. if (closed) {
  111. throw new IOException(file + " has already been closed.");
  112. }
  113. if (!opened) {
  114. fos = new FileOutputStream(file.getAbsolutePath(), append);
  115. opened = true;
  116. }
  117. }
  118. }