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.fukurou.util; 017 018import java.sql.Connection; 019import java.sql.CallableStatement; 020import java.sql.SQLException; 021 022/** 023 * <P>ApplicationInfo.java は、共通的に使用される 内部情報を格納するオブジェクトです。</P> 024 * 025 * 内部情報とは、接続ユーザーのクライアント情報と、実行状況のアプリケーション情報があります。 026 * 027 * クライアント情報とは、"i=192.168.51.81,h=null,u=C12345" 的な文字列で、 028 * i=の後ろに IPアドレス、h=の後ろにホスト名、u=の後ろにユーザー名をセットして、 029 * DBMS_APPLICATION_INFO.SET_CLIENT_INFO( "i=192.168.51.81,h=null,u=C12345" ) を 030 * CALL します。 031 * 032 * アプリケーション情報とは、"o=SELECT,p=GEXXXX" 的な文字列で、o=の後ろに 操作、 033 * p=の後ろにプログラムIDをセットして、 034 * DBMS_APPLICATION_INFO.SET_MODULE( "GE0010","o=操作,p=プログラムID" ) を 035 * CALL します。 036 * 037 * このPL/SQL を使用するコネクションについて実行すると、アクセスログ記録を行う為の 038 * 情報として取り出すことが可能になります。 039 * 確認は、V$SESSION の MODULE , ACTION , CLIENT_INFO で行います。 040 * 041 * このクラスは、同期化されていません。 042 * 043 * @og.rev 3.8.7.0 (2006/12/15) 新規追加 044 * 045 * @version 0.9.0 2000/10/12 046 * @author Kazuhiko Hasegawa 047 * @since JDK1.1, 048 */ 049public final class ApplicationInfo { 050 /** SET_CLIENT_INFO( "i=192.168.51.81,h=null,u=C12345" ) */ 051 public static final String CLIENT_INFO = "{ call DBMS_APPLICATION_INFO.SET_CLIENT_INFO( ? ) }" ; 052 /** SET_MODULE( "GE0010","o=操作,p=プログラムID" ) */ 053 public static final String MODULE = "{ call DBMS_APPLICATION_INFO.SET_MODULE( ?,? ) }" ; 054 055 private String gamenId = null; 056 private String clientInfo = ""; 057 private String moduleInfo = ""; 058 059 /** 060 * ユーザーID,IPアドレス,ホスト名 を指定して、クライアント情報を設定します。 061 * 062 * クライアント情報とは、"i=192.168.51.81,h=null,u=C12345" 的な文字列で、 063 * i=の後ろに IPアドレス、h=の後ろにホスト名、u=の後ろにユーザー名をセット 064 * しています。 065 * 066 * @param userId ユーザーID 067 * @param ipAdrs IPアドレス 068 * @param host ホスト名 069 */ 070 public void setClientInfo( final String userId,final String ipAdrs,final String host ) { 071 StringBuilder buf = new StringBuilder(); 072 append( "i=" , ipAdrs , buf ); 073 append( "h=" , host , buf ); 074 append( "u=" , userId , buf ); 075 076 clientInfo = buf.toString() ; 077 } 078 079 /** 080 * 画面ID,操作,プログラムIDを指定して、アプリケーションに関する情報を設定します。 081 * 082 * クライアント情報とは、"o=SELECT,p=GEXXXX" 的な文字列で、 083 * o=の後ろに 操作、p=の後ろにプログラムIDをセットしています。 084 * 085 * @param gamenId 画面ID 086 * @param ope オペレーション(操作) 087 * @param prgId プログラムID 088 */ 089 public void setModuleInfo( final String gamenId,final String ope,final String prgId ) { 090 this.gamenId = gamenId ; 091 092 StringBuilder buf = new StringBuilder(); 093 append( "o=" , ope , buf ); 094 append( "p=" , prgId , buf ); 095 096 moduleInfo = buf.toString() ; 097 } 098 099 /** 100 * setModuleInfo で最後に設定された 画面IDを返します。 101 * 102 * なにも設定されていない初期状態は、null です。 103 * 104 * @return 画面ID 105 * @see #setModuleInfo( String,String,String ) 106 */ 107 public String getGamenId() { 108 return gamenId ; 109 } 110 111 /** 112 * key と val を連結した文字列を作成します。 113 * 引数の val が null の場合は、何も操作しません。 114 * buf にすでになにかが登録済みの場合は、"," を追加してから、連結します。 115 * 116 * @param key キー 117 * @param val 値 118 * @param buf 連結するStringBuilderオブジェクト 119 */ 120 private void append( final String key,final String val,final StringBuilder buf ) { 121 if( val != null ) { 122 if( buf.length() == 0 ) { buf.append( key ).append( val ); } 123 else { buf.append( ',' ).append( key ).append( val ); } 124 } 125 } 126 127 /** 128 * アクセスログ記録を行う為の DBMS_APPLICATION_INFO.SET_CLIENT_INFO と、 129 * DBMS_APPLICATION_INFO.SET_MODULE を CALL します。 130 * 131 * SET_CLIENT_INFO( "i=192.168.51.81,h=null,u=C12345" ) では、 132 * クライアント情報として、"i=192.168.51.81,h=null,u=C12345" 的な文字列で、 133 * i=の後ろに IPアドレス、h=の後ろにホスト名、u=の後ろにユーザー名をセットしています。 134 * 135 * SET_MODULE( "GE0010","o=操作,p=プログラムID" )では、 136 * アプリケーションに関する情報として、"o=操作,p=プログラムID" をセットしています。 137 * 確認は、V$SESSION の MODULE , ACTION , CLIENT_INFO で行います。 138 * 139 * @param conn 接続先(コネクション) 140 */ 141 public void callAppInfo( final Connection conn ) { 142 CallableStatement callStmt ; 143 try { 144 callStmt = conn.prepareCall( CLIENT_INFO ); 145 callStmt.setString( 1,clientInfo ); 146 callStmt.executeUpdate(); 147 callStmt.close(); 148 149 callStmt = conn.prepareCall( MODULE ); 150 callStmt.setString( 1,gamenId ); 151 callStmt.setString( 2,moduleInfo ); 152 callStmt.executeUpdate(); 153 callStmt.close(); 154 } 155 catch (SQLException ex) { 156 String errMsg = "履歴収集処理を実行できませんでした。" 157 + ex.getMessage() + ":" + ex.getSQLState() ; 158 throw new RuntimeException( errMsg,ex ); 159 } 160 } 161 162 /** 163 * この接続が、PreparedStatement#getParameterMetaData() を使用するかどうかを判定します。 164 * 165 * PreparedStatement に対して、String化された 数字などを setObject( int,String ) するとき、 166 * ORACLE と SQLServer は、そのまま設定すれば、自動的に変換されます。 167 * postgreSQL では、ParameterMetaData#getParameterType(int) で、カラムタイプを取得し、 168 * setObject( int,String,int ) する必要があります。 169 * その判定に、このメソッドを使用します。 170 * この結果は、あくまで、各種データベース毎の実地調査の結果を元に、判定結果を 171 * 返すようにしています。 172 * ORACLE の場合は、使用しない(false)が返るように設定しています。 173 * SQLServer では、ORACLEと同様に、false を返します。 174 * 175 * @og.rev 4.0.0.0 (2007/09/25) 新規追加 176 * @og.rev 5.1.1.0 (2009/12/01) MySQL/PostgreSQL 対応 177 * @og.rev 5.3.8.0 (2011/08/01) 廃止( ConnectionFactory#useParameterMetaData(String) に移動 ) 178 * 179 * @param conn 接続先(コネクション) 180 * 181 * @return 使用する場合:true / その他:false 182 */ 183// public static boolean useParameterMetaData( final Connection conn ) { 184//// return false; 185// 186// try { 187// DatabaseMetaData meta = conn.getMetaData(); 188// String dbProductName = meta.getDatabaseProductName(); 189// 190// // if( "ORACLE".equalsIgnoreCase( dbProductName ) ) { return false; } 191// // if( "Microsoft SQL Server".equalsIgnoreCase( dbProductName ) ) { return false; } 192// 193// if( "PostgreSQL".equalsIgnoreCase( dbProductName ) ) { return true; } 194// 195// return false ; 196// } 197// catch (SQLException ex) { 198// String errMsg = "DatabaseMetaData から、getDatabaseProductName を取得できませんでした。" 199// + ex.getMessage() + ":" + ex.getSQLState() ; 200// throw new RuntimeException( errMsg,ex ); 201// } 202// } 203}