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.resource; 017 018import java.sql.SQLException; 019import java.util.List; 020import java.util.Set; 021import java.util.ArrayList; 022import java.util.Arrays; 023import java.util.Map; 024import java.util.LinkedHashMap; // 6.4.3.1 (2016/02/12) refactoring 025import java.util.HashMap; 026import java.util.concurrent.ConcurrentMap; // 6.4.3.3 (2016/03/04) 027import java.util.concurrent.ConcurrentHashMap; // 6.4.3.1 (2016/02/12) refactoring 028import java.util.Collections; // 6.4.3.1 (2016/02/12) refactoring 029 030import org.opengion.fukurou.db.DBSimpleTable; 031import org.opengion.fukurou.db.DBUtil; 032import org.opengion.fukurou.db.ApplicationInfo; 033import org.opengion.fukurou.util.Cleanable; 034import org.opengion.fukurou.util.HybsEntry; 035import org.opengion.fukurou.system.DateSet; // 6.4.2.0 (2016/01/29) 036import org.opengion.fukurou.system.LogWriter; 037import org.opengion.hayabusa.common.HybsSystem; 038import org.opengion.hayabusa.common.HybsSystemException; 039import org.opengion.hayabusa.common.UserSummary; 040import org.opengion.hayabusa.db.DBEditConfig; 041import org.opengion.hayabusa.db.DBEditConfigManager; 042import static org.opengion.fukurou.system.HybsConst.CR ; // 6.1.0.0 (2014/12/26) 043import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE; // 6.1.0.0 (2014/12/26) refactoring 044 045/** 046 * ユーザー情報の取得の為のインターフェースを実装したクラスです。 047 * 048 * ログイン時のパスワードのチェックや,国名の識別ID,ポータルページのURLなど 049 * 個人情報を管理させます。 050 * 特に,画面アクセス時の権限やメールの送信,各画面にユーザー情報を表示したり, 051 * エラー時のログファイル,テンポラリディレクトリなども管理します。 052 * 053 * {@USER.XXXX} で、XXXX 部に、UserInfo オブジェクトで定義されている 054 * 属性情報を取り出すことが出来ます。 055 * 056 * 以下の値は UserInfo オブジェクトの項目から取得します。 057 * ・JNAME ユーザー日本語名称 058 * ・ID ユーザーID 059 * ・INFO ユーザー情報(ユーザーID:日本語名称) 060 * ・LANG 言語 061 * ・ROLES ロール 062 * ・IPADDRESS IPアドレス 063 * ・LOGINTIME ログイン時刻 064 * ・LASTACCESS 最終アクセス画面ID 065 * 066 * 以下の値はあらかじめ、動的に作成されます。 067 * ・YMD 8byte の今日のシステム日付 068 * ・YMDH 14byte の今日のシステム日時 069 * 070 * それ以外は,外部より設定された値です。 071 * 従来は、USER.IDNO はUSER.ID が5Byte以上の時のみ先頭1文字を除いたユーザーIDとして 072 * オブジェクト項目からの取得でしたが、現在は初期値として設定してあります。 073 * 外部より再設定可能になっています。 074 * 075 * @og.group リソース管理 076 * 077 * @version 4.0 078 * @author Kazuhiko Hasegawa 079 * @since JDK5.0, 080 */ 081public class UserInfo implements UserSummary , Cleanable { 082 private static final long serialVersionUID = 568120130913L ; // 5.6.8.1 (2013/09/13) 083 084 // ユーザーリソースのキー指定読み込みのクエリー 085 private static final String QUERY_PARAM = HybsSystem.sys( "USER_PARAMETER_SQL" ); 086 087 /** 5.6.8.1 (2013/09/13) 最終リクエスト情報のユーザー永続化情報(GE20)へのセーブに使用するキーの接頭語 */ 088 private static final String LAST_REQUEST_DATA_SUFIX = "LAST_REQUEST_" ; 089 090 // アクセス統計テーブル(GE15)への接続先を、リソースの接続先より取得します。 091 private final String DBID = HybsSystem.sys( "RESOURCE_DBID" ); 092 093 //private static final String YOYAKU = "|JNAME|ID|INFO|LANG|ROLES|IPADDRESS|LOGINTIME|LASTACCESS|YMD|YMDH|" ; 094 private static final String YOYAKU = "|JNAME|ID|INFO|LANG|ROLES|IPADDRESS|LOGINTIME|LASTACCESS|YMD|YMDH|LASTGAMENNM" ; // 4.4.0.1 (2009/08/08) 095 096 private final boolean useAccessTable = HybsSystem.sysBool( "USE_ACCESS_TOKEI_TABLE" ); 097 098 private final String userID ; 099 private String lang ; // 5.1.4.0 (2010/03/01) lang を書き換え可能とする。 100 private final String jname ; 101 private final String roles ; 102 private final String droles ; // 4.4.0.0 (2009/08/02) データロール対応 103 private final String ipAddress ; 104 private final long loginTime ; 105 /** 6.4.3.1 (2016/02/12) val=null を登録しているため、単純に、ConcurrentHashMap に置き換えできない。 */ 106 private final Map<String,String> attriMap ; 107 private final RoleMode roleMode ; // ロールズとモードを管理するオブジェクト 108 private final DataRole dataRole ; // データロールを管理するオブジェクト 109 110 private final int hcode ; // 6.4.1.1 (2016/01/16) PMD refactoring. Field hashcode has the same name as a method 111 /** 6.4.3.1 (2016/02/12) Collections.synchronizedMap で同期処理を行います。 */ 112 private final Map<String,GUIInfo> guiMap = Collections.synchronizedMap( new LinkedHashMap<>() ); // 6.4.3.1 (2016/02/12) 113 private long usedTime ; // 4.0.0 (2005/01/31) 114 /** 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 */ 115 private final ConcurrentMap<String,String> paramMap = new ConcurrentHashMap<>(); // 6.4.3.3 (2016/03/04) 116 private final Object guiLock = new Object(); 117 private final String systemId ; 118 /** 6.4.3.1 (2016/02/12) 作成元のMapを、変更不可能なビューを返すようにするため、 ConcurrentHashMap に置き換え不要。 */ 119 private Map<String,FavoriteGUIData> favoriteGuiMap ; // 4.1.1.0 (2008/01/22) 120 private Set<String> forbidAddrSet ; // 5.2.0.0 (2010/09/01) 121 private final DBEditConfigManager editMgr ; // 6.0.2.2 (2014/10/03) 122 123 /** 6.4.3.1 (2016/02/12) val=null を登録しているため、単純に、ConcurrentHashMap に置き換えできない。 */ 124 private final Map<String,String> lastRequestMap = new HashMap<>(); // 5.6.8.1 (2013/09/13) 125 126 /** コネクションにアプリケーション情報を追記するかどうか指定 */ 127 public static final boolean USE_DB_APPLICATION_INFO = HybsSystem.sysBool( "USE_DB_APPLICATION_INFO" ) ; 128 129 // 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定 130 private final ApplicationInfo appInfo; 131 132 // ユーザー永続化情報(GE20)テーブル 読み込み用SQL 133 // 4.3.4.0 (2008/12/01) ROLE='*'も検索できるようにする 134 // 5.3.6.0 (2011/06/01) USERID='*'も検索できるようにする 135 private static final String QUERY_GE20 = "select PARAM_ID,PARAM from GE20" 136 + " where SYSTEM_ID = ? and USERID in ( ?, '*' )" 137 + " and ROLES in ( ?, '*' ) and FGJ = '1'" 138 + " order by USERID,ROLES"; 139 140 // 4.3.4.0 (2008/12/01) ユーザー永続化情報(GE20)にセーブ時に存在チェックを行うためのSQL 141 // 4.3.4.4 (2009/01/01) private static を付加 142 private static final String QUERY_GE20_KEY = "select KBSET from GE20" 143 + " where SYSTEM_ID = ? and USERID = ?" 144 + " and ROLES = ? and PARAM_ID = ? and FGJ = '1'"; 145 146 // 5.2.3.0 (2010/12/01) アクセス履歴管理 147 private GUIInfo lastGuiInfo ; 148 149 // saveGUIAccessInfo() メソッドでしか使用しない、定数宣言 150 private static final int C_SYSTEM_ID = 0 ; 151 private static final int C_USERID = 1 ; 152 private static final int C_USERADRS = 2 ; 153 private static final int C_HOSTADRS = 3 ; 154 private static final int C_GUIKEY = 4 ; 155 private static final int C_DYLOGIN = 5 ; 156 private static final int C_DYLOGOUT = 6 ; 157 private static final int C_USED_TIME = 7 ; 158 private static final int C_CNT_ACCESS = 8 ; 159 private static final int C_CNT_ERROR = 9 ; 160 private static final int C_CNT_READ = 10 ; 161 private static final int C_CNT_WRITE = 11 ; 162 private static final int C_TM_TOTAL_QUERY = 12 ; 163 private static final int C_TM_MAX_QUERY = 13 ; 164 private static final int C_MAX_QUERY = 14 ; 165 private static final int C_FGJ = 15 ; 166 private static final int C_DYSET = 16; 167 private static final int C_DYUPD = 17; 168 private static final int C_USRSET = 18; 169 private static final int C_USRUPD = 19; 170 private static final int C_PGUPD = 20; 171 172 // ユーザー永続化情報(GE20)設定でしか使用しない変数の宣言 173 private static final int C_GE20_SYSTEM_ID = 0; 174 private static final int C_GE20_USERID = 1; 175 private static final int C_GE20_ROLES = 2; 176 private static final int C_GE20_PARAM_ID = 3; 177 private static final int C_GE20_PARAM = 4; 178 private static final int C_GE20_KBSET = 5; 179 private static final int C_GE20_FGJ = 6; 180 private static final int C_GE20_DYSET = 7; 181 private static final int C_GE20_DYUPD = 8; 182 private static final int C_GE20_USRSET = 9; 183 private static final int C_GE20_USRUPD = 10; 184 private static final int C_GE20_PGUPD = 11; 185 186 private static final int GE20_KBSET_READONLY = 1; 187 private static final int GE20_KBSET_WRITABLE = 2; 188 189 // ロールは全て*で登録する。アプリケーションから動的に登録される値を、 190 // ロール単位設定しても、ロール変更時に整合性が合わない可能性大なので、 191 // UserInfoで設定する場合は、全てのロールで有効とする。 192 private static final String GE20_ROLES = "*"; 193 194 /** 195 * コンストラクター 196 * 197 * @og.rev 3.0.0.1 (2003/02/14) ユーザー毎のエンコード指定方法を廃止します。 198 * @og.rev 3.1.3.0 (2003/04/10) ユーザー情報から、エンコード情報を削除する。 199 * @og.rev 3.4.0.3 (2003/09/10) "root","manager","admin" のロールを、すべて root 権限を与える。 200 * @og.rev 3.8.5.3 (2006/06/30) USE_USER_IDNO_C_SAPLESS を判定条件に加える。 201 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定 202 * @og.rev 4.3.0.0 (2008/07/04) ロールモードマルチ対応 203 * @og.rev 4.4.0.0 (2009/08/02) データロール対応 204 * @og.rev 5.3.6.0 (2011/06/01) ユーザー永続化情報(GE20)の読み込みをUserInfoFactoryから移動 205 * @og.rev 6.0.2.2 (2014/10/03) DBEditConfigManager をここで作成する。 206 * 207 * @param userID ユーザー 208 * @param lang 言語 209 * @param jname 日本語名称 210 * @param roles ロール 211 * @param droles データロール 212 * @param systemId システムID 213 * @param ipAddress IPアドレス 214 * @param appInfo アプリ情報オブジェクト 215 */ 216 public UserInfo( final String userID , 217 final String lang , 218 final String jname , 219 final String roles , 220 final String droles , // 4.4.0.0 (2009/08/02) 221 final String systemId , 222 final String ipAddress , 223 final ApplicationInfo appInfo ) { 224 this.userID = userID ; 225 this.lang = lang ; 226 this.jname = jname ; 227 this.roles = roles ; 228 this.droles = droles ; // 4.4.0.0 (2009/08/02) 229 this.systemId = systemId ; 230 this.roleMode = RoleMode.newInstance( roles ); // 4.3.0.0 (2008/07/04) ロールモード 231 this.dataRole = DataRole.newInstance( droles, systemId, appInfo ); // 4.4.0.0 (2009/08/02) 232 this.ipAddress = ipAddress ; 233 this.appInfo = appInfo ; 234 loginTime = System.currentTimeMillis(); 235 usedTime = loginTime; 236 attriMap = new HashMap<>(); 237 238 // 3.5.6.0 (2004/06/18) hashCode を計算しておきます。 239 hcode = (int)(loginTime^(loginTime>>>32)) ; 240 241 // 3.8.1.2 (2005/12/19) USER.IDNO をAttributeにセットする。 242 // 3.8.5.3 (2006/06/30) USE_USER_IDNO_C_SAPLESS を判定条件に加える。 243 final boolean IDNO_C_SAPLESS = HybsSystem.sysBool( "USE_USER_IDNO_C_SAPLESS" ); // 6.4.2.1 (2016/02/05) PMD refactoring. Useless parentheses. 244 final String idno = userID.length() > 5 && IDNO_C_SAPLESS ? userID.substring(1) : userID ; 245 attriMap.put( "IDNO",idno ) ; // コンストラクタ内なので、同期処理は入れていません。 246 247 // ユーザーパラメータなどの初期設定を行います。 248 initLoad() ; 249 250 // 5.3.6.0 (2011/06/01) ユーザー永続化情報(GE20)からDBに保存されたUserInfo情報を読み出します。 251 dbLoad(); 252 253 // 5.3.6.0 (2011/06/01) Edit情報の一覧を作成します。 254 editMgr = new DBEditConfigManager( attriMap ); // 6.0.2.2 (2014/10/03) 作成方法変更 255 } 256 257 /** 258 * ユーザーパラメータを取得します。 259 * ユーザーパラメーターは、通常、GE16 テーブルより取得します。 260 * 取得するSQL文は、SystemData の USER_PARAMETER_SQL に記述しておきます。 261 * ユーザーパラメータに、値が存在しない場合は、システムリソースより 262 * 取得します。 263 * 264 * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 265 * 266 * @param key パラメータキー 267 * 268 * @return パラメータ値(ユーザーパラメータになければ、システムリソースより取得 269 */ 270 public String getParameter( final String key ) { 271 String val = null; 272 if( key != null ) { 273 // 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 274 val = paramMap.get( key ); 275 if( val == null ) { val = HybsSystem.sys( key ); } 276 } 277 return val; 278 } 279 280 /** 281 * ユーザーログイン時刻を取得します。 282 * 283 * @return ログイン時刻 284 */ 285 public long getLoginTime() { 286 return loginTime; 287 } 288 289 /** 290 * ユーザーのログインIPアドレスを取得します。 291 * 292 * @return IPアドレス 293 * 294 */ 295 public String getIPAddress() { 296 return ipAddress; 297 } 298 299 /** 300 * ユーザーを取得します。 301 * 302 * @return ユーザー 303 * 304 */ 305 public String getUserID() { 306 return userID; 307 } 308 309 /** 310 * ユーザー情報ロケール(言語)を取得します。 311 * 312 * @return ロケール(言語) 313 */ 314 public String getLang() { 315 return lang ; 316 } 317 318 /** 319 * ユーザー情報ロケール(言語)をセットします。 320 * 321 * @og.rev 5.1.4.0 (2010/03/01) lang を書き換え可能とする。 322 * 323 * @param newLang ロケール(言語) 324 */ 325 public void setLang( final String newLang ) { 326 lang = newLang ; 327 } 328 329 /** 330 * ユーザー情報 名称(日本語)を取得します。 331 * 332 * @return 名称(日本語) 333 */ 334 public String getJname() { 335 return jname ; 336 } 337 338 /** 339 * ユーザー情報 ロール(役割)を取得します。 340 * 341 * @return ロール(役割) 342 */ 343 public String getRoles() { 344 return roles ; 345 } 346 347 /** 348 * ロールモード情報を取得します。 349 * 350 * @og.rev 4.3.0.0 (2008/07/04) 新規追加 351 * 352 * @return ロールモード情報 353 */ 354 public RoleMode getRoleMode() { 355 return roleMode ; 356 } 357 358 /** 359 * オブジェクトの識別子として,ユーザー情報を返します。 360 * 361 * @return ユーザー情報 362 * @og.rtnNotNull 363 */ 364 public String getInfo() { 365 final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE ) 366 .append( userID ).append( " : " ) 367 .append( jname ).append( CR ); 368 return rtn.toString(); 369 } 370 371// /** 372// * DBEditConfigManagerオブジェクトを返します。 373// * 374// * ここでは、内部オブジェクトそのものを返します。 375// * 376// * @og.rev 6.4.5.0 (2016/04/08) 新規追加。UserInfo オブジェクトから、出来るだけEditConfig関係の処理を除外します。 377// * @og.rev 6.9.2.1 (2018/03/12) DBEditConfigManagerを直接取り出す処理を、廃止します。 378// * 379// * @return DBEditConfigManagerオブジェクト 380// */ 381// public DBEditConfigManager getEditConfigManager() { 382// return editMgr; 383// } 384 385 /** 386 * UserInfoの属性文字列を登録します。 387 * 388 * 予約文字(JNAME,ID,INFO,LANG,ROLES,IPADDRESS,LOGINTIME,LASTACCESS,YMD,YMDH,LASTGAMENNM)を 389 * 登録しようとした場合は、エラーにします。 390 * 391 * ※ 属性文字列キーが不正の場合、HybsSystemException が、throw されます。 392 * 393 * @param key キー 394 * @param value 値 395 * @param save ユーザー永続化情報(GE20)に情報を保存するか 396 */ 397 public void setAttribute( final String key,final String value, final boolean save ) { 398 setAttribute( key, value, save, false ); 399 } 400 401 /** 402 * UserInfoの属性文字列を登録します。 403 * 404 * 予約文字(JNAME,ID,INFO,LANG,ROLES,IPADDRESS,LOGINTIME,LASTACCESS,YMD,YMDH,LASTGAMENNM)を 405 * 登録しようとした場合は、エラーにします。 406 * 407 * ※ 属性文字列キーが不正の場合、HybsSystemException が、throw されます。 408 * 409 * @og.rev 3.5.6.0 (2004/06/18) synchronized をattriMap に行います。 410 * @og.rev 4.3.4.0 (2008/12/01) ユーザー永続化情報(GE20)へ登録するかのフラグを追加 411 * @og.rev 5.3.6.0 (2011/06/01) ユーザー永続化情報(GE20)へ登録時に全ユーザー公開するかのフラグを追加 412 * @og.rev 5.6.8.1 (2013/09/13) 値が null、またはゼロ文字列の場合、処理しません。 413 * @og.rev 5.7.2.2 (2014/01/24) 値が null、またはゼロ文字列の場合でも処理します。(5.6.8.1 以前に戻します) 414 * 415 * @param key キー 416 * @param value 値 417 * @param save ユーザー永続化情報(GE20)に情報を保存するか 418 * @param common ユーザー永続化情報(GE20)に保存した情報を全ユーザー公開するか 419 */ 420 private void setAttribute( final String key,final String value, final boolean save, final boolean common ) { 421 if( key != null && YOYAKU.indexOf( "|" + key + "|" ) < 0 ) { 422 // 5.6.8.1 (2013/09/13) 値が null、またはゼロ文字列の場合、処理しません。 423 // 5.7.2.2 (2014/01/24) 値が null、またはゼロ文字列の場合でも処理します。(5.6.8.1 以前に戻します) 424 synchronized( attriMap ) { 425 attriMap.put( key,value ) ; 426 } 427 428 // 4.3.4.0 (2008/12/01) 追加 429 if( save ) { 430 savePermanently( key ,value, common ); 431 } 432 } 433 else { 434 final String errMsg = "属性文字列キーが不正です。 key=[" + key + "]" 435 + CR 436 + "null または予約語(" + YOYAKU + ") は指定できません。"; 437 throw new HybsSystemException( errMsg ); 438 } 439 } 440 441 /** 442 * UserInfoの属性文字列を取得します。 443 * 444 * 以下の値は UserInfo オブジェクトの項目から取得します。 445 * <pre> 446 * ・JNAME ユーザー日本語名称 447 * ・ID ユーザーID 448 * ・IDNO (初期値)USER.ID が5Byte以上の時のみ先頭1文字を除いたユーザーID 449 * ・INFO ユーザー情報(ユーザーID:日本語名称) 450 * ・LANG 言語 451 * ・ROLES ロール 452 * ・IPADDRESS IPアドレス 453 * ・LOGINTIME ログイン時刻 454 * ・LASTACCESS 最終アクセス画面ID 455 * ・LASTGAMENNM 最終アクセス画面名 456 * 457 * 以下の値はあらかじめ、動的に作成されます。 458 * ・YMD 8byte の今日のシステム日付 459 * ・YMDH 14byte の今日のシステム日時 460 * </pre> 461 * 462 * それ以外は,外部より設定された値です。 463 * 464 * @og.rev 2.1.0.2 (2002/11/07) USER.IDNO の返す値をUSER.ID が5Byte以上の時のみ、 465 * 先頭1文字を除いた値を返す様に変更。それ以外は、USER.IDを返す。 466 * 467 * @og.rev 2.2.0.0 (2002/12/17) 中国語(国際化)対応 ENCODE 追加 468 * @og.rev 3.1.3.0 (2003/04/10) ユーザー情報から、エンコード情報を削除する。 469 * @og.rev 3.5.4.2 (2003/12/15) ENAME,MAILTO、MAILUSERID、MAILPASSWD、GROUP、PROJECTを削除する。 470 * @og.rev 3.5.6.0 (2004/06/18) synchronized をattriMap に行います。 471 * @og.rev 3.6.0.0 (2004/09/17) PASSWD を削除する。 472 * @og.rev 3.8.1.2 (2005/12/19) USER.IDNO を削除する。(外部設定可能にするため) 473 * @og.rev 3.8.7.0 (2006/12/15) ApplicationInfoオブジェクトから最終アクセス画面を取得 474 * @og.rev 4.4.0.0 (2009/08/02) データロール属性対応 475 * @og.rev 4.4.0.1 (2009/08/08) LASTGAMENNM追加 476 * @og.rev 6.4.1.1 (2016/01/16) PMD refactoring. Position literals first in String comparisons for EqualsIgnoreCase. 477 * @og.rev 6.4.2.0 (2016/01/29) DateSet.getDate( String ) を利用するように修正します。 478 * 479 * @param key キー 480 * 481 * @return UserInfoの属性文字列 482 */ 483 public String getAttribute( final String key ) { 484 final String rtn ; 485 486 if( key == null ) { rtn = null; } 487 else { 488 if( "JNAME" .equalsIgnoreCase( key ) ) { rtn = jname; } 489 else if( "ID" .equalsIgnoreCase( key ) ) { rtn = userID; } 490 else if( "INFO" .equalsIgnoreCase( key ) ) { rtn = getInfo(); } 491 else if( "LANG" .equalsIgnoreCase( key ) ) { rtn = lang; } 492 else if( "ROLE" .equalsIgnoreCase( key ) ) { rtn = roles; } 493 else if( "ROLES" .equalsIgnoreCase( key ) ) { rtn = roles; } 494 else if( "DROLES" .equalsIgnoreCase( key ) ) { rtn = droles; } // 4.4.0.0 (2009/08/02) 495 else if( "IPADDRESS" .equalsIgnoreCase( key ) ) { rtn = ipAddress; } 496 else if( "LOGINTIME" .equalsIgnoreCase( key ) ) { rtn = HybsSystem.getDate( loginTime ); } 497 else if( "YMD" .equalsIgnoreCase( key ) ) { rtn = DateSet.getDate( "yyyyMMdd" ); } // 6.4.2.0 (2016/01/29) 498 else if( "YMDH" .equalsIgnoreCase( key ) ) { rtn = DateSet.getDate( "yyyyMMddHHmmss" ); } // 6.4.2.0 (2016/01/29) 499 else if( "LASTACCESS" .equalsIgnoreCase( key ) ) { rtn = getGamenId(); } 500 else if( "LASTGAMENNM" .equalsIgnoreCase( key ) ) { rtn = getGamenName(); } 501 else { 502 synchronized( attriMap ) { 503 rtn = attriMap.get( key ) ; 504 } 505 } 506 } 507 508 return rtn ; 509 510 } 511 512 /** 513 * ApplicationInfo から、画面ID を取得します。 514 * ApplicationInfoが null の場合は、null を返します。 515 * 516 * @og.rev 6.4.1.1 (2016/01/16) 新規追加 517 * 518 * @return 画面ID(ApplicationInfo#getGamenId()) 519 */ 520 private String getGamenId() { 521 return appInfo == null ? null : appInfo.getGamenId(); 522 } 523 524 /** 525 * GUIInfo から、画面名 を取得します。 526 * GUIInfo がない場合、または、GUIInfo の取り出しも元の、画面ID がない、 527 * さらに、画面ID の取出し元の ApplicationInfoが null の場合は、null を返します。 528 * 529 * @og.rev 6.4.1.1 (2016/01/16) 新規追加 530 * 531 * @return 画面名(GUIInfo#getName()) 532 */ 533 private String getGamenName() { 534 final GUIInfo guiInfo = getGUIInfo( getGamenId() ); // 引数 null 対応済み 535 return guiInfo == null ? null : guiInfo.getName(); 536 } 537 538 /** 539 * UserInfoの属性文字列の内部情報を返します。 540 * この内部情報の中には、UserInfo 自身の管理情報も含めます。 541 * 独自管理キーは、JNAME,ID,IDNO,INFO,LANG,ROLES,IPADDRESS,LOGINTIME,LASTACCESS,LASTGAMENNM です。 542 * 543 * それ以外は,外部より設定された値です。 544 * 545 * @og.rev 4.0.0.0 (2004/12/31) 新規作成 546 * @og.rev 4.4.0.1 (2009/08/08) LASTGAMENNM追加 547 * 548 * @return 属性文字列のHybsEntryオブジェクト配列 549 * @og.rtnNotNull 550 */ 551 public HybsEntry[] getEntrys() { 552 final List<HybsEntry> list = new ArrayList<>(); 553 554 list.add( new HybsEntry( "JNAME" , getAttribute( "JNAME" ) ,"ユーザー日本語名称" ) ); 555 list.add( new HybsEntry( "ID" , getAttribute( "ID" ) ,"ユーザーID" ) ); 556 list.add( new HybsEntry( "IDNO" , getAttribute( "IDNO" ) ,"USER.ID が5Byte以上の時のみ先頭1文字を除いたユーザーID" ) ); 557 list.add( new HybsEntry( "INFO" , getAttribute( "INFO" ) ,"ユーザー情報(ユーザーID:日本語名称)" ) ); 558 list.add( new HybsEntry( "LANG" , getAttribute( "LANG" ) ,"言語" ) ); 559 list.add( new HybsEntry( "ROLES" , getAttribute( "ROLES" ) ,"ロールズ" ) ); 560 list.add( new HybsEntry( "IPADDRESS" , getAttribute( "IPADDRESS" ) ,"IPアドレス" ) ); 561 list.add( new HybsEntry( "LOGINTIME" , getAttribute( "LOGINTIME" ) ,"ログイン時刻" ) ); 562 list.add( new HybsEntry( "LASTACCESS" , getAttribute( "LASTACCESS" ) ,"最終アクセス画面ID" ) ); 563 list.add( new HybsEntry( "LASTGAMENNM" , getAttribute( "LASTGAMENNM") ,"最終アクセス画面名" ) ); // 4.4.0.1 (2009/08/08) 564 list.add( new HybsEntry( "YMD" , getAttribute( "YMD" ) ," 8byte の今日のシステム日付" ) ); 565 list.add( new HybsEntry( "YMDH" , getAttribute( "YMDH" ) ,"14byte の今日のシステム日時" ) ); 566 567 synchronized( attriMap ) { 568 final String[] keys = attriMap.keySet().toArray( new String[attriMap.size()] ); 569 Arrays.sort( keys ); 570 for( int i=0; i<keys.length; i++ ) { 571 list.add( new HybsEntry( keys[i],getAttribute( keys[i] ) ) ); 572 } 573 } 574 return list.toArray( new HybsEntry[list.size()] ); 575 } 576 577 /** 578 * UserInfoの属性文字列を削除します。 579 * 580 * @param key キー 581 * @param save ユーザー永続化情報(GE20)から情報を削除するか 582 */ 583 public void removeAttribute( final String key, final boolean save ) { 584 removeAttribute( key, save, false ); 585 } 586 587 /** 588 * UserInfoの属性文字列を削除します。 589 * 590 * @og.rev 3.5.6.0 (2004/06/18) synchronized をattriMap に行います。 591 * @og.rev 5.3.6.0 (2011/06/01) ユーザー永続化情報(GE20)から削除するかのフラグを追加 592 * 593 * @param key キー 594 * @param save ユーザー永続化情報(GE20)から情報を削除するか 595 * @param common ユーザー永続化情報(GE20)から情報削除時、全ユーザー公開情報を削除するか 596 */ 597 private void removeAttribute( final String key, final boolean save, final boolean common ) { 598 synchronized( attriMap ) { 599 attriMap.remove( key ) ; 600 } 601 602 if( save ) { 603 deletePermanently( key, common ); 604 } 605 } 606 607 /** 608 * ユーザー個別の画面オブジェクトのマップをセットします。 609 * 610 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定 611 * @og.rev 4.0.0.0 (2005/01/31) 新規追加 612 * @og.rev 4.1.1.0 (2008/01/29) 画面の格上げとお気に入りマップ作成はクラスUserAccessTableに依頼 613 * @og.rev 5.2.0.0 (2010/09/01) アクセス禁止アドレスによる不正アクセス防止機能追加 614 * @og.rev 6.4.3.1 (2016/02/12) Collections.synchronizedMap で同期処理を行います 615 * 616 * @param newGuiMap 画面オブジェクトのマップ 617 * @param newForbidAddrSet アクセス禁止アドレスセット 618 */ 619 public void setGUIMap( final Map<String,GUIInfo> newGuiMap, final Set<String> newForbidAddrSet ) { 620 if( newGuiMap != null ) { 621 synchronized( guiLock ) { 622 guiMap.clear(); // 6.4.3.1 (2016/02/12) 623 guiMap.putAll( newGuiMap ); // 6.4.3.1 (2016/02/12) 624 forbidAddrSet = newForbidAddrSet; 625 favoriteGuiMap = UserAccessTable.makeAccessDB( guiMap,systemId,userID,lang ); 626 } 627 } 628 } 629 630 /** 631 * ユーザー個別の画面オブジェクトを取得します。 632 * アクセスできない画面IDが指定されたときは、null が返ります。 633 * 634 * @og.rev 4.0.0.0 (2005/01/31) 新規追加 635 * @og.rev 5.2.0.0 (2010/09/01) guiMap の null 判定を追加 636 * @og.rev 6.4.1.1 (2016/01/16) 引数の gamenId が、null の場合は、null を返すように変更。 637 * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 638 * 639 * @param gamenId 画面ID 640 * 641 * @return 画面オブジェクト 642 */ 643 public GUIInfo getGUIInfo( final String gamenId ) { 644 return gamenId == null ? null : guiMap.get( gamenId ); 645 } 646 647 /** 648 * ユーザー個別の画面オブジェクトのマップを取得します。 649 * 650 * @og.rev 4.0.0.0 (2005/01/31) 新規追加 651 * @og.rev 5.2.0.0 (2010/09/01) guiMap の null 判定を追加 652 * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 653 * 654 * @return 画面オブジェクトの配列 655 */ 656 public GUIInfo[] getGUIInfos() { 657 return guiMap.values().toArray( new GUIInfo[guiMap.size()] ) ; 658 659 } 660 661 /** 662 * アクセスが許可されているアドレスかどうかをチェックします。 663 * 664 * チェックの方法は、ブラックリスト方式です。 665 * 画面リソースに登録された一覧の内、そのユーザーが許可されていないアドレスに 666 * 対してのみfalseが返ります。 667 * 画面リソースに登録されていないアドレスや、アドレスにURLの区切り文字(/)が 668 * 含まれている場合はチェックされません。(trueが返ります) 669 * 670 * @og.rev 5.2.0.0 (2010/09/01) 新規追加 671 * 672 * @param addr チェック対象のアドレス 673 * 674 * @return アクセスが許可されているアドレスかどうか 675 */ 676 public boolean isValidAddr( final String addr ) { 677 synchronized( guiLock ) { 678 return forbidAddrSet == null || !forbidAddrSet.contains( addr ) ; 679 } 680 } 681 682 /** 683 * ユーザー個別のお気に入り画面オブジェクトのマップを取得します。 684 * 685 * @og.rev 4.1.1.0 (2008/01/31) 新規追加 686 * @og.rev 6.4.3.1 (2016/02/12) Collections.unmodifiableMap( Map<? extends K,? extends V> ) で作成された変更不可のMapを返します。 687 * 688 * @return お気に入り画面オブジェクトのマップ 689 */ 690 public Map<String,FavoriteGUIData> getFavoriteMap() { 691 return favoriteGuiMap; 692 } 693 694 /** 695 * 画面オブジェクトのマップがセット済みかどうかを取得します。 696 * 697 * @og.rev 4.0.0.0 (2005/01/31) 新規追加 698 * @og.rev 6.4.3.1 (2016/02/12) isInfoSet 廃止。 699 * 700 * @return 画面オブジェクトのマップがセット済みかどうか(true:セット済み / false:未セット) 701 */ 702 public boolean isGUIInfoSet() { 703 return !guiMap.isEmpty(); // 6.4.3.1 (2016/02/12) 704 705 } 706 707 /** 708 * 指定のユーザーロールに対する最終的なアクセス条件を取得します。 709 * アクセス条件は、複数あるユーザーロールの中で、最大のアクセス条件を算出します。 710 * 例えば、AAA(-r)|BBB(-w)|CCC(mr) の3つのロール/モードが設定されている場合、 711 * ユーザーが、AAA だけの場合は、-r ですが、AAA|BBB を持っている場合は、-w になります。 712 * さらに、BBB|CCC と持っている場合は、(-w:書き込み許可)と(mr:メニューから読取許可)の 713 * 権限により、mw:メニューからの書き込み許可が与えられます。 714 * モード指定がある場合は、AND演算になります。 715 * 例えば、AAA(-r)|BBB(-w)|CCC(mr) と BBB|CCC(-r) の場合、(-r)+(-w)+(mr)*(-r)=-w に 716 * なります。ロールは、OR ですが、モードは、同一ロールでのAND になります。 717 * 実際には、メニュー表示の可否は、ポップアップ系によく用いられますので、上記のような 718 * 許可が実際にあるかどうかは不明ですが、すべてのモードのOR条件での結合になります。 719 * 720 * @og.rev 4.3.0.0 (2008/07/04) ロールモードマルチ対応 721 * 722 * @param other ロールモード 723 * 724 * @return アクセスビット 725 */ 726 public byte getAccessBitMode( final RoleMode other ) { 727 return roleMode.getAccessBitMode( other ); 728 } 729 730 /** 731 * このユーザーの権限で、指定のロールが許可されているかどうかを判定します。 732 * 733 * @og.rev 4.3.0.0 (2008/07/04) ロールモードマルチ対応 734 * @og.rev 4.3.0.1 (2008/08/11) ロールチェック時の引数間違い、是正 735 * @og.rev 6.3.6.1 (2015/08/28) '_' を、null と同等に扱います(すべて許可と同じ) 736 * 737 * @param role チェックを行うロール 738 * 739 * @return アクセスできる(true)/出来ない(false) 740 */ 741 public boolean isAccess( final String role ) { 742 // 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method 743 return role == null || role.isEmpty() || role.charAt(0) == '_' 744 || roleMode.getAccessBitMode( RoleMode.newInstance( role ) ) > 0 ; // 4.3.0.1 (2008/08/11) 745 746 } 747 748 /** 749 * 初期化(クリア)します(org.opengion.fukurou.util.Cleanable の実装)。 750 * 画面オブジェクトのマップをクリアし、セット済みフラグを未セットに設定します。 751 * システムリソースの USE_ACCESS_TOKEI_TABLE が true の場合は、 752 * 画面アクセス状況を、アクセス統計テーブル(GE15)に書き込みます。 753 * ユーザー単位のパラメータは、システムリソースの USER_PARAMETER_SQL で 754 * 定義された値を検索して、取り込みます。 755 * 756 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定 757 * @og.rev 4.0.0.0 (2005/01/31) 新規追加 758 * @og.rev 5.6.8.1 (2013/09/13) lastRequestMap を ユーザー永続化情報(GE20) に書き込みます。 759 * @og.rev 6.4.3.1 (2016/02/12) isInfoSet 廃止。 760 */ 761 public void clear() { 762 if( useAccessTable && isGUIInfoSet() ) { saveGUIAccessInfo(); } // 6.4.3.1 (2016/02/12) isInfoSet 廃止 763 initLoad() ; 764 765 saveLastRequestValues(); // 5.6.8.1 (2013/09/13) lastRequestMap を ユーザー永続化情報(GE20) に書き込みます。 766 } 767 768 /** 769 * ユーザーパラメータを取得します。 770 * 画面オブジェクトのマップをクリアし、セット済みフラグを未セットに設定します。 771 * ユーザー単位のパラメータは、システムリソースの USER_PARAMETER_SQL で 772 * 定義された値を検索して、取り込みます。 773 * 774 * @og.rev 4.0.0.0 (2005/01/31) 新規追加 775 * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 776 */ 777 private void initLoad() { 778 779 // ユーザーパラメータの取得 780 if( QUERY_PARAM != null && QUERY_PARAM.length() > 0 ) { 781 final String[] args = new String[] { systemId,userID }; 782 // 画面ID,操作,プログラムID 783 if( appInfo != null ) { 784 // 画面ID,操作,プログラムID 785 appInfo.setModuleInfo( "UserInfo",null,"initLoad" ); 786 } 787 final String[][] vals = DBUtil.dbExecute( QUERY_PARAM,args,appInfo,DBID ); 788 789 // 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 790 paramMap.clear(); 791 for( int i=0; i<vals.length; i++ ) { 792 final String key = vals[i][0]; 793 final String val = vals[i][1]; 794 // 6.4.3.1 (2016/02/12) ConcurrentMap 系は、key,val ともに not null 制限です。 795 if( key != null && val != null && !val.isEmpty() ) { // 元の条件 val.isEmpty() も加味しておきます。 796 paramMap.put( key,val ); 797 } 798 } 799 } 800 } 801 802 /** 803 * ユーザー永続化情報(GE20)からDBに保存されたUserInfoのパラメーターを取得します。 804 * 805 * ここでは、キーの先頭が、LAST_REQUEST_DATA_SUFIX(="LAST_REQUEST_")文字列が、 806 * 付いている物だけ lastRequestMap マップに設定します。(分けて管理します) 807 * 808 * @og.rev 5.3.6.0 (2011/06/01) 新規追加 809 * @og.rev 5.6.8.1 (2013/09/13) setAttribute メソッドではなく、直接 Mapに登録します。 810 * @og.rev 5.7.2.2 (2014/01/24) 値が null、またはゼロ文字列の場合でも処理します。(5.6.8.1 以前に戻します) 811 * 812 * ※ コンストラクタのみで呼ばれるため、synchronized は入れていません。 813 * @see #LAST_REQUEST_DATA_SUFIX 814 */ 815 private void dbLoad() { 816 // ユーザー永続化情報(GE20)テーブル読み込み 817 final String[] argsGe20 = new String[] { systemId,userID,roles }; 818 final String[][] valsGe20 = DBUtil.dbExecute( QUERY_GE20,argsGe20,appInfo,DBID ); 819 820 for( int i=0; i<valsGe20.length; i++ ) { 821 // 4.3.4.0 (2008/12/01) ユーザー永続化情報(GE20)から読み込んでいるので、当然保存しない 822 final String key = valsGe20[i][0]; 823 final String val = valsGe20[i][1]; 824 if( key != null && key.length() > 0 ) { 825 if( key.startsWith( LAST_REQUEST_DATA_SUFIX ) ) { 826 // val が null かどうかは問わない 827 lastRequestMap.put( key.substring( LAST_REQUEST_DATA_SUFIX.length() ) , val ); 828 } 829 else { 830 // 5.7.2.2 (2014/01/24) 値が null、またはゼロ文字列の場合でも処理します。(5.6.8.1 以前に戻します) 831 attriMap.put( key,val ) ; 832 } 833 } 834 } 835 } 836 837 /** 838 * 画面ID、編集名より編集設定オブジェクトを返します。 839 * また、ここで指定された編集名がこの画面での選択済み編集として登録されます。 840 * 841 * @og.rev 5.3.6.0 (2011/06/01) 新規追加 842 * @og.rev 6.4.5.0 (2016/04/08) UserInfo のEditConfig関連機能を、DBEditConfigManagerに移植します。 843 * 844 * @param guikey 画面ID 845 * @param editName 編集名 846 * 847 * @return 編集設定オブジェクト 848 */ 849 public DBEditConfig getEditConfig( final String guikey, final String editName ) { 850 if( editName != null ) { 851 final String selEditName = getAttribute( "EDIT_SELECTED_" + guikey ); 852 if( !editName.equals( selEditName ) ) { 853 setAttribute( "EDIT_SELECTED_" + guikey, editName, true ); 854 } 855 } 856 // else { 857 // setSelectedEdit( guikey, null ); 858 // } 859 return editMgr.getEditConfig( guikey, editName ); 860 } 861 862 863 /** 864 * 編集設定オブジェクトの配列を返します。 865 * 866 * DBEditConfigManagerを直接返していましたが、それを廃止します。 867 * 868 * @og.rev 6.9.2.1 (2018/03/12) DBEditConfigManagerを直接取り出す処理を、廃止します。 869 * 870 * @param guikey 画面ID 871 * @return 編集設定オブジェクトの配列 872 */ 873 public DBEditConfig[] getEditConfigs( final String guikey ) { 874 return editMgr.getEditConfigs( guikey ); 875 } 876 877 /** 878 * 指定の画面ID、編集名で編集設定オブジェクトを追加します。 879 * 既に登録されている場合は、既存の編集情報を更新します。 880 * 881 * ※ 廃止予定ですが、対応が間に合わないため、暫定的に残しています。 882 * 883 * @og.rev 5.3.6.0 (2011/06/01) 新規追加 884 * @og.rev 5.7.1.2 (2013/12/20) msg ⇒ errMsg 変更 885 * @og.rev 6.0.2.2 (2014/10/03) getEditKeys(String,String) を、DBEditConfig ⇒ DBEditConfigManager 変更 886 * @og.rev 6.3.9.1 (2015/11/27) getEditKeys(String,String) は、DBEditConfigManager ⇒ DBEditConfig へ移動。 887 * @og.rev 6.4.5.0 (2016/04/08) UserInfo のEditConfig関連機能を、DBEditConfigManagerに移植します。廃止 888 * 889 * @param guikey 画面ID 890 * @param editName 編集名 891 * @param config 編集設定オブジェクト 892 */ 893 public void addEditConfig( final String guikey, final String editName, final DBEditConfig config ) { 894 if( config != null ) { 895 editMgr.addEditConfig( guikey, editName, config ); 896 897 final boolean isCommon = config.isCommon(); 898 config.forEach( guikey 899 , (key,val) -> { 900 if( val != null && val.length() > 0 ) { 901 setAttribute( key, val, true, isCommon ); 902 } 903 else { 904 removeAttribute( key, true, isCommon ); 905 } 906 } ); 907 } 908 909 } 910 911 /** 912 * 指定の画面ID、編集名の編集設定を削除します。 913 * 914 * ※ 廃止予定ですが、対応が間に合わないため、暫定的に残しています。 915 * 916 * @og.rev 5.3.6.0 (2011/06/01) 新規追加 917 * @og.rev 5.7.1.2 (2013/12/20) msg ⇒ errMsg 変更 918 * @og.rev 6.0.2.2 (2014/10/03) getEditKeys( String, String ) を、DBEditConfig ⇒ DBEditConfigManager 変更 919 * @og.rev 6.3.9.1 (2015/11/27) getEditKeys(String,String) は、DBEditConfigManager ⇒ DBEditConfig へ移動。 920 * @og.rev 6.4.5.0 (2016/04/08) UserInfo のEditConfig関連機能を、DBEditConfigManagerに移植します。廃止 921 * 922 * @param guikey 画面ID 923 * @param editName 編集名 924 */ 925 public void deleteEditConfig( final String guikey, final String editName ) { 926 final DBEditConfig config = editMgr.deleteEditConfig( guikey, editName ); 927 if( config != null ) { 928 final boolean isCommon = config.isCommon(); 929 // final String[] editKeys = DBEditConfig.getEditKeys( guikey, editName ); // 6.3.9.1 (2015/11/27) メソッド移動 930 // // 編集設定が存在しない場合エラー。 931 // if( !isExistValue( editKeys[0], ( isCommon ? "*" : userID ), "*" ) ) { 932 // final String errMsg = "編集設定が存在しません。"; 933 // throw new HybsSystemException( errMsg ); // 5.7.1.2 (2013/12/20) msg ⇒ errMsg 変更 934 // } 935 936 config.forEach( guikey , (key,val) -> removeAttribute( key, true, isCommon ) ); 937 938 // for( int i=0; i<editKeys.length; i++ ) { 939 // removeAttribute( editKeys[i], true, isCommon ); 940 // } 941 removeAttribute( "EDIT_SELECTED_" + guikey, true, isCommon ); // 6.0.2.2 (2014/10/03) 初期値用のキーも削除 942 removeAttribute( "EDIT_NAME_SELECTED_" + guikey, true, isCommon ); // 6.0.2.2 (2014/10/03) 昔のキーは強制削除 943 } 944 945 // if( editName != null ) { 946 // String selEditName = getSelectedEdit( guikey ); 947 // if( !editName.equals( selEditName ) ) { 948 // setSelectedEdit( guikey, null ); 949 // } 950 // } 951 } 952 953 /** 954 * 指定の画面IDに対して選択済みの編集名を返します。 955 * 956 * @og.rev 5.3.6.0 (2011/06/01) 新規追加 957 * @og.rev 6.0.2.2 (2014/10/03) EDIT_NAME_SELECTED_ を、EDIT_SELECTED_ に変更 958 * @og.rev 6.4.5.0 (2016/04/08) UserInfo のEditConfig関連機能を、DBEditConfigManagerに移植します。廃止 959 * 960 * @param guikey 画面ID 961 * 962 * @return 選択済み編集名 963 */ 964 public String getSelectedEdit( final String guikey ) { 965 return getAttribute( "EDIT_SELECTED_" + guikey ); 966 } 967 968 /** 969 * 最後に使用されたリクエスト変数の値を、Mapを読み取って登録します。 970 * 971 * 読み取り対象は、先に lastRequestMap に登録済みのキーだけです。 972 * そのため、{@LAST.XXXX} で値を要求されたときに、キーが 973 * 登録されていない場合は、キーだけ(値 nullで)登録しておきます。 974 * 975 * @og.rev 5.6.8.1 (2013/09/13) 新規追加 976 * 977 * @param reqMap リクエスト変数のMap 978 */ 979 public void setLastRequestMap( final Map<String,String[]> reqMap ) { 980 if( reqMap != null ) { 981 synchronized( lastRequestMap ) { 982 for( final String key : lastRequestMap.keySet() ) { 983 if( key != null ) { // 6.4.3.3 (2016/03/04) 984 final String[] vals = reqMap.get( key ); 985 if( vals != null ) { 986 String val = null; 987 for( int i=0; i<vals.length; i++ ) { 988 val = vals[i]; 989 if( ! "0".equals( val ) ) { break; } // チェックボックス対応 990 } 991 lastRequestMap.put( key, val ); // val は、null もあり得る。 992 } 993 } 994 } 995 } 996 } 997 } 998 999 /** 1000 * 最後に使用されたリクエスト変数の値を、設定します。 1001 * 1002 * この処理は、{@LAST.XXXX} は、リクエスト値があれば、それが優先的に 1003 * 使われます。 1004 * 1005 * @og.rev 5.6.8.1 (2013/09/13) 新規追加 1006 * 1007 * @param key リクエストキー 1008 * @param val 設定値 1009 */ 1010 public void setLastRequestValue( final String key,final String val ) { 1011 if( key != null && key.length() > 0) { 1012 synchronized( lastRequestMap ) { 1013 lastRequestMap.put( key, val ); 1014 } 1015 } 1016 } 1017 1018 /** 1019 * 最後に使用されたリクエスト変数の値を、取得します。 1020 * 1021 * 画面で簡素に使用できるように、少し特殊な処理を行います。 1022 * query 画面で {@LAST.XXXX} を呼ぶと、lastRequestMap にキーがなければ、 1023 * キーだけ先に追加します。あれば、値を取得するだけです。 1024 * そして、result画面で command="NEW" の場合のみ、リクエスト情報のMapから、 1025 * lastRequestMap に持っているキーで(NULLでない場合は)上書きセットします。 1026 * キャッシュ量を減らすことと、処理の対象キーを減らす意味を持っています。 1027 * 1028 * @og.rev 5.6.8.1 (2013/09/13) 新規追加 1029 * 1030 * @param key リクエストキー 1031 * @return 設定値 1032 */ 1033 public String getLastRequestValue( final String key ) { 1034 String rtn = null; 1035 if( key != null && key.length() > 0) { 1036 synchronized( lastRequestMap ) { 1037 if( lastRequestMap.containsKey( key ) ) { // キーを持っているかどうかを判定 1038 rtn = lastRequestMap.get( key ); 1039 } 1040 else { 1041 lastRequestMap.put( key, null ); // キーだけ登録しておく。 1042 } 1043 } 1044 } 1045 return rtn ; 1046 } 1047 1048 /** 1049 * lastRequestMap を ユーザー永続化情報(GE20) に書き込みます。 1050 * 1051 * clear() 処理が実行された場合に、まとめて ユーザー永続化情報(GE20) に書き込みます。 1052 * タイミング的には、saveGUIAccessInfo() メソッドと同じですが、saveGUIAccessInfo() は、 1053 * 書き込む条件( useAccessTable && isInfoSet ) があります。 1054 * セーブする時には、他の属性と区別するため、接頭語 LAST_REQUEST_DATA_SUFIX(="LAST_REQUEST_") を 1055 * キーに付けて渡します。 1056 * 1057 * 読み取りは、dbLoad() で、attriMap と同じタイミングで、コンストラクタで、行います。 1058 * 1059 * @og.rev 5.6.8.1 (2013/09/13) 新規追加 1060 * @og.rev 6.3.9.0 (2015/11/06) Map.keySet() ではなく、Map.entrySet() を使う様に変更。 1061 * @og.rev 6.4.3.4 (2016/03/11) forループを、forEach メソッドに置き換えます。 1062 * 1063 * @see #clear() 1064 * @see #dbLoad() 1065 */ 1066 private void saveLastRequestValues() { 1067 int cnt = 0; 1068 synchronized( lastRequestMap ) { 1069 // 6.3.9.0 (2015/11/06) Map.keySet() ではなく、Map.entrySet() を使う様に変更。 1070 // 6.4.3.4 (2016/03/11) forループを、forEach メソッドに置き換えます。 1071 lastRequestMap.forEach( (key,val) -> savePermanently( LAST_REQUEST_DATA_SUFIX + key , val , false ) ); 1072 1073 cnt = lastRequestMap.size(); 1074 } 1075 System.out.println( " [" + userID + "] 最終リクエスト情報({@LAST.XXXX})を、(GE20)に、[" + cnt + "]件、登録しました。" ); 1076 } 1077 1078 /** 1079 * アクセスログ取得の為,ApplicationInfoオブジェクトを返します。 1080 * 1081 * @og.rev 3.8.7.0 (2006/12/15) 新規追加 1082 * 1083 * @param gamenId 実行中の画面ID 1084 * @param prgId 実行中のプログラムID 1085 * 1086 * @return ApplicationInfoオブジェクト 1087 */ 1088 public ApplicationInfo getApplicationInfo( final String gamenId,final String prgId ) { 1089 if( appInfo != null ) { 1090 // 画面ID,操作,プログラムID 1091 appInfo.setModuleInfo( gamenId,null,prgId ); 1092 } 1093 return appInfo; 1094 } 1095 1096 /** 1097 * 自然比較メソッド 1098 * インタフェース Comparable の 実装です。 1099 * ユーザーの順序は、ユーザーID そのものの順序であらわされます。 1100 * 同一ユーザーの場合は,ログインタイムの順番になります。 1101 * 1102 * @og.rev 5.1.8.0 (2010/07/01) UserSummary の Comparable を型設定 1103 * 1104 * @param object 比較対象のObject 1105 * 1106 * @return このオブジェクトが指定されたオブジェクトより小さい場合は負の整数、等しい場合はゼロ、大きい場合は正の整数 1107 */ 1108 @Override 1109 public int compareTo( final UserSummary object ) { 1110 int test1 = userID.compareTo( object.getUserID() ); 1111 if( test1 == 0 ) { 1112 test1 = (int)( loginTime - object.getLoginTime() ) ; 1113 } 1114 return test1; 1115 } 1116 1117 /** 1118 * このオブジェクトと他のオブジェクトが等しいかどうかを示します。 1119 * インタフェース Comparable の 実装に関連して、再定義しています。 1120 * ユーザーは、ユーザーIDが等しく、かつ ログイン時刻が同一の場合に、 1121 * 等しいと判断されます。 1122 * 1123 * @param object 比較対象の参照オブジェクト 1124 * 1125 * @return 引数に指定されたオブジェクトとこのオブジェクトが等しい場合は true、そうでない場合は false 1126 */ 1127 @Override 1128 public boolean equals( final Object object ) { 1129 // 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method 1130 return object instanceof UserInfo 1131 && userID.equals( ((UserInfo)object).getUserID() ) 1132 && loginTime == ( ((UserInfo)object).getLoginTime() ); 1133 1134 } 1135 1136 /** 1137 * オブジェクトのハッシュコード値を返します。 1138 * このメソッドは、java.util.Hashtable によって提供されるような 1139 * ハッシュテーブルで使用するために用意されています。 1140 * equals( Object ) メソッドをオーバーライトした場合は、hashCode() メソッドも 1141 * 必ず 記述する必要があります。 1142 * ここでは、ログイン時刻(long 値)の上位 32 ビットと下位 32 ビットの排他的論理和 1143 * を求めています。 1144 * (int)(this.longValue()^(this.longValue()>>>32)) 1145 * 1146 * ※ hashCode の 同一オブジェクトには同一ハッシュコードという規則と 1147 * 発生頻度,ランダム性を考慮すれば、ログイン時刻そのもの(long)の 1148 * ハッシュコードでも運用上は全く問題ないと考えられます。 1149 * 1150 * @og.rev 3.5.6.0 (2004/06/18) 新規追加 1151 * 1152 * @return このオブジェクトのハッシュコード値 1153 * 1154 */ 1155 @Override 1156 public int hashCode() { return hcode ; } 1157 1158 /** 1159 * オブジェクトの識別子として,詳細なユーザー情報を返します。 1160 * 1161 * @return 詳細なユーザー情報 1162 * @og.rtnNotNull 1163 */ 1164 @Override 1165 public String toString() { 1166 final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE ) 1167 .append( "userID :" ).append( userID ).append( CR ) 1168 .append( "lang :" ).append( lang ).append( CR ) 1169 .append( "jname :" ).append( jname ).append( CR ) 1170 .append( "roles :" ).append( roles ).append( CR ) 1171 .append( "IPAddress:" ).append( ipAddress ).append( CR ) 1172 .append( "loginTime:" ).append( loginTime ).append( CR ); 1173 return rtn.toString(); 1174 } 1175 1176 /** 1177 * ユーザー個別の画面オブジェクトの明細情報をアクセス統計テーブル(GE15)に登録します。 1178 * 1179 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定 1180 * @og.rev 4.0.0.0 (2005/01/31) 新規追加 1181 * @og.rev 4.0.0.0 (2007/10/05) SQLServer 互換性の為、SUBSTRB を廃止します。 1182 * @og.rev 4.1.1.0 (2008/01/30) ユーザーアクセス画面管理テーブルに画面の最終アクセス時間を更新 1183 * @og.rev 5.0.2.0 (2009/11/01) 作成・更新日付がセットされていないバグを修正 1184 * @og.rev 5.2.3.0 (2010/12/01) 画面アクセスの履歴(順番)を管理する機能を追加 1185 * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策 1186 * @og.rev 6.4.2.0 (2016/01/29) DateSet.getDate( String ) を利用するように修正します。 1187 * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 1188 */ 1189 private void saveGUIAccessInfo() { 1190 // if( !useAccessTable || !isInfoSet ) { return ; } 1191 1192 final GUIInfo[] infos = getGUIInfos() ; 1193 guiMap.clear(); // 6.4.3.1 (2016/02/12) getGUIInfos() してから、クリアします。 1194 1195 final long crntTime = System.currentTimeMillis(); 1196 1197 final String[] names = new String[] { "SYSTEM_ID","USERID","USERADRS","HOSTADRS","GUIKEY","DYLOGIN","DYLOGOUT", 1198 "USED_TIME","CNT_ACCESS","CNT_ERROR","CNT_READ","CNT_WRITE", 1199 "TM_TOTAL_QUERY","TM_MAX_QUERY","MAX_QUERY","FGJ","DYSET","DYUPD","USRSET","USRUPD","PGUPD" }; 1200 String[] values = new String[names.length]; 1201 1202 values[C_SYSTEM_ID ] = HybsSystem.sys( "SYSTEM_ID" ); 1203 values[C_USERID ] = userID; 1204 values[C_USERADRS ] = ipAddress; 1205 values[C_HOSTADRS ] = HybsSystem.sys( "HOST_ADRS" ); 1206 values[C_GUIKEY ] = ""; 1207 values[C_DYLOGIN ] = DateSet.getDate( loginTime,"yyyyMMddHHmmss" ); // 6.4.2.0 (2016/01/29) 1208 values[C_DYLOGOUT ] = DateSet.getDate( "yyyyMMddHHmmss" ); // 6.4.2.0 (2016/01/29) 1209 values[C_USED_TIME ] = String.valueOf( Math.round( (crntTime-usedTime) / 1000.0d ) ); // 秒に変換 1210 values[C_CNT_ACCESS ] = "0"; 1211 values[C_CNT_ERROR ] = "0"; 1212 values[C_CNT_READ ] = "0"; 1213 values[C_CNT_WRITE ] = "0"; 1214 values[C_TM_TOTAL_QUERY ] = "0"; 1215 values[C_TM_MAX_QUERY ] = "0"; 1216 values[C_MAX_QUERY ] = ""; 1217 values[C_FGJ ] = "1"; 1218 values[C_DYSET ] = DateSet.getDate( "yyyyMMddHHmmss" ); // 6.4.2.0 (2016/01/29) 1219 values[C_DYUPD ] = DateSet.getDate( "yyyyMMddHHmmss" ); // 6.4.2.0 (2016/01/29) 1220 values[C_USRSET ] = "userInfo"; 1221 values[C_USRUPD ] = "userInfo"; 1222 values[C_PGUPD ] = "userInfo"; 1223 1224 usedTime = crntTime ; 1225 1226 final DBSimpleTable dbTable = new DBSimpleTable( names ); 1227 // 画面ID,操作,プログラムID 1228 getApplicationInfo( "UserInfo","saveGUI" ); 1229 dbTable.setApplicationInfo( appInfo ); // 3.8.7.0 (2006/12/15) 1230 dbTable.setConnectionID( DBID ); // 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対応 1231 dbTable.setTable( "GE15" ); 1232 // 4.0.0.0 (2007/10/05) SQLServer 互換性の為、CLOB化します。 1233 // dbTable.addConstrain( names[C_MAX_QUERY],"SUBSTRB(?,1,4000)" ); 1234 1235 boolean okFlag = false; 1236 try { 1237 dbTable.startInsert(); 1238 1239 // UserInfo に関する情報の登録 1240 dbTable.execute( values ); 1241 1242 // GUIInfo に関する情報の登録 1243 if( infos != null ) { 1244 values[C_USED_TIME] = "0"; // USED_TIME をクリアしておきます。 1245 final String logoutTime = DateSet.getDate( "yyyyMMddHHmmss" ); // 6.4.2.0 (2016/01/29) 1246 for( int i=0; i<infos.length; i++ ) { 1247 final GUIAccessCount access = infos[i].getGUIAccessCount(); 1248 final int cnt = access.getAccessCount(); 1249 if( cnt > 0 ) { 1250 values[C_GUIKEY ] = access.getKey(); 1251 values[C_CNT_ACCESS ] = String.valueOf( cnt ); 1252 values[C_CNT_ERROR ] = String.valueOf( access.getErrorCount() ); 1253 values[C_CNT_READ ] = String.valueOf( access.getReadCount() ); 1254 values[C_CNT_WRITE ] = String.valueOf( access.getWriteCount() ); 1255 values[C_TM_TOTAL_QUERY ] = String.valueOf( access.getQueryTime() ); 1256 values[C_TM_MAX_QUERY ] = String.valueOf( access.getMaxQueryTime() ); 1257 values[C_MAX_QUERY ] = access.getMaxQuery(); 1258 // dbTable.addValues( values ); 1259 dbTable.execute( values ); 1260 // 4.1.1.0(2008/01/28)画面アクセス時間の更新 1261 // 5.2.3.0 (2010/12/01) 画面アクセスの履歴(順番)を管理する機能を追加 1262 final String keys = infos[i].getNextGuiKeys(); 1263 UserAccessTable.updateLastAccessTime( systemId,userID,access.getKey(),logoutTime,keys ); 1264 } 1265 } 1266 } 1267 okFlag = true; 1268 } 1269 catch( final SQLException ex) { 1270 LogWriter.log( " [" + userID + "] アクセス統計テーブル(GE15)登録時にエラーが発生しました" ); 1271 LogWriter.log( ex.getMessage() ); 1272 } 1273 finally { 1274 final int cnt = dbTable.close( okFlag ); 1275 System.out.println( " [" + userID + "] アクセス統計テーブル(GE15)に、[" + cnt + "]件、追加しました。" ); 1276 } 1277 } 1278 1279 /** 1280 * userInfoにセットされた値/キーをDBに登録します。 1281 * 既にキーが存在している場合は、既存データを更新し、なければ追加します。 1282 * 1283 * @og.rev 5.3.6.0 (2011/06/01) 全ユーザー情報として保存できるように対応 1284 * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策 1285 * @og.rev 6.4.2.0 (2016/01/29) DateSet.getDate( String ) を利用するように修正します。 1286 * @og.rev 6.4.5.0 (2016/04/08) DBEditConfigManager で使えるように、private → public にします(ちょっと不安)。 1287 * 1288 * @param key キー 1289 * @param value 値 1290 * @param isCommon ユーザーID='*'(全ユーザー公開)として登録するかどうか 1291 */ 1292 public void savePermanently( final String key, final String value, final boolean isCommon ) { 1293 1294 // 追加変更時に共通でセットされる値を設定 1295 final String[] names = new String[] { "SYSTEM_ID","USERID","ROLES","PARAM_ID","PARAM","KBSET" 1296 ,"FGJ","DYSET","DYUPD","USRSET","USRUPD","PGUPD" }; 1297 String[] values = new String[names.length]; 1298 values[C_GE20_SYSTEM_ID ] = HybsSystem.sys( "SYSTEM_ID" ); 1299 values[C_GE20_USERID ] = ( isCommon ? "*" : userID ); 1300 values[C_GE20_ROLES ] = GE20_ROLES; 1301 values[C_GE20_PARAM_ID ] = key; 1302 values[C_GE20_PARAM ] = value; 1303 values[C_GE20_KBSET ] = String.valueOf( GE20_KBSET_WRITABLE ); 1304 values[C_GE20_FGJ ] = "1"; 1305 values[C_GE20_DYSET ] = DateSet.getDate( "yyyyMMddHHmmss" ); // 6.4.2.0 (2016/01/29) 1306 values[C_GE20_DYUPD ] = DateSet.getDate( "yyyyMMddHHmmss" ); // 6.4.2.0 (2016/01/29) 1307 values[C_GE20_USRSET ] = userID; 1308 values[C_GE20_USRUPD ] = userID; 1309 values[C_GE20_PGUPD ] = "UserInfo"; 1310 1311 // 画面ID,操作,プログラムID 1312 getApplicationInfo( "UserInfo","registValueToDB" ); 1313 1314 final DBSimpleTable dbTable = new DBSimpleTable( names ); 1315 dbTable.setApplicationInfo( appInfo ); // 3.8.7.0 (2006/12/15) 1316 dbTable.setConnectionID( DBID ); // 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対応 1317 dbTable.setTable( "GE20" ); 1318 1319 boolean okFlag = false; 1320 try { 1321 if( isExistValue( key, ( isCommon ? "*" : userID ), GE20_ROLES ) ) { 1322 final String where = "SYSTEM_ID = [SYSTEM_ID] and USERID = [USERID] and ROLES = [ROLES] and PARAM_ID = [PARAM_ID] and FGJ='1'"; 1323 dbTable.setWhere( where ); 1324 dbTable.startUpdate(); 1325 } 1326 else { 1327 dbTable.startInsert(); 1328 } 1329 dbTable.execute( values ); 1330 okFlag = true; 1331 } 1332 catch( final SQLException ex ) { 1333 throw new HybsSystemException( "ユーザー永続化情報(GE20)設定時にエラーが発生しました", ex ); 1334 } 1335 finally { 1336 dbTable.close( okFlag ); 1337 } 1338 } 1339 1340 /** 1341 * userInfoから削除された値/キーをDBからも削除します。 1342 * 1343 * @og.rev 5.3.6.0 (2011/06/01) 新規追加 1344 * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策 1345 * 1346 * @param key キー 1347 * @param isCommon ユーザーID='*'(全ユーザー公開)から削除するかどうか 1348 */ 1349 private void deletePermanently( final String key, final boolean isCommon ) { 1350 1351 // 追加変更時に共通でセットされる値を設定 1352 final String[] names = new String[] { "SYSTEM_ID","USERID","ROLES","PARAM_ID" }; 1353 String[] values = new String[names.length]; 1354 values[C_GE20_SYSTEM_ID ] = HybsSystem.sys( "SYSTEM_ID" ); 1355 values[C_GE20_USERID ] = ( isCommon ? "*" : userID ); 1356 values[C_GE20_ROLES ] = GE20_ROLES; 1357 values[C_GE20_PARAM_ID ] = key; 1358 1359 // 画面ID,操作,プログラムID 1360 getApplicationInfo( "UserInfo","deleteValueFromDB" ); 1361 1362 final DBSimpleTable dbTable = new DBSimpleTable( names ); 1363 dbTable.setApplicationInfo( appInfo ); 1364 dbTable.setConnectionID( DBID ); // 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対応 1365 dbTable.setTable( "GE20" ); 1366 1367 boolean okFlag = false; 1368 try { 1369 final String where = "SYSTEM_ID = [SYSTEM_ID] and USERID = [USERID] and ROLES = [ROLES] and PARAM_ID = [PARAM_ID] and FGJ='1'"; 1370 dbTable.setWhere( where ); 1371 dbTable.startDelete(); 1372 dbTable.execute( values ); 1373 okFlag = true; 1374 } 1375 catch( final SQLException ex ) { 1376 throw new HybsSystemException( "ユーザー永続化情報(GE20)削除時にエラーが発生しました", ex ); 1377 } 1378 finally { 1379 dbTable.close( okFlag ); 1380 } 1381 } 1382 1383 /** 1384 * ユーザー永続化情報(GE20)に該当のキーが存在するかをチェックします。 1385 * 1386 * @og.rev 5.3.6.0 (2011/06/01) 全ユーザー情報として保存できるように対応 1387 * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策 1388 * 1389 * @param key キー 1390 * @param userid ユーザーID 1391 * @param roles ロール 1392 * 1393 * @return true:存在している/false:存在していない 1394 */ 1395 private boolean isExistValue( final String key, final String userid, final String roles ) { 1396 final String[] args = { HybsSystem.sys( "SYSTEM_ID" ), userid, roles, key }; 1397 1398 // 画面ID,操作,プログラムID 1399 getApplicationInfo( "UserInfo","isExistValue" ); 1400 1401 final String[][] rtn = DBUtil.dbExecute( QUERY_GE20_KEY, args, appInfo, DBID ); // 5.5.5.1 (2012/08/07) 1402 if( rtn == null || rtn.length == 0 ) { 1403 return false; 1404 } 1405 else if( rtn[0].length > 0 ) { 1406 if( String.valueOf( GE20_KBSET_READONLY ).equals( rtn[0][0] ) ) { 1407 throw new HybsSystemException( "読み取り専用情報のため、書き込みできません" ); 1408 } 1409 else { 1410 return true; 1411 } 1412 } 1413 else { 1414 throw new HybsSystemException( "ユーザー永続化情報(GE20)検索時にエラーが発生しました。" ); 1415 } 1416 } 1417 1418 /** 1419 * 指定されたカラムキーに対応するデータの条件式を返します。 1420 * 1421 * @og.rev 4.4.0.0 (2009/08/02) 新規追加 1422 * 1423 * @param clm カラム名 1424 * 1425 * @return データの条件式 1426 */ 1427 public String getDataCondition( final String clm ) { 1428 return dataRole.getCondition( clm ); 1429 } 1430 1431 /** 1432 * このユーザーでアクセスされた画面オブジェクトを設定します。 1433 * 1434 * これは、画面アクセスの履歴(順番)を管理する機能に使います。 1435 * 1436 * @og.rev 5.2.3.0 (2010/12/01) 新規追加 1437 * 1438 * @param guiInfo 画面オブジェクト 1439 */ 1440 public void setAccessGui( final GUIInfo guiInfo ) { 1441 if( lastGuiInfo != null && guiInfo != null ) { 1442 lastGuiInfo.setNextGuiKey( guiInfo.getKey() ); 1443 } 1444 lastGuiInfo = guiInfo ; // 最後にアクセスした GUIInfo を設定 1445 } 1446}