    001/*
    002 * Copyright (c) 2009 The openGion Project.
    003 *
    004 * Licensed under the Apache License, Version 2.0 (the "License");
    005 * you may not use this file except in compliance with the License.
    006 * You may obtain a copy of the License at
    007 *
    008 *     http://www.apache.org/licenses/LICENSE-2.0
    009 *
    010 * Unless required by applicable law or agreed to in writing, software
    011 * distributed under the License is distributed on an "AS IS" BASIS,
    012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
    013 * either express or implied. See the License for the specific language
    014 * governing permissions and limitations under the License.
    015 */
    016package org.opengion.hayabusa.servlet;
    017
    018import java.io.File;
    019
    020import org.opengion.fukurou.util.FileUtil;
    021import org.opengion.hayabusa.io.HybsFileOperationFactory;
    022
    023/**
    024 * ファイルをサーバーにアップロードする場合に使用されるファイル管理クラスです。
    025 * HTML5 ファイルアップロードの複数選択（multiple）対応 に伴い、一つのクラスとして public化します。
    026 *
    027 * @og.group その他機能
    028 * @og.rev 5.7.1.1 (2013/12/13) HTML5 ファイルアップロードの複数選択（multiple）対応
    029 * @og.rev 5.9.25.0 (2017/10/06) クラウドストレージ追加対応
    030 * @og.rev 5.10.9.0 (2019/03/01) oota クラウドストレージ対応を追加。(Fileクラスを拡張)
    031 *
    032 * @version  4.0
    033 * @author       Kazuhiko Hasegawa
    034 * @since    JDK5.0,
    035 */
    036public final class UploadedFile implements Comparable<UploadedFile> {
    037
    038        /** バッファの初期容量を通常より多い目に設定します。  {@value}  */
    039        public static final int BUFFER_MIDDLE = 200;
    040
    041        /** システム依存の改行記号をセットします。 */
    042        public static final String CR = System.getProperty("line.separator");
    043
    044        // 5.9.25.0 (2017/10/06) MODIFY File型をString型に変更
    045        //private File filename = null;         // 現時点での置き換え後ファイル名
    046        private String filename = null; // 現時点での置き換え後ファイル名
    047
    048        private final String uniqKey ;          // アップロードされたファイル名(ユニークにしておきます)
    049        private final String dir;
    050        private final String name;
    051        private final String original;
    052        private final String type;
    053
    054        /**
    055         * アップロードファイルの管理オブジェクトを作成します。
    056         *
    057         * @og.rev 5.7.1.1 (2013/12/13) HTML5 ファイルアップロードの複数選択（multiple）対応
    058         *
    059         * @param       uniqKey         ユニークキー(初期アップロードファイル名)
    060         * @param       dir                     ファイルを保管するフォルダ
    061         * @param       name            ファイルアップロードされた時のname属性
    062         * @param       original        ファイル名(オリジナル)
    063         * @param       type    コンテントタイプ
    064         */
    065//      UploadedFile( final String dir, final String name, final String filename, final String original, final String type) {
    066        UploadedFile( final String uniqKey, final String dir, final String name, final String original, final String type ) {
    067                this.uniqKey    = uniqKey;              // 5.7.1.1 (2013/12/13) uniqKey を確定させる。
    068                this.dir                = dir;
    069                this.name               = name;
    070//              this.filename   = filename;
    071                this.original   = original;
    072                this.type               = type;
    073        }
    074
    075        /**
    076         * ファイルアップロードされた時のname属性を取得します。
    077         *
    078         * @og.rev 5.7.1.1 (2013/12/13) HTML5 ファイルアップロードの複数選択（multiple）対応
    079         *
    080         * @return      ファイルアップロードされた時のname属性
    081         */
    082        public String getName() {
    083                return name;
    084        }
    085
    086        /**
    087         * コンテントタイプを取得します。
    088         *
    089         * @return      コンテントタイプ
    090         */
    091        public String getContentType() {
    092                return type;
    093        }
    094
    095        /**
    096         * ファイル名(置き換え後)を取得します。
    097         *
    098         * @og.rev 5.7.1.2 (2013/12/20) zip 対応で、Fileオブジェクトを返すようにします。
    099         * @og.rev 5.9.25.0 (2017/10/06) FILE型をString型に変更
    100         *
    101         * @return      ファイル名(置き換え後)
    102         */
    103//      public String getFilesystemName() {
    104//      public File getUploadFile() {
    105        public String getUploadFile(){
    106                return filename;
    107        }
    108
    109        /**
    110         * ファイル名(置き換え後)の置き換えを実行します。
    111         * useBackup = true にすると、dir の直下に、"_backup" フォルダを作成します。
    112         * バックアップファイル名は、元のファイル名(拡張子含む) ＋ "_" + 現在時刻のlong値 + "." + 元のファイルの拡張子
    113         *
    114         * newName が null の場合は、original のファイル名に、変換します。
    115         *
    116         * @og.rev 5.7.1.1 (2013/12/13) 新規追加
    117         * @og.rev 5.7.2.1 (2014/01/17) FileUtil.renameTo の引数の順番を間違えていた。
    118         * @og.rev 5.9.25.0 (2017/10/06) returnをString型に変更。引数にfileURLとsessionを追加
    119         * @og.rev 5.10.9.0 (2019/03/01) クラウドストレージ対応の追加。
    120         *
    121         * @param       newName         ファイル名(置き換え後)
    122         * @param       useBackup       置き換え後ファイルをバックアップするかどうか(true:バックアップする/false:しない)
    123         * @param  fileURL              クラウドストレージ用のURL
    124         * @param  storageType  クラウドプラグイン名
    125         * @param  bucketName   バケット名
    126         * @return      最終的に作成されたファイルオブジェクト
    127         */
    128        //public File renameTo( final String newName , final boolean useBackup) {
    129        // 5.10.9.0 (2019/03/01) MODIFY
    130//      public String renameTo( final String newName , final boolean useBackup, final String fileURL, HttpSession hsession) {
    131        public String renameTo( final String newName , final boolean useBackup, final String fileURL, String storageType, String bucketName) {
    132
    133                String newNm = newName ;
    134                // 新規ファイル名を作成します。(拡張子等)
    135                if( newNm != null && newNm.length() > 0 ) {
    136                        // 新ファイル名から拡張子取得
    137                        String newExt = FileUtil.getExtension( newNm );
    138                        if( newExt == null || newExt.length() == 0 ) {
    139                                String oldExt = FileUtil.getExtension( original );
    140                                newNm = newNm + "." + oldExt ;
    141                        }
    142                }
    143                else {
    144                        newNm = original;
    145                }
    146
    147                File newFile = null ;
    148                if( newNm != null && newNm.length() > 0 ) {
    149                        // ﾌｧｲﾙ作成
    150                        // 5.10.9.0 (2019/03/01) ADD
    151                        newFile = HybsFileOperationFactory.create(storageType, bucketName, dir, newNm );
    152
    153                        // 5.10.9.0 (2019/03/01) MODIFY
    154                        // File uniqFile = new File( dir , uniqKey );           // 5.7.1.1 (2013/12/13) アップロードされたファイル
    155                        File uniqFile = HybsFileOperationFactory.create(storageType, bucketName, dir, uniqKey);
    156
    157                        // 5.7.2.1 (2014/01/17) FileUtil.renameTo の引数の順番を間違えていた。
    158//                      FileUtil.renameTo( newFile, uniqFile , useBackup );
    159                        // 5.10.9.0 (2019/03/01) MODIFY HybsFileUtilクラスの利用に変更。
    160                        FileUtil.renameTo( uniqFile , newFile, useBackup );             // from ⇒ to の順番に指定。
    161
    162                        // (2017/09/22) ADD FILE型をString型に変更したので、getName()をfilenameに設定。
    163                        filename = newFile.getName();
    164
    165//                      // 置き換えファイルの存在チェック。
    166//                      if( newFile.exists() ) {
    167//                              if( useBackup ) {
    168//                                      // newNm にフォルダ階層を含む場合に、そなえて。
    169//                                      File parent = newFile.getParentFile();                  // バックアップすべきファイルのフォルダ
    170//                                      File backup = new File( parent , "_backup" );   // その直下に、"_backup" フォルダを作成
    171//                                      if( !backup.exists() && !backup.mkdirs() ) {
    172//                                              String errMsg = "バックアップ処理でbackupフォルダの作成に失敗しました。[" + backup + "]";
    173//                                              throw new RuntimeException( errMsg );
    174//                                      }
    175//                                      // バックアップファイル名は、元のファイル名(拡張子含む) ＋ "_" + 現在時刻のlong値 + "." + 元のファイルの拡張子
    176//                                      String bkupName = newFile.getName() + "_" + System.currentTimeMillis() + "."  + FileUtil.getExtension( newNm ) ;
    177//                                      File fromFile = new File( dir,newNm );          // オリジナルの newFile をrename するとまずいので、同名のFileオブジェクトを作成
    178//                                      File bkupFile = new File( backup,bkupName );
    179//
    180//                                      if( !fromFile.renameTo( bkupFile ) ) {
    181//                                              String errMsg = "バックアップ処理でバックアップファイルをリネームできませんでした。" +CR
    182//                                                                                       + "  [" + fromFile + "] ⇒ [" + bkupFile + "]" ;
    183//                                              throw new RuntimeException( errMsg );
    184//                                      }
    185//                              }
    186//                              else if( !newFile.delete() ) {
    187//                                      String errMsg = "既存のファイル[" + newNm + "]が削除できませんでした。";
    188//                                      throw new RuntimeException( errMsg );
    189//                              }
    190//                      }
    191//
    192//                      File uniqFile = new File( dir , uniqKey );              // 5.7.1.1 (2013/12/13) アップロードされたファイル
    193//                      if( !uniqFile.renameTo( newFile ) ) {
    194//                              String errMsg = "所定のファイルをリネームできませんでした。" + CR
    195//                                                                      + "  [" + uniqFile + "] ⇒ [" + newFile + "]" ;
    196//                              throw new RuntimeException( errMsg );
    197//                      }
    198
    199                }
    200                // 5.7.1.1 (2013/12/13) ここの処理が走ることは無いはず。
    201                else {
    202                        String errMsg = "新ファイル名が存在しません。[" + newNm + "]" ;
    203                        throw new RuntimeException( errMsg );
    204                }
    205                // 新ファイル名のセットは、すべての処理が完了してから、設定する。
    206                // 5.9.25.0 (2017/10/06) DELETE FILE型をString型に変更により、前の処理でfinenameは設定済み
    207                //filename = newFile ;
    208                return filename;
    209        }
    210
    211        /**
    212         * ファイル名(置き換え後)をセットします。
    213         *
    214         * @og.rev 5.7.1.1 (2013/12/13) 廃止
    215         *
    216         * @param       name    ファイル名(置き換え後)
    217         */
    218//      public void setFilesystemName( final String name ) {
    219//              filename = name;
    220//      }
    221
    222        /**
    223         * ファイル名(オリジナル)を取得します。
    224         *
    225         * @return      ファイル名(オリジナル)
    226         */
    227        public String getOriginalFileName() {
    228                return original;
    229        }
    230
    231        /**
    232         * ファイル名(置き換え後)の File オブジェクトを取得します。
    233         *
    234         * @og.rev 5.7.1.1 (2013/12/13) 廃止。
    235         *
    236         * @return Fileオブジェクト
    237         */
    238//      public File getFile() {
    239//              if(dir == null || filename == null) {
    240//                      return null;
    241//              }
    242//              else {
    243//                      return new File(dir + File.separator + filename);
    244//              }
    245//      }
    246
    247        /**
    248         * ファイル名から 拡張子を取得します。
    249         *
    250         * @og.rev 5.7.1.1 (2013/12/13) ローカルに移動。若干のロジック変更
    251         *
    252         * @param       fileName        ファイル名
    253         * @return      拡張子
    254         */
    255//      private String getExtension( final String fileName ) {
    256//              int index = fileName.lastIndexOf('.');
    257////            if(index!=-1) {
    258////                    return fileName.substring(index + 1, fileName.length());
    259////            }
    260//              if( index >= 0 ) {
    261//                      return fileName.substring( index + 1 );
    262//              }
    263//              return "";
    264//      }
    265
    266        /**
    267         * 自然比較メソッド
    268         * インタフェース Comparable の 実装に関連して、再定義しています。
    269         * 登録されたシーケンス(画面の表示順)で比較します。
    270         * equals メソッドでは、キーの同一性のみに着目して判定しています。
    271         * この比較では、(運用上同一キーは発生しませんが)たとえ同一キーが存在した
    272         * としても、その比較値が同じになることを保証していません。
    273         *
    274         * @param   other 比較対象のObject
    275         *
    276         * @return  このオブジェクトが指定されたオブジェクトより小さい場合は負の整数、等しい場合はゼロ、大きい場合は正の整数
    277         * @throws  ClassCastException 引数が UploadedFile ではない場合
    278         * @throws  IllegalArgumentException 引数が null の場合
    279         */
    280        @Override
    281        public int compareTo( final UploadedFile other ) {
    282                if( other == null ) {
    283                        String errMsg = "引数が、null です。" ;
    284                        throw new IllegalArgumentException( errMsg );
    285                }
    286
    287                return ( uniqKey ).compareTo( other.uniqKey );
    288        }
    289
    290        /**
    291         * このオブジェクトと他のオブジェクトが等しいかどうかを示します。
    292         * 画面は、画面IDが等しければ、言語や表示順に関係なく同一とみなされます。
    293         * GUIInfo は、ユーザー個別に扱われ、そのグループには、key は唯一で、かつ
    294         * 同一言語内で扱われるオブジェクトの為、同一とみなします。
    295         *
    296         * @param   object 比較対象の参照オブジェクト
    297         *
    298         * @return      引数に指定されたオブジェクトとこのオブジェクトが等しい場合は true、そうでない場合は false
    299         */
    300        @Override
    301        public boolean equals( final Object object ) {
    302                if( object instanceof UploadedFile ) {
    303                        return uniqKey.equals( ((UploadedFile)object).uniqKey );
    304                }
    305
    306                return false ;
    307        }
    308
    309        /**
    310         * オブジェクトのハッシュコード値を返します。
    311         * このメソッドは、java.util.Hashtable によって提供されるような
    312         * ハッシュテーブルで使用するために用意されています。
    313         * equals( Object ) メソッドをオーバーライトした場合は、hashCode() メソッドも
    314         * 必ず 記述する必要があります。
    315         * この実装では、getKey().hashCode() と同値を返します。
    316         *
    317         * @return  このオブジェクトのハッシュコード値
    318         */
    319        @Override
    320        public int hashCode() {
    321                return uniqKey.hashCode() ;
    322        }
    323
    324        /**
    325         * オブジェクトの識別子として，詳細な画面情報を返します。
    326         *
    327         * @return  詳細な画面情報
    328         */
    329        @Override
    330        public String toString() {
    331                StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE );
    332                rtn.append( this.getClass().getName()                   ).append( CR );
    333                rtn.append( "  uniqKey  :").append( uniqKey             ).append( CR );
    334                rtn.append( "  filename :").append( filename    ).append( CR );
    335                rtn.append( "  name     :").append( name                ).append( CR );
    336                rtn.append( "  dir      :").append( dir                 ).append( CR );
    337                rtn.append( "  original :").append( original    ).append( CR );
    338                rtn.append( "  type     :").append( type                ).append( CR );
    339                return rtn.toString();
    340        }
    341}