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.system; 017 018import java.util.ResourceBundle; 019import java.util.PropertyResourceBundle; 020import java.util.Locale; 021import java.util.Arrays; // 6.4.7.0 (2016/06/03) 022import java.text.MessageFormat; 023 024import java.io.InputStream; 025import java.io.InputStreamReader; 026import java.io.BufferedReader; 027import java.io.IOException; 028import java.net.URL; 029import java.net.URLConnection; 030 031/** 032 * 共通的に使用されるリソースからメッセージを作成する、ユーティリティークラスです。 033 * 034 * 現状は、fukurou,hayabusa のフォルダに、それぞれ、messagea.properties ファイルをおきます。 035 * これを、読み取る簡易メソッドを用意しておきます。 036 * 037 * ※ fukurou は、hayabusa の存在を知らないはずですが、簡易メソッドということと、動的作成なので良しとします。 038 * 039 * @og.rev 6.4.3.1 (2016/02/12) 新規追加 040 * 041 * @og.group その他 042 * 043 * @version 6.0 044 * @author Kazuhiko Hasegawa 045 * @since JDK8.0, 046 */ 047public final class MsgUtil { 048 /** 初期設定されているリソースバンドルのbaseName {@value} */ 049 public static final String F_BS_NM = "org.opengion.fukurou.message" ; 050 051 /** 初期設定されているリソースバンドルのbaseName {@value} */ 052 public static final String H_BS_NM = "org.opengion.hayabusa.message" ; 053 054 /** 055 * "org.opengion.fukurou.message" の、Locale.JAPANESE リソースから取得するメッセージを文字列で返します。 056 * 057 * id と引数を受け取り、ResourceBundle と、MessageFormat.format で加工した 058 * 文字列を返します。 059 * baseName は、F_BS_NM で、Locale に、Locale.JAPANESE を指定したメッセージを作成します。 060 * 061 * @og.rev 6.4.3.1 (2016/02/12) 新規追加 062 * 063 * @param id リソースのキーとなるID。 064 * @param args リソースを、MessageFormat.format で加工する場合の引数。 065 * 066 * @return MessageFormat.formatで加工された文字列 067 * @see #F_BS_NM 068 */ 069 public static String getMsg( final String id , final Object... args ) { 070 return getMsg( F_BS_NM , Locale.JAPANESE , id , args ); 071 } 072 073 /** 074 * リソースから取得するメッセージを文字列で返します。 075 * id と引数を受け取り、ResourceBundle と、MessageFormat.format で加工した 076 * 文字列を返します。 077 * 078 * @og.rev 6.4.3.1 (2016/02/12) 新規追加 079 * @og.rev 6.4.7.0 (2016/06/03) IllegalArgumentException が発生した場合に、見えるようにする。 080 * 081 * @param baseName バンドルのベース名 082 * @param locale リソース・バンドルが必要なロケール 083 * @param id リソースのキーとなるID 084 * @param args リソースを、MessageFormat.format で加工する場合の引数 085 * 086 * @return MessageFormat.formatで加工された文字列 087 */ 088 public static String getMsg( final String baseName , final Locale locale , final String id , final Object... args ) { 089 // ResourceBundle.getBundle は、キャッシュされる・・・はず。 090 final ResourceBundle resource = ResourceBundle.getBundle( baseName , locale , UTF8_CONTROL ); // リソースバンドルのすべてがキャッシュに格納されます。 091 // 6.4.7.0 (2016/06/03) IllegalArgumentException が発生した場合に、見えるようにする。 092 try { 093 return MessageFormat.format( resource.getString( id ) , args ); 094 } 095 catch( final IllegalArgumentException ex ) { 096 final String errMsg = "MessageFormatエラー:" 097 + " id [" + id + "]" 098 + " Pattern [" + resource.getString( id ) + "]" 099 + " Arguments [" + Arrays.toString( args ) + "]" ; 100 throw new OgRuntimeException( errMsg,ex ); 101 } 102 } 103 104 /** 105 * デフォルトコンストラクターをprivateにして、 106 * オブジェクトの生成をさせないようにする。 107 */ 108 private MsgUtil() {} 109 110 /** 111 * ResourceBundle.Controlは、バンドル・ロード処理中にResourceBundle.getBundleファクトリによって呼び出される一連のコールバック・メソッドを定義します。 112 * 113 * @og.rev 6.4.3.1 (2016/02/12) 新規追加 114 */ 115 private static final ResourceBundle.Control UTF8_CONTROL = new ResourceBundle.Control() { 116 private static final String CHARSET = "UTF-8"; 117 118 /** 119 * 指定された形式とロケールを持つ指定されたバンドル名のリソース・バンドルを、指定されたクラス・ローダーを必要に応じて使用してインスタンス化します。 120 * 121 * 指定されたパラメータに対応する使用可能なリソース・バンドルが存在しない場合、このメソッドはnullを返します。 122 * 予想外のエラーが発生したためにリソース・バンドルのインスタンス化が行えない場合には、単純にnullを返す代わりに、 123 * ErrorまたはExceptionをスローすることでエラーを報告する必要があります。 124 * reloadフラグがtrueの場合、それは、以前にロードされたリソース・バンドルの有効期限が切れたためにこのメソッドが呼び出されたことを示します。 125 * 126 * @og.rev 6.4.3.1 (2016/02/12) 新規追加 127 * 128 * @param baseName リソース・バンドルの基底バンドル名。完全指定クラス名 129 * @param locale リソース・バンドルのインスタンス化対象となるロケール 130 * @param format ロードされるリソース・バンドルの形式 131 * @param loader バンドルをロードするために使用するClassLoader 132 * @param reload バンドルの再ロードを示すフラグ。有効期限の切れたリソース・バンドルを再ロードする場合はtrue、それ以外の場合はfalse 133 * 134 * @return ResourceBundle.Controオブジェクト 135 * 136 * @throws NullPointerException bundleName、locale、format、またはloaderがnullの場合、またはtoBundleNameからnullが返された場合 137 * @throws IllegalArgumentException formatが不明である場合、または指定されたパラメータに対して見つかったリソースに不正なデータが含まれている場合。 138 * @throws ClassCastException ロードされたクラスをResourceBundleにキャストできない場合 139 * @throws IllegalAccessException クラスまたはその引数なしのコンストラクタにアクセスできない場合。 140 * @throws InstantiationException クラスのインスタンス化が何かほかの理由で失敗する場合。 141 * @throws ExceptionInInitializerError このメソッドによる初期化に失敗した場合。 142 * @throws SecurityException セキュリティ・マネージャが存在し、新しいインスタンスの作成が拒否された場合。詳細は、Class.newInstance()を参照してください。 143 * @throws IOException 何らかの入出力操作を使ってリソースを読み取る際にエラーが発生した場合 144 */ 145 @Override // ResourceBundle.Control 146 public ResourceBundle newBundle( final String baseName, 147 final Locale locale, 148 final String format, 149 final ClassLoader loader, 150 final boolean reload ) throws IllegalAccessException, InstantiationException, IOException { 151 // The below is a copy of the default implementation. 152 final String bundleName = toBundleName( baseName , locale ); 153 final String resourceName = toResourceName( bundleName, "properties" ); 154 InputStream stream = null; 155 if( reload ) { 156 final URL url = loader.getResource( resourceName ); 157 if( url != null ) { 158 final URLConnection connection = url.openConnection(); 159 if( connection != null ) { 160 connection.setUseCaches( false ); 161 stream = connection.getInputStream(); 162 } 163 } 164 } else { 165 stream = loader.getResourceAsStream( resourceName ); 166 } 167 168 ResourceBundle bundle = null; 169 if( stream != null ) { 170 try { 171 // Only this line is changed to make it to read properties files as UTF-8. 172 bundle = new PropertyResourceBundle( new BufferedReader( new InputStreamReader( stream,CHARSET ) ) ); 173 } finally { 174 stream.close(); 175 } 176 } 177 return bundle; 178 } 179 }; 180}