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 directory. The directory is created if it does not exist.
050 *
051 * @return the target directory
052 */
053 public static File unzip(File zip, File toDir) throws IOException {
054 unzip(zip, toDir, new ZipEntryFilter() {
055 @Override
056 public boolean accept(ZipEntry entry) {
057 return true;
058 }
059 });
060 return toDir;
061 }
062
063 public static File unzip(File zip, File toDir, ZipEntryFilter filter) throws IOException {
064 if (!toDir.exists()) {
065 FileUtils.forceMkdir(toDir);
066 }
067
068 ZipFile zipFile = new ZipFile(zip);
069 try {
070 Enumeration<? extends ZipEntry> entries = zipFile.entries();
071 while (entries.hasMoreElements()) {
072 ZipEntry entry = entries.nextElement();
073 if (filter.accept(entry)) {
074 File to = new File(toDir, entry.getName());
075 if (entry.isDirectory()) {
076 if (!to.exists() && !to.mkdirs()) {
077 throw new IOException(ERROR_CREATING_DIRECTORY + to);
078 }
079 } else {
080 File parent = to.getParentFile();
081 if (parent != null && !parent.exists() && !parent.mkdirs()) {
082 throw new IOException(ERROR_CREATING_DIRECTORY + parent);
083 }
084
085 copy(zipFile, entry, to);
086 }
087 }
088 }
089 return toDir;
090
091 } finally {
092 zipFile.close();
093 }
094 }
095
096 private static void copy(ZipFile zipFile, ZipEntry entry, File to) throws IOException {
097 FileOutputStream fos = new FileOutputStream(to);
098 InputStream input = null;
099 try {
100 input = zipFile.getInputStream(entry);
101 IOUtils.copy(input, fos);
102 } finally {
103 IOUtils.closeQuietly(input);
104 IOUtils.closeQuietly(fos);
105 }
106 }
107
108 public static void zipDir(File dir, File zip) throws IOException {
109 OutputStream out = null;
110 ZipOutputStream zout = null;
111 try {
112 out = FileUtils.openOutputStream(zip);
113 zout = new ZipOutputStream(out);
114 zip(dir, zout);
115
116 } finally {
117 IOUtils.closeQuietly(zout);
118 IOUtils.closeQuietly(out);
119 }
120 }
121
122 private static void doZip(String entryName, InputStream in, ZipOutputStream out) throws IOException {
123 ZipEntry zentry = new ZipEntry(entryName);
124 out.putNextEntry(zentry);
125 IOUtils.copy(in, out);
126 out.closeEntry();
127 }
128
129 private static void doZip(String entryName, File file, ZipOutputStream out) throws IOException {
130 if (file.isDirectory()) {
131 entryName += '/';
132 ZipEntry zentry = new ZipEntry(entryName);
133 out.putNextEntry(zentry);
134 out.closeEntry();
135 File[] files = file.listFiles();
136 for (int i = 0, len = files.length; i < len; i++) {
137 doZip(entryName + files[i].getName(), files[i], out);
138 }
139
140 } else {
141 InputStream in = null;
142 try {
143 in = new BufferedInputStream(new FileInputStream(file));
144 doZip(entryName, in, out);
145 } finally {
146 IOUtils.closeQuietly(in);
147 }
148 }
149 }
150
151 private static void zip(File file, ZipOutputStream out) throws IOException {
152 for (File child : file.listFiles()) {
153 String name = child.getName();
154 doZip(name, child, out);
155 }
156 }
157
158 public interface ZipEntryFilter {
159 boolean accept(ZipEntry entry);
160 }
161
162 }