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