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