2013-03-09 10:12:01 -05:00
2014-04-19 02:30:29 -04:00
package net.filebot.archive ;
2013-03-09 10:12:01 -05:00
import java.text.MessageFormat ;
import java.util.ArrayList ;
import java.util.List ;
import net.sf.sevenzipjbinding.IArchiveOpenVolumeCallback ;
import net.sf.sevenzipjbinding.IInStream ;
import net.sf.sevenzipjbinding.PropID ;
import net.sf.sevenzipjbinding.SevenZipException ;
public class VolumedArchiveInStream implements IInStream {
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
private static final String FIRST_VOLUME_POSTFIX = " .001 " ;
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
private long absoluteOffset ;
private long absoluteLength = - 1 ;
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
private int currentIndex = - 1 ;
private IInStream currentInStream ;
private long currentVolumeOffset ;
private long currentVolumeLength ;
private List < Long > volumePositions = new ArrayList < Long > ( ) ;
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
private final IArchiveOpenVolumeCallback archiveOpenVolumeCallback ;
private String cuttedVolumeFilename ;
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
public VolumedArchiveInStream ( IArchiveOpenVolumeCallback archiveOpenVolumeCallback ) throws SevenZipException {
this ( ( String ) archiveOpenVolumeCallback . getProperty ( PropID . NAME ) , archiveOpenVolumeCallback ) ;
}
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
public VolumedArchiveInStream ( String firstVolumeFilename , IArchiveOpenVolumeCallback archiveOpenVolumeCallback ) throws SevenZipException {
this . archiveOpenVolumeCallback = archiveOpenVolumeCallback ;
volumePositions . add ( Long . valueOf ( 0 ) ) ;
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
if ( ! firstVolumeFilename . endsWith ( FIRST_VOLUME_POSTFIX ) ) {
throw new SevenZipException ( " The first volume filename ' " + firstVolumeFilename + " ' don't ends with the postfix: ' " + FIRST_VOLUME_POSTFIX + " '. Can't proceed " ) ;
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
}
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
cuttedVolumeFilename = firstVolumeFilename . substring ( 0 , firstVolumeFilename . length ( ) - 3 ) ;
openVolume ( 1 , true ) ;
}
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
private void openVolume ( int index , boolean seekToBegin ) throws SevenZipException {
if ( currentIndex = = index ) {
return ;
}
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
for ( int i = volumePositions . size ( ) ; i < index & & absoluteLength = = - 1 ; i + + ) {
openVolume ( i , false ) ;
}
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
if ( absoluteLength ! = - 1 & & volumePositions . size ( ) < = index ) {
return ;
}
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
String volumeFilename = cuttedVolumeFilename + MessageFormat . format ( " {0,number,000} " , Integer . valueOf ( index ) ) ;
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
// Get new IInStream
IInStream newInStream = archiveOpenVolumeCallback . getStream ( volumeFilename ) ;
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
if ( newInStream = = null ) {
absoluteLength = volumePositions . get ( volumePositions . size ( ) - 1 ) . longValue ( ) ;
return ;
}
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
currentInStream = newInStream ;
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
if ( volumePositions . size ( ) = = index ) {
// Determine volume size
currentVolumeLength = currentInStream . seek ( 0 , SEEK_END ) ;
if ( currentVolumeLength = = 0 ) {
throw new RuntimeException ( " Volume " + index + " is empty " ) ;
}
volumePositions . add ( Long . valueOf ( volumePositions . get ( index - 1 ) . longValue ( ) + currentVolumeLength ) ) ;
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
if ( seekToBegin ) {
currentInStream . seek ( 0 , SEEK_SET ) ;
}
} else {
currentVolumeLength = volumePositions . get ( index ) . longValue ( ) - volumePositions . get ( index - 1 ) . longValue ( ) ;
}
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
if ( seekToBegin ) {
currentVolumeOffset = 0 ;
absoluteOffset = volumePositions . get ( index - 1 ) . longValue ( ) ;
}
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
currentIndex = index ;
}
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
private void openVolumeToAbsoluteOffset ( ) throws SevenZipException {
int index = volumePositions . size ( ) - 1 ;
if ( absoluteLength ! = - 1 & & absoluteOffset > = absoluteLength ) {
return ;
}
while ( volumePositions . get ( index ) . longValue ( ) > absoluteOffset ) {
index - - ;
}
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
if ( index < volumePositions . size ( ) - 1 ) {
openVolume ( index + 1 , false ) ;
return ;
}
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
do {
index + + ;
openVolume ( index , false ) ;
} while ( ( absoluteLength = = - 1 | | absoluteOffset < absoluteLength ) & & volumePositions . get ( index ) . longValue ( ) < = absoluteOffset ) ;
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
}
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
@Override
public long seek ( long offset , int seekOrigin ) throws SevenZipException {
long newOffset ;
boolean proceedWithSeek = false ;
switch ( seekOrigin ) {
2015-07-25 18:47:19 -04:00
case SEEK_SET :
newOffset = offset ;
break ;
case SEEK_CUR :
newOffset = absoluteOffset + offset ;
break ;
case SEEK_END :
if ( absoluteLength = = - 1 ) {
openVolume ( Integer . MAX_VALUE , false ) ;
proceedWithSeek = true ;
}
newOffset = absoluteLength + offset ;
break ;
default :
throw new RuntimeException ( " Seek: unknown origin: " + seekOrigin ) ;
2013-03-09 10:12:01 -05:00
}
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
if ( newOffset = = absoluteOffset & & ! proceedWithSeek ) {
return newOffset ;
}
absoluteOffset = newOffset ;
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
openVolumeToAbsoluteOffset ( ) ;
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
if ( absoluteLength ! = - 1 & & absoluteLength < = absoluteOffset ) {
absoluteOffset = absoluteLength ;
return absoluteLength ;
}
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
currentVolumeOffset = absoluteOffset - volumePositions . get ( currentIndex - 1 ) . longValue ( ) ;
currentInStream . seek ( currentVolumeOffset , SEEK_SET ) ;
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
return newOffset ;
}
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
@Override
public int read ( byte [ ] data ) throws SevenZipException {
if ( absoluteLength ! = - 1 & & absoluteOffset > = absoluteLength ) {
return 0 ;
}
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
int read = currentInStream . read ( data ) ;
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
absoluteOffset + = read ;
currentVolumeOffset + = read ;
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
if ( currentVolumeOffset > = currentVolumeLength ) {
openVolume ( currentIndex + 1 , true ) ;
}
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
return read ;
}
2015-07-25 18:47:19 -04:00
2013-03-09 10:12:01 -05:00
}