001: /*
002: * MCS Media Computer Software Copyright (c) 2005 by MCS
003: * -------------------------------------- Created on 16.01.2004 by w.klaas
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
006: * use this file except in compliance with the License. You may obtain a copy of
007: * 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, WITHOUT
013: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014: * License for the specific language governing permissions and limitations under
015: * the License.
016: */
017: package de.mcs.utils;
018:
019: import java.io.File;
020: import java.io.FileNotFoundException;
021: import java.io.FileOutputStream;
022: import java.io.FilePermission;
023: import java.io.IOException;
024: import java.io.InputStream;
025: import java.security.AccessControlException;
026: import java.util.Enumeration;
027: import java.util.zip.ZipEntry;
028: import java.util.zip.ZipFile;
029:
030: /**
031: * Extract files from a .ear, .war or .jar archive file.
032: *
033: * @author j.froehlich
034: */
035: public class XarExtracter {
036:
037: /** the archive file to work with. */
038: private File archiveFile;
039:
040: /** the archive file to work with. */
041: private ZipFile archive;
042:
043: /** the base directory. */
044: private String baseDirPath; // OS dependent path
045:
046: /** a recursion counter. */
047: private static int recursioncnt = 0;
048:
049: /**
050: * @return getting the archive file.
051: */
052: public final File getFile() {
053: return archiveFile;
054: }
055:
056: /**
057: * @see java.util.zip.ZipFile#getName()
058: */
059: public final String getName() {
060: return null == archive ? null : archive.getName();
061: }
062:
063: /**
064: * converting a filename to a zip name.
065: *
066: * @param osFilename
067: * filename to convert
068: * @return converted name.
069: */
070: private String toZipName(final String osFilename) {
071: String zipName = osFilename;
072: if (null != baseDirPath && baseDirPath.length() > 0
073: && baseDirPath.length() < osFilename.length()
074: && osFilename.startsWith(baseDirPath)) {
075: zipName = osFilename.substring(baseDirPath.length() + 1);
076: }
077: return zipName.replace(File.separatorChar, '/');
078: }
079:
080: /**
081: * constructor with the archive name and a working target.
082: *
083: * @param aArchiveFile
084: * the archive name
085: * @param aBaseDirFile
086: * where to extract.
087: * @throws IOException
088: * if something goes wrong.
089: */
090: public XarExtracter(final File aArchiveFile, final File aBaseDirFile)
091: throws IOException {
092: super ();
093: if (!aArchiveFile.exists()) {
094: throw new FileNotFoundException(aArchiveFile
095: .getAbsolutePath());
096: }
097: if (!aArchiveFile.canRead()) {
098: throw new AccessControlException("No read access",
099: new FilePermission(aArchiveFile.getAbsolutePath(),
100: "read"));
101: }
102: this .archiveFile = aArchiveFile;
103:
104: if (null == aBaseDirFile
105: || 0 == aBaseDirFile.getName().length()) {
106: baseDirPath = new File(System.getProperty("java.io.tmpdir"))
107: .getPath();
108: } else {
109: baseDirPath = aBaseDirFile.getPath();
110: }
111:
112: toZipName(aArchiveFile.getPath());
113: }
114:
115: /**
116: * constructor with the archive name and a working target.
117: *
118: * @param archiveFilename
119: * the archive name
120: * @param baseDir
121: * where to extract.
122: * @throws IOException
123: * if something goes wrong.
124: */
125: public XarExtracter(final String archiveFilename,
126: final String baseDir) throws IOException {
127: this (new File(archiveFilename), new File(baseDir));
128: }
129:
130: /**
131: * doing the extraction.
132: *
133: * @param fromFilename
134: * filename in zip file
135: * @param toLocalFilename
136: * local file name
137: * @return File
138: * @throws IOException
139: * if something goes wrong.
140: */
141: public final File extract(final String fromFilename,
142: final String toLocalFilename) throws IOException {
143: if (null == archive) {
144: archive = new ZipFile(archiveFile);
145: }
146:
147: File localFilename;
148: if (null == toLocalFilename) {
149: localFilename = new File(this .baseDirPath, fromFilename);
150: } else {
151: localFilename = new File(toLocalFilename);
152: }
153: File parent = localFilename.getParentFile();
154: if (null != parent) {
155: parent.mkdirs();
156: }
157:
158: Enumeration archiveEntries = archive.entries();
159: byte[] buffer = new byte[8 * 1024];
160: while (archiveEntries.hasMoreElements()) {
161: ZipEntry entry = (ZipEntry) archiveEntries.nextElement();
162: if (!entry.isDirectory()
163: && entry.getName().equalsIgnoreCase(fromFilename)
164: && entry.getSize() > 0) {
165: // --- extracting ---
166: InputStream input = archive.getInputStream(entry);
167: FileOutputStream output = new FileOutputStream(
168: localFilename);
169: int size = 0;
170: int len;
171: while ((len = input.read(buffer, 0, buffer.length)) != -1) {
172: output.write(buffer, 0, len);
173: size += len;
174: }
175: output.close();
176: // ------------------
177: return localFilename;
178: }
179: }
180: throw new FileNotFoundException("The file '" + fromFilename
181: + "' is not contained in '" + archive.getName()
182: + " or is a directory.");
183:
184: }
185:
186: /**
187: * closing the zip file.
188: *
189: * @throws IOException
190: * if something goes wrong.
191: */
192: public final void close() throws IOException {
193: if (null != archive) {
194: archive.close();
195: archive = null;
196: }
197: }
198:
199: /**
200: * @see java.lang.Object#toString()
201: */
202: public final String toString() {
203: return archiveFile.toString();
204: }
205:
206: /**
207: * extract all files from the zip file.
208: *
209: * @throws IOException
210: * if something goes wrong.
211: */
212: public final void extractAll() throws IOException {
213: extractAll(false, 0);
214: }
215:
216: /**
217: * extract all files from the zip file, with all or none subfolder, or with
218: * subfolder up to the defined depth..
219: *
220: * @param recursive
221: * should all subfolder be extracted.
222: * @param recursionDepth
223: * if recursive = true, how depth-
224: * @throws IOException
225: * if something goes wrong.
226: */
227: public final void extractAll(final boolean recursive,
228: final int recursionDepth) throws IOException {
229: if (null == archive) {
230: archive = new ZipFile(archiveFile);
231: }
232:
233: Enumeration archiveEntries = archive.entries();
234: byte[] buffer = new byte[8 * 1024];
235: while (archiveEntries.hasMoreElements()) {
236: ZipEntry entry = (ZipEntry) archiveEntries.nextElement();
237: if (!entry.isDirectory() && entry.getSize() > 0) {
238: // --- extracting ---
239: File outfile = new File(baseDirPath, entry.getName());
240: outfile.getParentFile().mkdirs();
241: InputStream input = archive.getInputStream(entry);
242: FileOutputStream output = new FileOutputStream(outfile);
243: int size = 0;
244: int len;
245: while ((len = input.read(buffer, 0, buffer.length)) != -1) {
246: output.write(buffer, 0, len);
247: size += len;
248: }
249: output.close();
250: input.close();
251: // --- recursion ---
252: // in case of a .zip .war .ear or .jar file, we can unzip them
253: // too! just if u want to...
254: if (recursive
255: && entry.getName().matches(
256: "(.*[(e)|(w)|(j)]ar)|(.*zip)")
257: && recursioncnt < recursionDepth) {
258: recursioncnt++;
259: File subdir = new File(baseDirPath, entry.getName()
260: .substring(0, entry.getName().length() - 4));
261: File subjar = new File(baseDirPath, entry.getName());
262: XarExtracter xarex = new XarExtracter(subjar,
263: subdir);
264: xarex.extractAll(true, recursionDepth);
265: xarex.close();
266: recursioncnt--;
267: }
268: }
269: }
270: }
271: }
|