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