org.squashtest.tm.service.internal.archive.ZipReader.java Source code

Java tutorial

Introduction

Here is the source code for org.squashtest.tm.service.internal.archive.ZipReader.java

Source

/**
 *     This file is part of the Squashtest platform.
 *     Copyright (C) 2010 - 2016 Henix, henix.fr
 *
 *     See the NOTICE file distributed with this work for additional
 *     information regarding copyright ownership.
 *
 *     This is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Lesser General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     this software is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Lesser General Public License for more details.
 *
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with this software.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.squashtest.tm.service.internal.archive;

import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.squashtest.tm.exception.ZipCorruptedException;

/*
 * TODO : make an interface for it.
 */
public class ZipReader implements ArchiveReader {

    private ZipArchiveInputStream zipStream;
    private String encoding = "UTF8";

    private ZipReaderEntry currentEntry;
    private ZipReaderEntry nextEntry;

    public ZipReader(InputStream stream, String encoding) {
        doSetEncoding(encoding);
        doSetStream(stream);
    }

    @Override
    public void setEncoding(String encoding) {
        doSetEncoding(encoding);
    }

    private void doSetEncoding(String encoding) {
        this.encoding = encoding;
    }

    // todo : make the encoding configurable one day
    @Override
    public void setStream(InputStream stream) {
        doSetStream(stream);
    }

    private void doSetStream(InputStream stream) {
        zipStream = new ZipArchiveInputStream(stream, encoding, false);
    }

    @Override
    public void close() {
        try {
            zipStream.close();
        } catch (IOException ex) {
            throw new ZipCorruptedException(ex);
        }

    }

    /* ****************** nested entry impl****************** */

    private static final class ZipReaderEntry implements Entry {

        private InputStream zipStream;
        private String name;
        private boolean isDirectory;

        private ZipReaderEntry(InputStream stream, String name, boolean isDirectory) {
            this.zipStream = stream;
            this.name = stripSuffix(name);
            this.isDirectory = isDirectory;
        }

        private ZipReaderEntry(InputStream stream, ArchiveEntry entry) {
            this(stream, "/" + entry.getName(), entry.isDirectory());
        }

        @Override
        public String getName() {
            return name;
        }

        @Override
        public String getShortName() {
            return getName().replaceAll(".*/", "");
        }

        @Override
        public Entry getParent() {
            return new ZipReaderEntry(null, getParentString(), true);
        }

        // the parent of the root is itself
        private String getParentString() {
            String res = getName().replaceAll("/[^/]*$", "");
            if (res != null && res.isEmpty()) {
                res = "/";
            }
            return res;
        }

        @Override
        public boolean isDirectory() {
            return isDirectory;
        }

        @Override
        public boolean isFile() {
            return !isDirectory;
        }

        @Override
        public InputStream getStream() {
            if (isFile()) {
                return new UnclosableStream(zipStream);
            } else {
                return null;
            }
        }

        private String stripSuffix(String original) {
            String res = original.charAt(original.length() - 1) == '/'
                    ? original.substring(0, original.length() - 1)
                    : original;

            if (res.isEmpty()) {
                res = "/";
            }
            return res;
        }

    }

    /* ****************** extra ***************************** */

    private static class UnclosableStream extends InputStream {

        private InputStream innerStream;

        public UnclosableStream(InputStream stream) {
            innerStream = stream;
        }

        @Override
        public int read() throws IOException {
            return innerStream.read();
        }

        @Override
        public void close() {
            // :P
        }

    }

    /* ************** iterator impl ************************ */

    @Override
    public boolean hasNext() {
        readNext();
        return nextEntry != null;
    }

    @Override
    public Entry next() {
        if (nextEntry == null) {
            readNext();
        }
        currentEntry = nextEntry;
        nextEntry = null;
        return currentEntry;
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException();
    }

    private void readNext() {
        try {
            ArchiveEntry entry = zipStream.getNextEntry();
            if (entry != null) {
                nextEntry = new ZipReaderEntry(zipStream, entry);
            } else {
                nextEntry = null;
            }
        } catch (IOException ex) {
            throw new ZipCorruptedException(ex);
        }
    }

}