001 /*
002 * Created on Sep 23, 2006
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
005 * the License. You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
010 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
011 * specific language governing permissions and limitations under the License.
012 *
013 * Copyright @2006 the original author or authors.
014 */
015 package org.fest.util;
016
017 import static java.io.File.separator;
018 import static org.fest.util.Arrays.isEmpty;
019 import static org.fest.util.Closeables.close;
020 import static org.fest.util.Flushables.flush;
021 import static org.fest.util.Strings.*;
022
023 import java.io.File;
024 import java.io.IOException;
025 import java.io.OutputStream;
026 import java.io.Writer;
027 import java.util.ArrayList;
028 import java.util.List;
029
030 /**
031 * Understands utility methods related to files.
032 *
033 * @author Yvonne Wang
034 * @author Alex Ruiz
035 */
036 public class Files {
037
038 /**
039 * Returns the names of the files inside the specified directory.
040 * @param dirName the name of the directory to start the search from.
041 * @param recurse if <code>true</code>, we will look in subdirectories.
042 * @return the names of the files inside the specified directory.
043 * @throws IllegalArgumentException if the given directory name does not point to an existing directory.
044 */
045 public static List<String> fileNamesIn(String dirName, boolean recurse) {
046 File dir = new File(dirName);
047 if (!dir.isDirectory())
048 throw new IllegalArgumentException(concat(quote(dirName), " is not a directory or does not exist"));
049 return fileNamesIn(dir, recurse);
050 }
051
052 /**
053 * Returns the names of the files inside the specified directory.
054 * @param dir the name of the directory to start the search from.
055 * @param recurse if <code>true</code>, we will look in subdirectories.
056 * @return the names of the files inside the specified directory.
057 */
058 private static List<String> fileNamesIn(File dir, boolean recurse) {
059 List<String> scriptNames = new ArrayList<String>();
060 File[] existingFiles = dir.listFiles();
061 if (isEmpty(existingFiles)) return scriptNames;
062 for (File existingFile : existingFiles) {
063 if (existingFile.isDirectory()) {
064 if (recurse) scriptNames.addAll(fileNamesIn(existingFile, recurse));
065 continue;
066 }
067 String filename = existingFile.getAbsolutePath();
068 if (!scriptNames.contains(filename)) scriptNames.add(filename);
069 }
070 return scriptNames;
071 }
072
073 /**
074 * Returns the system's temporary folder.
075 * @return the system's temporary folder.
076 * @throws FilesException if this method cannot find or create the system's temporary folder.
077 */
078 public static File temporaryFolder() {
079 File temp = new File(temporaryFolderPath());
080 if (!temp.isDirectory()) throw new FilesException("Unable to find temporary folder");
081 return temp;
082 }
083
084 /**
085 * Returns the path of the system's temporary folder. This method appends the system's file separator at the end of
086 * the path.
087 * @return the path of the system's temporary folder.
088 */
089 public static String temporaryFolderPath() {
090 return append(separator).to(System.getProperty("java.io.tmpdir"));
091 }
092
093 /**
094 * Creates a new file in the system's temporary folder. The name of the file will be the result of:
095 * <pre>
096 * concat(String.valueOf(System.currentTimeMillis()), ".txt");
097 * </pre>
098 * @return the created file.
099 */
100 public static File newTemporaryFile() {
101 String tempFileName = concat(String.valueOf(System.currentTimeMillis()), ".txt");
102 return newFile(concat(temporaryFolderPath(), tempFileName));
103 }
104
105 /**
106 * Creates a new folder in the system's temporary folder. The name of the folder will be the result of:
107 * <pre>
108 * System.currentTimeMillis();
109 * </pre>
110 * @return the created file.
111 */
112 public static File newTemporaryFolder() {
113 String tempFileName = String.valueOf(System.currentTimeMillis());
114 return newFolder(concat(temporaryFolderPath(), tempFileName));
115 }
116
117 /**
118 * Creates a new file using the given path.
119 * @param path the path of the new file.
120 * @return the new created file.
121 * @throws FilesException if the path belongs to an existing non-empty directory.
122 * @throws FilesException if the path belongs to an existing file.
123 * @throws FilesException if any I/O error is thrown when creating the new file.
124 */
125 public static File newFile(String path) {
126 File file = new File(path);
127 if (file.isDirectory() && !isEmpty(file.list()))
128 throw cannotCreateNewFile(path, "a non-empty directory was found with the same path");
129 try {
130 if (!file.createNewFile()) throw cannotCreateNewFile(path, "a file was found with the same path");
131 } catch (IOException e) {
132 throw cannotCreateNewFile(path, e);
133 }
134 return file;
135 }
136
137 /**
138 * Creates a new folder using the given path.
139 * @param path the path of the new folder.
140 * @return the new created folder.
141 * @throws FilesException if the path belongs to an existing non-empty directory.
142 * @throws FilesException if the path belongs to an existing file.
143 * @throws FilesException if any I/O error is thrown when creating the new folder.
144 */
145 public static File newFolder(String path) {
146 File file = new File(path);
147 if (file.isDirectory() && !isEmpty(file.list()))
148 throw cannotCreateNewFile(path, "a non-empty directory was found with the same path");
149 try {
150 if (!file.mkdir()) throw cannotCreateNewFile(path, "a file was found with the same path");
151 } catch (Exception e) {
152 throw cannotCreateNewFile(path, e);
153 }
154 return file;
155 }
156
157 private static FilesException cannotCreateNewFile(String path, String reason) {
158 throw cannotCreateNewFile(path, reason, null);
159 }
160
161 private static FilesException cannotCreateNewFile(String path, Exception cause) {
162 throw cannotCreateNewFile(path, null, cause);
163 }
164
165 private static FilesException cannotCreateNewFile(String path, String reason, Exception cause) {
166 String message = concat("Unable to create the new file ", quote(path));
167 if (!Strings.isEmpty(reason)) message = concat(message, ": ", reason);
168 if (cause != null) throw new FilesException(message, cause);
169 throw new FilesException(message);
170 }
171
172 /**
173 * Flushes and closes the given <code>{@link Writer}</code>. Any I/O errors catched by this method are ignored and
174 * not rethrown.
175 * @param writer the writer to flush and close.
176 */
177 public static void flushAndClose(Writer writer) {
178 if (writer == null) return;
179 flush(writer);
180 close(writer);
181 }
182
183 /**
184 * Flushes and closes the given <code>{@link OutputStream}</code>. Any I/O errors catched by this method are ignored
185 * and not rethrown.
186 * @param out the output stream to flush and close.
187 */
188 public static void flushAndClose(OutputStream out) {
189 if (out == null) return;
190 flush(out);
191 close(out);
192 }
193
194 /**
195 * Returns the current directory.
196 * @return the current directory.
197 * @throws FilesException if the current directory cannot be obtained.
198 */
199 public static File currentFolder() {
200 try {
201 return new File(".").getCanonicalFile();
202 } catch (IOException e) {
203 throw new FilesException("Unable to get current directory", e);
204 }
205 }
206
207 /**
208 * Deletes the given file or directory.
209 * @param file the file or directory to delete.
210 */
211 public static void delete(File file) {
212 if (file.isFile()) {
213 file.delete();
214 return;
215 }
216 if (!file.isDirectory()) return;
217 for (File f : file.listFiles()) delete(f);
218 file.delete();
219 }
220
221 private Files() {}
222 }