/* * Copyright 2010 Srikanth Reddy Lingala * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.lingala.zip4j.unzip; import java.io.File; import java.util.ArrayList; import net.lingala.zip4j.exception.ZipException; import net.lingala.zip4j.io.ZipInputStream; import net.lingala.zip4j.model.CentralDirectory; import net.lingala.zip4j.model.FileHeader; import net.lingala.zip4j.model.UnzipParameters; import net.lingala.zip4j.model.ZipModel; import net.lingala.zip4j.progress.ProgressMonitor; import net.lingala.zip4j.util.InternalZipConstants; import net.lingala.zip4j.util.Zip4jUtil; public class Unzip { private ZipModel zipModel; public Unzip(ZipModel zipModel) throws ZipException { if (zipModel == null) { throw new ZipException("ZipModel is null"); } this.zipModel = zipModel; } public void extractAll(final UnzipParameters unzipParameters, final String outPath, final ProgressMonitor progressMonitor, boolean runInThread) throws ZipException { CentralDirectory centralDirectory = zipModel.getCentralDirectory(); if (centralDirectory == null || centralDirectory.getFileHeaders() == null) { throw new ZipException("invalid central directory in zipModel"); } final ArrayList fileHeaders = centralDirectory.getFileHeaders(); progressMonitor.setCurrentOperation(ProgressMonitor.OPERATION_EXTRACT); progressMonitor.setTotalWork(calculateTotalWork(fileHeaders)); progressMonitor.setState(ProgressMonitor.STATE_BUSY); if (runInThread) { Thread thread = new Thread(InternalZipConstants.THREAD_NAME) { public void run() { try { initExtractAll(fileHeaders, unzipParameters, progressMonitor, outPath); progressMonitor.endProgressMonitorSuccess(); } catch (ZipException e) { } } }; thread.start(); } else { initExtractAll(fileHeaders, unzipParameters, progressMonitor, outPath); } } private void initExtractAll(ArrayList fileHeaders, UnzipParameters unzipParameters, ProgressMonitor progressMonitor, String outPath) throws ZipException { for (int i = 0; i < fileHeaders.size(); i++) { FileHeader fileHeader = (FileHeader)fileHeaders.get(i); initExtractFile(fileHeader, outPath, unzipParameters, null, progressMonitor); if (progressMonitor.isCancelAllTasks()) { progressMonitor.setResult(ProgressMonitor.RESULT_CANCELLED); progressMonitor.setState(ProgressMonitor.STATE_READY); return; } } } public void extractFile(final FileHeader fileHeader, final String outPath, final UnzipParameters unzipParameters, final String newFileName, final ProgressMonitor progressMonitor, boolean runInThread) throws ZipException { if (fileHeader == null) { throw new ZipException("fileHeader is null"); } progressMonitor.setCurrentOperation(ProgressMonitor.OPERATION_EXTRACT); progressMonitor.setTotalWork(fileHeader.getCompressedSize()); progressMonitor.setState(ProgressMonitor.STATE_BUSY); progressMonitor.setPercentDone(0); progressMonitor.setFileName(fileHeader.getFileName()); if (runInThread) { Thread thread = new Thread(InternalZipConstants.THREAD_NAME) { public void run() { try { initExtractFile(fileHeader, outPath, unzipParameters, newFileName, progressMonitor); progressMonitor.endProgressMonitorSuccess(); } catch (ZipException e) { } } }; thread.start(); } else { initExtractFile(fileHeader, outPath, unzipParameters, newFileName, progressMonitor); progressMonitor.endProgressMonitorSuccess(); } } private void initExtractFile(FileHeader fileHeader, String outPath, UnzipParameters unzipParameters, String newFileName, ProgressMonitor progressMonitor) throws ZipException { if (fileHeader == null) { throw new ZipException("fileHeader is null"); } try { progressMonitor.setFileName(fileHeader.getFileName()); if (!outPath.endsWith(InternalZipConstants.FILE_SEPARATOR)) { outPath += InternalZipConstants.FILE_SEPARATOR; } // If file header is a directory, then check if the directory exists // If not then create a directory and return if (fileHeader.isDirectory()) { try { String fileName = fileHeader.getFileName(); if (!Zip4jUtil.isStringNotNullAndNotEmpty(fileName)) { return; } String completePath = outPath + fileName; File file = new File(completePath); if (!file.exists()) { file.mkdirs(); } } catch (Exception e) { progressMonitor.endProgressMonitorError(e); throw new ZipException(e); } } else { //Create Directories checkOutputDirectoryStructure(fileHeader, outPath, newFileName); UnzipEngine unzipEngine = new UnzipEngine(zipModel, fileHeader); try { unzipEngine.unzipFile(progressMonitor, outPath, newFileName, unzipParameters); } catch (Exception e) { progressMonitor.endProgressMonitorError(e); throw new ZipException(e); } } } catch (ZipException e) { progressMonitor.endProgressMonitorError(e); throw e; } catch (Exception e) { progressMonitor.endProgressMonitorError(e); throw new ZipException(e); } } public ZipInputStream getInputStream(FileHeader fileHeader) throws ZipException { UnzipEngine unzipEngine = new UnzipEngine(zipModel, fileHeader); return unzipEngine.getInputStream(); } private void checkOutputDirectoryStructure(FileHeader fileHeader, String outPath, String newFileName) throws ZipException { if (fileHeader == null || !Zip4jUtil.isStringNotNullAndNotEmpty(outPath)) { throw new ZipException("Cannot check output directory structure...one of the parameters was null"); } String fileName = fileHeader.getFileName(); if (Zip4jUtil.isStringNotNullAndNotEmpty(newFileName)) { fileName = newFileName; } if (!Zip4jUtil.isStringNotNullAndNotEmpty(fileName)) { // Do nothing return; } String compOutPath = outPath + fileName; try { File file = new File(compOutPath); String parentDir = file.getParent(); File parentDirFile = new File(parentDir); if (!parentDirFile.exists()) { parentDirFile.mkdirs(); } } catch (Exception e) { throw new ZipException(e); } } private long calculateTotalWork(ArrayList fileHeaders) throws ZipException { if (fileHeaders == null) { throw new ZipException("fileHeaders is null, cannot calculate total work"); } long totalWork = 0; for (int i = 0; i < fileHeaders.size(); i++) { FileHeader fileHeader = (FileHeader)fileHeaders.get(i); if (fileHeader.getZip64ExtendedInfo() != null && fileHeader.getZip64ExtendedInfo().getUnCompressedSize() > 0) { totalWork += fileHeader.getZip64ExtendedInfo().getCompressedSize(); } else { totalWork += fileHeader.getCompressedSize(); } } return totalWork; } }