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.deployment.util; 018 019 import java.io.BufferedOutputStream; 020 import java.io.File; 021 import java.io.FileInputStream; 022 import java.io.FileOutputStream; 023 import java.io.IOException; 024 import java.io.InputStream; 025 import java.io.InputStreamReader; 026 import java.io.OutputStream; 027 import java.io.Reader; 028 import java.io.Writer; 029 import java.net.MalformedURLException; 030 import java.net.URL; 031 import java.util.Collection; 032 import java.util.Collections; 033 import java.util.Enumeration; 034 import java.util.LinkedList; 035 import java.util.jar.JarFile; 036 import java.util.jar.JarOutputStream; 037 import java.util.jar.Manifest; 038 import java.util.zip.ZipEntry; 039 import java.util.zip.ZipFile; 040 041 /** 042 * @version $Rev: 566266 $ $Date: 2007-08-15 13:05:16 -0400 (Wed, 15 Aug 2007) $ 043 */ 044 public final class DeploymentUtil { 045 private DeploymentUtil() { 046 } 047 048 public static final File DUMMY_JAR_FILE; 049 static { 050 try { 051 DUMMY_JAR_FILE = DeploymentUtil.createTempFile(); 052 new JarOutputStream(new FileOutputStream(DeploymentUtil.DUMMY_JAR_FILE), new Manifest()).close(); 053 } catch (IOException e) { 054 throw new ExceptionInInitializerError(e); 055 } 056 } 057 058 // be careful to clean up the temp directory 059 public static File createTempDir() throws IOException { 060 File tempDir = File.createTempFile("geronimo-deploymentUtil", ".tmpdir"); 061 tempDir.delete(); 062 tempDir.mkdirs(); 063 return tempDir; 064 } 065 066 // be careful to clean up the temp file... we tell the vm to delete this on exit 067 // but VMs can't be trusted to acutally delete the file 068 public static File createTempFile() throws IOException { 069 File tempFile = File.createTempFile("geronimo-deploymentUtil", ".tmpdir"); 070 tempFile.deleteOnExit(); 071 return tempFile; 072 } 073 074 // be careful to clean up the temp file... we tell the vm to delete this on exit 075 // but VMs can't be trusted to acutally delete the file 076 private static File createTempFile(String extension) throws IOException { 077 File tempFile = File.createTempFile("geronimo-deploymentUtil", extension == null? ".tmpdir": extension); 078 tempFile.deleteOnExit(); 079 return tempFile; 080 } 081 082 083 public static void copyFile(File source, File destination) throws IOException { 084 File destinationDir = destination.getParentFile(); 085 if (false == destinationDir.exists() && false == destinationDir.mkdirs()) { 086 throw new java.io.IOException("Cannot create directory : " + destinationDir); 087 } 088 089 InputStream in = null; 090 OutputStream out = null; 091 try { 092 in = new FileInputStream(source); 093 out = new FileOutputStream(destination); 094 writeAll(in, out); 095 } finally { 096 close(in); 097 close(out); 098 } 099 } 100 101 private static void writeAll(InputStream in, OutputStream out) throws IOException { 102 byte[] buffer = new byte[4096]; 103 int count; 104 while ((count = in.read(buffer)) > 0) { 105 out.write(buffer, 0, count); 106 } 107 out.flush(); 108 } 109 public static File toTempFile(JarFile jarFile, String path) throws IOException { 110 return toTempFile(createJarURL(jarFile, path)); 111 } 112 113 public static File toTempFile(URL url) throws IOException { 114 InputStream in = null; 115 OutputStream out = null; 116 try { 117 in = url.openStream(); 118 119 int index = url.getPath().lastIndexOf("."); 120 String extension = null; 121 if (index > 0) { 122 extension = url.getPath().substring(index); 123 } 124 File tempFile = createTempFile(extension); 125 126 out = new FileOutputStream(tempFile); 127 128 writeAll(in, out); 129 return tempFile; 130 } finally { 131 close(out); 132 close(in); 133 } 134 } 135 136 public static String readAll(URL url) throws IOException { 137 Reader reader = null; 138 try { 139 reader = new InputStreamReader(url.openStream()); 140 141 char[] buffer = new char[4000]; 142 StringBuffer out = new StringBuffer(); 143 for(int count = reader.read(buffer); count >= 0; count = reader.read(buffer)) { 144 out.append(buffer, 0, count); 145 } 146 return out.toString(); 147 } finally { 148 close(reader); 149 } 150 } 151 152 public static File toFile(JarFile jarFile) throws IOException { 153 if (jarFile instanceof UnpackedJarFile) { 154 return ((UnpackedJarFile) jarFile).getBaseDir(); 155 } else { 156 throw new IOException("jarFile is not a directory"); 157 } 158 } 159 160 // be careful with this method as it can leave a temp lying around 161 public static File toFile(JarFile jarFile, String path) throws IOException { 162 if (jarFile instanceof UnpackedJarFile) { 163 File baseDir = ((UnpackedJarFile) jarFile).getBaseDir(); 164 File file = new File(baseDir, path); 165 if (!file.isFile()) { 166 throw new IOException("No such file: " + file.getAbsolutePath()); 167 } 168 return file; 169 } else { 170 String urlString = "jar:" + new File(jarFile.getName()).toURL() + "!/" + path; 171 return toTempFile(new URL(urlString)); 172 } 173 } 174 175 public static URL createJarURL(JarFile jarFile, String path) throws MalformedURLException { 176 if (jarFile instanceof NestedJarFile) { 177 NestedJarFile nestedJar = (NestedJarFile) jarFile; 178 if (nestedJar.isUnpacked()) { 179 JarFile baseJar = nestedJar.getBaseJar(); 180 String basePath = nestedJar.getBasePath(); 181 if (baseJar instanceof UnpackedJarFile) { 182 File baseDir = ((UnpackedJarFile) baseJar).getBaseDir(); 183 baseDir = new File(baseDir, basePath); 184 return new File(baseDir, path).toURL(); 185 } 186 } 187 } 188 189 if (jarFile instanceof UnpackedJarFile) { 190 File baseDir = ((UnpackedJarFile) jarFile).getBaseDir(); 191 return new File(baseDir, path).toURL(); 192 } else { 193 String urlString = "jar:" + new File(jarFile.getName()).toURL() + "!/" + path; 194 return new URL(urlString); 195 } 196 } 197 198 public static JarFile createJarFile(File jarFile) throws IOException { 199 if (jarFile.isDirectory()) { 200 return new UnpackedJarFile(jarFile); 201 } else { 202 return new JarFile(jarFile); 203 } 204 } 205 206 public static void copyToPackedJar(JarFile inputJar, File outputFile) throws IOException { 207 if (inputJar.getClass() == JarFile.class) { 208 // this is a plain old jar... nothign special 209 copyFile(new File(inputJar.getName()), outputFile); 210 } else if (inputJar instanceof NestedJarFile && ((NestedJarFile)inputJar).isPacked()) { 211 NestedJarFile nestedJarFile = (NestedJarFile)inputJar; 212 JarFile baseJar = nestedJarFile.getBaseJar(); 213 String basePath = nestedJarFile.getBasePath(); 214 if (baseJar instanceof UnpackedJarFile) { 215 // our target jar is just a file in upacked jar (a plain old directory)... now 216 // we just need to find where it is and copy it to the outptu 217 copyFile(((UnpackedJarFile)baseJar).getFile(basePath), outputFile); 218 } else { 219 // out target is just a plain old jar file directly accessabel from the file system 220 copyFile(new File(baseJar.getName()), outputFile); 221 } 222 } else { 223 // copy out the module contents to a standalone jar file (entry by entry) 224 JarOutputStream out = null; 225 try { 226 out = new JarOutputStream(new FileOutputStream(outputFile)); 227 byte[] buffer = new byte[4096]; 228 Enumeration entries = inputJar.entries(); 229 while (entries.hasMoreElements()) { 230 ZipEntry entry = (ZipEntry) entries.nextElement(); 231 InputStream in = inputJar.getInputStream(entry); 232 try { 233 out.putNextEntry(new ZipEntry(entry.getName())); 234 try { 235 int count; 236 while ((count = in.read(buffer)) > 0) { 237 out.write(buffer, 0, count); 238 } 239 } finally { 240 out.closeEntry(); 241 } 242 } finally { 243 close(in); 244 } 245 } 246 } finally { 247 close(out); 248 } 249 } 250 } 251 252 public static void jarDirectory(File sourceDirecotry, File destinationFile) throws IOException { 253 JarFile inputJar = new UnpackedJarFile(sourceDirecotry); 254 try { 255 copyToPackedJar(inputJar, destinationFile); 256 } finally { 257 close(inputJar); 258 } 259 } 260 261 private static void createDirectory(File dir) throws IOException { 262 if (dir != null && !dir.exists()) { 263 boolean success = dir.mkdirs(); 264 if (!success) { 265 throw new IOException("Cannot create directory " + dir.getAbsolutePath()); 266 } 267 } 268 } 269 270 public static void unzipToDirectory(ZipFile zipFile, File destDir) throws IOException { 271 Enumeration entries = zipFile.entries(); 272 try { 273 while (entries.hasMoreElements()) { 274 ZipEntry entry = (ZipEntry) entries.nextElement(); 275 if (entry.isDirectory()) { 276 File dir = new File(destDir, entry.getName()); 277 createDirectory(dir); 278 } else { 279 File file = new File(destDir, entry.getName()); 280 createDirectory(file.getParentFile()); 281 OutputStream out = null; 282 InputStream in = null; 283 try { 284 out = new BufferedOutputStream(new FileOutputStream(file)); 285 in = zipFile.getInputStream(entry); 286 writeAll(in, out); 287 } finally { 288 if (null != out) { 289 out.close(); 290 } 291 if (null != in) { 292 in.close(); 293 } 294 } 295 } 296 } 297 } finally { 298 zipFile.close(); 299 } 300 } 301 302 303 public static boolean recursiveDelete(File root, Collection unableToDeleteCollection) { 304 if (root == null) { 305 return true; 306 } 307 308 if (root.isDirectory()) { 309 File[] files = root.listFiles(); 310 if (files != null) { 311 for (int i = 0; i < files.length; i++) { 312 File file = files[i]; 313 if (file.isDirectory()) { 314 recursiveDelete(file, unableToDeleteCollection); 315 } else { 316 if (!file.delete() && unableToDeleteCollection != null) { 317 unableToDeleteCollection.add(file.getAbsolutePath()); 318 } 319 } 320 // help out the GC of file handles by nulling the references 321 file = null; 322 files[i] = null; 323 } 324 } 325 } 326 boolean rootDeleteStatus = false; 327 if (!(rootDeleteStatus = root.delete()) && unableToDeleteCollection != null) 328 unableToDeleteCollection.add(root); 329 330 return rootDeleteStatus; 331 } 332 333 public static boolean recursiveDelete(File root) { 334 return recursiveDelete(root,null); 335 } 336 337 public static Collection listRecursiveFiles(File file) { 338 LinkedList list = new LinkedList(); 339 listRecursiveFiles(file, list); 340 return Collections.unmodifiableCollection(list); 341 } 342 343 public static void listRecursiveFiles(File file, Collection collection) { 344 File[] files = file.listFiles(); 345 if ( null == files ) { 346 return; 347 } 348 for (int i = 0; i < files.length; i++) { 349 collection.add(files[i]); 350 if (files[i].isDirectory()) { 351 listRecursiveFiles(files[i], collection); 352 } 353 } 354 } 355 356 public static void flush(OutputStream thing) { 357 if (thing != null) { 358 try { 359 thing.flush(); 360 } catch(Exception ignored) { 361 } 362 } 363 } 364 365 public static void flush(Writer thing) { 366 if (thing != null) { 367 try { 368 thing.flush(); 369 } catch(Exception ignored) { 370 } 371 } 372 } 373 374 public static void close(JarFile thing) { 375 if (thing != null) { 376 try { 377 thing.close(); 378 } catch(Exception ignored) { 379 } 380 } 381 } 382 383 public static void close(InputStream thing) { 384 if (thing != null) { 385 try { 386 thing.close(); 387 } catch(Exception ignored) { 388 } 389 } 390 } 391 392 public static void close(OutputStream thing) { 393 if (thing != null) { 394 try { 395 thing.close(); 396 } catch(Exception ignored) { 397 } 398 } 399 } 400 401 public static void close(Reader thing) { 402 if (thing != null) { 403 try { 404 thing.close(); 405 } catch(Exception ignored) { 406 } 407 } 408 } 409 410 public static void close(Writer thing) { 411 if (thing != null) { 412 try { 413 thing.close(); 414 } catch(Exception ignored) { 415 } 416 } 417 } 418 419 public static final class EmptyInputStream extends InputStream { 420 public int read() { 421 return -1; 422 } 423 424 public int read(byte b[]) { 425 return -1; 426 } 427 428 public int read(byte b[], int off, int len) { 429 return -1; 430 } 431 432 public long skip(long n) { 433 return 0; 434 } 435 436 public int available() { 437 return 0; 438 } 439 440 public void close() { 441 } 442 443 public synchronized void mark(int readlimit) { 444 } 445 446 public synchronized void reset() { 447 } 448 449 public boolean markSupported() { 450 return false; 451 } 452 } 453 }