/*
このファイルの中身は、NTT オープンソースライセンス　バージョン 1.0（「本
契約」という）の適用を受けます。
本契約を遵守しない限り、このファイルを使用してはなりません。
本契約のコピーは、次のＵＲＬから入手できます。
【配布サイトのURL】 http://www.oss.ecl.ntt.co.jp/lms/

本契約に基づき頒布されるソフトウェアは、現状のまま、明示又は黙示のあらゆ
る種類の保証なしで、頒布されます。本契約に基づく権利及び制限を律する特定
の文言については、本契約を参照してください。

「オリジナルコード」は、 NTT Cyber Space Laboratories Code です。 
「オリジナルコード」の「初期開発者」は、日本電信電話株式会社です。  
日本電信電話株式会社により創作された部分は、Copyright (C) 2004 
日本電信電話株式会社 です。
全ての権利が留保されます。 
「コントリビュータ」：_____________________________________ 


The contents of this file are subject to the NTT Opensource License
Version 1.0 (the License); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
【配布サイトのURL】 http://www.oss.ecl.ntt.co.jp/lms/

Software distributed under the License is distributed on an AS IS
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific language governing rights and limitations
under the License.

The Original Code is NTT Cyber Space Laboratories Code .

The Initial Developer of the Original Code is NIPPON TELEGRAPH AND 
TELEPHONE CORPORATION.
Portions created by the NIPPON TELEGRAPH AND TELEPHONE CORPORATION 
are Copyright (C) 2004 NIPPON TELEGRAPH AND TELEPHONE CORPORATION. 
All Rights Reserved.

Contributor(s) ______________________________________.
*/

//
//	ファイルコントロールクラス
//			変更履歴
//				2004.01.08	新規作成	五木田 泰史
//
package jp.co.ntt.lms.xmo.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FilenameFilter;
import java.io.IOException;


/**
 * ファイルに関して以下の操作を行うクラスです。<BR>
 * <PRE>
 *    1.1. コピー　　指定したファイルをコピーします
 *    1.2. アペンド　指定したファイルの内容を追加先ファイルに追加します
 *    1.3. リスト　　指定したフォルダ以下のファイルおよびフォルダの一覧を取得します。
 * </PRE>
 * @author Nijou
 * @version 0.0.0.1 2004.01.08
 */
public class FileControl {

	/**
	 * ファイル一覧取得で、ファイルおよびディレクトリの一覧作成を指定します。
	 */
	public static final int ALL_LIST = 0;

	/**
	 * ファイル一覧取得で、ファイルのみの一覧作成を指定します。
	 */
	public static final int FILE_LIST = 1;

	/**
	 * ファイル一覧取得で、ディレクトリのみの一覧作成を指定します。
	 */
	public static final int DIR_LIST = 2;

	// バッファサイズの定義
	static final int	BUFFER_SIZE = 1024 * 16;

	/**
	 * ファイルのコピーを行います。
	 * @param strFileFrom コピー元ファイルパス（ファイル名を必ず含めてください。）
	 * @param strFileTo コピー先ファイルパス<BR>
	 *            ファイル名が含まれていない場合はコピー元のファイル名と同名のファイルを
	 *            作成して、コピーします。
	 * @return int ファイルコピーの結果を返します。
	 * @exception IOException ファイルのコピーに失敗した場合
	 */
	public static int copy( String strFileFrom, String strFileTo )
		throws IOException
	{
		// 内部コピーメソッド　append区分をfalseに設定
		copy( strFileFrom, strFileTo, false );

		// 呼び出し元に戻る
		return 0;
	}

	/**
	 * 指定したファイルの内容を追加先ファイルに追加します。<BR>
	 * 追加先ファイルが存在しない場合はコピーを行います。
	 * @param strFileFrom 追加元ファイルパス（ファイル名を必ず含めてください。）
	 * @param strFileTo 追加先ファイルパス<BR>
	 *            ファイル名が含まれていない場合は追加元のファイル名と同名のファイルに
	 *            追加します。
	 * @return int ファイル追加の結果を返します
	 * @exception IOException ファイル追加に失敗した場合
	 */
	public static int append( String strFileFrom, String strFileTo )
		throws IOException
	{
		// 内部コピーメソッドappend区分をtrueに設定
		copy( strFileFrom, strFileTo, true );

		return 0;
	}

	private static int copy( String strFileFrom, String strFileTo, boolean isAppend )
		throws IOException
	{

		InputStream objFromStream = null;	// 入力ファイルストリーム・オブジェクト
		OutputStream objToStream = null;	// 出力ファイルストリーム・オブジェクト
		int rcount; 						// 実際に読み込めたデータの大きさを保持
		// バッファを作る
		byte[] buffer = new byte[BUFFER_SIZE];

		try {
			// 複写元のファイルを開く
			objFromStream = new FileInputStream(strFileFrom);
			// 複写先フォルダを作成する
			File objToFile = new File( strFileTo );
			File objParentDir = objToFile.getParentFile();
			objParentDir.mkdirs();
			// 複写先のファイルを開く
			objToStream = new FileOutputStream(strFileTo, isAppend);
			// 複写を行なう
			while ((rcount = objFromStream.read(buffer)) >= 0){
				objToStream.write(buffer, 0, rcount);
			}
		} catch (IOException e){		// 入出力例外(エラー)の捕捉
			if (objFromStream != null)
				objFromStream.close();
			if (objToStream != null)
				objToStream.close();
			throw e;		// 呼出元に入出力例外を通知させる
		}

		// 複写元のファイルを閉じる
		objFromStream.close();
		// 複写先のファイルを閉じる
		objToStream.close();

		return 0;
	}

	/**
	 * ファイルおよびファイルの削除を行います
	 * @param strPath ファイルおよびディレクトリのパス
	 * @return int 削除結果
	 */
	public static int delete( String strPath )
		throws IOException
	{
		File objFile = new File( strPath );

		// 生成したファイルオブジェクトがディレクトリの場合は
		// その配下のファイルおよびディレクトリを消去する必要がある
		if( objFile.isDirectory() ) {
			String[] strList = objFile.list();
			for( int i = 0; i < strList.length; i++ ) {
				String strChildPath = strPath + "/" + strList[i];
				// ディレクトリ配下に存在したらそれを消去
				delete( strChildPath );
			}
		}

		objFile.delete();

		return 0;
	}


	/**
	 * ディレクトリのコピーを行います
	 * @param strDirFrom コピー元ディレクトリパス
	 * @param strDirTo コピー先ディレクトリパス
	 * @return int ディレクトリコピー結果
	 * @exception IOException ディレクトリのコピーに失敗した場合
	 */
	public static int copyDir( String strDirFrom, String strDirTo )
	throws IOException
	{
	
		String[] strFileList = getFileList(strDirFrom, ALL_LIST);
		String strTempDir = strDirTo +  strDirFrom.substring(strDirFrom.lastIndexOf("/"));

		for( int i = 0; i < strFileList.length; i++ ) {

			String strFilePathFrom = strDirFrom + "/" + strFileList[i];
			String strFilePathTo = strTempDir + "/" + strFileList[i];

			File objFile = new File( strFilePathFrom );
			if( objFile.isDirectory() ) {
				copyDir( strFilePathFrom ,strTempDir );
			}
			else {
				copy(strFilePathFrom ,strFilePathTo ,false);
			}
		}
		if (strFileList.length == 0) {
			File objDir = new File( strTempDir );
			objDir.mkdirs();
		}

		return 0;
	}


	/**
	 * 指定したディレクトリ内のファイルおよびディレクトリの一覧を作成します。
	 * @param strDir ディレクトリパスを指定してください。
	 * @return File[] 取得したファイルの一覧です。
	 * @exception IOException 一覧の取得に失敗した場合
	 */
	public static String[] getFileList( String strDir )
		throws IOException
	{
		String[] strFileList = null;
		try {
			strFileList = getFileList( strDir, ALL_LIST );
		}
		catch( IOException e ) {
			throw e;
		}
		return strFileList;
	}

	/**
	 * 指定したディレクトリ内のファイルのみの一覧または、ディレクトリのみの一覧を取得します。
	 * @param strDir ディレクトリパスを指定してください。
	 * @param intPattern
	 * <PRE>
	 *                   ALL_LIST: ファイルおよびディレクトリの一覧を作成します。
	 *                   FILE_LIST: ファイルのみの一覧を作成します。
	 *                   DIR_LIST: ディレクトリのみの一覧を作成します。
	 * </PRE>
	 * @return String[] 取得したファイルの一覧です。
	 * @exception IOException 一覧の取得に失敗した場合
	 */
	public static String[] getFileList( String strDir, int intPattern )
		throws IOException
	{
		File objFile = new File( strDir );
		FilenameFilter objListFilter = new ListFileFilter( intPattern );
		String[] strList = objFile.list( objListFilter );
		// 一覧取得ができないときは長さ０の配列を返します。
		if( strList == null ) {
			strList = new String[0];
		}
		return strList;
	}

	/**
	 * 指定したファイル、フォルダ名称を変更します。
	 * @param strDirBefore 変更前ファイルパスを指定してください。
	 * @param strDirAfter 変更後ファイルパスを指定してください。
	 * @return int 変更結果結果
	 */
	public static int renameDir( String strDirBefore, String strDirAfter )
		throws IOException
	{
		// ファイル名称変更
		File objOldPath = new File( strDirBefore );
		File objNewPath = new File( strDirAfter );
		objOldPath.renameTo(objNewPath);
		
		return 0;
	}


	/**
	 * 内部クラス<BR>
	 * ファイル一覧取得で、ファイルのみ、ディレクトリのみ、の場合のフィルタです。
	 */
	private static class ListFileFilter implements FilenameFilter {

		private int intPattern = FILE_LIST;

		/**
		 * 引数なしのコンストラクタ、
		 * デフォルトで、ファイルのみを指定します。
		 */
		public ListFileFilter() {
			intPattern = FILE_LIST;
		}

		/**
		 * 一覧取得パターンを指定する、コンストラクタです。
		 * @param intPattern ALL_LIST: ファイルおよびディレクトリの一覧を作成します。<BR>
		 *                   FILE_LIST: ファイルのみの一覧を作成します<BR>
		 *                   DIR_LIST: ディレクトリのみの一覧を作成します<BR>
		 */
		public ListFileFilter( int Pattern ) {
			this.intPattern = Pattern;
		}

		/**
		 * FilenameFilterインタフェースのacceptメソッドの実装です。
		 * コンストラクタで指定されたパターンを元に返す値を決定します
		 */
		public boolean accept( File dir, String name ) {
			String strFileName = null;
			File objFile = null;
			boolean blReturn = false;
			if( dir != null ) {
				strFileName = dir.toString() + "/" + name;
				objFile = new File( strFileName );
				switch( intPattern ) {
					case ALL_LIST:
						// すべてtrue
						blReturn = true;
						break;
					case FILE_LIST:
						// 作成したファイルがファイルのみtrue
						if( objFile.isFile() ) {
							blReturn = true;
						}
						break;
					case DIR_LIST:
						// 作成したファイルがディレクトリのみtrue
						if( objFile.isDirectory() ) {
							blReturn = true;
						}
						break;
				}
			}

			return blReturn;
		}

	}
}
