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 }