
software.coley.llzip.format.model.ZipArchive Maven / Gradle / Ivy
package software.coley.llzip.format.model;
import software.coley.llzip.util.OffsetComparator;
import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* Zip file outline.
*
* @author Matt Coley
*/
public class ZipArchive implements AutoCloseable {
private final List parts = new ArrayList<>();
private final Closeable closableBackingResource;
/**
* @param closableBackingResource
* Closable resource backing the zip archive.
*/
public ZipArchive(Closeable closableBackingResource) {
this.closableBackingResource = closableBackingResource;
}
/**
* @return All parts of the zip archive.
*/
public List getParts() {
return parts;
}
/**
* @param nameFilter
* Filter to limit entries with by file path name.
*
* @return Central directory header entries matching the given file path filter.
*/
public List getNameFilteredCentralDirectories(Predicate nameFilter) {
return getCentralDirectories().stream()
.filter(c -> nameFilter.test(c.getFileNameAsString()))
.collect(Collectors.toList());
}
/**
* @param nameFilter
* Filter to limit entries with by file path name.
*
* @return Local file header entries matching the given file path filter.
*/
public List getNameFilteredLocalFiles(Predicate nameFilter) {
return getCentralDirectories().stream()
.filter(c -> nameFilter.test(c.getFileNameAsString())) // Use central names, as they are authoritative
.map(CentralDirectoryFileHeader::getLinkedFileHeader)
.collect(Collectors.toList());
}
/**
* Searches for a local file entry for the given name.
* The authoritative {@link CentralDirectoryFileHeader#getFileName()} is used,
* not the {@link LocalFileHeader#getFileName()}.
*
* @param name
* Name to fetch contents of.
*
* @return Local file header for the path, or {@code null} if no such entry for the name exists.
*/
public LocalFileHeader getLocalFileByName(String name) {
List matches = getNameFilteredLocalFiles(name::equals);
if (matches.isEmpty()) return null;
return matches.get(0);
}
/**
* @return Local file header entries.
*/
public List getLocalFiles() {
return parts.stream()
.filter(part -> part.type() == PartType.LOCAL_FILE_HEADER)
.map(part -> (LocalFileHeader) part)
.collect(Collectors.toList());
}
/**
* @return Central directory header entries.
*/
public List getCentralDirectories() {
return parts.stream()
.filter(part -> part.type() == PartType.CENTRAL_DIRECTORY_FILE_HEADER)
.map(part -> (CentralDirectoryFileHeader) part)
.collect(Collectors.toList());
}
/**
* @return End of central directory.
*/
public EndOfCentralDirectory getEnd() {
return parts.stream()
.filter(part -> part.type() == PartType.END_OF_CENTRAL_DIRECTORY)
.sorted(new OffsetComparator().reversed()) // Yield the LAST entry
.limit(1)
.map(part -> (EndOfCentralDirectory) part)
.findFirst().orElse(null);
}
/**
* @return Closable resource backing the zip archive.
*/
protected Closeable getClosableBackingResource() {
return closableBackingResource;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ZipArchive that = (ZipArchive) o;
return parts.equals(that.parts);
}
@Override
public int hashCode() {
return parts.hashCode();
}
@Override
public void close() throws IOException {
if (closableBackingResource != null)
closableBackingResource.close();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy