    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
    018// import jakarta.servlet.http.HttpSession;                                     // 5.9.25.0 (2017/10/06) ｸﾗｳﾄﾞｽﾄﾚｰｼﾞ追加対応
    019
    020import org.opengion.fukurou.system.OgRuntimeException ;         // 6.4.2.0 (2016/01/29)
    021import static org.opengion.fukurou.system.HybsConst.CR ;        // 6.1.0.0 (2014/12/26)
    022import org.opengion.fukurou.util.FileUtil;
    023import org.opengion.fukurou.util.FileInfo;                                      // 6.2.0.0 (2015/02/27)
    024import org.opengion.fukurou.util.StringUtil;                            // 6.0.2.4 (2014/10/17)
    025
    026// import org.opengion.hayabusa.common.HybsSystem;                      // 5.9.25.0 (2017/10/06) ｸﾗｳﾄﾞｽﾄﾚｰｼﾞ追加対応
    027// import org.opengion.hayabusa.io.StorageAPI;                          // 5.9.25.0 (2017/10/06) ｸﾗｳﾄﾞｽﾄﾚｰｼﾞ追加対応
    028// import org.opengion.hayabusa.io.StorageAPIFactory;           // 5.9.25.0 (2017/10/06) ｸﾗｳﾄﾞｽﾄﾚｰｼﾞ追加対応
    029import org.opengion.hayabusa.io.HybsFileOperationFactory;       // 8.0.0.0 (2021/09/30)
    030
    031import java.io.File;
    032
    033/**
    034 * ﾌｧｲﾙをｻｰﾊﾞｰにｱｯﾌﾟﾛｰﾄﾞする場合に使用されるﾌｧｲﾙ管理ｸﾗｽです｡
    035 * HTML5 ﾌｧｲﾙｱｯﾌﾟﾛｰﾄﾞの複数選択（multiple）対応 に伴い､一つのｸﾗｽとして public化します｡
    036 *
    037 * @og.group その他機能
    038 * @og.rev 5.7.1.1 (2013/12/13) HTML5 ﾌｧｲﾙｱｯﾌﾟﾛｰﾄﾞの複数選択（multiple）対応
    039 * @og.rev 5.9.25.0 (2017/10/06) ｸﾗｳﾄﾞｽﾄﾚｰｼﾞ追加対応
    040 *
    041 * @version  4.0
    042 * @author       Kazuhiko Hasegawa
    043 * @since    JDK5.0,
    044 */
    045public final class UploadedFile implements Comparable<UploadedFile> {
    046
    047        /** ﾊﾞｯﾌｧの初期容量を通常より多い目に設定します｡  {@value}  */
    048        public static final int BUFFER_MIDDLE = 200;
    049
    050        // 5.9.25.0 (2017/10/06) MODIFY File型をString型に変更
    051        private String filename ;                               // 現時点での置き換え後ﾌｧｲﾙ名
    052
    053        private final String uniqKey    ;               // ｱｯﾌﾟﾛｰﾄﾞされたﾌｧｲﾙ名(ﾕﾆｰｸにしておきます)
    054        private final String dir                ;
    055        private final String name               ;
    056        private final String original   ;
    057        private final String type               ;
    058
    059        /**
    060         * ｱｯﾌﾟﾛｰﾄﾞﾌｧｲﾙの管理ｵﾌﾞｼﾞｪｸﾄを作成します｡
    061         *
    062         * @og.rev 5.7.1.1 (2013/12/13) HTML5 ﾌｧｲﾙｱｯﾌﾟﾛｰﾄﾞの複数選択（multiple）対応
    063         *
    064         * @param       uniqKey         ﾕﾆｰｸｷｰ(初期ｱｯﾌﾟﾛｰﾄﾞﾌｧｲﾙ名)
    065         * @param       dir                     ﾌｧｲﾙを保管するﾌｫﾙﾀﾞ
    066         * @param       name            ﾌｧｲﾙｱｯﾌﾟﾛｰﾄﾞされた時のname属性
    067         * @param       original        ﾌｧｲﾙ名(ｵﾘｼﾞﾅﾙ)
    068         * @param       type    ｺﾝﾃﾝﾄﾀｲﾌﾟ
    069         */
    070        UploadedFile( final String uniqKey, final String dir, final String name, final String original, final String type ) {
    071                this.uniqKey    = uniqKey;              // 5.7.1.1 (2013/12/13) uniqKey を確定させる｡
    072                this.dir                = dir;
    073                this.name               = name;
    074                this.original   = original;
    075                this.type               = type;
    076        }
    077
    078        /**
    079         * ﾌｧｲﾙｱｯﾌﾟﾛｰﾄﾞされた時のname属性を取得します｡
    080         *
    081         * @og.rev 5.7.1.1 (2013/12/13) HTML5 ﾌｧｲﾙｱｯﾌﾟﾛｰﾄﾞの複数選択（multiple）対応
    082         *
    083         * @return      ﾌｧｲﾙｱｯﾌﾟﾛｰﾄﾞされた時のname属性
    084         */
    085        public String getName() {
    086                return name;
    087        }
    088
    089        /**
    090         * ｺﾝﾃﾝﾄﾀｲﾌﾟを取得します｡
    091         *
    092         * @return      ｺﾝﾃﾝﾄﾀｲﾌﾟ
    093         */
    094        public String getContentType() {
    095                return type;
    096        }
    097
    098        /**
    099         * ﾌｧｲﾙ名(置き換え後)を取得します｡
    100         *
    101         * @og.rev 5.7.1.2 (2013/12/20) zip 対応で､Fileｵﾌﾞｼﾞｪｸﾄを返すようにします｡
    102         * @og.rev 5.9.25.0 (2017/10/06) FILE型をString型に変更
    103         *
    104         * @return      ﾌｧｲﾙ名(置き換え後)
    105         */
    106        public String getUploadFile(){
    107                return filename;
    108        }
    109
    110        /**
    111         * ﾌｧｲﾙ名(置き換え後)の置き換えを実行します｡
    112         * useBackup = true にすると､dir の直下に､"_backup" ﾌｫﾙﾀﾞを作成します｡
    113         * ﾊﾞｯｸｱｯﾌﾟﾌｧｲﾙ名は､元のﾌｧｲﾙ名(拡張子含む) ＋ "_" + 現在時刻のlong値 + "." + 元のﾌｧｲﾙの拡張子
    114         *
    115         * newName が null の場合は､original のﾌｧｲﾙ名に､変換します｡
    116         *
    117         * 6.0.2.4 (2014/10/17)
    118         * useBackup="rename" で､すでに同名のﾌｧｲﾙが存在した場合に､"_001" のような文字列を追加したﾌｧｲﾙにﾘﾈｰﾑします｡
    119         * Windowsの " - ｺﾋﾟｰ (2)" に近いですが､桁数を抑えるのと､useBackup="true" と異なり､過去の同一ﾌｧｲﾙ名は
    120         * そのまま､有効になります｡同一ﾌｧｲﾙが同一ﾌｫﾙﾀﾞに存在する場合のみ連番が付与されます｡
    121         *
    122         * newName の指定に､ﾌｫﾙﾀﾞ名を含めることを可能にしました｡
    123         *
    124         * @og.rev 5.7.1.1 (2013/12/13) 新規追加
    125         * @og.rev 5.7.2.1 (2014/01/17) FileUtil.renameTo の引数の順番を間違えていた｡
    126         * @og.rev 6.0.2.4 (2014/10/17) useBackup 修正､newName に､ﾌｫﾙﾀﾞ名を含めることが可能
    127         * @og.rev 6.2.0.0 (2015/02/27) FileInfoｸﾗｽを使用｡ (FileUtil#getExtension(String) の廃止)
    128         * @og.rev 5.9.25.0 (2017/10/06) returnをString型に変更｡引数にfileURLとsessionを追加
    129         * @og.rev 5.10.9.0 (2019/03/01) ｸﾗｳﾄﾞｽﾄﾚｰｼﾞ対応の追加｡
    130         * @og.rev 8.0.1.0 (2021/10/29) useLocal 属性を追加｡storageType , bucketName 削除
    131         *
    132         * @param       newName         ﾌｧｲﾙ名(nullの場合は､ｵﾘｼﾞﾅﾙ)
    133         * @param       prefix          接頭辞(nullの場合は､何もつけない)
    134         * @param       sufix           接尾辞(nullの場合は､何もつけない)
    135         * @param       useBackup       置き換え後ﾌｧｲﾙの処理方法(true:backupﾌｫﾙﾀﾞ/false:しない/rename:重複しない連番)
    136         * @param       fileURL         ｸﾗｳﾄﾞｽﾄﾚｰｼﾞ用のURL
    137//       * @param       hsession        ｾｯｼｮﾝ
    138//       * @param       storage         ｸﾗｳﾄﾞﾌﾟﾗｸﾞｲﾝ名(ﾛｰｶﾙﾌｧｲﾙを強制する場合は､LOCAL を指定する)
    139//       * @param       bucket          ﾊﾞｹｯﾄ名(ﾛｰｶﾙﾌｧｲﾙを強制する場合は､LOCAL を指定する)
    140         * @param       useLocal        強制的にﾛｰｶﾙﾌｧｲﾙを使用する場合､true にｾｯﾄします｡
    141         * @return      最終的に作成されたﾌｧｲﾙｵﾌﾞｼﾞｪｸﾄ
    142         */
    143//      public String renameTo( final String newName , final String prefix , final String sufix , final String useBackup, final String fileURL, final HttpSession hsession ) {
    144        public String renameTo( final String newName , final String prefix , final String sufix , final String useBackup, final String fileURL,
    145//                              final String storage, final String bucket ) {
    146                                final boolean useLocal ) {
    147
    148                // 6.0.2.4 (2014/10/17) prfix が null でなければ､連結｡newName が null なら､original を使う｡
    149                String newNm = StringUtil.nvalAdd( prefix, StringUtil.coalesce( newName,original ) );
    150
    151                if( newNm == null || newNm.isEmpty() ) {
    152                        final String errMsg = "新ﾌｧｲﾙ名が存在しません｡[" + newNm + "]" ;
    153                        throw new OgRuntimeException( errMsg );
    154                }
    155
    156                // 新ﾌｧｲﾙ名から拡張子取得
    157                final String newExt = FileInfo.getSUFIX( newNm );                       // 6.2.3.0 (2015/05/01)
    158                if( newExt == null || newExt.isEmpty() ) {                                                              // 拡張子なし
    159                        final String oldExt = FileInfo.getSUFIX( original );
    160                        newNm = StringUtil.nvalAdd( newNm , sufix , "." , oldExt ) ;            // sufix を入れ込む｡
    161                }
    162                else if( sufix != null ) {                                                                                              // 拡張子あり､sufixあり
    163                        final StringBuilder buf = new StringBuilder( newNm );
    164                        buf.insert( newNm.length()-newExt.length()-1 , sufix );
    165                        newNm = buf.toString() ;
    166                }
    167
    168                // 8.0.1.0 (2021/10/29) storageType , bucketName 削除
    169        //      File newFile = new File( dir,newNm );
    170//              final File newFile = HybsFileOperationFactory.create(storage, bucket, dir, newNm );     // 8.0.0.0
    171                final File newFile = HybsFileOperationFactory.create(useLocal, dir, newNm );    // 8.0.0.0
    172
    173                // 5.10.9.0 (2019/03/01) MODIFY
    174                // File uniqFile = new File( dir , uniqKey );           // 5.7.1.1 (2013/12/13) ｱｯﾌﾟﾛｰﾄﾞされたﾌｧｲﾙ
    175//              final File uniqFile = HybsFileOperationFactory.create(storage, bucket, dir, uniqKey);
    176                final File uniqFile = HybsFileOperationFactory.create(useLocal, dir, uniqKey);
    177
    178                // 5.10.9.0 (2019/03/01) MODIFY HybsFileUtilｸﾗｽの利用に変更｡
    179                FileUtil.renameTo( uniqFile , newFile, useBackup );             // from ⇒ to の順番に指定｡
    180
    181                // (2017/09/22) ADD FILE型をString型に変更したので､getName()をfilenameに設定｡
    182                filename = newFile.getName();
    183
    184        //      if( newNm != null && newNm.length() > 0 ) {
    185                        // 5.9.25.0 (2017/10/06) ADD bluemixｸﾗｳﾄﾞｽﾄﾚｰｼﾞを利用する処理を追加
    186//                      final String storage = HybsSystem.sys( "CLOUD_TARGET");
    187//                      if(storage != null && storage.length() > 0){
    188//                              // ｽﾄﾚｰｼﾞに保存
    189//                              final StorageAPI storageApi = StorageAPIFactory.newStorageAPI(storage, HybsSystem.sys("CLOUD_BUCKET"), hsession);
    190//                              storageApi.rename(fileURL, uniqKey, newNm, Boolean.valueOf( useBackup ), hsession);
    191//                              // ﾌｧｲﾙ名をfilenameに設定する
    192//                              filename = newNm;
    193//                      } else {
    194//                              // 標準のﾌｧｲﾙ作成
    195//      //                      newFile = new File( dir,newNm );
    196//
    197//                              final File uniqFile = new File( dir , uniqKey );                // 5.7.1.1 (2013/12/13) ｱｯﾌﾟﾛｰﾄﾞされたﾌｧｲﾙ
    198//
    199//                              // 6.0.2.4 (2014/10/17) 戻り値は､変更後の新しい File ｵﾌﾞｼﾞｪｸﾄ
    200//                              newFile = FileUtil.renameTo( uniqFile, newFile, useBackup );            // from ⇒ to の順番に指定｡
    201//
    202//                              // 5.7.2.1 (2014/01/17) FileUtil.renameTo の引数の順番を間違えていた｡
    203//      //                      FileUtil.renameTo( newFile, uniqFile , useBackup );
    204//      //                      FileUtil.renameTo( uniqFile , newFile, useBackup );             // from ⇒ to の順番に指定｡
    205//                              // (2017/09/22) ADD FILE型をString型に変更したので､getName()をfilenameに設定｡
    206//                              filename = newFile.getName();
    207//                      }
    208        //      }
    209        //      // 5.7.1.1 (2013/12/13) ここの処理が走ることは無いはず｡
    210        //      else {
    211        //              String errMsg = "新ﾌｧｲﾙ名が存在しません｡[" + newNm + "]" ;
    212        //              throw new RuntimeException( errMsg );
    213        //      }
    214
    215                        // 5.7.2.1 (2014/01/17) FileUtil.renameTo の引数の順番を間違えていた｡
    216                        // 6.0.2.4 (2014/10/17) 戻り値は､変更後の新しい File ｵﾌﾞｼﾞｪｸﾄ
    217                // 新ﾌｧｲﾙ名のｾｯﾄは､すべての処理が完了してから､設定する｡
    218                // 5.9.25.0 (2017/10/06) DELETE FILE型をString型に変更により､前の処理でfinenameは設定済み
    219                return filename;
    220        }
    221
    222        /**
    223         * ﾌｧｲﾙ名(ｵﾘｼﾞﾅﾙ)を取得します｡
    224         *
    225         * @return      ﾌｧｲﾙ名(ｵﾘｼﾞﾅﾙ)
    226         */
    227        public String getOriginalFileName() {
    228                return original;
    229        }
    230
    231        /**
    232         * 自然比較ﾒｿｯﾄﾞ
    233         * ｲﾝﾀﾌｪｰｽ Comparable の 実装に関連して､再定義しています｡
    234         * 登録されたｼｰｹﾝｽ(画面の表示順)で比較します｡
    235         * equals ﾒｿｯﾄﾞでは､ｷｰの同一性のみに着目して判定しています｡
    236         * この比較では､(運用上同一ｷｰは発生しませんが)たとえ同一ｷｰが存在した
    237         * としても､その比較値が同じになることを保証していません｡
    238         *
    239         * @param   other 比較対象のObject
    240         *
    241         * @return  このｵﾌﾞｼﾞｪｸﾄが指定されたｵﾌﾞｼﾞｪｸﾄより小さい場合は負の整数､等しい場合はｾﾞﾛ､大きい場合は正の整数
    242         * @throws  ClassCastException 引数が UploadedFile ではない場合
    243         * @throws  IllegalArgumentException 引数が null の場合
    244         */
    245        @Override
    246        public int compareTo( final UploadedFile other ) {
    247                if( other == null ) {
    248                        final String errMsg = "引数が､null です｡" ;
    249                        throw new IllegalArgumentException( errMsg );
    250                }
    251
    252                return uniqKey.compareTo( other.uniqKey );
    253        }
    254
    255        /**
    256         * このｵﾌﾞｼﾞｪｸﾄと他のｵﾌﾞｼﾞｪｸﾄが等しいかどうかを示します｡
    257         * 画面は､画面IDが等しければ､言語や表示順に関係なく同一とみなされます｡
    258         * GUIInfo は､ﾕｰｻﾞｰ個別に扱われ､そのｸﾞﾙｰﾌﾟには､key は唯一で､かつ
    259         * 同一言語内で扱われるｵﾌﾞｼﾞｪｸﾄの為､同一とみなします｡
    260         *
    261         * @param   object 比較対象の参照ｵﾌﾞｼﾞｪｸﾄ
    262         *
    263         * @return      引数に指定されたｵﾌﾞｼﾞｪｸﾄとこのｵﾌﾞｼﾞｪｸﾄが等しい場合は true､そうでない場合は false
    264         */
    265        @Override
    266        public boolean equals( final Object object ) {
    267                // 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method
    268                return object instanceof UploadedFile && uniqKey.equals( ((UploadedFile)object).uniqKey ) ;
    269        }
    270
    271        /**
    272         * ｵﾌﾞｼﾞｪｸﾄのﾊｯｼｭｺｰﾄﾞ値を返します｡
    273         * このﾒｿｯﾄﾞは､java.util.Hashtable によって提供されるような
    274         * ﾊｯｼｭﾃｰﾌﾞﾙで使用するために用意されています｡
    275         * equals( Object ) ﾒｿｯﾄﾞをｵｰﾊﾞｰﾗｲﾄした場合は､hashCode() ﾒｿｯﾄﾞも
    276         * 必ず 記述する必要があります｡
    277         * この実装では､getKey().hashCode() と同値を返します｡
    278         *
    279         * @return  このｵﾌﾞｼﾞｪｸﾄのﾊｯｼｭｺｰﾄﾞ値
    280         */
    281        @Override
    282        public int hashCode() {
    283                return uniqKey.hashCode() ;
    284        }
    285
    286        /**
    287         * ｵﾌﾞｼﾞｪｸﾄの識別子として，詳細な画面情報を返します｡
    288         *
    289         * @return  詳細な画面情報
    290         * @og.rtnNotNull
    291         */
    292        @Override
    293        public String toString() {
    294                final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE )
    295                        .append( this.getClass().getName()                      ).append( CR )
    296                        .append( "  uniqKey  :").append( uniqKey        ).append( CR )
    297                        .append( "  filename :").append( filename       ).append( CR )
    298                        .append( "  name     :").append( name           ).append( CR )
    299                        .append( "  dir      :").append( dir            ).append( CR )
    300                        .append( "  original :").append( original       ).append( CR )
    301                        .append( "  type     :").append( type           ).append( CR );
    302                return rtn.toString();
    303        }
    304}