14fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy/* 24fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Licensed to the Apache Software Foundation (ASF) under one or more 34fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * contributor license agreements. See the NOTICE file distributed with 44fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * this work for additional information regarding copyright ownership. 54fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The ASF licenses this file to You under the Apache License, Version 2.0 64fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * (the "License"); you may not use this file except in compliance with 74fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * the License. You may obtain a copy of the License at 84fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 94fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * http://www.apache.org/licenses/LICENSE-2.0 104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Unless required by applicable law or agreed to in writing, software 124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * distributed under the License is distributed on an "AS IS" BASIS, 134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * See the License for the specific language governing permissions and 154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * limitations under the License. 164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedypackage org.apache.commons.io.output; 184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.File; 204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.FileOutputStream; 214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.FileWriter; 224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.IOException; 234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.OutputStream; 244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.OutputStreamWriter; 254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.Writer; 264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport org.apache.commons.io.FileUtils; 284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport org.apache.commons.io.IOUtils; 294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy/** 314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * FileWriter that will create and honor lock files to allow simple 324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * cross thread file lock handling. 334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This class provides a simple alternative to <code>FileWriter</code> 354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * that will use a lock file to prevent duplicate writes. 364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * By default, the file will be overwritten, but this may be changed to append. 384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The lock directory may be specified, but defaults to the system property 394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <code>java.io.tmpdir</code>. 404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The encoding may also be specified, and defaults to the platform default. 414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @author <a href="mailto:sanders@apache.org">Scott Sanders</a> 434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @author <a href="mailto:ms@collab.net">Michael Salmon</a> 444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @author <a href="mailto:jon@collab.net">Jon S. Stevens</a> 454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a> 464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @author Stephen Colebourne 474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @author Andy Lehane 484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @version $Id: LockableFileWriter.java 610010 2008-01-08 14:50:59Z niallp $ 494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedypublic class LockableFileWriter extends Writer { 514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // Cannot extend ProxyWriter, as requires writer to be 524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // known when super() is called 534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** The extension for the lock file. */ 554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private static final String LCK = ".lck"; 564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** The writer to decorate. */ 584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private final Writer out; 594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** The lock file. */ 604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private final File lockFile; 614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Constructs a LockableFileWriter. 644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * If the file exists, it is overwritten. 654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param fileName the file to write to, not null 674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws NullPointerException if the file is null 684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException in case of an I/O error 694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public LockableFileWriter(String fileName) throws IOException { 714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy this(fileName, false, null); 724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Constructs a LockableFileWriter. 764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param fileName file to write to, not null 784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param append true if content should be appended, false to overwrite 794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws NullPointerException if the file is null 804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException in case of an I/O error 814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public LockableFileWriter(String fileName, boolean append) throws IOException { 834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy this(fileName, append, null); 844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Constructs a LockableFileWriter. 884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param fileName the file to write to, not null 904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param append true if content should be appended, false to overwrite 914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param lockDir the directory in which the lock file should be held 924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws NullPointerException if the file is null 934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException in case of an I/O error 944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public LockableFileWriter(String fileName, boolean append, String lockDir) throws IOException { 964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy this(new File(fileName), append, lockDir); 974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 1004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Constructs a LockableFileWriter. 1014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * If the file exists, it is overwritten. 1024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 1034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param file the file to write to, not null 1044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws NullPointerException if the file is null 1054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException in case of an I/O error 1064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 1074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public LockableFileWriter(File file) throws IOException { 1084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy this(file, false, null); 1094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 1124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Constructs a LockableFileWriter. 1134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 1144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param file the file to write to, not null 1154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param append true if content should be appended, false to overwrite 1164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws NullPointerException if the file is null 1174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException in case of an I/O error 1184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 1194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public LockableFileWriter(File file, boolean append) throws IOException { 1204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy this(file, append, null); 1214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 1244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Constructs a LockableFileWriter. 1254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 1264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param file the file to write to, not null 1274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param append true if content should be appended, false to overwrite 1284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param lockDir the directory in which the lock file should be held 1294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws NullPointerException if the file is null 1304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException in case of an I/O error 1314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 1324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public LockableFileWriter(File file, boolean append, String lockDir) throws IOException { 1334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy this(file, null, append, lockDir); 1344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 1374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Constructs a LockableFileWriter with a file encoding. 1384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 1394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param file the file to write to, not null 1404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param encoding the encoding to use, null means platform default 1414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws NullPointerException if the file is null 1424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException in case of an I/O error 1434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 1444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public LockableFileWriter(File file, String encoding) throws IOException { 1454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy this(file, encoding, false, null); 1464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 1494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Constructs a LockableFileWriter with a file encoding. 1504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 1514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param file the file to write to, not null 1524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param encoding the encoding to use, null means platform default 1534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param append true if content should be appended, false to overwrite 1544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param lockDir the directory in which the lock file should be held 1554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws NullPointerException if the file is null 1564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException in case of an I/O error 1574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 1584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public LockableFileWriter(File file, String encoding, boolean append, 1594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy String lockDir) throws IOException { 1604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy super(); 1614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // init file to create/append 1624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy file = file.getAbsoluteFile(); 1634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (file.getParentFile() != null) { 1644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy FileUtils.forceMkdir(file.getParentFile()); 1654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (file.isDirectory()) { 1674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy throw new IOException("File specified is a directory"); 1684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // init lock file 1714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (lockDir == null) { 1724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy lockDir = System.getProperty("java.io.tmpdir"); 1734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy File lockDirFile = new File(lockDir); 1754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy FileUtils.forceMkdir(lockDirFile); 1764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy testLockDir(lockDirFile); 1774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy lockFile = new File(lockDirFile, file.getName() + LCK); 1784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // check if locked 1804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy createLock(); 1814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // init wrapped writer 1834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy out = initWriter(file, encoding, append); 1844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy //----------------------------------------------------------------------- 1874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 1884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Tests that we can write to the lock directory. 1894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 1904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param lockDir the File representing the lock directory 1914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException if we cannot write to the lock directory 1924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException if we cannot find the lock file 1934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 1944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private void testLockDir(File lockDir) throws IOException { 1954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (!lockDir.exists()) { 1964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy throw new IOException( 1974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy "Could not find lockDir: " + lockDir.getAbsolutePath()); 1984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (!lockDir.canWrite()) { 2004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy throw new IOException( 2014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy "Could not write to lockDir: " + lockDir.getAbsolutePath()); 2024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 2064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Creates the lock file. 2074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 2084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException if we cannot create the file 2094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 2104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private void createLock() throws IOException { 2114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy synchronized (LockableFileWriter.class) { 2124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (!lockFile.createNewFile()) { 2134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy throw new IOException("Can't write file, lock " + 2144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy lockFile.getAbsolutePath() + " exists"); 2154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy lockFile.deleteOnExit(); 2174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 2214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Initialise the wrapped file writer. 2224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Ensure that a cleanup occurs if the writer creation fails. 2234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 2244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param file the file to be accessed 2254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param encoding the encoding to use 2264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param append true to append 2274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return The initialised writer 2284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException if an error occurs 2294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 2304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private Writer initWriter(File file, String encoding, boolean append) throws IOException { 2314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy boolean fileExistedAlready = file.exists(); 2324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy OutputStream stream = null; 2334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy Writer writer = null; 2344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy try { 2354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (encoding == null) { 2364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy writer = new FileWriter(file.getAbsolutePath(), append); 2374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else { 2384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy stream = new FileOutputStream(file.getAbsolutePath(), append); 2394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy writer = new OutputStreamWriter(stream, encoding); 2404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } catch (IOException ex) { 2424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy IOUtils.closeQuietly(writer); 2434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy IOUtils.closeQuietly(stream); 2444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy lockFile.delete(); 2454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (fileExistedAlready == false) { 2464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy file.delete(); 2474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy throw ex; 2494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } catch (RuntimeException ex) { 2504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy IOUtils.closeQuietly(writer); 2514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy IOUtils.closeQuietly(stream); 2524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy lockFile.delete(); 2534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (fileExistedAlready == false) { 2544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy file.delete(); 2554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy throw ex; 2574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return writer; 2594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy //----------------------------------------------------------------------- 2624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 2634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Closes the file writer. 2644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 2654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException if an I/O error occurs 2664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 2674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public void close() throws IOException { 2684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy try { 2694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy out.close(); 2704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } finally { 2714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy lockFile.delete(); 2724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy //----------------------------------------------------------------------- 2764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 2774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Write a character. 2784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param idx the character to write 2794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException if an I/O error occurs 2804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 2814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public void write(int idx) throws IOException { 2824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy out.write(idx); 2834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 2864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Write the characters from an array. 2874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param chr the characters to write 2884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException if an I/O error occurs 2894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 2904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public void write(char[] chr) throws IOException { 2914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy out.write(chr); 2924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 2954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Write the specified characters from an array. 2964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param chr the characters to write 2974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param st The start offset 2984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param end The number of characters to write 2994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException if an I/O error occurs 3004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 3014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public void write(char[] chr, int st, int end) throws IOException { 3024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy out.write(chr, st, end); 3034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 3044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 3054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 3064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Write the characters from a string. 3074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param str the string to write 3084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException if an I/O error occurs 3094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 3104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public void write(String str) throws IOException { 3114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy out.write(str); 3124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 3134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 3144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 3154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Write the specified characters from a string. 3164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param str the string to write 3174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param st The start offset 3184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param end The number of characters to write 3194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException if an I/O error occurs 3204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 3214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public void write(String str, int st, int end) throws IOException { 3224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy out.write(str, st, end); 3234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 3244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 3254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 3264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Flush the stream. 3274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException if an I/O error occurs 3284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 3294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public void flush() throws IOException { 3304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy out.flush(); 3314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 3324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 3334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy} 334