/*
 * @(#)ZipEntryDataSource.java  1.0  2002-02-11
 *
 * Copyright (c) 1999 Werner Randelshofer, Immensee, Switzerland.
 * All rights reserved.
 *
 * You may not use, copy or modify this file, except in compliance with the
 * license agreement you entered into with Werner Randelshofer.
 * For details see accompanying license terms.
 */
package ch.randelshofer.view;

import java.util.zip.*;
import java.io.*;
import javax.activation.*;

/**
 * The FileDataSource class implements a simple DataSource object that encapsulates a zip entry.
 * It provides data typing services via a FileTypeMap object. 
 * <p>
 * FileDataSource Typing Semantics:
 * <p>
 * The FileDataSource class delegates data typing of files to an object subclassed from the
 * FileTypeMap class.The setFileTypeMap method can be used to explicitly set the FileTypeMap
 * for an instance of FileDataSource. If no FileTypeMap is set, the FileDataSource will call
 * the FileTypeMap's getDefaultFileTypeMap method to get the System's default FileTypeMap.
 *
 * @author  Werner Randelshofer
 */
public class ZipEntryDataSource implements javax.activation.DataSource {
    /**
     * The zip file that holds the data.
     * This is used when the zip entry
     * was generated from a zip file.
     */
    private ZipFile zipFile;
    /**
     * A byte array that holds the contents of the zip entry.
     * This is used when the zip entry
     * was generated from a zip input stream.
     */
    private byte[] data;
    
    /**
     * The zip entry.
     */
    private ZipEntry zipEntry;
    /**
     * The file type map used to determine the content type of the data.
     * If this value is null, the getDefaultFileTypeMap is used.
     */
    private FileTypeMap fileTypeMap;
    
    /**
     * Creates a new instance of ZipEntryDataSource
     * from a ZipEntry object. 
     */
    public ZipEntryDataSource(ZipFile zipFile, ZipEntry zipEntry) {
        this.zipFile = zipFile;
        this.zipEntry = zipEntry;
    }
    /**
     * Creates a new instance of ZipEntryDataSource
     * from a ZipEntry object. 
     */
    public ZipEntryDataSource(byte[] data, ZipEntry zipEntry) {
        this.data = data;
        this.zipEntry = zipEntry;
    }
    
    /**
     * This method returns the MIME type of the data in the form of a string. 
     * This method uses the currently installed FileTypeMap.
     * If there is no FileTypeMap explictly set, the FileDataSource will call
     * the getDefaultFileTypeMap method on FileTypeMap to acquire a default
     * FileTypeMap.
     */
    public String getContentType() {
        if (fileTypeMap != null) {
            return fileTypeMap.getContentType(getName());
        } else {
            return FileTypeMap.getDefaultFileTypeMap().getContentType(getName());
        }
    }
    
    /**
     * This method returns an InputStream representing the the data and
     * throws the appropriate exception if it can not do so.
     *
     * @return an InputStream
     */
    public java.io.InputStream getInputStream()
    throws IOException {
        return (zipFile == null)
        ? new ByteArrayInputStream(data) 
        : zipFile.getInputStream(zipEntry);
    }
    
    /**
     * Return the name of this object where the name of the object
     * is dependant on the nature of the underlying objects.
     * DataSources encapsulating files may choose to return the
     * filename of the object. (Typically this would be the last
     * component of the filename, not an entire pathname.)
     */
    public String getName() {
        String path = zipEntry.getName();
        int pos = path.lastIndexOf('/');
        return path.substring(pos + 1);
    }
    
    public OutputStream getOutputStream()
    throws IOException {
        throw new IOException("Writing in ZipEntry not support");
    }   
    
    /**
     * Set the FileTypeMap to use with this FileDataSource.
     *
     * @param map The FileTypeMap for this object.    
     */
    public void setFileTypeMap(FileTypeMap map) {
        this.fileTypeMap = map;
    }
}
