001 /* 002 * SonarQube, open source software quality management tool. 003 * Copyright (C) 2008-2013 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 FileOutputStream fos = new FileOutputStream(to); 100 InputStream input = null; 101 try { 102 input = zipFile.getInputStream(entry); 103 IOUtils.copy(input, fos); 104 } finally { 105 IOUtils.closeQuietly(input); 106 IOUtils.closeQuietly(fos); 107 } 108 } 109 } 110 } 111 return toDir; 112 113 } finally { 114 zipFile.close(); 115 } 116 } 117 118 public static void zipDir(File dir, File zip) throws IOException { 119 OutputStream out = null; 120 ZipOutputStream zout = null; 121 try { 122 out = FileUtils.openOutputStream(zip); 123 zout = new ZipOutputStream(out); 124 zip(dir, zout); 125 126 } finally { 127 IOUtils.closeQuietly(zout); 128 IOUtils.closeQuietly(out); 129 } 130 } 131 132 private static void doZip(String entryName, InputStream in, ZipOutputStream out) throws IOException { 133 ZipEntry zentry = new ZipEntry(entryName); 134 out.putNextEntry(zentry); 135 IOUtils.copy(in, out); 136 out.closeEntry(); 137 } 138 139 private static void doZip(String entryName, File file, ZipOutputStream out) throws IOException { 140 if (file.isDirectory()) { 141 entryName += '/'; 142 ZipEntry zentry = new ZipEntry(entryName); 143 out.putNextEntry(zentry); 144 out.closeEntry(); 145 File[] files = file.listFiles(); 146 for (int i = 0, len = files.length; i < len; i++) { 147 doZip(entryName + files[i].getName(), files[i], out); 148 } 149 150 } else { 151 InputStream in = null; 152 try { 153 in = new BufferedInputStream(new FileInputStream(file)); 154 doZip(entryName, in, out); 155 } finally { 156 IOUtils.closeQuietly(in); 157 } 158 } 159 } 160 161 private static void zip(File file, ZipOutputStream out) throws IOException { 162 for (File child : file.listFiles()) { 163 String name = child.getName(); 164 doZip(name, child, out); 165 } 166 } 167 168 public interface ZipEntryFilter { 169 boolean accept(ZipEntry entry); 170 } 171 172 }