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