1. /*
  2. * Copyright 2001-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. package org.apache.commons.io.output;
  17. import java.io.File;
  18. import java.io.FileWriter;
  19. import java.io.IOException;
  20. import java.io.Writer;
  21. /**
  22. * FileWriter that will create and honor lock files to allow simple
  23. * cross thread file lock handling. If <code>Writer</code> attributes
  24. * are unspecified, the default behavior is to overwrite (rather than
  25. * to append), and to use the value of the system property
  26. * <code>java.io.tmpdir</code> for the lock file directory.
  27. *
  28. * @author <a href="mailto:sanders@apache.org">Scott Sanders</a>
  29. * @author <a href="mailto:ms@collab.net">Michael Salmon</a>
  30. * @author <a href="mailto:jon@collab.net">Jon S. Stevens</a>
  31. * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
  32. * @version $Id: LockableFileWriter.java,v 1.7 2004/02/23 04:40:29 bayard Exp $
  33. */
  34. public class LockableFileWriter extends Writer {
  35. private static final String LCK = ".lck";
  36. private File lockFile = null;
  37. private FileWriter writer = null;
  38. private boolean append = false;
  39. /**
  40. * Constructs a LockableFileWriter. If the file exists, it is overwritten.
  41. * @param fileName file to write to
  42. * @throws IOException in case of an I/O error
  43. */
  44. public LockableFileWriter(String fileName)
  45. throws IOException {
  46. this(fileName, false, null);
  47. }
  48. /**
  49. * Constructs a LockableFileWriter.
  50. * @param fileName file to write to
  51. * @param append true if content should be appended (default is to overwrite).
  52. * @throws IOException in case of an I/O error
  53. */
  54. public LockableFileWriter(String fileName, boolean append)
  55. throws IOException {
  56. this(fileName, append, null);
  57. }
  58. /**
  59. * Constructs a LockableFileWriter.
  60. * @param fileName file to write to
  61. * @param append true if content should be appended (default is to overwrite).
  62. * @param lockDir Specifies the directory in which the lock file should be held.
  63. * @throws IOException in case of an I/O error
  64. */
  65. public LockableFileWriter(String fileName, boolean append, String lockDir)
  66. throws IOException {
  67. this(new File(fileName), append, lockDir);
  68. }
  69. /**
  70. * Constructs a LockableFileWriter. If the file exists, it is overwritten.
  71. * @param file file to write to
  72. * @throws IOException in case of an I/O error
  73. */
  74. public LockableFileWriter(File file)
  75. throws IOException {
  76. this(file, false, null);
  77. }
  78. /**
  79. * Constructs a LockableFileWriter.
  80. * @param file file to write to
  81. * @param append true if content should be appended (default is to overwrite).
  82. * @throws IOException in case of an I/O error
  83. */
  84. public LockableFileWriter(File file, boolean append)
  85. throws IOException {
  86. this(file, append, null);
  87. }
  88. /**
  89. * Constructs a LockableFileWriter.
  90. * @param file file to write to
  91. * @param append true if content should be appended (default is to overwrite).
  92. * @param lockDir Specifies the directory in which the lock file should be held.
  93. * @throws IOException in case of an I/O error
  94. */
  95. public LockableFileWriter(File file, boolean append, String lockDir)
  96. throws IOException {
  97. this.append = append;
  98. if (lockDir == null) {
  99. lockDir = System.getProperty("java.io.tmpdir");
  100. }
  101. testLockDir(new File(lockDir));
  102. this.lockFile = new File(lockDir, file.getName() + LCK);
  103. createLock();
  104. this.writer = new FileWriter(file.getAbsolutePath(), this.append);
  105. }
  106. private void testLockDir(File lockDir)
  107. throws IOException {
  108. if (!lockDir.exists()) {
  109. throw new IOException(
  110. "Could not find lockDir: " + lockDir.getAbsolutePath());
  111. }
  112. if (!lockDir.canWrite()) {
  113. throw new IOException(
  114. "Could not write to lockDir: " + lockDir.getAbsolutePath());
  115. }
  116. }
  117. private void createLock()
  118. throws IOException {
  119. synchronized (LockableFileWriter.class) {
  120. if (!lockFile.createNewFile()) {
  121. throw new IOException("Can't write file, lock " +
  122. lockFile.getAbsolutePath() + " exists");
  123. }
  124. lockFile.deleteOnExit();
  125. }
  126. }
  127. /** @see java.io.Writer#close() */
  128. public void close()
  129. throws IOException {
  130. try {
  131. writer.close();
  132. } finally {
  133. lockFile.delete();
  134. }
  135. }
  136. /** @see java.io.Writer#write(char[], int, int) */
  137. public void write(char[] cbuf, int off, int len)
  138. throws IOException {
  139. writer.write(cbuf, off, len);
  140. }
  141. /** @see java.io.Writer#flush() */
  142. public void flush()
  143. throws IOException {
  144. writer.flush();
  145. }
  146. }