1 package org.codehaus.plexus.util; 2 3 /* 4 * The Apache Software License, Version 1.1 5 * 6 * Copyright (c) 2000-2002 The Apache Software Foundation. All rights 7 * reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. The end-user documentation included with the redistribution, if 22 * any, must include the following acknowledgement: 23 * "This product includes software developed by the 24 * Apache Software Foundation (http://www.codehaus.org/)." 25 * Alternately, this acknowledgement may appear in the software itself, 26 * if and wherever such third-party acknowledgements normally appear. 27 * 28 * 4. The names "The Jakarta Project", "Ant", and "Apache Software 29 * Foundation" must not be used to endorse or promote products derived 30 * from this software without prior written permission. For written 31 * permission, please contact codehaus@codehaus.org. 32 * 33 * 5. Products derived from this software may not be called "Apache" 34 * nor may "Apache" appear in their names without prior written 35 * permission of the Apache Group. 36 * 37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 48 * SUCH DAMAGE. 49 * ==================================================================== 50 * 51 * This software consists of voluntary contributions made by many 52 * individuals on behalf of the Apache Software Foundation. For more 53 * information on the Apache Software Foundation, please see 54 * <http://www.codehaus.org/>. 55 */ 56 57 import java.io.File; 58 import java.io.FileNotFoundException; 59 import java.io.IOException; 60 import java.io.InputStream; 61 import java.io.OutputStream; 62 import java.nio.file.Files; 63 import java.util.Date; 64 import java.util.zip.ZipEntry; 65 import java.util.zip.ZipInputStream; 66 67 /** 68 * Unzip a file. 69 * 70 * @author costin@dnt.ro 71 * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> 72 * @author <a href="mailto:umagesh@codehaus.org">Magesh Umasankar</a> 73 * @since Ant 1.1 @ant.task category="packaging" name="unzip" name="unjar" name="unwar" 74 * 75 */ 76 public class Expand { 77 78 private File dest; // req 79 80 private File source; // req 81 82 private boolean overwrite = true; 83 84 /** 85 * Do the work. 86 * 87 * @exception Exception Thrown in unrecoverable error. 88 */ 89 public void execute() throws Exception { 90 expandFile(source, dest); 91 } 92 93 protected void expandFile(final File srcF, final File dir) throws Exception { 94 // code from WarExpand 95 try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(srcF.toPath()))) { 96 for (ZipEntry ze = zis.getNextEntry(); ze != null; ze = zis.getNextEntry()) { 97 extractFile(srcF, dir, zis, ze.getName(), new Date(ze.getTime()), ze.isDirectory()); 98 } 99 } catch (IOException ioe) { 100 throw new Exception("Error while expanding " + srcF.getPath(), ioe); 101 } 102 } 103 104 protected void extractFile( 105 File srcF, 106 File dir, 107 InputStream compressedInputStream, 108 String entryName, 109 Date entryDate, 110 boolean isDirectory) 111 throws Exception { 112 File f = FileUtils.resolveFile(dir, entryName); 113 114 if (!f.getAbsolutePath().startsWith(dir.getAbsolutePath())) { 115 throw new IOException("Entry '" + entryName + "' outside the target directory."); 116 } 117 118 try { 119 if (!overwrite && f.exists() && f.lastModified() >= entryDate.getTime()) { 120 return; 121 } 122 123 // create intermediary directories - sometimes zip don't add them 124 File dirF = f.getParentFile(); 125 dirF.mkdirs(); 126 127 if (isDirectory) { 128 f.mkdirs(); 129 } else { 130 byte[] buffer = new byte[65536]; 131 132 try (OutputStream fos = Files.newOutputStream(f.toPath())) { 133 for (int length = compressedInputStream.read(buffer); 134 length >= 0; 135 fos.write(buffer, 0, length), length = compressedInputStream.read(buffer)) 136 ; 137 } 138 } 139 140 f.setLastModified(entryDate.getTime()); 141 } catch (FileNotFoundException ex) { 142 throw new Exception("Can't extract file " + srcF.getPath(), ex); 143 } 144 } 145 146 /** 147 * Set the destination directory. File will be unzipped into the destination directory. 148 * 149 * @param d Path to the directory. 150 */ 151 public void setDest(File d) { 152 this.dest = d; 153 } 154 155 /** 156 * Set the path to zip-file. 157 * 158 * @param s Path to zip-file. 159 */ 160 public void setSrc(File s) { 161 this.source = s; 162 } 163 164 /** 165 * @param b Should we overwrite files in dest, even if they are newer than the corresponding entries in the archive? 166 */ 167 public void setOverwrite(boolean b) { 168 overwrite = b; 169 } 170 }