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