View Javadoc
1   /**
2    *
3    * Copyright 2004 The Apache Software Foundation
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    * http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.codehaus.plexus.archiver;
18  
19  import java.io.File;
20  import java.io.FileNotFoundException;
21  import java.io.FileOutputStream;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.io.OutputStream;
25  import java.util.ArrayList;
26  import java.util.Date;
27  import java.util.List;
28  import org.codehaus.plexus.archiver.util.ArchiveEntryUtils;
29  import org.codehaus.plexus.components.io.attributes.SymlinkUtils;
30  import org.codehaus.plexus.components.io.fileselectors.FileSelector;
31  import org.codehaus.plexus.components.io.resources.PlexusIoResource;
32  import org.codehaus.plexus.logging.AbstractLogEnabled;
33  import org.codehaus.plexus.util.FileUtils;
34  import org.codehaus.plexus.util.IOUtil;
35  import org.codehaus.plexus.util.StringUtils;
36  
37  /**
38   * @author <a href="mailto:evenisse@codehaus.org">Emmanuel Venisse</a>
39   * @todo there should really be constructors which take the source file.
40   */
41  public abstract class AbstractUnArchiver
42      extends AbstractLogEnabled
43      implements UnArchiver, FinalizerEnabled
44  {
45  
46      private File destDirectory;
47  
48      private File destFile;
49  
50      private File sourceFile;
51  
52      private boolean overwrite = true;
53  
54      private List finalizers;
55  
56      private FileSelector[] fileSelectors;
57  
58      /**
59       * since 2.3 is on by default
60       *
61       * @since 1.1
62       */
63      private boolean useJvmChmod = true;
64  
65      /**
66       * @since 1.1
67       */
68      private boolean ignorePermissions = false;
69  
70      public AbstractUnArchiver()
71      {
72          // no op
73      }
74  
75      public AbstractUnArchiver( final File sourceFile )
76      {
77          this.sourceFile = sourceFile;
78      }
79  
80      @Override
81      public File getDestDirectory()
82      {
83          return destDirectory;
84      }
85  
86      @Override
87      public void setDestDirectory( final File destDirectory )
88      {
89          this.destDirectory = destDirectory;
90      }
91  
92      @Override
93      public File getDestFile()
94      {
95          return destFile;
96      }
97  
98      @Override
99      public void setDestFile( final File destFile )
100     {
101         this.destFile = destFile;
102     }
103 
104     @Override
105     public File getSourceFile()
106     {
107         return sourceFile;
108     }
109 
110     @Override
111     public void setSourceFile( final File sourceFile )
112     {
113         this.sourceFile = sourceFile;
114     }
115 
116     @Override
117     public boolean isOverwrite()
118     {
119         return overwrite;
120     }
121 
122     @Override
123     public void setOverwrite( final boolean b )
124     {
125         overwrite = b;
126     }
127 
128     @Override
129     public final void extract()
130         throws ArchiverException
131     {
132         validate();
133         execute();
134         runArchiveFinalizers();
135     }
136 
137     @Override
138     public final void extract( final String path, final File outputDirectory )
139         throws ArchiverException
140     {
141         validate( path, outputDirectory );
142         execute( path, outputDirectory );
143         runArchiveFinalizers();
144     }
145 
146     @Override
147     public void addArchiveFinalizer( final ArchiveFinalizer finalizer )
148     {
149         if ( finalizers == null )
150         {
151             finalizers = new ArrayList();
152         }
153 
154         finalizers.add( finalizer );
155     }
156 
157     @Override
158     public void setArchiveFinalizers( final List archiveFinalizers )
159     {
160         finalizers = archiveFinalizers;
161     }
162 
163     private void runArchiveFinalizers()
164         throws ArchiverException
165     {
166         if ( finalizers != null )
167         {
168             for ( Object finalizer1 : finalizers )
169             {
170                 final ArchiveFinalizer finalizer = (ArchiveFinalizer) finalizer1;
171 
172                 finalizer.finalizeArchiveExtraction( this );
173             }
174         }
175     }
176 
177     protected void validate( final String path, final File outputDirectory )
178     {
179     }
180 
181     protected void validate()
182         throws ArchiverException
183     {
184         if ( sourceFile == null )
185         {
186             throw new ArchiverException( "The source file isn't defined." );
187         }
188 
189         if ( sourceFile.isDirectory() )
190         {
191             throw new ArchiverException( "The source must not be a directory." );
192         }
193 
194         if ( !sourceFile.exists() )
195         {
196             throw new ArchiverException( "The source file " + sourceFile + " doesn't exist." );
197         }
198 
199         if ( destDirectory == null && destFile == null )
200         {
201             throw new ArchiverException( "The destination isn't defined." );
202         }
203 
204         if ( destDirectory != null && destFile != null )
205         {
206             throw new ArchiverException( "You must choose between a destination directory and a destination file." );
207         }
208 
209         if ( destDirectory != null && !destDirectory.isDirectory() )
210         {
211             destFile = destDirectory;
212             destDirectory = null;
213         }
214 
215         if ( destFile != null && destFile.isDirectory() )
216         {
217             destDirectory = destFile;
218             destFile = null;
219         }
220     }
221 
222     @Override
223     public void setFileSelectors( final FileSelector[] fileSelectors )
224     {
225         this.fileSelectors = fileSelectors;
226     }
227 
228     @Override
229     public FileSelector[] getFileSelectors()
230     {
231         return fileSelectors;
232     }
233 
234     protected boolean isSelected( final String fileName, final PlexusIoResource fileInfo )
235         throws ArchiverException
236     {
237         if ( fileSelectors != null )
238         {
239             for ( FileSelector fileSelector : fileSelectors )
240             {
241                 try
242                 {
243 
244                     if ( !fileSelector.isSelected( fileInfo ) )
245                     {
246                         return false;
247                     }
248                 }
249                 catch ( final IOException e )
250                 {
251                     throw new ArchiverException(
252                         "Failed to check, whether " + fileInfo.getName() + " is selected: " + e.getMessage(), e );
253                 }
254             }
255         }
256         return true;
257     }
258 
259     protected abstract void execute()
260         throws ArchiverException;
261 
262     protected abstract void execute( String path, File outputDirectory )
263         throws ArchiverException;
264 
265     /**
266      * @since 1.1
267      */
268     @Override
269     public boolean isUseJvmChmod()
270     {
271         return useJvmChmod;
272     }
273 
274     /**
275      * <b>jvm chmod won't set group level permissions !</b>
276      *
277      * @since 1.1
278      */
279     @Override
280     public void setUseJvmChmod( final boolean useJvmChmod )
281     {
282         this.useJvmChmod = useJvmChmod;
283     }
284 
285     /**
286      * @since 1.1
287      */
288     @Override
289     public boolean isIgnorePermissions()
290     {
291         return ignorePermissions;
292     }
293 
294     /**
295      * @since 1.1
296      */
297     @Override
298     public void setIgnorePermissions( final boolean ignorePermissions )
299     {
300         this.ignorePermissions = ignorePermissions;
301     }
302 
303     protected void extractFile( final File srcF, final File dir, final InputStream compressedInputStream,
304                                 final String entryName, final Date entryDate, final boolean isDirectory,
305                                 final Integer mode, String symlinkDestination )
306         throws IOException, ArchiverException
307     {
308         // Hmm. Symlinks re-evaluate back to the original file here. Unsure if this is a good thing...
309         final File f = FileUtils.resolveFile( dir, entryName );
310 
311         try
312         {
313             if ( !isOverwrite() && f.exists() && ( f.lastModified() >= entryDate.getTime() ) )
314             {
315                 return;
316             }
317 
318             // create intermediary directories - sometimes zip don't add them
319             final File dirF = f.getParentFile();
320             if ( dirF != null )
321             {
322                 dirF.mkdirs();
323             }
324 
325             if ( !StringUtils.isEmpty( symlinkDestination ) )
326             {
327                 SymlinkUtils.createSymbolicLink( f, new File( symlinkDestination ) );
328             }
329             else if ( isDirectory )
330             {
331                 f.mkdirs();
332             }
333             else
334             {
335                 OutputStream out = null;
336                 try
337                 {
338                     out = new FileOutputStream( f );
339 
340                     IOUtil.copy( compressedInputStream, out );
341                     out.close();
342                     out = null;
343                 }
344                 finally
345                 {
346                     IOUtil.close( out );
347                 }
348             }
349 
350             f.setLastModified( entryDate.getTime() );
351 
352             if ( !isIgnorePermissions() && mode != null && !isDirectory )
353             {
354                 ArchiveEntryUtils.chmod( f, mode );
355             }
356         }
357         catch ( final FileNotFoundException ex )
358         {
359             getLogger().warn( "Unable to expand to file " + f.getPath() );
360         }
361     }
362 
363 }