package com.jware.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;


import org.apache.struts.upload.FormFile;

import com.jware.base.error.JwareApplicationException;

/**
 * ファイルアップロードユーティリティクラス。
 * @author $Id: FileUploader.java,v 1.1 2010/01/13 11:52:32 clmg Exp $
 */
public class FileUploader{
	
    static final int BUFFER_SIZE = 2048;
	//各変数の宣言と初期化
    private FormFile formFile = null;
	private String fileName = null;
    private String contentType = null;
    private String size = null;
    private String distination = null;
    
    /**
     * コンストラクタ
     * @param file アップロードファイル
     */
    public FileUploader(FormFile file){
    	formFile = file; 
    }
    
    /**
     * ファイルを保存する。
     * @param resourceBundle リソースバンドル
     * @param key （リソースバンドルから）アップロードファイルディレクトリのパスを取得するキー
     * @throws JwareApplicationException
     */
    public List executeWithZipExtract(String resourceBundle, String filePath, boolean extractFlg) throws JwareApplicationException{
            	
		ArrayList fileNames = null;
		
    	//ファイル名の保管
		if (this.fileName == null) {
			this.fileName= formFile.getFileName();
		}

		//コンテンツタイプの保管
		this.contentType = formFile.getContentType();
		//ファイルサイズの保管
		this.size = Integer.toString(formFile.getFileSize());
		
		if( extractFlg != true || !this.fileName.endsWith( ".zip") ){

			this.distination = filePath + System.getProperty("file.separator") + this.fileName;
	
			fileNames = new ArrayList(1);
			fileNames.add(  this.fileName );
			//ファイルの書込み
			try {
				InputStream stream = formFile.getInputStream();
	
				File pathFile = new File( filePath );
				if( !pathFile.exists() ){
					pathFile.mkdirs();
				}
				
				//ファイルの書き込み実行用の変数の宣言と初期化
				OutputStream os = new FileOutputStream(this.distination);
				int bytesRead = 0;
				byte[] buffer = new byte[8192];
	
				//ファイルの書き込み実行
				while ((bytesRead = stream.read(buffer, 0, 8192)) != -1) {
					os.write(buffer, 0, bytesRead);
				}
				
				//各ストリームのクローズ
				os.close();
				stream.close();
	
			}
			catch (FileNotFoundException fnfe) {
	
				throw new JwareApplicationException("20000",fnfe);
	
			}
			catch (IOException ioe) {
	
				throw new JwareApplicationException("20000",ioe);
	
			}
			
		} else {
	        //ファイルの書込み
			try {

				InputStream stream = formFile.getInputStream();
				
				fileNames = unzip( stream, filePath );
				
				stream.close();
	
			} catch (FileNotFoundException fnfe) {
				
				throw new JwareApplicationException("20000",fnfe);
	
			} catch (IOException ioe) {
	
				throw new JwareApplicationException("20000",ioe);
	
			}
			
		}

		//テンポラリーファイルの削除
		formFile.destroy();
		
		return fileNames;
    }

    /**
     * ファイルを保存する。
     * @param resourceBundle リソースバンドル
     * @param key （リソースバンドルから）アップロードファイルディレクトリのパスを取得するキー
     * @throws JwareApplicationException
     */
    public void execute(String resourceBundle, String filePath) throws JwareApplicationException{
            	
		//ファイル名の保管
		if (this.fileName == null) {
			this.fileName= formFile.getFileName();
		}

		//コンテンツタイプの保管
		this.contentType = formFile.getContentType();
		//ファイルサイズの保管
		this.size = Integer.toString(formFile.getFileSize());
		this.distination = filePath + System.getProperty("file.separator") + this.fileName;

        //ファイルの書込み
		try {
			InputStream stream = formFile.getInputStream();

			File pathFile = new File( filePath );
			if( !pathFile.exists() ){
				pathFile.mkdirs();
			}
			
			//ファイルの書き込み実行用の変数の宣言と初期化
			OutputStream os = new FileOutputStream(this.distination);
			int bytesRead = 0;
			byte[] buffer = new byte[8192];

			//ファイルの書き込み実行
			while ((bytesRead = stream.read(buffer, 0, 8192)) != -1) {
				os.write(buffer, 0, bytesRead);
			}
			
			//各ストリームのクローズ
			os.close();
			stream.close();

		}
		catch (FileNotFoundException fnfe) {

			throw new JwareApplicationException("20000",fnfe);

		}
		catch (IOException ioe) {

			throw new JwareApplicationException("20000",ioe);

		}

		//テンポラリーファイルの削除
		formFile.destroy();
    }

	/**
	 * コンテントタイプの取得
	 * @return　コンテントタイプ
	 */
	public String getContentType() {
		return contentType;
	}

	/**
	 * ファイル保存場所の取得
	 * @return　ファイル保存場所
	 */
	public String getDistination() {
		return distination;
	}

	/**
	 * ファイル名の取得
	 * @return　ファイル名
	 */
	public String getFileName() {
		return fileName;
	}

	/**
	 * フォームファイルの取得
	 * @return　フォームファイル
	 */
	public FormFile getFormFile() {
		return formFile;
	}

	/**
	 * ファイルサイズの取得
	 * @return　ファイルサイズ
	 */
	public String getSize() {
		return size;
	}

	/**
	 * ファイル名の格納
	 * @param string
	 */
	public void setFileName(String string) {
		fileName = string;
	}

	/**
	 * フォームファイルの格納
	 * @param file
	 */
	public void setFormFile(FormFile file) {
		formFile = file;
	}

    private ArrayList unzip(InputStream zipStream, String outbase)
    {
        File f = new File(outbase);
        if(!f.exists())
            f.mkdirs();
        ArrayList filenames = new ArrayList();
        try
        {
            BufferedOutputStream dest = null;
            ZipInputStream zis = new ZipInputStream(new BufferedInputStream(zipStream));
            ZipEntry entry;
            while((entry = zis.getNextEntry()) != null) 
            {
                byte data[] = new byte[BUFFER_SIZE];
                String en = entry.getName();
                if( !en.endsWith( "/") ){
                	int indexDir = en.lastIndexOf( "/" );
                	if( indexDir > 0 ){
                    	String dir = en.substring( 0, indexDir );
                    	File tempDir = new File(outbase + File.separator+dir);
                        if(!tempDir.exists())
                        	tempDir.mkdirs();
                	}
	                en = outbase + File.separator + en;
	                filenames.add(en);
	                FileOutputStream fos = new FileOutputStream(en);
	                dest = new BufferedOutputStream(fos, BUFFER_SIZE);
	                int count;
	                while((count = zis.read(data, 0, BUFFER_SIZE)) != -1) 
	                    dest.write(data, 0, count);
	                dest.flush();
	                dest.close();
                }
            }
            zis.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        return filenames;
    }

	
}
