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 }