/*
 * Copyright (c) 2009 The openGion Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package org.opengion.hayabusa.servlet.multipart;

import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpSession;				// 5.9.25.0 (2017/10/06) クラウド対応

import org.opengion.fukurou.system.Closer ;			// 5.9.25.0 (2017/10/06) クラウド対応
import org.opengion.hayabusa.common.HybsSystem;		// 5.9.25.0 (2017/10/06) クラウド対応
import org.opengion.hayabusa.io.StorageAPI;			// 5.9.25.0 (2017/10/06) クラウド対応
import org.opengion.hayabusa.io.StorageAPIFactory;	// 5.9.25.0 (2017/10/06) クラウド対応

/**
 * ファイルアップロード時のマルチパート処理のファイルパート部品です。
 *
 * ファイル情報を取り扱います。
 *
 * @og.group その他機能
 *
 * @version  4.0
 * @author   Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public class FilePart extends Part {

	private String filename;
	private final String filePath;
	private final String contentType;
	private final PartInputStream partInput;

	/**
	 * ファイルパート部品 オブジェクトを構築する、コンストラクター
	 *
	 * @param	name		Part名称
	 * @param	in			ServletInputStreamオブジェクト
	 * @param	boundary	境界文字
	 * @param	contentType	コンテンツタイプ
	 * @param	filename	ファイル名
	 * @param	filePath	ファイルパス
	 * @throws IOException 入出力エラーが発生したとき
	 */
	FilePart( final String name, final ServletInputStream in, final String boundary,
			final String contentType, final String filename, final String filePath)
											throws IOException {
		super(name);
		this.filename = filename;
		this.filePath = filePath;
		this.contentType = contentType;
		partInput = new PartInputStream(in, boundary);
	}

	/**
	 * ファイル名を取得します。
	 *
	 * @return	ファイル名
	 */
	public String getFilename() {
		return filename;
	}

	/**
	 * ファイル名をセットします。
	 *
	 * @param  fname ファイル名
	 */
	public void setFilename( final String fname ) {
		filename = fname ;
	}

	/**
	 * ファイルパスを取得します。
	 *
	 * @return	ファイルパス
	 */
	public String getFilePath() {
		return filePath;
	}

	/**
	 * コンテンツタイプを取得します。
	 *
	 * @return	コンテンツタイプ
	 */
	public String getContentType() {
		return contentType;
	}

	/**
	 * 入力ストリームを取得します。
	 *
	 * @return	入力ストリーム
	 */
	public InputStream getInputStream() {
		return partInput;
	}

	/**
	 * ｸﾗｳﾄﾞｽﾄﾚｰｼﾞへのｱｯﾌﾟﾛｰﾄﾞ。
	 *
	 * @og.rev 5.9.25.0 (2017/10/06) 追加
	 * 
	 * @param storage		クラウド種別 
	 * @param directory		ｱｯﾌﾟﾛｰﾄﾞ先ﾃﾞｨﾚｸﾄﾘ
	 * @param hsession		ｾｯｼｮﾝ
	 */
	public void writeToCloud( final String storage, final String directory, final HttpSession hsession ) {
		final StorageAPI storageApi = StorageAPIFactory.newStorageAPI( storage, HybsSystem.sys("CLOUD_STORAGE_CONTAINER"), hsession );
		storageApi.add( partInput, directory, filename, hsession );
	}

	/**
	 * 指定のファイルに書き出します。
	 *
	 * @param	fileOrDirectory	出力先ファイル名/ディレクトリ名
	 *
	 * @return	ストリームに書き出したバイト数
	 * @throws  IOException 入出力エラーが発生したとき
	 */
	public long writeTo( final File fileOrDirectory ) throws IOException {
		long written = 0;

		OutputStream fileOut = null;
		try {
			// Only do something if this part contains a file
			if( filename != null ) {
				// Check if user supplied directory
				File file;
				if( fileOrDirectory.isDirectory() ) {
					// Write it to that dir the user supplied,
					// with the filename it arrived with
					file = new File(fileOrDirectory, filename);
				}
				else {
					// Write it to the file the user supplied,
					// ignoring the filename it arrived with
					file = fileOrDirectory;
				}
				fileOut = new BufferedOutputStream(new FileOutputStream(file));
				written = write(fileOut);
			}
		}
		finally {
			Closer.ioClose( fileOut );		// 4.0.0 (2006/01/31) close 処理時の IOException を無視
		}
		return written;
	}

	/**
	 * 指定のストリームに書き出します。
	 *
	 * @og.rev 6.3.9.1 (2015/11/27) 修飾子を、なし → private に変更。
	 *
	 * @param	outStrm	OutputStreamオブジェクト
	 *
	 * @return	ストリームに書き出したバイト数
	 * @throws  IOException 入出力エラーが発生したとき
	 */
	private long write( final OutputStream outStrm ) throws IOException {
		// decode macbinary if this was sent
		long size=0;
		int read;
		final byte[] buf = new byte[8 * 1024];
		while((read = partInput.read(buf)) != -1) {
			outStrm.write(buf, 0, read);
			size += read;
		}
		return size;
	}

	/**
	 * ファイルかどうか。
	 *
	 * @return	(常に true)
	 */
	@Override
	public boolean isFile() {
		return true;
	}
}
