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,DROLES がこの順番で含まれており、 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 * 133 * @param userID ユーザーID 134 * @param ipAddress ログイン端末のIPアドレス 135 * @param roles データロール 136 * 137 * @return UserInfoオブジェクト 138 */ 139 public static UserInfo newInstance( final String userID,final String ipAddress,final String roles ) { 140 // 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定 141 ApplicationInfo appInfo = null ; 142 if( USE_DB_APPLICATION_INFO ) { 143 appInfo = new ApplicationInfo(); 144 // ユーザーID,IPアドレス,ホスト名 145 appInfo.setClientInfo( userID,ipAddress,null ); 146 // 画面ID,操作,プログラムID 147 appInfo.setModuleInfo( "UserInfoFactory",null,"newInstance" ); 148 } 149 150 String[][] vals; 151 if( "LDAP".equalsIgnoreCase( srcType ) ) { 152 vals = getValsByLdap( userID, roles ); 153 } 154 else { 155 vals = getVals( userID, roles, appInfo ); 156 } 157 158 final UserInfo info ; 159 final int len = vals.length ; // システムID ** を含む。 160 if( len >= 1 && vals[0].length >= 5 ) { 161 // システムIDでソートされる。SYSTEM_ID="**"は最初に現れるので、最後を取得 162 info = new UserInfo( 163 userID , // userID 164 vals[len-1][1] , // lang 165 vals[len-1][2] , // jname 166 vals[len-1][3] , // roles 167 vals[len-1][4] , // droles // 4.4.0.0 (2009/08/02) 168 SYSTEM_ID , // systemId 169 ipAddress , // ipAddress 170 appInfo ) ; // ApplicationInfo 171 } 172 else { 173 final String errMsg = "UserInfo のデータ(USERID,LANG,NAME,ROLES,DROLES)が取得できません。" 174 + " Key [" + userID + "]" 175 + " SQL [" + query + "]" ; 176 LogWriter.log( errMsg ); 177 throw new HybsSystemException( errMsg ); 178 } 179 180 return info ; 181 } 182 183 /** 184 * UserInfoFactoryをクリアします。 185 * 186 * @og.rev 5.2.0.0 (2010/09/01) LDAP対応 187 * 188 */ 189 public static void clear() { 190 synchronized( LOCK ) { 191 dbid = StringUtil.nval( 192 HybsSystem.sys( "RESOURCE_USER_DBID" ) , 193 HybsSystem.sys( "RESOURCE_DBID" ) 194 ) ; 195 query = HybsSystem.sys( "RESOURCE_USER_SQL" ); 196 queryRole = HybsSystem.sys( "RESOURCE_USER_ROLE_SQL" ); 197 198 // 5.2.0.0 (2010/09/01) LDAP対応 199 srcType = HybsSystem.sys( "RESOURCE_USER_SRC_TYPE" ); 200 ldapClm = StringUtil.csv2Array( HybsSystem.sys( "RESOURCE_USER_LDAP_CLM" ) ); 201 ldapFilter = HybsSystem.sys( "RESOURCE_USER_LDAP_FILTER" ); 202 ldapRoleFilter = HybsSystem.sys( "RESOURCE_USER_ROLE_LDAP_FILTER" ); 203 204 searchScope = HybsSystem.sys( "LDAP_SEARCH_SCOPE" ); 205 initctx = HybsSystem.sys( "LDAP_INITIAL_CONTEXT_FACTORY" ); 206 providerURL = HybsSystem.sys( "LDAP_PROVIDER_URL" ); 207 entrydn = HybsSystem.sys( "LDAP_ENTRYDN" ); 208 password = HybsSystem.sys( "LDAP_PASSWORD" ); 209 searchbase = HybsSystem.sys( "LDAP_SEARCH_BASE" ); 210 } 211 } 212 213 /** 214 * DBからユーザーリソースの情報を取得します。 215 * 216 * @og.rev 5.2.0.0 (2010/09/01) 新規作成 217 * 218 * @param userId ユーザーID 219 * @param roles ロール 220 * @param appInfo DB接続情報 221 * 222 * @return ユーザーリソース情報 223 */ 224 private static String[][] getVals( final String userId, final String roles, final ApplicationInfo appInfo ) { 225 String[] args; 226 String[][] rtn; 227 228 if( roles == null || roles.isEmpty() ) { 229 args = new String[] { SYSTEM_ID,userId }; 230 synchronized( LOCK ) { 231 rtn = DBUtil.dbExecute( query,args,appInfo,dbid ); 232 } 233 } 234 // 4.0.0.0 (2007/10/31) 235 else { 236 args = new String[] { SYSTEM_ID,userId,roles }; 237 synchronized( LOCK ) { 238 rtn = DBUtil.dbExecute( queryRole,args,appInfo,dbid ); 239 } 240 } 241 242 return rtn; 243 } 244 245 /** 246 * LDAPからユーザーリソースの情報を取得します。 247 * 248 * @og.rev 5.2.0.0 (2010/09/01) 新規作成 249 * @og.rev 6.4.7.0 (2016/06/03) IllegalArgumentException が発生した場合に、見えるようにする。 250 * 251 * @param userId ユーザーID 252 * @param roles ロール 253 * 254 * @return ユーザーリソース情報 255 */ 256 private static String[][] getValsByLdap( final String userId, final String roles ) { 257 final LDAPSearch serch = new LDAPSearch(); 258 serch.setSearchScope( searchScope ) ; 259 serch.setInitctx( initctx ) ; 260 serch.setProviderURL( providerURL ) ; 261 serch.setSearchbase( searchbase ) ; 262 if( entrydn != null ) { serch.setEntrydn( entrydn ) ; } 263 if( password != null ) { serch.setPassword( password ) ; } 264 serch.setAttributes( ldapClm ) ; 265 serch.init(); 266 267 // 6.4.2.1 (2016/02/05) PMD refactoring. Useless parentheses. 268 String filter = roles == null || roles.isEmpty() ? ldapFilter : ldapRoleFilter; 269 final String[] args = roles == null || roles.isEmpty() ? new String[] { SYSTEM_ID,userId } : new String[] { SYSTEM_ID,userId,roles }; 270 271 // 6.4.7.0 (2016/06/03) IllegalArgumentException が発生した場合に、見えるようにする。 272 try { 273 filter = MessageFormat.format( filter,(Object[])args ); 274 } 275 catch( final IllegalArgumentException ex ) { 276 final String errMsg = "MessageFormatエラー:" 277 + " Pattern [" + filter + "]" 278 + " Arguments [" + Arrays.toString( (Object[])args ) + "]" ; 279 throw new HybsSystemException( errMsg,ex ); 280 } 281 282 final List<String[]> list = serch.search( filter ); 283 284 String[][] rtn = null; 285 if( !list.isEmpty() ) { // 6.1.1.0 (2015/01/17) refactoring 286 rtn = new String[1][]; 287 rtn[0] = list.get( 0 ); 288 rtn[0][1] = StringUtil.nval( rtn[0][1], "ja" ); // 言語のデフォルト値は、'ja' 289 rtn[0][2] = StringUtil.nval( rtn[0][2], rtn[0][0] ); // 名称のデフォルト値は、ユーザーID 290 rtn[0][3] = StringUtil.nval( rtn[0][3], ldapClm[3] ); // ロールズの初期値は、ロールに設定された項目名 291 rtn[0][4] = StringUtil.nval( rtn[0][4], "" ); 292 } 293 294 return rtn; 295 } 296}