View Javadoc
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.FileInputStream;
59  import java.io.FileNotFoundException;
60  import java.io.FileOutputStream;
61  import java.io.IOException;
62  import java.io.InputStream;
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   * @version $Id$
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      /*
97       * This method is to be overridden by extending unarchival tasks.
98       */
99      /**
100      * Description of the Method
101      */
102     protected void expandFile( final File srcF, final File dir )
103         throws Exception
104     {
105         ZipInputStream zis = null;
106         try
107         {
108             // code from WarExpand
109             zis = new ZipInputStream( new FileInputStream( srcF ) );
110 
111             for ( ZipEntry ze = zis.getNextEntry(); ze != null; ze = zis.getNextEntry() )
112             {
113                 extractFile( srcF, dir, zis, ze.getName(), new Date( ze.getTime() ), ze.isDirectory() );
114             }
115 
116             // log("expand complete", Project.MSG_VERBOSE);
117             zis.close();
118             zis = null;
119         }
120         catch ( IOException ioe )
121         {
122             throw new Exception( "Error while expanding " + srcF.getPath(), ioe );
123         }
124         finally
125         {
126             IOUtil.close( zis );
127         }
128     }
129 
130     /**
131      * Description of the Method
132      */
133     protected void extractFile( File srcF, File dir, InputStream compressedInputStream, String entryName,
134                                 Date entryDate, boolean isDirectory )
135         throws Exception
136     {
137         File f = FileUtils.resolveFile( dir, entryName );
138 
139         if ( !f.getAbsolutePath().startsWith( dir.getAbsolutePath() ) )
140         {
141             throw new IOException( "Entry '" + entryName + "' outside the target directory." );
142         }
143 
144         try
145         {
146             if ( !overwrite && f.exists() && f.lastModified() >= entryDate.getTime() )
147             {
148                 return;
149             }
150 
151             // create intermediary directories - sometimes zip don't add them
152             File dirF = f.getParentFile();
153             dirF.mkdirs();
154 
155             if ( isDirectory )
156             {
157                 f.mkdirs();
158             }
159             else
160             {
161                 byte[] buffer = new byte[65536];
162                 FileOutputStream fos = null;
163                 try
164                 {
165                     fos = new FileOutputStream( f );
166 
167                     for ( int length =
168                         compressedInputStream.read( buffer ); length >= 0; fos.write( buffer, 0, length ), length =
169                             compressedInputStream.read( buffer ) )
170                         ;
171 
172                     fos.close();
173                     fos = null;
174                 }
175                 finally
176                 {
177                     IOUtil.close( fos );
178                 }
179             }
180 
181             f.setLastModified( entryDate.getTime() );
182         }
183         catch ( FileNotFoundException ex )
184         {
185             throw new Exception( "Can't extract file " + srcF.getPath(), ex );
186         }
187 
188     }
189 
190     /**
191      * Set the destination directory. File will be unzipped into the destination directory.
192      *
193      * @param d Path to the directory.
194      */
195     public void setDest( File d )
196     {
197         this.dest = d;
198     }
199 
200     /**
201      * Set the path to zip-file.
202      *
203      * @param s Path to zip-file.
204      */
205     public void setSrc( File s )
206     {
207         this.source = s;
208     }
209 
210     /**
211      * Should we overwrite files in dest, even if they are newer than the corresponding entries in the archive?
212      */
213     public void setOverwrite( boolean b )
214     {
215         overwrite = b;
216     }
217 
218 }