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.geronimo.kernel.config; 018 019 import java.io.File; 020 import java.io.FileInputStream; 021 import java.io.FileOutputStream; 022 import java.io.IOException; 023 import java.io.InputStream; 024 import java.io.OutputStream; 025 import java.io.Reader; 026 import java.io.Writer; 027 import java.net.MalformedURLException; 028 import java.net.URL; 029 import java.util.Collections; 030 import java.util.Enumeration; 031 import java.util.HashMap; 032 import java.util.LinkedHashMap; 033 import java.util.LinkedHashSet; 034 import java.util.Map; 035 import java.util.Set; 036 import java.util.jar.JarFile; 037 import java.util.zip.ZipEntry; 038 039 import org.apache.commons.logging.Log; 040 import org.apache.commons.logging.LogFactory; 041 042 /** 043 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $ 044 */ 045 public class IOUtil { 046 private final static Log log = LogFactory.getLog(IOUtil.class); 047 048 public static void recursiveCopy(File srcDir, File destDir) throws IOException { 049 if (srcDir == null) throw new NullPointerException("sourceDir is null"); 050 if (destDir == null) throw new NullPointerException("destDir is null"); 051 if (!srcDir.isDirectory() || !srcDir.canRead()) { 052 throw new IllegalArgumentException("Source directory must be a readable directory " + srcDir); 053 } 054 if (destDir.exists()) { 055 throw new IllegalArgumentException("Destination directory already exists " + destDir); 056 } 057 if (srcDir.equals(destDir)) { 058 throw new IllegalArgumentException("Source and destination directory are the same " + srcDir); 059 } 060 061 destDir.mkdirs(); 062 if (!destDir.exists()) { 063 throw new IOException("Could not create destination directory " + destDir); 064 } 065 066 067 File[] srcFiles = srcDir.listFiles(); 068 if (srcFiles != null) { 069 for (int i = 0; i < srcFiles.length; i++) { 070 File srcFile = srcFiles[i]; 071 File destFile = new File(destDir, srcFile.getName()); 072 if (srcFile.isDirectory()) { 073 recursiveCopy(srcFile, destFile); 074 } else { 075 copyFile(srcFile, destFile); 076 } 077 } 078 } 079 } 080 081 public static void copyFile(File source, File destination) throws IOException { 082 File destinationDir = destination.getParentFile(); 083 if (!destinationDir.exists() && !destinationDir.mkdirs()) { 084 throw new IOException("Cannot create directory : " + destinationDir); 085 } 086 087 InputStream in = null; 088 OutputStream out = null; 089 try { 090 in = new FileInputStream(source); 091 out = new FileOutputStream(destination); 092 writeAll(in, out); 093 } finally { 094 close(in); 095 close(out); 096 } 097 } 098 099 public static void writeAll(InputStream in, OutputStream out) throws IOException { 100 byte[] buffer = new byte[4096]; 101 int count; 102 while ((count = in.read(buffer)) > 0) { 103 out.write(buffer, 0, count); 104 } 105 out.flush(); 106 } 107 108 private static void listFiles(File directory) { 109 if (!log.isDebugEnabled() || !directory.isDirectory()) { 110 return; 111 } 112 File[] files = directory.listFiles(); 113 log.debug(directory.getPath() + " has " + files.length + " files:"); 114 for (File file : files) { 115 log.debug(file.getPath()); 116 } 117 } 118 119 private static boolean deleteFile(File file) { 120 boolean fileDeleted = file.delete(); 121 if (fileDeleted) { 122 return true; 123 } 124 125 // special retry code to handle occasional Windows JDK and Unix NFS timing failures 126 int retryLimit = 5; 127 int retries; 128 int interruptions = 0; 129 for (retries = 1; !fileDeleted && retries <= retryLimit; retries++) { 130 if (log.isDebugEnabled()) { 131 listFiles(file); 132 } 133 System.runFinalization(); 134 try { 135 Thread.sleep(1000); 136 } catch (InterruptedException ie) { 137 interruptions++; 138 } 139 System.gc(); 140 try { 141 Thread.sleep(1000); 142 } catch (InterruptedException ie) { 143 interruptions++; 144 } 145 fileDeleted = file.delete(); 146 } 147 if (fileDeleted) { 148 if (log.isDebugEnabled()) { 149 log.debug(file.getPath() + " deleted after " + retries 150 + " retries, with " + interruptions + " interruptions."); 151 } 152 } else { 153 log.warn(file.getPath() + " not deleted after " + retryLimit 154 + " retries, with " + interruptions + " interruptions."); 155 } 156 return fileDeleted; 157 } 158 159 public static boolean recursiveDelete(File root) { 160 if (root == null) { 161 return true; 162 } 163 164 if (root.isDirectory()) { 165 File[] files = root.listFiles(); 166 if (files != null) { 167 for (int i = 0; i < files.length; i++) { 168 File file = files[i]; 169 if (file.isDirectory()) { 170 recursiveDelete(file); 171 } else { 172 deleteFile(file); 173 } 174 } 175 } 176 } 177 return deleteFile(root); 178 } 179 180 public static void flush(OutputStream thing) { 181 if (thing != null) { 182 try { 183 thing.flush(); 184 } catch (Exception ignored) { 185 } 186 } 187 } 188 189 public static void flush(Writer thing) { 190 if (thing != null) { 191 try { 192 thing.flush(); 193 } catch (Exception ignored) { 194 } 195 } 196 } 197 198 public static void close(JarFile thing) { 199 if (thing != null) { 200 try { 201 thing.close(); 202 } catch (Exception ignored) { 203 } 204 } 205 } 206 207 public static void close(InputStream thing) { 208 if (thing != null) { 209 try { 210 thing.close(); 211 } catch (Exception ignored) { 212 } 213 } 214 } 215 216 public static void close(OutputStream thing) { 217 if (thing != null) { 218 try { 219 thing.close(); 220 } catch (Exception ignored) { 221 } 222 } 223 } 224 225 public static void close(Reader thing) { 226 if (thing != null) { 227 try { 228 thing.close(); 229 } catch (Exception ignored) { 230 } 231 } 232 } 233 234 public static void close(Writer thing) { 235 if (thing != null) { 236 try { 237 thing.close(); 238 } catch (Exception ignored) { 239 } 240 } 241 } 242 243 public static Map<String, File> find(File root, String pattern) { 244 Map<String, File> matches = new HashMap<String, File>(); 245 find(root, pattern, matches); 246 return matches; 247 } 248 249 public static void find(File root, String pattern, Map<String, File> matches) { 250 if (!SelectorUtils.hasWildcards(pattern)) { 251 File match = new File(root, pattern); 252 if (match.exists() && match.canRead()) { 253 matches.put(pattern, match); 254 } 255 } else { 256 Map<String, File> files = IOUtil.listAllFileNames(root); 257 for (Map.Entry<String, File> entry : files.entrySet()) { 258 String fileName = entry.getKey(); 259 if (SelectorUtils.matchPath(pattern, fileName)) { 260 matches.put(fileName, entry.getValue()); 261 } 262 } 263 } 264 } 265 266 public static Set<URL> search(File root, String pattern) throws MalformedURLException { 267 if (root.isDirectory()) { 268 if (pattern == null || pattern.length() == 0) { 269 return Collections.singleton(new URL("file:" + root.toURI().normalize().getPath())); 270 } 271 if (!SelectorUtils.hasWildcards(pattern)) { 272 File match = new File(root, pattern); 273 if (match.exists() && match.canRead()) { 274 return Collections.singleton(new URL("file:" + match.toURI().normalize().getPath())); 275 } else { 276 return Collections.emptySet(); 277 } 278 } else { 279 Set<URL> matches = new LinkedHashSet<URL>(); 280 Map<String, File> files = listAllFileNames(root); 281 for (Map.Entry<String, File> entry : files.entrySet()) { 282 String fileName = entry.getKey(); 283 if (SelectorUtils.matchPath(pattern, fileName)) { 284 File file = entry.getValue(); 285 matches.add(new URL("file:" + file.toURI().normalize().getPath())); 286 } 287 } 288 return matches; 289 } 290 } else { 291 JarFile jarFile = null; 292 try { 293 jarFile = new JarFile(root); 294 URL baseURL = new URL("jar:" + root.toURL().toString() + "!/"); 295 if (pattern == null || pattern.length() == 0) { 296 return Collections.singleton(baseURL); 297 } 298 if (!SelectorUtils.hasWildcards(pattern)) { 299 ZipEntry entry = jarFile.getEntry(pattern); 300 if (entry != null) { 301 URL match = new URL(baseURL, entry.getName()); 302 return Collections.singleton(match); 303 } else { 304 return Collections.emptySet(); 305 } 306 } else { 307 Set<URL> matches = new LinkedHashSet<URL>(); 308 Enumeration entries = jarFile.entries(); 309 while (entries.hasMoreElements()) { 310 ZipEntry entry = (ZipEntry) entries.nextElement(); 311 String fileName = entry.getName(); 312 if (SelectorUtils.matchPath(pattern, fileName)) { 313 URL url = new URL(baseURL, fileName); 314 matches.add(url); 315 } 316 } 317 return matches; 318 } 319 } catch (MalformedURLException e) { 320 throw e; 321 } catch (IOException e) { 322 return Collections.emptySet(); 323 } finally { 324 close(jarFile); 325 } 326 } 327 } 328 329 public static Map<String, File> listAllFileNames(File base) { 330 return listAllFileNames(base, ""); 331 } 332 333 private static Map<String, File> listAllFileNames(File base, String prefix) { 334 if (!base.canRead() || !base.isDirectory()) { 335 throw new IllegalArgumentException(base.getAbsolutePath()); 336 } 337 Map<String, File> map = new LinkedHashMap<String, File>(); 338 File[] hits = base.listFiles(); 339 for (File hit : hits) { 340 if (hit.canRead()) { 341 if (hit.isDirectory()) { 342 map.putAll(listAllFileNames(hit, prefix.equals("") ? hit.getName() : prefix + "/" + hit.getName())); 343 } else { 344 map.put(prefix.equals("") ? hit.getName() : prefix + "/" + hit.getName(), hit); 345 } 346 } 347 } 348 map.put(prefix, base); 349 return map; 350 } 351 }