net.ovres.tuxcourser.TarStreamCourseInput.java Source code

Java tutorial

Introduction

Here is the source code for net.ovres.tuxcourser.TarStreamCourseInput.java

Source

/*
 * TuxCourser
 * Copyright (C) 2003-2004 Adam Elliott
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program 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 General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package net.ovres.tuxcourser;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Logger;

import net.ovres.util.UncompressedInputStream;

import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;

/**
 * Represents a tar file. This class will automatically
 * decompress the file if possible, and currently supports
 * gz, bzip2, and Z compression methods. Decompression is
 * based on magic number, not on file extension, so misnamed
 * files should not be an issue. tgz files with a tar extension
 * seem all too common, and this gets around that.
 *
 * One (rather important) caveat: Each time a file is requested,
 * the input stream is re-opened. This means it will probably
 * be significantly more inefficient than other methods. This can
 * probably be fixed with a bit more work, but only if necessary.
 */
public class TarStreamCourseInput implements CourseInput {
    private final static Logger logger = Logger.getLogger(TarStreamCourseInput.class.getName());

    File source;

    public TarStreamCourseInput(String zipfile) {
        this(new File(zipfile));
    }

    public TarStreamCourseInput(File zipfile) {
        source = zipfile;
    }

    /**
    * Create a stream corresponding to the given file.
    * This stream should be closed when it is not needed
    * any more.
    *
    * This file should be in the main directory, but this
    * is not validated.
    * 
    * @returns stream corresponding to the given file.
    */
    public InputStream getInputStream(String filename) throws FileNotFoundException, IOException {

        String altFilename = filename.replaceAll(".rgb$", ".png");

        // First, get a stream we can use...
        InputStream in = new FileInputStream(source);

        // Next, decompress it if possible...
        in = new UncompressedInputStream(in);

        // Now the tar file...
        TarArchiveInputStream tar = new TarArchiveInputStream(in);
        ArchiveEntry entry = null;
        ArchiveEntry e;

        e = tar.getNextEntry();
        while (entry == null && e != null) {
            if ((e.getName().endsWith(filename) || e.getName().endsWith(altFilename))
                    && e.getName().indexOf(".xvpics") == -1) {
                entry = e;
            } else {
                e = tar.getNextEntry();
            }
        }
        if (entry == null) {
            tar.close();
            throw new FileNotFoundException("File not found in " + source + ": " + filename);
        }
        logger.fine("Using: " + entry.getName());

        // We could just return tar at this point...
        // But it's a bit nicer to clean up the tar file
        // immediately, and return a byte array stream instead.
        int size = (int) (entry.getSize());
        byte[] b = new byte[size];
        int num = tar.read(b, 0, size);
        if (num < size) {
            logger.warning("Tried to read " + size + " bytes, got " + num);
        }
        ByteArrayInputStream intemp;
        intemp = new ByteArrayInputStream(b);

        // finally, clean up the various input streams
        tar.close();
        in.close();

        return intemp;

    }

    public String getBaseName() {
        String base = source.getName();
        int i = base.lastIndexOf(".");
        if (i <= 0) {
            return base;
        }
        if (i >= base.length() - 3 && i > 1) {
            int j = base.lastIndexOf(".", i - 1);
            if (j > 0) {
                return base.substring(0, j);
            }
        }
        return base.substring(0, i);
    }

    public File getSourceFile() {
        return source;
    }

}