001/* 002 * Copyright 2010-2015 Institut Pasteur. 003 * 004 * This file is part of Icy. 005 * 006 * Icy is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * Icy 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 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with Icy. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package icy.util; 020 021import icy.file.FileUtil; 022import icy.network.NetworkUtil; 023import icy.system.IcyExceptionHandler; 024 025import java.io.ByteArrayOutputStream; 026import java.io.IOException; 027import java.util.Enumeration; 028import java.util.zip.DataFormatException; 029import java.util.zip.Deflater; 030import java.util.zip.Inflater; 031import java.util.zip.ZipEntry; 032import java.util.zip.ZipFile; 033 034/** 035 * @author Stephane 036 */ 037public class ZipUtil 038{ 039 /** 040 * Compress the specified array of byte with given level of compression and return packed data.<br/> 041 * 042 * @param packer 043 * the packer object, can be <code>null</code> in which case we create a new Deflater object 044 * @param rawData 045 * raw data to compress 046 * @param level 047 * level of compression where 0 is low and 9 is high (use -1 to keep current / use default level) 048 */ 049 public static byte[] pack(Deflater packer, byte[] rawData, int level) 050 { 051 final Deflater compressor; 052 053 if (packer != null) 054 { 055 compressor = packer; 056 compressor.reset(); 057 } 058 else 059 compressor = new Deflater(); 060 061 if (level != -1) 062 compressor.setLevel(level); 063 064 // give data to compress 065 compressor.setInput(rawData); 066 compressor.finish(); 067 068 // create an expandable byte array to hold the compressed data. 069 final ByteArrayOutputStream bos = new ByteArrayOutputStream(rawData.length); 070 final byte[] buf = new byte[65536]; 071 072 // pack data 073 while (!compressor.finished()) 074 { 075 final int count = compressor.deflate(buf); 076 077 // nothing more to do ? --> end here 078 if (count == 0) 079 break; 080 081 bos.write(buf, 0, count); 082 } 083 084 try 085 { 086 bos.close(); 087 } 088 catch (IOException e) 089 { 090 // we can freely ignore this one 091 } 092 093 // return packed data 094 return bos.toByteArray(); 095 } 096 097 /** 098 * Compress the specified array of byte and return packed data 099 */ 100 public static byte[] pack(byte[] rawData) 101 { 102 return pack(null, rawData, -1); 103 } 104 105 /** 106 * Uncompress the specified array of byte and return unpacked data 107 * 108 * @param unpacker 109 * the unpacker object, can be <code>null</code> in which case we create a new Inflater object 110 * @param packedData 111 * packed data to uncompress 112 * @throws DataFormatException 113 */ 114 public static byte[] unpack(Inflater unpacker, byte[] packedData) throws DataFormatException 115 { 116 final Inflater decompressor; 117 118 if (unpacker != null) 119 { 120 decompressor = unpacker; 121 decompressor.reset(); 122 } 123 else 124 decompressor = new Inflater(); 125 126 // give the data to uncompress 127 decompressor.setInput(packedData); 128 129 // create an expandable byte array to hold the uncompressed data 130 final ByteArrayOutputStream bos = new ByteArrayOutputStream(packedData.length); 131 final byte[] buf = new byte[65536]; 132 133 // unpack data 134 while (!decompressor.finished()) 135 { 136 final int count = decompressor.inflate(buf); 137 138 // nothing more to do ? --> end here 139 if (count == 0) 140 break; 141 142 bos.write(buf, 0, count); 143 } 144 try 145 { 146 bos.close(); 147 } 148 catch (IOException e) 149 { 150 // we can freely ignore this one 151 } 152 153 // return unpacked data 154 return bos.toByteArray(); 155 } 156 157 /** 158 * Uncompress the specified array of byte and return unpacked data 159 * 160 * @throws DataFormatException 161 */ 162 public static byte[] unpack(byte[] packedData) throws DataFormatException 163 { 164 return unpack(null, packedData); 165 } 166 167 /** 168 * Extract the specified zip file to the specified destination directory. 169 * 170 * @param zipFile 171 * input zip file name 172 * @param outputDirectory 173 * output directory name 174 * @return true if file was correctly extracted, false otherwise 175 */ 176 public static boolean extract(String zipFile, String outputDirectory) 177 { 178 boolean ok = true; 179 180 try 181 { 182 final ZipFile file = new ZipFile(zipFile); 183 final Enumeration<? extends ZipEntry> entries = file.entries(); 184 185 while (entries.hasMoreElements()) 186 { 187 ZipEntry entry = entries.nextElement(); 188 189 if (entry.isDirectory()) 190 { 191 if (!FileUtil.createDir(outputDirectory + FileUtil.separator + entry.getName())) 192 { 193 System.err.println("ZipUtil.extract(" + zipFile + "," + outputDirectory + ") error :"); 194 System.err.println("Can't create directory : '" + outputDirectory + FileUtil.separator 195 + entry.getName() + "'"); 196 ok = false; 197 break; 198 } 199 } 200 else if (!FileUtil.save(outputDirectory + FileUtil.separator + entry.getName(), 201 NetworkUtil.download(file.getInputStream(entry)), true)) 202 { 203 System.err.println("ZipUtil.extract(" + zipFile + "," + outputDirectory + ") failed."); 204 ok = false; 205 break; 206 } 207 } 208 209 file.close(); 210 } 211 catch (IOException ioe) 212 { 213 System.err.println("ZipUtil.extract(" + zipFile + "," + outputDirectory + ") error :"); 214 IcyExceptionHandler.showErrorMessage(ioe, false); 215 ok = false; 216 } 217 218 return ok; 219 } 220 221 /** 222 * Extract the specified zip file in to default location. 223 * 224 * @param zipFile 225 * input zip file name 226 * @return true if file was correctly extracted, false otherwise 227 */ 228 public static boolean extract(String zipFile) 229 { 230 return extract(zipFile, FileUtil.getDirectory(zipFile) + FileUtil.getFileName(zipFile, false)); 231 } 232 233 /** 234 * Verify that specified file is a valid ZIP file 235 * 236 * @param zipFile 237 * input zip file name 238 * @throws IOException 239 * if the input file is not a valid zip file. 240 */ 241 public static void isValid(String zipFile) throws IOException 242 { 243 final ZipFile file = new ZipFile(zipFile); 244 try 245 { 246 final Enumeration<? extends ZipEntry> entries = file.entries(); 247 248 while (entries.hasMoreElements()) 249 { 250 ZipEntry entry = entries.nextElement(); 251 entry.getName(); 252 } 253 } 254 finally 255 { 256 file.close(); 257 } 258 } 259 260 /** 261 * Verify that specified file is a valid ZIP file 262 * 263 * @param zipFile 264 * input zip file name 265 * @param showError 266 * indicate if the method should show the error (in the output console) if the verify operation failed. 267 * @return true if the specified file is a valid ZIP file 268 */ 269 public static boolean isValid(String zipFile, boolean showError) 270 { 271 try 272 { 273 isValid(zipFile); 274 } 275 catch (IOException e) 276 { 277 if (showError) 278 { 279 System.err.println("ZipUtil.isValid(" + zipFile + ") error :"); 280 IcyExceptionHandler.showErrorMessage(e, false); 281 } 282 283 return false; 284 } 285 286 return true; 287 } 288}