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 79 private File dest;// req 80 81 private File source;// req 82 83 private boolean overwrite = true; 84 85 /** 86 * Do the work. 87 * 88 * @exception Exception Thrown in unrecoverable error. 89 */ 90 public void execute() 91 throws Exception 92 { 93 expandFile( source, dest ); 94 } 95 96 protected void expandFile( final File srcF, final File dir ) 97 throws Exception 98 { 99 // code from WarExpand 100 try ( ZipInputStream zis = new ZipInputStream( Files.newInputStream( srcF.toPath() ) ) ) 101 { 102 for ( ZipEntry ze = zis.getNextEntry(); ze != null; ze = zis.getNextEntry() ) 103 { 104 extractFile( srcF, dir, zis, ze.getName(), new Date( ze.getTime() ), ze.isDirectory() ); 105 } 106 } 107 catch ( IOException ioe ) 108 { 109 throw new Exception( "Error while expanding " + srcF.getPath(), ioe ); 110 } 111 } 112 113 protected void extractFile( File srcF, File dir, InputStream compressedInputStream, String entryName, 114 Date entryDate, boolean isDirectory ) 115 throws Exception 116 { 117 File f = FileUtils.resolveFile( dir, entryName ); 118 119 if ( !f.getAbsolutePath().startsWith( dir.getAbsolutePath() ) ) 120 { 121 throw new IOException( "Entry '" + entryName + "' outside the target directory." ); 122 } 123 124 try 125 { 126 if ( !overwrite && f.exists() && f.lastModified() >= entryDate.getTime() ) 127 { 128 return; 129 } 130 131 // create intermediary directories - sometimes zip don't add them 132 File dirF = f.getParentFile(); 133 dirF.mkdirs(); 134 135 if ( isDirectory ) 136 { 137 f.mkdirs(); 138 } 139 else 140 { 141 byte[] buffer = new byte[65536]; 142 143 try ( OutputStream fos = Files.newOutputStream( f.toPath() ) ) 144 { 145 for ( int length = compressedInputStream.read( buffer ); 146 length >= 0; 147 fos.write( buffer, 0, length ), length = compressedInputStream.read( buffer ) ) 148 ; 149 } 150 } 151 152 f.setLastModified( entryDate.getTime() ); 153 } 154 catch ( FileNotFoundException ex ) 155 { 156 throw new Exception( "Can't extract file " + srcF.getPath(), ex ); 157 } 158 159 } 160 161 /** 162 * Set the destination directory. File will be unzipped into the destination directory. 163 * 164 * @param d Path to the directory. 165 */ 166 public void setDest( File d ) 167 { 168 this.dest = d; 169 } 170 171 /** 172 * Set the path to zip-file. 173 * 174 * @param s Path to zip-file. 175 */ 176 public void setSrc( File s ) 177 { 178 this.source = s; 179 } 180 181 /** 182 * @param b Should we overwrite files in dest, even if they are newer than the corresponding entries in the archive? 183 */ 184 public void setOverwrite( boolean b ) 185 { 186 overwrite = b; 187 } 188 189 }