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: */package org.apache.openejb.util;
017:
018: import java.io.BufferedOutputStream;
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.nio.channels.FileChannel;
025: import java.util.Enumeration;
026: import java.util.jar.JarEntry;
027: import java.util.jar.JarFile;
028:
029: /**
030: * @version $Rev: 637617 $ $Date: 2008-03-16 10:42:30 -0700 $
031: */
032: public class JarExtractor {
033: public static final Logger logger = Logger.getInstance(
034: LogCategory.OPENEJB_STARTUP_CONFIG,
035: "org.apache.openejb.util.resources");
036:
037: /**
038: * Extract the Jar file into an unpacked directory structure, and
039: * return the absolute pathname to the extracted directory.
040: *
041: * @param file Jar file to unpack
042: * @param pathname Context path name for web application
043: * @throws IllegalArgumentException if this is not a "jar:" URL
044: * @throws java.io.IOException if an input/output error was encountered
045: * during expansion
046: */
047: public static File extract(File file, String pathname)
048: throws IOException {
049: File docBase = new File(file.getParentFile(), pathname);
050: extract(file, docBase);
051: return docBase;
052: }
053:
054: /**
055: * Extract the jar file into the specifiec destination directory. If the destination directory
056: * already exists, the jar will not be unpacked.
057: *
058: * @param file jar file to unpack
059: * @param destinationDir the directory in which the jar will be unpacked; must not exist
060: * @throws java.io.IOException if an input/output error was encountered during expansion
061: */
062: public static void extract(File file, File destinationDir)
063: throws IOException {
064: if (destinationDir.exists()) {
065: // Ear file is already installed
066: return;
067: }
068:
069: logger.info("Extracting jar: " + file.getAbsolutePath());
070:
071: // Create the new document base directory
072: destinationDir.mkdirs();
073:
074: // Extract the JAR into the new directory
075: JarFile jarFile = null;
076: InputStream input = null;
077: try {
078: jarFile = new JarFile(file);
079: Enumeration jarEntries = jarFile.entries();
080: while (jarEntries.hasMoreElements()) {
081: JarEntry jarEntry = (JarEntry) jarEntries.nextElement();
082: String name = jarEntry.getName();
083: int last = name.lastIndexOf('/');
084: if (last >= 0) {
085: File parent = new File(destinationDir, name
086: .substring(0, last));
087: parent.mkdirs();
088: }
089: if (name.endsWith("/")) {
090: continue;
091: }
092: input = jarFile.getInputStream(jarEntry);
093:
094: File extractedFile = extract(input, destinationDir,
095: name);
096: long lastModified = jarEntry.getTime();
097: if ((lastModified != -1) && (lastModified != 0)
098: && (extractedFile != null)) {
099: extractedFile.setLastModified(lastModified);
100: }
101:
102: input.close();
103: input = null;
104: }
105: } catch (IOException e) {
106: // If something went wrong, delete extracted dir to keep things
107: // clean
108: deleteDir(destinationDir);
109: throw e;
110: } finally {
111: if (input != null) {
112: try {
113: input.close();
114: } catch (Throwable t) {
115: }
116: }
117: if (jarFile != null) {
118: try {
119: jarFile.close();
120: } catch (Throwable t) {
121: }
122: }
123: }
124:
125: // Return the absolute path to our new document base directory
126: logger.info("Extracted path: "
127: + destinationDir.getAbsolutePath());
128: }
129:
130: /**
131: * Copy the specified file or directory to the destination.
132: *
133: * @param src File object representing the source
134: * @param dest File object representing the destination
135: */
136: public static boolean copy(File src, File dest) {
137:
138: boolean result = true;
139:
140: String files[];
141: if (src.isDirectory()) {
142: files = src.list();
143: result = dest.mkdir();
144: } else {
145: files = new String[1];
146: files[0] = "";
147: }
148: if (files == null) {
149: files = new String[0];
150: }
151: for (int i = 0; (i < files.length) && result; i++) {
152: File fileSrc = new File(src, files[i]);
153: File fileDest = new File(dest, files[i]);
154: if (fileSrc.isDirectory()) {
155: result = copy(fileSrc, fileDest);
156: } else {
157: FileChannel ic = null;
158: FileChannel oc = null;
159: try {
160: ic = (new FileInputStream(fileSrc)).getChannel();
161: oc = (new FileOutputStream(fileDest)).getChannel();
162: ic.transferTo(0, ic.size(), oc);
163: } catch (IOException e) {
164: logger.error("Copy failed: src: " + fileSrc
165: + ", dest: " + fileDest, e);
166: result = false;
167: } finally {
168: if (ic != null) {
169: try {
170: ic.close();
171: } catch (IOException e) {
172: }
173: }
174: if (oc != null) {
175: try {
176: oc.close();
177: } catch (IOException e) {
178: }
179: }
180: }
181: }
182: }
183: return result;
184:
185: }
186:
187: /**
188: * Delete the specified directory, including all of its contents and
189: * subdirectories recursively.
190: *
191: * @param dir File object representing the directory to be deleted
192: */
193: public static boolean delete(File dir) {
194: if (dir == null)
195: return true;
196:
197: if (dir.isDirectory()) {
198: return deleteDir(dir);
199: } else {
200: return dir.delete();
201: }
202: }
203:
204: /**
205: * Delete the specified directory, including all of its contents and
206: * subdirectories recursively.
207: *
208: * @param dir File object representing the directory to be deleted
209: */
210: public static boolean deleteDir(File dir) {
211: if (dir == null)
212: return true;
213:
214: String fileNames[] = dir.list();
215: if (fileNames == null) {
216: fileNames = new String[0];
217: }
218: for (String fileName : fileNames) {
219: File file = new File(dir, fileName);
220: if (file.isDirectory()) {
221: deleteDir(file);
222: } else {
223: file.delete();
224: }
225: }
226: return dir.delete();
227:
228: }
229:
230: /**
231: * Extract the specified input stream into the specified directory, creating
232: * a file named from the specified relative path.
233: *
234: * @param input InputStream to be copied
235: * @param docBase Document base directory into which we are extracting
236: * @param name Relative pathname of the file to be created
237: * @return A handle to the extracted File
238: * @throws java.io.IOException if an input/output error occurs
239: */
240: protected static File extract(InputStream input, File docBase,
241: String name) throws IOException {
242:
243: File file = new File(docBase, name);
244: BufferedOutputStream output = null;
245: try {
246: output = new BufferedOutputStream(
247: new FileOutputStream(file));
248: byte buffer[] = new byte[2048];
249: while (true) {
250: int n = input.read(buffer);
251: if (n <= 0)
252: break;
253: output.write(buffer, 0, n);
254: }
255: } finally {
256: if (output != null) {
257: try {
258: output.close();
259: } catch (IOException e) {
260: // Ignore
261: }
262: }
263: }
264:
265: return file;
266: }
267:
268: }
|