All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.plexus.archiver.tar.TarFile Maven / Gradle / Ivy

There is a newer version: 4.10.0
Show newest version
package org.codehaus.plexus.archiver.tar;

import java.io.File;
import java.io.FileInputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.Enumeration;
import java.util.NoSuchElementException;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.codehaus.plexus.archiver.ArchiveFile;
import static org.codehaus.plexus.archiver.util.Streams.bufferedInputStream;

/**
 * 

* Implementation of {@link ArchiveFile} for tar files.

*

* Compared to * {@link org.apache.commons.compress.archivers.zip.ZipFile}, this one should be used with some care, due to the * nature of a tar file: While a zip file contains a catalog, a tar * file does not. In other words, the only way to read a tar file in * a performant manner is by iterating over it from the beginning to * the end. If you try to open another entry than the "next" entry, * then you force to skip entries, until the requested entry is found. * This may require to reread the entire file!

*

* In other words, the recommended use of this class is to use * {@link #getEntries()} and invoke {@link #getInputStream(TarArchiveEntry)} * only for the current entry. Basically, this is to handle it like * {@link TarArchiveInputStream}.

*

* The advantage of this class is that you may write code for the * {@link ArchiveFile}, which is valid for both tar files and zip files.

*/ public class TarFile implements ArchiveFile { private final java.io.File file; private TarArchiveInputStream inputStream; private TarArchiveEntry currentEntry; /** * Creates a new instance with the given file. */ public TarFile( File file ) { this.file = file; } /** * Implementation of {@link ArchiveFile#getEntries()}. Note, that there is * an interaction between this method and {@link #getInputStream(TarArchiveEntry)}, * or {@link #getInputStream(org.apache.commons.compress.archivers.ArchiveEntry)}: * If an input stream is opened for any other entry than the enumerations * current entry, then entries may be skipped. */ @Override public Enumeration getEntries() throws IOException { if ( inputStream != null ) { close(); } open(); return new Enumeration() { boolean currentEntryValid; @Override public boolean hasMoreElements() { if ( !currentEntryValid ) { try { currentEntry = inputStream.getNextTarEntry(); } catch ( IOException e ) { throw new UndeclaredThrowableException( e ); } } return currentEntry != null; } @Override public org.apache.commons.compress.archivers.ArchiveEntry nextElement() { if ( currentEntry == null ) { throw new NoSuchElementException(); } currentEntryValid = false; return currentEntry; } }; } public void close() throws IOException { if ( inputStream != null ) { inputStream.close(); inputStream = null; } } @Override public InputStream getInputStream( org.apache.commons.compress.archivers.ArchiveEntry entry ) throws IOException { return getInputStream( new TarArchiveEntry( entry.getName() ) ); } /** * Returns an {@link InputStream} with the given entries * contents. This {@link InputStream} may be closed: Nothing * happens in that case, because an actual close would invalidate * the underlying {@link TarArchiveInputStream}. */ public InputStream getInputStream( TarArchiveEntry entry ) throws IOException { if ( entry.equals( (Object) currentEntry ) && inputStream != null ) { return new FilterInputStream( inputStream ) { public void close() throws IOException { // Does nothing. } }; } return getInputStream( entry, currentEntry ); } protected InputStream getInputStream( File file ) throws IOException { return new FileInputStream( file ); } private InputStream getInputStream( TarArchiveEntry entry, TarArchiveEntry currentEntry ) throws IOException { if ( currentEntry == null || inputStream == null ) { // Search for the entry from the beginning of the file to the end. if ( inputStream != null ) { close(); } open(); if ( !findEntry( entry, null ) ) { throw new IOException( "Unknown entry: " + entry.getName() ); } } else { // Search for the entry from the current position to the end of the file. if ( findEntry( entry, null ) ) { return getInputStream( entry ); } close(); open(); if ( !findEntry( entry, currentEntry ) ) { throw new IOException( "No such entry: " + entry.getName() ); } } return getInputStream( entry ); } private void open() throws IOException { inputStream = new TarArchiveInputStream( bufferedInputStream( getInputStream( file ) ), "UTF8" ); } private boolean findEntry( TarArchiveEntry entry, TarArchiveEntry currentEntry ) throws IOException { for ( ;; ) { this.currentEntry = inputStream.getNextTarEntry(); if ( this.currentEntry == null || ( currentEntry != null && this.currentEntry.equals( currentEntry ) ) ) { return false; } if ( this.currentEntry.equals( entry ) ) { return true; } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy