/* * #%L * BSD implementations of Bio-Formats readers and writers * %% * Copyright (C) 2005 - 2015 Open Microscopy Environment: * - Board of Regents of the University of Wisconsin-Madison * - Glencoe Software, Inc. * - University of Dundee * %% * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * #L% */ package loci.formats.in; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import loci.common.IRandomAccess; import loci.common.Location; import loci.common.RandomAccessInputStream; import loci.common.ZipHandle; import loci.formats.CoreMetadata; import loci.formats.FormatException; import loci.formats.FormatReader; import loci.formats.ImageReader; /** * Reader for Zip files. */ public class ZipReader extends FormatReader { // -- Fields -- private transient ImageReader reader; private String entryName; private ArrayList<String> mappedFiles = new ArrayList<String>(); // -- Constructor -- public ZipReader() { super("Zip", "zip"); } // -- IFormatReader API methods -- /* @see loci.formats.IFormatReader#get8BitLookupTable() */ @Override public byte[][] get8BitLookupTable() throws FormatException, IOException { return reader.get8BitLookupTable(); } /* @see loci.formats.IFormatReader#get16BitLookupTable() */ @Override public short[][] get16BitLookupTable() throws FormatException, IOException { return reader.get16BitLookupTable(); } /* @see loci.formats.IFormatReader#setGroupFiles(boolean) */ @Override public void setGroupFiles(boolean groupFiles) { super.setGroupFiles(groupFiles); if (reader != null) reader.setGroupFiles(groupFiles); } /** * @see loci.formats.IFormatReader#openBytes(int, byte[], int, int, int, int) */ @Override public byte[] openBytes(int no, byte[] buf, int x, int y, int w, int h) throws FormatException, IOException { if (Location.getMappedFile(entryName) == null) { initFile(currentId); } reader.setId(entryName); return reader.openBytes(no, buf, x, y, w, h); } /* @see loci.formats.IFormatReader#close(boolean) */ @Override public void close(boolean fileOnly) throws IOException { super.close(fileOnly); if (reader != null) reader.close(fileOnly); if (!fileOnly) reader = null; for (String name : mappedFiles) { IRandomAccess handle = Location.getMappedFile(name); Location.mapFile(name, null); if (handle != null) { handle.close(); } } mappedFiles.clear(); entryName = null; } // -- Internal FormatReader API methods -- /* @see loci.formats.FormatReader#initFile(String) */ @Override protected void initFile(String id) throws FormatException, IOException { super.initFile(id); reader = new ImageReader(); reader.setMetadataOptions(getMetadataOptions()); reader.setMetadataFiltered(isMetadataFiltered()); reader.setOriginalMetadataPopulated(isOriginalMetadataPopulated()); reader.setNormalized(isNormalized()); reader.setMetadataStore(getMetadataStore()); String innerFile = id; if (checkSuffix(id, "zip")) { innerFile = id.substring(0, id.length() - 4); } int sep = innerFile.lastIndexOf(File.separator); if (sep < 0) { sep = innerFile.lastIndexOf("/"); } if (sep >= 0) { innerFile = innerFile.substring(sep + 1); } // NB: We need a raw handle on the ZIP data itself, not a ZipHandle. IRandomAccess rawHandle = Location.getHandle(id, false, false); in = new RandomAccessInputStream(rawHandle, id); ZipInputStream zip = new ZipInputStream(in); ZipEntry ze = null; entryName = null; boolean matchFound = false; while (true) { ze = zip.getNextEntry(); if (ze == null) break; if (entryName == null) { entryName = ze.getName(); } if (!matchFound && ze.getName().startsWith(innerFile)) { entryName = ze.getName(); matchFound = true; } ZipHandle handle = new ZipHandle(id, ze); Location.mapFile(ze.getName(), handle); mappedFiles.add(ze.getName()); } if (entryName == null) { throw new FormatException("Zip file does not contain any valid files"); } reader.setId(entryName); metadataStore = reader.getMetadataStore(); core = new ArrayList<CoreMetadata>(reader.getCoreMetadataList()); metadata = reader.getGlobalMetadata(); } }