001 /* 002 * SonarQube, open source software quality management tool. 003 * Copyright (C) 2008-2014 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * SonarQube is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * SonarQube is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public License 017 * along with this program; if not, write to the Free Software Foundation, 018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 019 */ 020 package org.sonar.api.utils; 021 022 import org.apache.commons.io.FileUtils; 023 import org.apache.commons.io.IOUtils; 024 025 import java.io.BufferedInputStream; 026 import java.io.File; 027 import java.io.FileInputStream; 028 import java.io.FileOutputStream; 029 import java.io.IOException; 030 import java.io.InputStream; 031 import java.io.OutputStream; 032 import java.util.Enumeration; 033 import java.util.zip.ZipEntry; 034 import java.util.zip.ZipFile; 035 import java.util.zip.ZipOutputStream; 036 037 /** 038 * @since 1.10 039 */ 040 public final class ZipUtils { 041 042 private static final String ERROR_CREATING_DIRECTORY = "Error creating directory: "; 043 044 private ZipUtils() { 045 // only static methods 046 } 047 048 /** 049 * Unzip a file into a new temporary directory. The directory is not deleted on JVM exit, so it 050 * must be explicitely deleted. 051 * 052 * @return the temporary directory 053 * @since 2.2 054 * @deprecated since 3.4 use by {@link org.sonar.api.scan.filesystem.ModuleFileSystem#workingDir()} or {@link org.sonar.api.platform.ServerFileSystem#getTempDir} 055 */ 056 @Deprecated 057 public static File unzipToTempDir(File zip) throws IOException { 058 File toDir = TempFileUtils.createTempDirectory(); 059 unzip(zip, toDir); 060 return toDir; 061 } 062 063 /** 064 * Unzip a file into a directory. The directory is created if it does not exist. 065 * 066 * @return the target directory 067 */ 068 public static File unzip(File zip, File toDir) throws IOException { 069 unzip(zip, toDir, new ZipEntryFilter() { 070 public boolean accept(ZipEntry entry) { 071 return true; 072 } 073 }); 074 return toDir; 075 } 076 077 public static File unzip(File zip, File toDir, ZipEntryFilter filter) throws IOException { 078 if (!toDir.exists()) { 079 FileUtils.forceMkdir(toDir); 080 } 081 082 ZipFile zipFile = new ZipFile(zip); 083 try { 084 Enumeration<? extends ZipEntry> entries = zipFile.entries(); 085 while (entries.hasMoreElements()) { 086 ZipEntry entry = entries.nextElement(); 087 if (filter.accept(entry)) { 088 File to = new File(toDir, entry.getName()); 089 if (entry.isDirectory()) { 090 if (!to.exists() && !to.mkdirs()) { 091 throw new IOException(ERROR_CREATING_DIRECTORY + to); 092 } 093 } else { 094 File parent = to.getParentFile(); 095 if (parent != null && !parent.exists() && !parent.mkdirs()) { 096 throw new IOException(ERROR_CREATING_DIRECTORY + parent); 097 } 098 099 copy(zipFile, entry, to); 100 } 101 } 102 } 103 return toDir; 104 105 } finally { 106 zipFile.close(); 107 } 108 } 109 110 private static void copy(ZipFile zipFile, ZipEntry entry, File to) throws IOException { 111 FileOutputStream fos = new FileOutputStream(to); 112 InputStream input = null; 113 try { 114 input = zipFile.getInputStream(entry); 115 IOUtils.copy(input, fos); 116 } finally { 117 IOUtils.closeQuietly(input); 118 IOUtils.closeQuietly(fos); 119 } 120 } 121 122 public static void zipDir(File dir, File zip) throws IOException { 123 OutputStream out = null; 124 ZipOutputStream zout = null; 125 try { 126 out = FileUtils.openOutputStream(zip); 127 zout = new ZipOutputStream(out); 128 zip(dir, zout); 129 130 } finally { 131 IOUtils.closeQuietly(zout); 132 IOUtils.closeQuietly(out); 133 } 134 } 135 136 private static void doZip(String entryName, InputStream in, ZipOutputStream out) throws IOException { 137 ZipEntry zentry = new ZipEntry(entryName); 138 out.putNextEntry(zentry); 139 IOUtils.copy(in, out); 140 out.closeEntry(); 141 } 142 143 private static void doZip(String entryName, File file, ZipOutputStream out) throws IOException { 144 if (file.isDirectory()) { 145 entryName += '/'; 146 ZipEntry zentry = new ZipEntry(entryName); 147 out.putNextEntry(zentry); 148 out.closeEntry(); 149 File[] files = file.listFiles(); 150 for (int i = 0, len = files.length; i < len; i++) { 151 doZip(entryName + files[i].getName(), files[i], out); 152 } 153 154 } else { 155 InputStream in = null; 156 try { 157 in = new BufferedInputStream(new FileInputStream(file)); 158 doZip(entryName, in, out); 159 } finally { 160 IOUtils.closeQuietly(in); 161 } 162 } 163 } 164 165 private static void zip(File file, ZipOutputStream out) throws IOException { 166 for (File child : file.listFiles()) { 167 String name = child.getName(); 168 doZip(name, child, out); 169 } 170 } 171 172 public interface ZipEntryFilter { 173 boolean accept(ZipEntry entry); 174 } 175 176 }