@ -28,6 +28,7 @@ package net.yacy.utils;
import java.io.File ;
import java.io.FileInputStream ;
import java.io.FileNotFoundException ;
import java.io.FileOutputStream ;
import java.io.IOException ;
import java.io.InputStream ;
@ -39,69 +40,138 @@ import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream ;
import org.apache.commons.io.IOUtils ;
/ * *
* Tar archives utilities for YaCy
* /
public class tarTools {
public static InputStream getInputStream ( final String tarFileName ) throws Exception {
if ( tarFileName . endsWith ( ".gz" ) ) {
try {
return new GZIPInputStream ( new FileInputStream ( new File ( tarFileName ) ) ) ;
} catch ( final IOException e ) {
/ * *
* Convenience method to open a stream on a tar archive file eventually
* compressed with gzip .
*
* @param tarPath
* . tar or . tar . gz file path
* @return an opened input stream
* @throws FileNotFoundException
* when the file does not exist , is a directory rather than a
* regular file , or for some other reason cannot be opened for
* reading .
* /
public static InputStream getInputStream ( final String tarPath ) throws FileNotFoundException {
if ( tarPath . endsWith ( ".gz" ) ) {
try {
return new GZIPInputStream ( new FileInputStream ( new File ( tarPath ) ) ) ;
} catch ( FileNotFoundException e ) {
/ *
* FileNotFoundException is is a subClass of IOException but the
* following behavior does not apply
* /
throw e ;
} catch ( final IOException e ) {
// this might happen if the stream is not in gzip format.
// there may be a 'gz' extension, but it may still be a raw tar file
// this can be caused by 'one too much gzip-content header' that was attached
// by a release file server, so just try to open is as normal stream
return new FileInputStream ( new File ( tarFileName ) ) ;
}
return new FileInputStream ( new File ( tarPath ) ) ;
}
}
return new FileInputStream ( new File ( tarFileName ) ) ;
return new FileInputStream ( new File ( tar Path ) ) ;
}
public static InputStream getInputStream ( final File tarFileName ) throws Exception {
return getInputStream ( tarFileName . toString ( ) ) ;
/ * *
* Convenience method to open a stream on a tar archive file eventually
* compressed with gzip .
*
* @param tarFile
* . tar or . tar . gz file
* @return an opened input stream
* @throws FileNotFoundException
* when the file does not exist , is a directory rather than a
* regular file , or for some other reason cannot be opened for
* reading .
* /
public static InputStream getInputStream ( final File tarFile ) throws Exception {
return getInputStream ( tarFile . toString ( ) ) ;
}
/ * *
* untar for any archive , overwrites existing data
* @param in use getInputStream ( ) for convenience
* @param untarDir destination path
* @throws Exception ( IOException or FileNotFoundException )
* Untar for any tar archive , overwrites existing data . Closes the
* InputStream once terminated .
*
* @param in
* input stream . Must not be null . ( use
* { @link # getInputStream ( String ) } for convenience )
* @param untarDir
* destination path . Must not be null .
* @throws IOException
* when a read / write error occurred
* @throws FileNotFoundException
* when the untarDir does not exists
* @throws NullPointerException
* when a parameter is null
* /
public static void unTar ( final InputStream in , final String untarDir ) throws Exception {
public static void unTar ( final InputStream in , final String untarDir ) throws IO Exception {
ConcurrentLog . info ( "UNTAR" , "starting" ) ;
if ( new File ( untarDir ) . exists ( ) ) {
if ( new File ( untarDir ) . exists ( ) ) {
final TarArchiveInputStream tin = new TarArchiveInputStream ( in ) ;
TarArchiveEntry tarEntry = tin . getNextTarEntry ( ) ;
while ( tarEntry ! = null ) {
final File destPath = new File ( untarDir + File . separator + tarEntry . getName ( ) ) ;
if ( ! tarEntry . isDirectory ( ) ) {
new File ( destPath . getParent ( ) ) . mkdirs ( ) ; // create missing subdirectories
final FileOutputStream fout = new FileOutputStream ( destPath ) ;
IOUtils . copyLarge ( tin , fout , 0 , tarEntry . getSize ( ) ) ;
fout . close ( ) ;
} else {
destPath . mkdir ( ) ;
try {
TarArchiveEntry tarEntry = tin . getNextTarEntry ( ) ;
if ( tarEntry = = null ) {
throw new IOException ( "tar archive is empty or corrupted" ) ;
}
while ( tarEntry ! = null ) {
final File destPath = new File ( untarDir + File . separator + tarEntry . getName ( ) ) ;
if ( ! tarEntry . isDirectory ( ) ) {
new File ( destPath . getParent ( ) ) . mkdirs ( ) ; // create missing subdirectories
final FileOutputStream fout = new FileOutputStream ( destPath ) ;
IOUtils . copyLarge ( tin , fout , 0 , tarEntry . getSize ( ) ) ;
fout . close ( ) ;
} else {
destPath . mkdir ( ) ;
}
tarEntry = tin . getNextTarEntry ( ) ;
}
} finally {
try {
tin . close ( ) ;
} catch ( IOException ignored ) {
ConcurrentLog . warn ( "UNTAR" , "InputStream could not be closed" ) ;
}
tarEntry = tin . getNextTarEntry ( ) ;
}
tin . close ( ) ;
} else { // untarDir doesn't exist
ConcurrentLog . warn ( "UNTAR" , "destination " + untarDir + " doesn't exist." ) ;
/* Still have to close the input stream */
try {
in . close ( ) ;
} catch ( IOException ignored ) {
ConcurrentLog . warn ( "UNTAR" , "InputStream could not be closed" ) ;
}
throw new FileNotFoundException ( "Output untar directory not found : " + untarDir ) ;
}
ConcurrentLog . info ( "UNTAR" , "finished" ) ;
}
/ * *
* Untar a tar archive .
* @param args
* < ol >
* < li > args [ 0 ] : source file path < / li >
* < li > args [ 1 ] : destination directory path < / li >
* < / ol >
* /
public static void main ( final String args [ ] ) {
// @arg0 source
// @arg1 destination
if ( args . length = = 2 ) {
try {
unTar ( getInputStream ( args [ 0 ] ) , args [ 1 ] ) ;
} catch ( final Exception e ) {
System . out . println ( e ) ;
}
} else {
System . out . println ( "usage: <source> <destination>" ) ;
if ( args . length = = 2 ) {
try {
unTar ( getInputStream ( args [ 0 ] ) , args [ 1 ] ) ;
} catch ( final Exception e ) {
System . out . println ( e ) ;
}
} else {
System . out . println ( "usage: <source> <destination>" ) ;
}
} finally {
ConcurrentLog . shutdown ( ) ;
}
}
}