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

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

The newest version!
package org.codehaus.plexus.archiver.tar;

import java.io.File;
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 org.codehaus.plexus.archiver.util.Streams;

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 Streams.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