Coverage Report - org.codehaus.plexus.archiver.AbstractUnArchiver
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractUnArchiver
63 %
71/111
64 %
35/54
2,407
 
 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  45
     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  45
     private boolean useJvmChmod = true;
 64  
 
 65  
     /**
 66  
      * @since 1.1
 67  
      */
 68  45
     private boolean ignorePermissions = false;
 69  
 
 70  0
     public AbstractUnArchiver()
 71  45
     {
 72  
         // no op
 73  45
     }
 74  
 
 75  0
     public AbstractUnArchiver( final File sourceFile )
 76  0
     {
 77  0
         this.sourceFile = sourceFile;
 78  0
     }
 79  
 
 80  
     @Override
 81  
     public File getDestDirectory()
 82  
     {
 83  117
         return destDirectory;
 84  
     }
 85  
 
 86  
     @Override
 87  
     public void setDestDirectory( final File destDirectory )
 88  
     {
 89  19
         this.destDirectory = destDirectory;
 90  19
     }
 91  
 
 92  
     @Override
 93  
     public File getDestFile()
 94  
     {
 95  0
         return destFile;
 96  
     }
 97  
 
 98  
     @Override
 99  
     public void setDestFile( final File destFile )
 100  
     {
 101  6
         this.destFile = destFile;
 102  6
     }
 103  
 
 104  
     @Override
 105  
     public File getSourceFile()
 106  
     {
 107  167
         return sourceFile;
 108  
     }
 109  
 
 110  
     @Override
 111  
     public void setSourceFile( final File sourceFile )
 112  
     {
 113  34
         this.sourceFile = sourceFile;
 114  34
     }
 115  
 
 116  
     @Override
 117  
     public boolean isOverwrite()
 118  
     {
 119  175
         return overwrite;
 120  
     }
 121  
 
 122  
     @Override
 123  
     public void setOverwrite( final boolean b )
 124  
     {
 125  0
         overwrite = b;
 126  0
     }
 127  
 
 128  
     @Override
 129  
     public final void extract()
 130  
         throws ArchiverException
 131  
     {
 132  20
         validate();
 133  20
         execute();
 134  20
         runArchiveFinalizers();
 135  20
     }
 136  
 
 137  
     @Override
 138  
     public final void extract( final String path, final File outputDirectory )
 139  
         throws ArchiverException
 140  
     {
 141  14
         validate( path, outputDirectory );
 142  14
         execute( path, outputDirectory );
 143  13
         runArchiveFinalizers();
 144  13
     }
 145  
 
 146  
     @Override
 147  
     public void addArchiveFinalizer( final ArchiveFinalizer finalizer )
 148  
     {
 149  0
         if ( finalizers == null )
 150  
         {
 151  0
             finalizers = new ArrayList();
 152  
         }
 153  
 
 154  0
         finalizers.add( finalizer );
 155  0
     }
 156  
 
 157  
     @Override
 158  
     public void setArchiveFinalizers( final List archiveFinalizers )
 159  
     {
 160  0
         finalizers = archiveFinalizers;
 161  0
     }
 162  
 
 163  
     private void runArchiveFinalizers()
 164  
         throws ArchiverException
 165  
     {
 166  33
         if ( finalizers != null )
 167  
         {
 168  0
             for ( Object finalizer1 : finalizers )
 169  
             {
 170  0
                 final ArchiveFinalizer finalizer = (ArchiveFinalizer) finalizer1;
 171  
 
 172  0
                 finalizer.finalizeArchiveExtraction( this );
 173  0
             }
 174  
         }
 175  33
     }
 176  
 
 177  
     protected void validate( final String path, final File outputDirectory )
 178  
     {
 179  14
     }
 180  
 
 181  
     protected void validate()
 182  
         throws ArchiverException
 183  
     {
 184  20
         if ( sourceFile == null )
 185  
         {
 186  0
             throw new ArchiverException( "The source file isn't defined." );
 187  
         }
 188  
 
 189  20
         if ( sourceFile.isDirectory() )
 190  
         {
 191  0
             throw new ArchiverException( "The source must not be a directory." );
 192  
         }
 193  
 
 194  20
         if ( !sourceFile.exists() )
 195  
         {
 196  0
             throw new ArchiverException( "The source file " + sourceFile + " doesn't exist." );
 197  
         }
 198  
 
 199  20
         if ( destDirectory == null && destFile == null )
 200  
         {
 201  0
             throw new ArchiverException( "The destination isn't defined." );
 202  
         }
 203  
 
 204  20
         if ( destDirectory != null && destFile != null )
 205  
         {
 206  0
             throw new ArchiverException( "You must choose between a destination directory and a destination file." );
 207  
         }
 208  
 
 209  20
         if ( destDirectory != null && !destDirectory.isDirectory() )
 210  
         {
 211  0
             destFile = destDirectory;
 212  0
             destDirectory = null;
 213  
         }
 214  
 
 215  20
         if ( destFile != null && destFile.isDirectory() )
 216  
         {
 217  6
             destDirectory = destFile;
 218  6
             destFile = null;
 219  
         }
 220  20
     }
 221  
 
 222  
     @Override
 223  
     public void setFileSelectors( final FileSelector[] fileSelectors )
 224  
     {
 225  11
         this.fileSelectors = fileSelectors;
 226  11
     }
 227  
 
 228  
     @Override
 229  
     public FileSelector[] getFileSelectors()
 230  
     {
 231  0
         return fileSelectors;
 232  
     }
 233  
 
 234  
     protected boolean isSelected( final String fileName, final PlexusIoResource fileInfo )
 235  
         throws ArchiverException
 236  
     {
 237  205
         if ( fileSelectors != null )
 238  
         {
 239  86
             for ( FileSelector fileSelector : fileSelectors )
 240  
             {
 241  
                 try
 242  
                 {
 243  
 
 244  56
                     if ( !fileSelector.isSelected( fileInfo ) )
 245  
                     {
 246  26
                         return false;
 247  
                     }
 248  
                 }
 249  0
                 catch ( final IOException e )
 250  
                 {
 251  0
                     throw new ArchiverException(
 252  0
                         "Failed to check, whether " + fileInfo.getName() + " is selected: " + e.getMessage(), e );
 253  30
                 }
 254  
             }
 255  
         }
 256  179
         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  0
         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  0
         this.useJvmChmod = useJvmChmod;
 283  0
     }
 284  
 
 285  
     /**
 286  
      * @since 1.1
 287  
      */
 288  
     @Override
 289  
     public boolean isIgnorePermissions()
 290  
     {
 291  175
         return ignorePermissions;
 292  
     }
 293  
 
 294  
     /**
 295  
      * @since 1.1
 296  
      */
 297  
     @Override
 298  
     public void setIgnorePermissions( final boolean ignorePermissions )
 299  
     {
 300  1
         this.ignorePermissions = ignorePermissions;
 301  1
     }
 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  176
         final File f = FileUtils.resolveFile( dir, entryName );
 310  
 
 311  
         // Make sure that the resolved path of the extracted file doesn't escape the destination directory
 312  176
         String canonicalDirPath = dir.getCanonicalPath();
 313  176
         String canonicalDestPath = f.getCanonicalPath();
 314  
 
 315  176
         if ( !canonicalDestPath.startsWith( canonicalDirPath ) )
 316  
         {
 317  1
             throw new ArchiverException( "Entry is outside of the target directory (" + entryName + ")" );
 318  
         }
 319  
 
 320  
         try
 321  
         {
 322  175
             if ( !isOverwrite() && f.exists() && ( f.lastModified() >= entryDate.getTime() ) )
 323  
             {
 324  0
                 return;
 325  
             }
 326  
 
 327  
             // create intermediary directories - sometimes zip don't add them
 328  175
             final File dirF = f.getParentFile();
 329  175
             if ( dirF != null )
 330  
             {
 331  175
                 dirF.mkdirs();
 332  
             }
 333  
 
 334  175
             if ( !StringUtils.isEmpty( symlinkDestination ) )
 335  
             {
 336  28
                 SymlinkUtils.createSymbolicLink( f, new File( symlinkDestination ) );
 337  0
             }
 338  147
             else if ( isDirectory )
 339  
             {
 340  66
                 f.mkdirs();
 341  0
             }
 342  
             else
 343  
             {
 344  81
                 OutputStream out = null;
 345  
                 try
 346  
                 {
 347  81
                     out = new FileOutputStream( f );
 348  
 
 349  81
                     IOUtil.copy( compressedInputStream, out );
 350  81
                     out.close();
 351  81
                     out = null;
 352  0
                 }
 353  
                 finally
 354  0
                 {
 355  81
                     IOUtil.close( out );
 356  81
                 }
 357  
             }
 358  
 
 359  175
             f.setLastModified( entryDate.getTime() );
 360  
 
 361  175
             if ( !isIgnorePermissions() && mode != null && !isDirectory )
 362  
             {
 363  90
                 ArchiveEntryUtils.chmod( f, mode );
 364  
             }
 365  0
         }
 366  0
         catch ( final FileNotFoundException ex )
 367  
         {
 368  0
             getLogger().warn( "Unable to expand to file " + f.getPath() );
 369  175
         }
 370  175
     }
 371  
 
 372  
 }