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