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.fukurou.util; 017 018import java.io.File; 019import java.util.concurrent.ConcurrentMap; // 6.4.3.3 (2016/03/04) 020import java.util.concurrent.ConcurrentHashMap; // 6.4.3.1 (2016/02/12) refactoring 021import java.util.Locale ; 022import java.util.Set; 023 024import org.opengion.fukurou.system.ThrowUtil; // 6.4.2.0 (2016/01/29) package変更 fukurou.util → fukurou.system 025 026/** 027 * FileMap は、ファイルを読み取って、キー情報から、ファイルへのリンクを作成するための 028 * 情報を返します。 029 * ファイルそのものは、指定のディレクトリをすべて読み取り、拡張子以外の部分を、キーとして 030 * 登録します。(キーは大文字に統一されます。) 031 * 実際のファイルの拡張子は、リンク作成時の処理で付与されます。 032 * 例えば、HELPファイルを、XXXX.html や、XXXX.htm 、XXXX.pdf など、色々な形態で作成した 033 * 場合でも、キーとしては、XXXX で存在チェックをかけることができるようになります。 034 * 035 * ファイルは、一旦すべて読み取ってメモリ上で管理されます。 036 * ディレクトリの再読取が必要な場合は、オブジェクトを再作成する必要があります。 037 * 038 * @version 4.0 039 * @author Kazuhiko Hasegawa 040 * @since JDK5.0, 041 */ 042public final class FileMap implements Cleanable { 043 /** 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 */ 044 private final ConcurrentMap<String,String> fMap = new ConcurrentHashMap<>(); // 6.4.3.1 (2016/02/12) 変数名も変えておきます。 045 046 /** 047 * デフォルトコンストラクター 048 * 049 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 050 */ 051 public FileMap() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 052 053 /** 054 * 読み取るディレクトリを指定して、ファイルマップを構築します。 055 * 056 * このディレクトリは、OSに対する物理アドレスになります。 057 * 058 * @og.rev 5.5.4.2 (2012/07/13) makeFileMap() を直接コンストラクターとして使用 059 * @og.rev 6.3.8.4 (2015/10/09) 別のコンストラクターを呼ぶようにします。 060 * @og.rev 6.3.8.5 (2015/10/16) コンストラクターで、Exception を throw しないようにします。 061 * @og.rev 6.3.9.0 (2015/11/06) コンストラクターを止めて、初期化メソッドに変更する。 062 * 063 * @param dir ディレクトリ 064 */ 065 public void init( final String dir ) { 066 init( dir , null , null ); 067 } 068 069 /** 070 * 読み取るディレクトリを指定して、ファイルマップを構築します。 071 * 072 * このディレクトリは、OSに対する物理アドレスになります。 073 * 074 * @og.rev 5.5.4.2 (2012/07/13) makeFileMap() を直接コンストラクターとして使用 075 * @og.rev 6.3.8.4 (2015/10/09) 別のコンストラクターを呼ぶようにします。 076 * @og.rev 6.3.8.5 (2015/10/16) コンストラクターで、Exception を throw しないようにします。 077 * @og.rev 6.3.9.0 (2015/11/06) コンストラクターを止めて、初期化メソッドに変更する。 078 * 079 * @param dir ディレクトリ 080 * @param path ファイル名に付与するパス文字列 081 */ 082 public void init( final String dir , final String path ) { 083 init( dir , path , null ); 084 } 085 086 /** 087 * すでに読み取った Set オブジェクトを指定して、ファイルマップを構築します。 088 * 089 * これは、ServletContext を利用した、META-INF/resources からの読み取り対応になります。 090 * 一覧を取得するのは、ServletContext 関連の実装が必要になるため、fukurou では 091 * java の一般的なオブジェクトである Set を処理するだけとします。 092 * 093 * ファイル名は、dir を削除した残りで構築します。フォルダ階層を含みます。 094 * Mapのキーは、フォルダ階層を含まない、ファイル名のみとします。 095 * つまり、フォルダ階層を持ってリソースを用意しておいても、キーとしては、 096 * ファイル名のみを使用します。 097 * 098 * @og.rev 5.5.4.2 (2012/07/13) 新規作成 099 * @og.rev 6.3.8.4 (2015/10/09) 別のコンストラクターを呼ぶようにします。 100 * @og.rev 6.3.8.5 (2015/10/16) コンストラクターで、Exception を throw しないようにします。 101 * @og.rev 6.3.9.0 (2015/11/06) コンストラクターを止めて、初期化メソッドに変更する。 102 * 103 * @param dir ディレクトリ 104 * @param resourcePaths リソースパス 105 */ 106 public void init( final String dir , final Set<?> resourcePaths ) { 107 init( dir , null , resourcePaths ); 108 } 109 110 /** 111 * すでに読み取った Set オブジェクトを指定して、ファイルマップを構築します。 112 * 113 * これは、ServletContext を利用した、META-INF/resources からの読み取り対応になります。 114 * 一覧を取得するのは、ServletContext 関連の実装が必要になるため、fukurou では 115 * java の一般的なオブジェクトである Set を処理するだけとします。 116 * 117 * ファイル名は、dir を削除した残りで構築します。フォルダ階層を含みます。 118 * Mapのキーは、フォルダ階層を含まない、ファイル名のみとします。 119 * つまり、フォルダ階層を持ってリソースを用意しておいても、キーとしては、 120 * ファイル名のみを使用します。 121 * 122 * @og.rev 5.5.4.2 (2012/07/13) 新規作成 123 * @og.rev 6.3.8.4 (2015/10/09) 別のコンストラクターを呼ぶようにします。 124 * @og.rev 6.3.8.5 (2015/10/16) コンストラクターで、Exception を throw しないようにします。 125 * @og.rev 6.3.9.0 (2015/11/06) null になっている可能性があるメソッドの戻り値のnullチェックを追加。 126 * @og.rev 6.3.9.0 (2015/11/06) コンストラクターを止めて、初期化メソッドに変更する。 127 * @og.rev 6.4.2.0 (2016/01/29) StringUtil にあったメソッドを移動するとともに、メソッド名を、ogThrowMsgPrint → ogThrowMsgPrint に変更。 128 * @og.rev 6.4.3.2 (2016/02/19) 指定のフォルダが存在しない場合、作成します。 129 * 130 * @param dir ディレクトリ 131 * @param path ファイル名に付与するパス文字列 132 * @param resourcePaths リソースパス 133 */ 134 public void init( final String dir , final String path , final Set<?> resourcePaths ) { 135 if( resourcePaths == null ) { 136 final File directory = new File( dir ); 137 if( ! directory.exists() ) { 138 final String errMsg = "指定のディレクトリは、存在しません。[" + directory + "]"; 139 // 6.3.8.5 (2015/10/16) コンストラクターで、Exception を throw しないようにします。 140 System.out.println( errMsg ); 141 // 6.4.3.2 (2016/02/19) 指定のフォルダが存在しない場合、作成します。 142 if( directory.mkdirs() ) { 143 final String errMsg2 = "指定のディレクトリを自動作成しました。[" + directory + "]"; 144 System.out.println( errMsg2 ); 145 } 146 else { 147 final String errMsg3 = "指定のディレクトリの自動作成に失敗しました。[" + directory + "]"; 148 System.err.println( ThrowUtil.ogThrowMsg( errMsg3 ) ); 149 } 150 return ; 151 } 152 153 if( ! directory.isDirectory() ) { 154 final String errMsg = "指定のキーは、ディレクトリではありません。[" + directory + "]"; 155 // 6.3.8.5 (2015/10/16) コンストラクターで、Exception を throw しないようにします。 156 System.err.println( ThrowUtil.ogThrowMsg( errMsg ) ); 157 return ; 158 } 159 // 6.3.8.4 (2015/10/09) ファイルのみ取り込む 160 // 6.3.9.0 (2015/11/06) null になっている可能性があるメソッドの戻り値のnullチェックを追加。 161 final File[] files = directory.listFiles(); 162 if( files != null ) { 163 for( final File file : files ) { 164 if( file != null && file.isFile() ) { 165 dataSet( file.getName() , path ); 166 } 167 } 168 } 169 } 170 else { 171 final int len = dir.length() ; 172 173 for( final Object rpath : resourcePaths ) { 174 final String fname = String.valueOf( rpath ).substring( len ); // ファイル名 175 dataSet( fname , path ); 176 } 177 } 178 } 179 180 /** 181 * ファイルマップを構築する内部処理。 182 * 183 * これは、ServletContext を利用した、META-INF/resources からの読み取り対応と、 184 * 通常のフォルダスキャンの読み取りの共通処理をまとめた目疎度です。 185 * 186 * @og.rev 6.3.8.4 (2015/10/09) 新規作成 187 * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。変数名も変えておきます。 188 * 189 * @param fname ファイル名 190 * @param path ファイル名に付与するパス文字列 191 */ 192 private void dataSet( final String fname , final String path ) { 193 final String upkey = fname.toUpperCase( Locale.JAPAN ) ; 194 String tmpName = fname; 195 196 // path が、nullやゼロ文字列以外の場合は、最後の文字を判定して、ファイル名に連結します。 197 if( path != null && !path.isEmpty() ) { 198 final char ch = path.charAt( path.length()-1 ) ; 199 if( ch == '/' || ch == '\\' ) { 200 tmpName = path + fname; 201 } 202 else { 203 tmpName = path + '/' + fname; 204 } 205 } 206 207 // 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。変数名も変えておきます。 208 final int idx = upkey.lastIndexOf( '.' ); 209 if( idx >= 0 ) { 210 fMap.put( upkey.substring( 0,idx ), tmpName ); 211 } 212 else { 213 fMap.put( upkey, tmpName ); 214 } 215 } 216 217 /** 218 * 指定のキーのファイルが存在しているかどうかを返します。 219 * 存在している場合は、true , 存在していない場合は、false になります。 220 * 221 * @og.rev 6.3.8.5 (2015/10/16) Exception を throw しないようにします。 222 * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 223 * 224 * @param key 指定のキー 225 * 226 * @return 存在しているかどうか(true:存在する/false:存在しない) 227 */ 228 public boolean exists( final String key ) { 229 // 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。変数名も変えておきます。 230 return key != null && fMap.containsKey( key.toUpperCase( Locale.JAPAN ) ); 231 } 232 233 /** 234 * キーに対応したファイル名を返します。 235 * 指定のキーに対するファイル名が存在しない場合は、null を返します。 236 * 237 * 引数を可変長引数にして、前から順番にMapを調べます。最初に、null でない 238 * 値を返します。最後まで一致しなければ、null を返します。 239 * 引数のキーが、nullや、ゼロ配列の場合も、nullになります。 240 * 241 * @og.rev 6.3.8.4 (2015/10/09) FileMap のコンストラクタ変更に伴う対応。 242 * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 243 * 244 * @param keys 指定のキー配列(可変長引数) 245 * 246 * @return ファイル名(ディレクトリパスは含まず)、存在しない場合は、null 247 */ 248 public String getFilename( final String... keys ) { 249 if( keys != null ) { 250 for( final String key : keys ) { 251 // 6.3.8.4 (2015/10/09) 最初に見つけた値を返す。 252 if( key != null ) { 253 // 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。変数名も変えておきます。 254 final String rtn = fMap.get( key.toUpperCase( Locale.JAPAN ) ); 255 if( rtn != null ) { return rtn; } 256 } 257 } 258 } 259 return null; 260 } 261 262 /** 263 * 初期化が完了しているかどうかを、返します。 264 * 完了している場合は、true を返します。未完了、または、clear() 実行後は、falseです。 265 * 266 * インスタンスは、init処理が完了するまでは、false が返る為、簡易的な同期処理は 267 * 行われています。 268 * (内部のMapへの書き込みは、init処理でのみ行われます。) 269 * 270 * @og.rev 6.3.9.0 (2015/11/06) 新規作成。 271 * @og.rev 6.4.3.2 (2016/02/19) initFlagを廃止し、直接 Mapが空かどうかで判定します。。 272 * 273 * @return 初期化が完了していればtrue 274 */ 275 public boolean isInit() { return !fMap.isEmpty(); } 276 277 /** 278 * 初期化(クリア)します。 279 * 280 * @og.rev 6.3.9.0 (2015/11/06) 新規作成。 281 * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 282 */ 283 @Override 284 public void clear() { 285 // 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。変数名も変えておきます。 286 fMap.clear(); 287 } 288}