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.text.MessageFormat; 019import java.util.List; 020import java.util.Arrays; // 6.4.7.0 (2016/06/03) 021 022import org.opengion.hayabusa.common.HybsSystem; 023import org.opengion.hayabusa.common.HybsSystemException; 024import org.opengion.hayabusa.common.SystemManager; 025import org.opengion.fukurou.system.LogWriter; 026import org.opengion.fukurou.util.Cleanable; 027import org.opengion.fukurou.util.StringUtil; 028import org.opengion.fukurou.db.ApplicationInfo; 029import org.opengion.fukurou.db.DBUtil; 030 031/** 032 * systemId に対応したユーザー情報を作成するファクトリクラスです。 033 * 034 * UserInfoオブジェクトは,キャッシュせずに、要求都度、データベースを検索します。 035 * これは、ユーザー登録が、他システムより行われる可能性を考慮している為です。 036 * ユーザーオブジェクトの要求は、基本的にログイン時のみで、その後セッションに 037 * キープされます。 038 * 039 * 検索するカラムには、必ず、USERID,LANG,NAME,ROLES がこの順番で含まれており、 040 * 絞込み条件(?パラメータ)として、SYSTEM_ID,USERID がこの順番で指定される必要があります。 041 * (カラム名は関係ありません。並び順と意味が重要です。) 042 * また、検索順(ORDER BY)は、優先順位の低い順に検索してください。使用するのは、一番最後に 043 * 検索された行を使用します。 044 * ユーザーリソースは、RESOURCE_USER_DBID で指定のデータベースから取得します。 045 * 未定義の場合は、RESOURCE_DBID から、それも未定義の場合は デフォルトの接続先を 046 * 使用します。 047 * 048 * SYSTEM_ID='**' は、共通リソースです(ROLESも共通に設定する必要があります。)。 049 * これは、システム間で共通に使用されるリソース情報を登録しておきます。 050 * SYSTEM_ID は、指定のシステムIDと**を検索対象にします。**は、全システム共通の 051 * 指定のシステムIDと**と両方存在する場合は、指定のシステムIDが優先されます。 052 * 053 * ver4 では、デフォルトロールという考え方がなくなりましたので、画面のロールに、 054 * (*)を明示的に追加し、RWMODE を指定する必要があります。 055 * 056 * @og.rev 4.0.0.0 (2004/12/31) 新規作成 057 * @og.group リソース管理 058 * 059 * @version 4.0 060 * @author Kazuhiko Hasegawa 061 * @since JDK5.0, 062 */ 063public final class UserInfoFactory { 064 065 private static final String SYSTEM_ID = HybsSystem.sys( "SYSTEM_ID" ); 066 067 // ユーザーリソースの接続先を、取得します。 068 private static String dbid = StringUtil.nval( 069 HybsSystem.sys( "RESOURCE_USER_DBID" ) , 070 HybsSystem.sys( "RESOURCE_DBID" ) 071 ) ; 072 073 // ユーザーリソースのキー指定読み込みのクエリー 074 private static String query = HybsSystem.sys( "RESOURCE_USER_SQL" ); 075 private static String queryRole = HybsSystem.sys( "RESOURCE_USER_ROLE_SQL" ); 076 077 // 5.2.0.0 (2010/09/01) LDAP対応 078 private static String srcType = HybsSystem.sys( "RESOURCE_USER_SRC_TYPE" ); 079 private static String[] ldapClm = StringUtil.csv2Array( HybsSystem.sys( "RESOURCE_USER_LDAP_CLM" ) ); 080 private static String ldapFilter = HybsSystem.sys( "RESOURCE_USER_LDAP_FILTER" ); 081 private static String ldapRoleFilter= HybsSystem.sys( "RESOURCE_USER_ROLE_LDAP_FILTER" ); 082 083 private static String searchScope = HybsSystem.sys( "LDAP_SEARCH_SCOPE" ); 084 private static String initctx = HybsSystem.sys( "LDAP_INITIAL_CONTEXT_FACTORY" ); 085 private static String providerURL = HybsSystem.sys( "LDAP_PROVIDER_URL" ); 086 private static String entrydn = HybsSystem.sys( "LDAP_ENTRYDN" ); 087 private static String password = HybsSystem.sys( "LDAP_PASSWORD" ); 088 private static String searchbase = HybsSystem.sys( "LDAP_SEARCH_BASE" ); 089 090 private static final Object LOCK = new Object(); // 6.4.1.1 (2016/01/16) lock → LOCK refactoring 091 092 /** コネクションにアプリケーション情報を追記するかどうか指定 */ 093 public static final boolean USE_DB_APPLICATION_INFO = HybsSystem.sysBool( "USE_DB_APPLICATION_INFO" ) ; 094 095 // 4.0.0 (2005/01/31) Cleanable インターフェースによる初期化処理 096 static { 097 final Cleanable clr = new Cleanable() { 098 /** 099 * 初期化(クリア)します。 100 * 主に、キャッシュクリアで利用します。 101 */ 102 public void clear() { 103 UserInfoFactory.clear(); 104 } 105 }; 106 107 SystemManager.addCleanable( clr ); 108 } 109 110 /** 111 * デフォルトコンストラクターをprivateにして、 112 * オブジェクトの生成をさせないようにする。 113 * 114 */ 115 private UserInfoFactory() { 116 } 117 118 /** 119 * UserInfo オブジェクトを取得します。 120 * 121 * UserInfoオブジェクトは,キャッシュせずに、要求都度、データベースを検索します。 122 * これは、ユーザー登録が、他システムより行われる可能性を考慮している為です。 123 * ユーザーオブジェクトの要求は、基本的にログイン時のみで、その後セッションに 124 * キープされます。 125 * 126 * @og.rev 3.7.0.4 (2005/03/18) ゲストログイン機能追加 127 * @og.rev 4.0.0.0 (2007/10/31) ロール指定でのログイン機能追加 128 * @og.rev 4.3.4.0 (2008/12/01) GE20(ユーザー定数)へ登録するかのフラグへの対応 129 * @og.rev 4.4.0.0 (2009/08/02) データロール対応 130 * @og.rev 5.2.0.0 (2010/09/01) LDAP対応 131 * @og.rev 5.3.6.0 (2011/06/01) GE20の読み込みをUserInfo内に移動 132 * @og.rev 7.4.4.0 (2021/06/30) openGionV8事前準備(DataRole.java廃止) 133 * 134 * @param userID ユーザーID 135 * @param ipAddress ログイン端末のIPアドレス 136 * @param roles データロール 137 * 138 * @return UserInfoオブジェクト 139 */ 140 public static UserInfo newInstance( final String userID,final String ipAddress,final String roles ) { 141 // 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定 142 ApplicationInfo appInfo = null ; 143 if( USE_DB_APPLICATION_INFO ) { 144 appInfo = new ApplicationInfo(); 145 // ユーザーID,IPアドレス,ホスト名 146 appInfo.setClientInfo( userID,ipAddress,null ); 147 // 画面ID,操作,プログラムID 148 appInfo.setModuleInfo( "UserInfoFactory",null,"newInstance" ); 149 } 150 151 String[][] vals; 152 if( "LDAP".equalsIgnoreCase( srcType ) ) { 153 vals = getValsByLdap( userID, roles ); 154 } 155 else { 156 vals = getVals( userID, roles, appInfo ); 157 } 158 159 final UserInfo info ; 160 final int len = vals.length ; // システムID ** を含む。 161 // if( len >= 1 && vals[0].length >= 5 ) { // 7.4.4.0 (2021/06/30) Modify 162 if( len >= 1 && vals[0].length >= 4 ) { 163 // システムIDでソートされる。SYSTEM_ID="**"は最初に現れるので、最後を取得 164 info = new UserInfo( 165 userID , // userID 166 vals[len-1][1] , // lang 167 vals[len-1][2] , // jname 168 vals[len-1][3] , // roles 169 // vals[len-1][4] , // droles // 4.4.0.0 (2009/08/02) 7.4.4.0 (2021/06/30) Delete 170 SYSTEM_ID , // systemId 171 ipAddress , // ipAddress 172 appInfo ) ; // ApplicationInfo 173 } 174 else { 175 // final String errMsg = "UserInfo のデータ(USERID,LANG,NAME,ROLES,DROLES)が取得できません。" // 7.4.4.0 (2021/06/30) Modify 176 final String errMsg = "UserInfo のデータ(USERID,LANG,NAME,ROLES)が取得できません。" 177 + " Key [" + userID + "]" 178 + " SQL [" + query + "]" ; 179 LogWriter.log( errMsg ); 180 throw new HybsSystemException( errMsg ); 181 } 182 183 return info ; 184 } 185 186 /** 187 * UserInfoFactoryをクリアします。 188 * 189 * @og.rev 5.2.0.0 (2010/09/01) LDAP対応 190 * 191 */ 192 public static void clear() { 193 synchronized( LOCK ) { 194 dbid = StringUtil.nval( 195 HybsSystem.sys( "RESOURCE_USER_DBID" ) , 196 HybsSystem.sys( "RESOURCE_DBID" ) 197 ) ; 198 query = HybsSystem.sys( "RESOURCE_USER_SQL" ); 199 queryRole = HybsSystem.sys( "RESOURCE_USER_ROLE_SQL" ); 200 201 // 5.2.0.0 (2010/09/01) LDAP対応 202 srcType = HybsSystem.sys( "RESOURCE_USER_SRC_TYPE" ); 203 ldapClm = StringUtil.csv2Array( HybsSystem.sys( "RESOURCE_USER_LDAP_CLM" ) ); 204 ldapFilter = HybsSystem.sys( "RESOURCE_USER_LDAP_FILTER" ); 205 ldapRoleFilter = HybsSystem.sys( "RESOURCE_USER_ROLE_LDAP_FILTER" ); 206 207 searchScope = HybsSystem.sys( "LDAP_SEARCH_SCOPE" ); 208 initctx = HybsSystem.sys( "LDAP_INITIAL_CONTEXT_FACTORY" ); 209 providerURL = HybsSystem.sys( "LDAP_PROVIDER_URL" ); 210 entrydn = HybsSystem.sys( "LDAP_ENTRYDN" ); 211 password = HybsSystem.sys( "LDAP_PASSWORD" ); 212 searchbase = HybsSystem.sys( "LDAP_SEARCH_BASE" ); 213 } 214 } 215 216 /** 217 * DBからユーザーリソースの情報を取得します。 218 * 219 * @og.rev 5.2.0.0 (2010/09/01) 新規作成 220 * 221 * @param userId ユーザーID 222 * @param roles ロール 223 * @param appInfo DB接続情報 224 * 225 * @return ユーザーリソース情報 226 */ 227 private static String[][] getVals( final String userId, final String roles, final ApplicationInfo appInfo ) { 228 String[] args; 229 String[][] rtn; 230 231 if( roles == null || roles.isEmpty() ) { 232 args = new String[] { SYSTEM_ID,userId }; 233 synchronized( LOCK ) { 234 rtn = DBUtil.dbExecute( query,args,appInfo,dbid ); 235 } 236 } 237 // 4.0.0.0 (2007/10/31) 238 else { 239 args = new String[] { SYSTEM_ID,userId,roles }; 240 synchronized( LOCK ) { 241 rtn = DBUtil.dbExecute( queryRole,args,appInfo,dbid ); 242 } 243 } 244 245 return rtn; 246 } 247 248 /** 249 * LDAPからユーザーリソースの情報を取得します。 250 * 251 * @og.rev 5.2.0.0 (2010/09/01) 新規作成 252 * @og.rev 6.4.7.0 (2016/06/03) IllegalArgumentException が発生した場合に、見えるようにする。 253 * @og.rev 7.4.4.0 (2021/06/30) openGionV8事前準備(DataRole.java廃止) 254 * 255 * @param userId ユーザーID 256 * @param roles ロール 257 * 258 * @return ユーザーリソース情報 259 */ 260 private static String[][] getValsByLdap( final String userId, final String roles ) { 261 final LDAPSearch serch = new LDAPSearch(); 262 serch.setSearchScope( searchScope ) ; 263 serch.setInitctx( initctx ) ; 264 serch.setProviderURL( providerURL ) ; 265 serch.setSearchbase( searchbase ) ; 266 if( entrydn != null ) { serch.setEntrydn( entrydn ) ; } 267 if( password != null ) { serch.setPassword( password ) ; } 268 serch.setAttributes( ldapClm ) ; 269 serch.init(); 270 271 // 6.4.2.1 (2016/02/05) PMD refactoring. Useless parentheses. 272 String filter = roles == null || roles.isEmpty() ? ldapFilter : ldapRoleFilter; 273 final String[] args = roles == null || roles.isEmpty() ? new String[] { SYSTEM_ID,userId } : new String[] { SYSTEM_ID,userId,roles }; 274 275 // 6.4.7.0 (2016/06/03) IllegalArgumentException が発生した場合に、見えるようにする。 276 try { 277 filter = MessageFormat.format( filter,(Object[])args ); 278 } 279 catch( final IllegalArgumentException ex ) { 280 final String errMsg = "MessageFormatエラー:" 281 + " Pattern [" + filter + "]" 282 + " Arguments [" + Arrays.toString( (Object[])args ) + "]" ; 283 throw new HybsSystemException( errMsg,ex ); 284 } 285 286 final List<String[]> list = serch.search( filter ); 287 288 String[][] rtn = null; 289 if( !list.isEmpty() ) { // 6.1.1.0 (2015/01/17) refactoring 290 rtn = new String[1][]; 291 rtn[0] = list.get( 0 ); 292 rtn[0][1] = StringUtil.nval( rtn[0][1], "ja" ); // 言語のデフォルト値は、'ja' 293 rtn[0][2] = StringUtil.nval( rtn[0][2], rtn[0][0] ); // 名称のデフォルト値は、ユーザーID 294 rtn[0][3] = StringUtil.nval( rtn[0][3], ldapClm[3] ); // ロールズの初期値は、ロールに設定された項目名 295 // rtn[0][4] = StringUtil.nval( rtn[0][4], "" ); // 7.4.4.0 (2021/06/30) Delete 296 } 297 298 return rtn; 299 } 300}