001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.camel.util;
018
019 import java.io.BufferedReader;
020 import java.io.File;
021 import java.io.FileInputStream;
022 import java.io.FileReader;
023 import java.io.IOException;
024 import java.io.InputStream;
025 import java.io.InputStreamReader;
026 import java.util.ArrayList;
027 import java.util.Iterator;
028 import java.util.List;
029 import java.util.Locale;
030 import java.util.Stack;
031 import java.util.regex.Matcher;
032 import java.util.regex.Pattern;
033
034 /**
035 * File utilities
036 */
037 public final class FileUtil {
038
039 private static final int RETRY_SLEEP_MILLIS = 10;
040 private static File defaultTempDir;
041
042 private FileUtil() {
043 }
044
045 /**
046 * Normalizes the path to cater for Windows and other platforms
047 */
048 public static String normalizePath(String path) {
049 // special handling for Windows where we need to convert / to \\
050 if (path != null && System.getProperty("os.name").startsWith("Windows") && path.indexOf("/") >= 0) {
051 return path.replace('/', '\\');
052 }
053 return path;
054 }
055
056 private static synchronized File getDefaultTempDir() {
057 if (defaultTempDir != null
058 && defaultTempDir.exists()) {
059 return defaultTempDir;
060 }
061
062 String s = null;
063 try {
064 s = System.getProperty(FileUtil.class.getName() + ".TempDirectory");
065 } catch (SecurityException e) {
066 //Ignorable, we'll use the default
067 }
068 if (s == null) {
069 int x = (int)(Math.random() * 1000000);
070 s = System.getProperty("java.io.tmpdir");
071 File checkExists = new File(s);
072 if (!checkExists.exists()) {
073 throw new RuntimeException("The directory "
074 + checkExists.getAbsolutePath()
075 + " does not exist, please set java.io.tempdir"
076 + " to an existing directory");
077 }
078 File f = new File(s, "camel-tmp-" + x);
079 while (!f.mkdir()) {
080 x = (int)(Math.random() * 1000000);
081 f = new File(s, "camel-tmp-" + x);
082 }
083 defaultTempDir = f;
084 Thread hook = new Thread() {
085 @Override
086 public void run() {
087 removeDir(defaultTempDir);
088 }
089 };
090 Runtime.getRuntime().addShutdownHook(hook);
091 } else {
092 //assume someone outside of us will manage the directory
093 File f = new File(s);
094 f.mkdirs();
095 defaultTempDir = f;
096 }
097 return defaultTempDir;
098 }
099
100 public static void mkDir(File dir) {
101 if (dir == null) {
102 throw new RuntimeException("dir attribute is required");
103 }
104
105 if (dir.isFile()) {
106 throw new RuntimeException("Unable to create directory as a file "
107 + "already exists with that name: " + dir.getAbsolutePath());
108 }
109
110 if (!dir.exists()) {
111 boolean result = doMkDirs(dir);
112 if (!result) {
113 String msg = "Directory " + dir.getAbsolutePath()
114 + " creation was not successful for an unknown reason";
115 throw new RuntimeException(msg);
116 }
117 }
118 }
119
120 /**
121 * Attempt to fix possible race condition when creating directories on
122 * WinXP, also Windows2000. If the mkdirs does not work, wait a little and
123 * try again.
124 */
125 private static boolean doMkDirs(File f) {
126 if (!f.mkdirs()) {
127 try {
128 Thread.sleep(RETRY_SLEEP_MILLIS);
129 return f.mkdirs();
130 } catch (InterruptedException ex) {
131 return f.mkdirs();
132 }
133 }
134 return true;
135 }
136
137 public static void removeDir(File d) {
138 String[] list = d.list();
139 if (list == null) {
140 list = new String[0];
141 }
142 for (int i = 0; i < list.length; i++) {
143 String s = list[i];
144 File f = new File(d, s);
145 if (f.isDirectory()) {
146 removeDir(f);
147 } else {
148 delete(f);
149 }
150 }
151 delete(d);
152 }
153
154 public static void delete(File f) {
155 if (!f.delete()) {
156 if (isWindows()) {
157 System.gc();
158 }
159 try {
160 Thread.sleep(RETRY_SLEEP_MILLIS);
161 } catch (InterruptedException ex) {
162 // Ignore Exception
163 }
164 if (!f.delete()) {
165 f.deleteOnExit();
166 }
167 }
168 }
169
170 private static boolean isWindows() {
171 String osName = System.getProperty("os.name").toLowerCase(Locale.US);
172 return osName.indexOf("windows") > -1;
173 }
174
175 public static File createTempFile(String prefix, String suffix) throws IOException {
176 return createTempFile(prefix, suffix, null, false);
177 }
178
179 public static File createTempFile(String prefix, String suffix, File parentDir,
180 boolean deleteOnExit) throws IOException {
181 File result = null;
182 File parent = (parentDir == null)
183 ? getDefaultTempDir()
184 : parentDir;
185
186 if (suffix == null) {
187 suffix = ".tmp";
188 }
189 if (prefix == null) {
190 prefix = "camel";
191 } else if (prefix.length() < 3) {
192 prefix = prefix + "camel";
193 }
194 result = File.createTempFile(prefix, suffix, parent);
195
196 //if parentDir is null, we're in our default dir
197 //which will get completely wiped on exit from our exit
198 //hook. No need to set deleteOnExit() which leaks memory.
199 if (deleteOnExit && parentDir != null) {
200 result.deleteOnExit();
201 }
202 return result;
203 }
204
205 public static String getStringFromFile(File location) {
206 InputStream is = null;
207 String result = null;
208
209 try {
210 is = new FileInputStream(location);
211 result = normalizeCRLF(is);
212 } catch (Exception e) {
213 e.printStackTrace();
214 } finally {
215 if (is != null) {
216 try {
217 is.close();
218 } catch (Exception e) {
219 //do nothing
220 }
221 }
222 }
223
224 return result;
225 }
226
227 public static String normalizeCRLF(InputStream instream) {
228 BufferedReader in = new BufferedReader(new InputStreamReader(instream));
229 StringBuffer result = new StringBuffer();
230 String line = null;
231
232 try {
233 line = in.readLine();
234 while (line != null) {
235 String[] tok = line.split("\\s");
236
237 for (int x = 0; x < tok.length; x++) {
238 String token = tok[x];
239 result.append(" " + token);
240 }
241 line = in.readLine();
242 }
243 } catch (Exception ex) {
244 ex.printStackTrace();
245 }
246
247 String rtn = result.toString();
248
249 rtn = ignoreTokens(rtn, "<!--", "-->");
250 rtn = ignoreTokens(rtn, "/*", "*/");
251 return rtn;
252 }
253
254 private static String ignoreTokens(final String contents,
255 final String startToken, final String endToken) {
256 String rtn = contents;
257 int headerIndexStart = rtn.indexOf(startToken);
258 int headerIndexEnd = rtn.indexOf(endToken);
259 if (headerIndexStart != -1 && headerIndexEnd != -1 && headerIndexStart < headerIndexEnd) {
260 rtn = rtn.substring(0, headerIndexStart - 1)
261 + rtn.substring(headerIndexEnd + endToken.length() + 1);
262 }
263 return rtn;
264 }
265
266 public static List<File> getFiles(File dir, final String pattern) {
267 return getFiles(dir, pattern, null);
268 }
269 public static List<File> getFilesRecurse(File dir, final String pattern) {
270 return getFilesRecurse(dir, pattern, null);
271 }
272
273 public static List<File> getFiles(File dir, final String pattern, File exclude) {
274 return getFilesRecurse(dir, Pattern.compile(pattern), exclude, false, new ArrayList<File>());
275 }
276 public static List<File> getFilesRecurse(File dir, final String pattern, File exclude) {
277 return getFilesRecurse(dir, Pattern.compile(pattern), exclude, true, new ArrayList<File>());
278 }
279 private static List<File> getFilesRecurse(File dir,
280 Pattern pattern,
281 File exclude, boolean rec,
282 List<File> fileList) {
283 for (File file : dir.listFiles()) {
284 if (file.equals(exclude)) {
285 continue;
286 }
287 if (file.isDirectory() && rec) {
288 getFilesRecurse(file, pattern, exclude, rec, fileList);
289 } else {
290 Matcher m = pattern.matcher(file.getName());
291 if (m.matches()) {
292 fileList.add(file);
293 }
294 }
295 }
296 return fileList;
297 }
298
299 public static List<String> readLines(File file) throws Exception {
300 if (!file.exists()) {
301 return new ArrayList<String>();
302 }
303 BufferedReader reader = new BufferedReader(new FileReader(file));
304 List<String> results = new ArrayList<String>();
305 String line = reader.readLine();
306 while (line != null) {
307 results.add(line);
308 line = reader.readLine();
309 }
310 return results;
311 }
312
313 /**
314 * Strip any leading separators
315 */
316 public static String stripLeadingSeparator(String name) {
317 if (name == null) {
318 return null;
319 }
320 while (name.startsWith("/") || name.startsWith(File.separator)) {
321 name = name.substring(1);
322 }
323 return name;
324 }
325
326 /**
327 * Strip any trailing separators
328 */
329 public static String stripTrailingSeparator(String name) {
330 if (name == null) {
331 return null;
332 }
333 while (name.endsWith("/") || name.endsWith(File.separator)) {
334 name = name.substring(0, name.length() - 1);
335 }
336 return name;
337 }
338
339 /**
340 * Strips any leading paths
341 */
342 public static String stripPath(String name) {
343 if (name == null) {
344 return null;
345 }
346 int pos = name.lastIndexOf("/");
347 if (pos == -1) {
348 pos = name.lastIndexOf(File.separator);
349 }
350 if (pos != -1) {
351 return name.substring(pos + 1);
352 }
353 return name;
354 }
355
356 /**
357 * Compacts a path by stacking it and reducing <tt>..</tt>
358 */
359 public static String compactPath(String path) {
360 // only normalize path if it contains .. as we want to avoid: path/../sub/../sub2 as this can leads to trouble
361 if (path.indexOf("..") == -1) {
362 return path;
363 }
364
365 Stack<String> stack = new Stack<String>();
366 String[] parts = path.split(File.separator);
367 for (String part : parts) {
368 if (part.equals("..") && !stack.isEmpty()) {
369 // only pop if there is a previous path
370 stack.pop();
371 } else {
372 stack.push(part);
373 }
374 }
375
376 // build path based on stack
377 StringBuilder sb = new StringBuilder();
378 for (Iterator it = stack.iterator(); it.hasNext();) {
379 sb.append(it.next());
380 if (it.hasNext()) {
381 sb.append(File.separator);
382 }
383 }
384
385 return sb.toString();
386 }
387
388 }