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.mail; 017 018import org.opengion.fukurou.system.OgRuntimeException ; // 6.4.2.0 (2016/01/29) 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.concurrent.ConcurrentSkipListMap; // 6.4.3.1 (2016/02/12) refactoring 022 023import org.opengion.fukurou.system.DateSet; // 6.4.2.0 (2016/01/29) 024import org.opengion.fukurou.db.DBUtil; 025import org.opengion.fukurou.db.ApplicationInfo; 026import org.opengion.fukurou.db.Transaction; // 5.9.31.1 (2018/04/13) 027import org.opengion.fukurou.db.TransactionReal; // 5.9.31.1 (2018/04/13) 028import org.opengion.fukurou.db.ConnectionFactory; // 5.9.31.1 (2018/04/13) 029import org.opengion.fukurou.db.DBFunctionName; // 5.9.31.1 (2018/04/13) 030import org.opengion.fukurou.util.StringUtil; 031import org.opengion.hayabusa.common.HybsSystem; 032 033import static org.opengion.fukurou.util.StringUtil.nval; // 6.4.3.3 (2016/03/04) 034 035/** 036 * メールモジュール関係の機能の一部を他から使用するためのクラスです。 037 * 038 * ※MailSenderTagからGE32,34へ履歴を出力する機能を追加する際に、モジュール系の動作を本パッケージに集約しておくために作成。 039 * 必要としている箇所のみ実装。 040 * 041 * @og.rev 5.9.2.3 (2015/11/27) 新規作成 042 * 043 * @og.group メールモジュール 044 * 045 * @version 4.0 046 * @author Takahashi Masakazu 047 * @since JDK1.6 048 */ 049public class MailModuleUtil { 050 051// // Ver4互換モード対応 052// // 6.9.5.0 (2018/04/23) VER4_COMPATIBLE_MODE 廃止 053// private static final String CONTENTS = HybsSystem.sysBool( "VER4_COMPATIBLE_MODE" ) ? "CONTENT" : "CONTENTS"; 054 055// // 6.4.1.1 (2016/01/16) selYkno → SEL_YKNO , insGE32 → INS_GE32 , insGE34 → INS_GE34 refactoring 056// private static final String SEL_YKNO = "SELECT GE32S02.NEXTVAL YKNO FROM DUAL"; 057 058 private static final String SEL_YKNO = "GE32S02"; // 5.9.31.1 (2018/04/13) 059 // 6.9.5.0 (2018/04/23) VER4_COMPATIBLE_MODE 廃止 060// private static final String INS_GE32 = "INSERT INTO GE32(YKNO,PARA_KEY,PTN_ID,FROM_ADDR,TITLE,"+CONTENTS+",ATTACH1,ATTACH2,ATTACH3,ATTACH4,ATTACH5,DYSET,USRSET,PGUPD,SYSTEM_ID,FGJ)" 061 private static final String INS_GE32 = "INSERT INTO GE32(YKNO,PARA_KEY,PTN_ID,FROM_ADDR,TITLE,CONTENTS,ATTACH1,ATTACH2,ATTACH3,ATTACH4,ATTACH5,DYSET,USRSET,PGUPD,SYSTEM_ID,FGJ)" 062 + " VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,'1')"; 063 private static final String INS_GE34 = "INSERT INTO GE34(YKNO,DST_ID,GROUP_ID,DST_NAME,DST_ADDR,DST_KBN,FGJ,DYSET,USRSET,PGUPD)" 064 + " VALUES(?,?,?,?,?,?,?,?,?,?)"; 065 066 // 内部データのカラム番号(履歴テーブル) 067 private static final int GE32_YKNO = 0 ; 068 private static final int GE32_PARAKEY = 1 ; 069 private static final int GE32_PTN_ID = 2; 070 private static final int GE32_FROM_ADDR = 3; 071 private static final int GE32_TITLE = 4; 072 private static final int GE32_CONTENTS = 5; 073 // private static final int GE32_ATTACH1 = 6; 074 // private static final int GE32_ATTACH2 = 7; 075 // private static final int GE32_ATTACH3 = 8; 076 // private static final int GE32_ATTACH4 = 9; 077 // private static final int GE32_ATTACH5 = 10; 078 private static final int GE32_DYSET = 11; 079 private static final int GE32_USRSET = 12; 080 private static final int GE32_PGUPD = 13; 081 private static final int GE32_SYSTEM_ID = 14; 082 // 内部データのカラム番号(履歴テーブル) 083 private static final int GE34_YKNO = 0 ; 084 private static final int GE34_DST_ID = 1 ; 085 private static final int GE34_GROUP_ID = 2 ; 086 private static final int GE34_DST_NAME = 3 ; 087 private static final int GE34_DST_ADDR = 4 ; 088 private static final int GE34_DST_KBN = 5 ; 089 private static final int GE34_FGJ = 6 ; 090 private static final int GE34_DYSET = 7 ; 091 private static final int GE34_USRSET = 8 ; 092 private static final int GE34_PGUPD = 9 ; 093 094 // アドレスマップ 095 private static final int IDX_DST_ADDR = 0; 096 private static final int IDX_DST_KBN = 1; 097 098 /** メール送信区分 {@value} */ 099 private static final int KBN_TO = 0 ; // メール送信区分(TO) 100 /** メール送信区分 {@value} */ 101 private static final int KBN_CC = 1 ; // メール送信区分(CC) 102 /** メール送信区分 {@value} */ 103 private static final int KBN_BCC = 2 ; // メール送信区分(BCC) 104 105 /** 6.4.3.1 (2016/02/12) PMD refactoring. TreeMap → ConcurrentSkipListMap に置き換え。 */ 106 private final ConcurrentMap<String, String[]> mailDstMap = new ConcurrentSkipListMap<>() ; // 6.4.3.3 (2016/03/04) 107 108 /** 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 */ 109 private final ConcurrentMap<String, String> initParamMap = new ConcurrentHashMap<>(); // パラメータマップ 110 111 /** データベース接続ID */ 112 protected final String DBID = HybsSystem.sys( "RESOURCE_DBID" ); // 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対応 113 /** ファンクション名オブジェクト */ 114 protected final DBFunctionName dbName = DBFunctionName.getDBName( ConnectionFactory.getDBName( DBID ) ); // 5.9.31.1 (2018/04/13) 115 116 /** コネクションにアプリケーション情報を追記するかどうか指定 */ 117 private static final boolean USE_DB_APPLICATION_INFO = HybsSystem.sysBool( "USE_DB_APPLICATION_INFO" ) ; 118 119 /** アプリケーション情報 */ 120 private static final ApplicationInfo APP_INFO; // 6.4.1.1 (2016/01/16) appInfo → APP_INFO refactoring 121 122 static { 123 if( USE_DB_APPLICATION_INFO ) { 124 APP_INFO = new ApplicationInfo(); 125 // ユーザーID,IPアドレス,ホスト名 126 APP_INFO.setClientInfo( "MailModuel", HybsSystem.HOST_ADRS, HybsSystem.HOST_NAME ); 127 // 画面ID,操作,プログラムID 128 APP_INFO.setModuleInfo( "MailModuel", "MailManager", "MailManager" ); 129 } 130 else { 131 APP_INFO = null; 132 } 133 } 134 135 /** 136 * デフォルトコンストラクター 137 * 138 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 139 */ 140 public MailModuleUtil() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 141 142 /** 143 * 履歴テーブル(GE32)と宛先テーブル(GE34)に登録します。 144 * 登録時に、桁数オーバーにならないように、テーブル定義の桁数を上限として、 145 * 登録前に各項目の桁数整理を行います。 146 * 147 * @og.rev 5.9.3.0 (2015/12/04) 添付ファイル対応 148 * @og.rev 6.4.2.0 (2016/01/29) DateSet.getDate( String ) を利用するように修正します。 149 * @og.rev 6.4.3.2 (2016/02/19) Map を、 keySet() ではなく、values() に変更します。 150 * 151 */ 152 public void commitMailDB(){ 153 // 履歴テーブルの追加 154 String[] insGE32Args = new String[15]; 155 final String ykno = getYkno(); 156 final String[] attachFiles = StringUtil.csv2Array( initParamMap.get( "FILES" ) ); // 5.9.3.0 157 158 insGE32Args[GE32_YKNO] = ykno; 159 insGE32Args[GE32_PARAKEY] = initParamMap.get( "PARAKEY" ); 160 insGE32Args[GE32_PTN_ID] = trim( initParamMap.get( "PTN_ID" ), 20 ); 161 insGE32Args[GE32_FROM_ADDR] = trim( initParamMap.get( "FROM" ), 100); 162 insGE32Args[GE32_TITLE] = trim( initParamMap.get( "TITLE" ), 300); 163 insGE32Args[GE32_CONTENTS] = initParamMap.get( "CONTENT" ); 164 // insGE32Args[GE32_ATTACH1] = ""; 165 // insGE32Args[GE32_ATTACH2] = ""; 166 // insGE32Args[GE32_ATTACH3] = ""; 167 // insGE32Args[GE32_ATTACH4] = ""; 168 // insGE32Args[GE32_ATTACH5] = ""; 169 // 5.9.3.0 170 if( attachFiles != null ) { 171 final int attSize = attachFiles.length; 172 for( int i = 0; i < attSize; i++ ) { 173 insGE32Args[6 + i] = trim( attachFiles[i], 256); 174 } 175 } 176 177 insGE32Args[GE32_DYSET] = DateSet.getDate( "yyyyMMddHHmmss" ); // 6.4.2.0 (2016/01/29) 178 insGE32Args[GE32_USRSET] = initParamMap.get( "LOGIN_USERID" ); 179 insGE32Args[GE32_PGUPD] = initParamMap.get( "PGID" ); 180 insGE32Args[GE32_SYSTEM_ID] = initParamMap.get( "SYSTEM_ID" ); 181 DBUtil.dbExecute( INS_GE32, insGE32Args, APP_INFO, DBID ); // 5.5.5.1 (2012/08/07) 182 183 // 宛先テーブル追加 184 String[] insGE34Args = new String[10]; 185 insGE34Args[GE34_YKNO]= ykno; 186 // 6.4.3.2 (2016/02/19) Map を、 keySet() ではなく、values() に変更します。 187 for( final String[] vals : mailDstMap.values() ) { 188 insGE34Args[GE34_DST_ID] = trim( vals[IDX_DST_ADDR], 10 ); 189 insGE34Args[GE34_GROUP_ID] = ""; 190 insGE34Args[GE34_DST_NAME] = ""; 191 insGE34Args[GE34_DST_ADDR] = trim( vals[IDX_DST_ADDR], 100 ); 192 insGE34Args[GE34_DST_KBN] = vals[IDX_DST_KBN]; 193 insGE34Args[GE34_FGJ] = "1"; 194 insGE34Args[GE34_DYSET] = DateSet.getDate( "yyyyMMddHHmmss" ); // 6.4.2.0 (2016/01/29) 195 insGE34Args[GE34_USRSET] = initParamMap.get( "LOGIN_USERID" ); 196 insGE34Args[GE34_PGUPD] = initParamMap.get( "PGID" ); 197 DBUtil.dbExecute( INS_GE34, insGE34Args, APP_INFO, DBID ); // 5.5.5.1 (2012/08/07) 198 } 199 } 200 201 /** 202 * パラメータマップをセットします。 203 * 204 * @param params パラメータのマップ 205 */ 206 207 /** 208 * パラメータからマップをセットします。 209 * 210 * @og.rev 5.9.3.0 (2015/11/30) files追加 211 * @og.rev 6.4.2.0 (2016/01/29) DateSet.getDate( String ) を利用するように修正します。 212 * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. Map → ConcurrentMap に置き換え。 213 * @og.rev 6.4.3.3 (2016/03/04) ConcurrentHashMap の not null制限のチェック追加 214 * 215 * @param systemId システムID(not null) 216 * @param from FROMアドレス(not null) 217 * @param tos TOアドレス(CSV形式) 218 * @param ccs CCアドレス(CSV形式) 219 * @param bccs BCCアドレス(CSV形式) 220 * @param content 本文 221 * @param title タイトル 222 * @param userid 登録ユーザ 223 * @param pgid 登録PG 224 * @param files 添付ファイル 225 */ 226 public void setInitParams( final String systemId, final String from, final String[] tos, final String[] ccs 227 ,final String[] bccs, final String content, final String title, final String userid, final String pgid 228 ,final String[] files ) { 229 230 // 6.4.3.3 (2016/03/04) ConcurrentHashMap の not null制限のチェック追加 231 if( systemId == null || from == null ) { 232 final String errMsg = "systemId または、from が null です。" 233 + " systemId=" + systemId + " , from=" + from ; 234 throw new OgRuntimeException( errMsg ); 235 } 236 237 initParamMap.clear(); 238 239 initParamMap.put( "SYSTEM_ID" , systemId ); 240 initParamMap.put( "FROM" , from ); 241 initParamMap.put( "TO" , StringUtil.array2csv( tos ) ); 242 initParamMap.put( "CC" , StringUtil.array2csv( ccs ) ); 243 initParamMap.put( "BCC" , StringUtil.array2csv( bccs ) ); 244 initParamMap.put( "CONTENT" , nval( content , "No Content" ) ); 245 initParamMap.put( "TITLE" , nval( title , "No Title" ) ); 246 initParamMap.put( "DATE" , DateSet.getDate("yyyy/MM/dd") ); // 6.4.2.0 (2016/01/29) 247 initParamMap.put( "TIME" , DateSet.getDate("HH:mm:ss") ); // 6.4.2.0 (2016/01/29) 248 initParamMap.put( "LOGIN_USERID", nval( userid , "No UserID" ) ); 249 initParamMap.put( "PGID" , nval( pgid , "No PGID" ) ); 250 initParamMap.put( "FILES" , StringUtil.array2csv( files ) ); // 5.9.3.0 (2015/12/04) 251 252 getDstMap( tos, ccs, bccs ); 253 } 254 255 /** 256 * 指定の長さ以内の文字列を返します。 257 * 258 * @og.rev 5.9.1.3 (2015/10/30) 文字数ではなくByte数に変更 259 * 260 * @param src オリジナルの文字列 261 * @param maxLen 指定の長さ 262 * 263 * @return 指定の長さに短縮された文字列 264 */ 265 private String trim( final String src, final int maxLen ) { 266 String rtn = src; 267 if( src != null && src.length() > maxLen ) { 268 rtn = StringUtil.cut( src, maxLen ); 269 } 270 return rtn; 271 } 272 273 /** 274 * 要求NOを採番します。 275 * この要求NOで履歴テーブル(GE32)と宛先テーブル(GE30)の関連付けを持たせます。 276 * 277 * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策 278 * @og.rev 5.9.31.1 (2018/04/13) シーケンスの取り方変更 279 * @og.rev 7.0.6.4 (2019/11/29) TransactionRealのclose漏れ対応 280 * 281 * @return 要求NO 282 */ 283 private String getYkno() { 284// final String[][] tmp = DBUtil.dbExecute( SEL_YKNO, new String[0], APP_INFO, DBID ); // 5.5.5.1 (2012/08/07) 285// if( tmp == null || tmp.length == 0 ) { 286// final String errMsg = "要求NO採番エラー" 287// + " SQL=" + SEL_YKNO ; // 5.1.8.0 (2010/07/01) errMsg 修正 288// throw new OgRuntimeException( errMsg ); 289// } 290// return tmp[0][0]; 291 292// final Transaction tran = new TransactionReal( APP_INFO ); 293// final int rtn_ykno = dbName.getSequence( SEL_YKNO,tran,DBID ); 294// return Integer.toString( rtn_ykno ); 295 296 try( Transaction tran = new TransactionReal( APP_INFO ) ) { // 7.0.6.4 (2019/11/29) try-with-resources文 297 return Integer.toString( dbName.getSequence( SEL_YKNO,tran,DBID ) ); 298 } 299 catch( final Throwable ex ) { 300 final String errMsg = "要求NO採番エラー" 301 + " SQL=" + SEL_YKNO ; // 5.1.8.0 (2010/07/01) errMsg 修正 302// throw new OgRuntimeException( errMsg ); 303 throw new OgRuntimeException( errMsg,ex ); // 8.0.0.0 (2021/07/31) original stack trace may be lost 304 } 305 } 306 307 /** 308 * 送信先のアドレスをセットします。 309 * 310 * @og.rev 6.4.3.1 (2016/02/12) インスタンス変数で初期化した、ConcurrentSkipListMap を使用します。 311 * 312 * @param toId 送信先TOのアドレス 313 * @param ccId 送信先CCのアドレス 314 * @param bccId 送信先BCCのアドレス 315 */ 316 private void getDstMap( final String[] toId, final String[] ccId, final String[] bccId ){ 317 // 送信先(TO、CC、BCC)のマップを初期化します。 318 mailDstMap.clear(); 319 320 // 送信先(TO、CC、BCC)のマップに、値をセットします。セット順ではなく、自然ソート順です。 321 setDstAddrMap( mailDstMap , bccId, KBN_BCC ); 322 setDstAddrMap( mailDstMap , ccId, KBN_CC ); 323 setDstAddrMap( mailDstMap , toId, KBN_TO ); 324 } 325 326 /** 327 * 送信先のアドレス・マップを作成します。 328 * 329 * @og.rev 6.4.3.1 (2016/02/12) インスタンス変数で初期化した、ConcurrentSkipListMap を使用します。 330 * @og.rev 6.4.3.3 (2016/03/04) ConcurrentHashMap を受け取ることを明確にするため、I/FをConcurrentMapに変更します。 331 * @og.rev 5.9.33.0 (2018/06/01) dstBufがnullの場合の処理 332 * 333 * @param dstMap 設定するMapオブジェクト 334 * @param dstBuf 送信先配列 335 * @param kbn 送信区分[0:TO/1:CC/2:BCC] 336 */ 337 private void setDstAddrMap( final ConcurrentMap<String, String[]> dstMap, final String[] dstBuf, final int kbn ){ 338 if( dstBuf != null && dstBuf.length > 0 ) { // 5.9.33.0 (2018/06/01) 339 // IDX_DST_ADDR ,IDX_DST_KBN 340 final String[] dstInit = { "", Integer.toString( kbn ) }; 341 342 final int len = dstBuf.length; 343 for( int i=0; i < len; i++ ){ 344 String[] indMember = dstInit.clone(); 345 indMember[IDX_DST_ADDR] = dstBuf[i]; // メールアドレス 346 347 dstMap.put( dstBuf[i], indMember ); 348 } 349 } 350 } 351}