001/* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2008-2012 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar 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 * Sonar 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 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020package org.sonar.api.utils; 021 022import org.apache.commons.io.FileUtils; 023import org.apache.commons.io.IOUtils; 024 025import java.io.BufferedInputStream; 026import java.io.File; 027import java.io.FileInputStream; 028import java.io.FileOutputStream; 029import java.io.IOException; 030import java.io.InputStream; 031import java.io.OutputStream; 032import java.util.Enumeration; 033import java.util.zip.ZipEntry; 034import java.util.zip.ZipFile; 035import java.util.zip.ZipOutputStream; 036 037/** 038 * @since 1.10 039 */ 040public final class ZipUtils { 041 042 private ZipUtils() { 043 // only static methods 044 } 045 046 /** 047 * Unzip a file into a new temporary directory. The directory is not deleted on JVM exit, so it 048 * must be explicitely deleted. 049 * 050 * @return the temporary directory 051 * @since 2.2 052 * @deprecated since 3.4 use by {@link org.sonar.api.scan.filesystem.ModuleFileSystem#workingDir()} or {@link org.sonar.api.platform.ServerFileSystem#getTempDir} 053 */ 054 @Deprecated 055 public static File unzipToTempDir(File zip) throws IOException { 056 File toDir = TempFileUtils.createTempDirectory(); 057 unzip(zip, toDir); 058 return toDir; 059 } 060 061 /** 062 * Unzip a file into a directory. The directory is created if it does not exist. 063 * 064 * @return the target directory 065 */ 066 public static File unzip(File zip, File toDir) throws IOException { 067 unzip(zip, toDir, new ZipEntryFilter() { 068 public boolean accept(ZipEntry entry) { 069 return true; 070 } 071 }); 072 return toDir; 073 } 074 075 public static File unzip(File zip, File toDir, ZipEntryFilter filter) throws IOException { 076 if (!toDir.exists()) { 077 FileUtils.forceMkdir(toDir); 078 } 079 080 ZipFile zipFile = new ZipFile(zip); 081 try { 082 Enumeration<? extends ZipEntry> entries = zipFile.entries(); 083 while (entries.hasMoreElements()) { 084 ZipEntry entry = entries.nextElement(); 085 if (filter.accept(entry)) { 086 File to = new File(toDir, entry.getName()); 087 if (entry.isDirectory()) { 088 if (!to.exists() && !to.mkdirs()) { 089 throw new IOException("Error creating directory: " + to); 090 } 091 } else { 092 File parent = to.getParentFile(); 093 if (parent != null && !parent.exists() && !parent.mkdirs()) { 094 throw new IOException("Error creating directory: " + parent); 095 } 096 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 } 109 return toDir; 110 111 } finally { 112 zipFile.close(); 113 } 114 } 115 116 public static void zipDir(File dir, File zip) throws IOException { 117 OutputStream out = null; 118 ZipOutputStream zout = null; 119 try { 120 out = FileUtils.openOutputStream(zip); 121 zout = new ZipOutputStream(out); 122 zip(dir, zout); 123 124 } finally { 125 IOUtils.closeQuietly(zout); 126 IOUtils.closeQuietly(out); 127 } 128 } 129 130 131 private static void _zip(String entryName, InputStream in, ZipOutputStream out) throws IOException { 132 ZipEntry zentry = new ZipEntry(entryName); 133 out.putNextEntry(zentry); 134 IOUtils.copy(in, out); 135 out.closeEntry(); 136 } 137 138 private static void _zip(String entryName, File file, ZipOutputStream out) throws IOException { 139 if (file.isDirectory()) { 140 entryName += '/'; 141 ZipEntry zentry = new ZipEntry(entryName); 142 out.putNextEntry(zentry); 143 out.closeEntry(); 144 File[] files = file.listFiles(); 145 for (int i = 0, len = files.length; i < len; i++) { 146 _zip(entryName + files[i].getName(), files[i], out); 147 } 148 149 } else { 150 InputStream in = null; 151 try { 152 in = new BufferedInputStream(new FileInputStream(file)); 153 _zip(entryName, in, out); 154 } finally { 155 IOUtils.closeQuietly(in); 156 } 157 } 158 } 159 160 private static void zip(File file, ZipOutputStream out) throws IOException { 161 for (File child : file.listFiles()) { 162 String name = child.getName(); 163 _zip(name, child, out); 164 } 165 } 166 167 public interface ZipEntryFilter { 168 boolean accept(ZipEntry entry); 169 } 170 171} 172