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        /** コネクションにアプリケーション情報を追記するかどうか指定 */
090        public static final boolean USE_DB_APPLICATION_INFO  = HybsSystem.sysBool( "USE_DB_APPLICATION_INFO" ) ;
091
092        // 4.0.0 (2005/01/31) Cleanable インターフェースによる初期化処理
093        static {
094                Cleanable clr = new Cleanable() {
095                        public void clear() {
096                                UserInfoFactory.clear();
097                        }
098                };
099
100                SystemManager.addCleanable( clr );
101        }
102
103        private static final Object lock = new Object();
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[] args;
146//              String[][] vals;
147
148//              if( roles == null || roles.length() == 0 ) {
149//                      args = new String[] { SYSTEM_ID,userID };
150//                      synchronized( lock ) {
151//                              vals = DBUtil.dbExecute( query,args,appInfo,dbid );
152//                      }
153//              }
154//              // 4.0.0.0 (2007/10/31)
155//              else {
156//                      args = new String[] { SYSTEM_ID,userID,roles };
157//                      synchronized( lock ) {
158//                              vals = DBUtil.dbExecute( queryRole,args,appInfo,dbid );
159//                      }
160//              }
161
162                String[][] vals;
163                if( "LDAP".equalsIgnoreCase( srcType ) ) {
164                        vals = getValsByLdap( userID, roles );
165                }
166                else {
167                        vals = getVals( userID, roles, appInfo );
168                }
169
170                final UserInfo info ;
171                int len = vals.length ; // システムID ** を含む。
172                if( len >= 1 && vals[0].length >= 5 ) {
173                        // システムIDでソートされる。SYSTEM_ID="**"は最初に現れるので、最後を取得
174                        info = new UserInfo(
175                                                                userID          ,                       // userID
176                                                                vals[len-1][1]  ,               // lang
177                                                                vals[len-1][2]  ,               // jname
178                                                                vals[len-1][3]  ,               // roles
179                                                                vals[len-1][4]  ,               // droles // 4.4.0.0 (2009/08/02)
180                                                                SYSTEM_ID               ,               // systemId
181                                                                ipAddress               ,               // ipAddress
182                                                                appInfo                 ) ;             // ApplicationInfo
183                }
184                else {
185                        String errMsg = "UserInfo のデータ(USERID,LANG,NAME,ROLES,DROLES)が取得できません。"
186                                                + " Key [" + userID + "]"
187                                                + " SQL [" + query + "]" ;
188                        LogWriter.log( errMsg );
189                        throw new HybsSystemException( errMsg );
190                }
191
192                return info ;
193        }
194
195        /**
196         * UserInfoFactoryをクリアします。
197         *
198         * @og.rev 5.2.0.0 (2010/09/01) LDAP対応
199         *
200         */
201        public static void clear() {
202                synchronized( lock ) {
203                        dbid = StringUtil.nval(
204                                                                        HybsSystem.sys( "RESOURCE_USER_DBID" ) ,
205                                                                        HybsSystem.sys( "RESOURCE_DBID" )
206                                                                ) ;
207                        query = HybsSystem.sys( "RESOURCE_USER_SQL" );
208                        queryRole = HybsSystem.sys( "RESOURCE_USER_ROLE_SQL" );
209
210                        // 5.2.0.0 (2010/09/01) LDAP対応
211                        srcType                 = HybsSystem.sys( "RESOURCE_USER_SRC_TYPE" );
212                        ldapClm                 = StringUtil.csv2Array( HybsSystem.sys( "RESOURCE_USER_LDAP_CLM" ) );
213                        ldapFilter              = HybsSystem.sys( "RESOURCE_USER_LDAP_FILTER" );
214                        ldapRoleFilter  = HybsSystem.sys( "RESOURCE_USER_ROLE_LDAP_FILTER" );
215
216                        searchScope             = HybsSystem.sys( "LDAP_SEARCH_SCOPE" );
217                        initctx                 = HybsSystem.sys( "LDAP_INITIAL_CONTEXT_FACTORY" );
218                        providerURL     = HybsSystem.sys( "LDAP_PROVIDER_URL" );
219                        entrydn                 = HybsSystem.sys( "LDAP_ENTRYDN" );
220                        password                = HybsSystem.sys( "LDAP_PASSWORD" );
221                        searchbase              = HybsSystem.sys( "LDAP_SEARCH_BASE" );
222                }
223        }
224
225        /**
226         * DBからユーザーリソースの情報を取得します。
227         *
228         * @og.rev 5.2.0.0 (2010/09/01) 新規作成
229         *
230         * @param       userId  ユーザーID
231         * @param       roles   ロール
232         * @param       appInfo DB接続情報
233         *
234         * @return ユーザーリソース情報
235         */
236        private static String[][] getVals( final String userId, final String roles, final ApplicationInfo appInfo ) {
237                String[] args;
238                String[][] rtn = null;
239
240                if( roles == null || roles.length() == 0 ) {
241                        args = new String[] { SYSTEM_ID,userId };
242                        synchronized( lock ) {
243                                rtn = DBUtil.dbExecute( query,args,appInfo,dbid );
244                        }
245                }
246                // 4.0.0.0 (2007/10/31)
247                else {
248                        args = new String[] { SYSTEM_ID,userId,roles };
249                        synchronized( lock ) {
250                                rtn = DBUtil.dbExecute( queryRole,args,appInfo,dbid );
251                        }
252                }
253
254                return rtn;
255        }
256
257        /**
258         * LDAPからユーザーリソースの情報を取得します。
259         *
260         * @og.rev 5.2.0.0 (2010/09/01) 新規作成
261         *
262         * @param       userId  ユーザーID
263         * @param       roles   ロール
264         *
265         * @return ユーザーリソース情報
266         */
267        private static String[][] getValsByLdap( final String userId, final String roles ) {
268                LDAPSearch serch = new LDAPSearch();
269                serch.setSearchScope( searchScope ) ;
270                serch.setInitctx( initctx ) ;
271                serch.setProviderURL( providerURL ) ;
272                serch.setSearchbase( searchbase ) ;
273                if( entrydn != null  ) { serch.setEntrydn( entrydn ) ; }
274                if( password != null ) { serch.setPassword( password ) ; }
275                serch.setAttributes( ldapClm ) ;
276                serch.init();
277
278                String filter = ( roles == null || roles.length() == 0 ) ? ldapFilter : ldapRoleFilter;
279                String[] args = ( roles == null || roles.length() == 0 ) ? new String[] { SYSTEM_ID,userId } : new String[] { SYSTEM_ID,userId,roles };
280                filter = MessageFormat.format( filter,(Object[])args );
281
282                List<String[]> list = serch.search( filter );
283
284                String[][] rtn = null;
285                if( list.size() > 0 ) {
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}