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