WebSphereからMySQL,Db2,Oracle,SQLServerへDataSource接続（プロパティ確認その２）

[前回](https://qiita.com/ch7821/items/c81bd7d8503cceb4a8a2)はWASからMySQL Connector/Jを使ってDataSourceを作成してみたところ、カスタムプロパティが云々というお話で、ドライバからConnectionPoolDataSource実装クラスのクラス情報を取得するコードを書いたというお話でした。そいつを少々いじって、サーバ上のDataSourceオブジェクトがどんなプロパティを持っているのか、ほぼ初期設定で試してみます。

# 改造版ユーティリティクラス
適当にPropertyDescriptorでフィールド情報を取得すると、順番がわかりづらいので、一旦`LinkedHashMap`に放り込んでフィールド名をキーにしてソートしてもらうようにしました。その関係で、`BeanProp`という値を保持するだけのクラスを作っています。`LinkedHashMap<String, BeanProp>`にしておいて、拡張for文でまわせばいい具合にソートしてくれるでしょうと。

```java:ClassInfo.java
package net.mognet.servlet;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;

class BeanProp {
	private String pre, post;
	private String name;
	private String type;
	private String value;
	private String getter;
	private String setter;
	private String delimiter;

	public BeanProp(String name, String type, String value, String getter, String setter, String pre, String post,
			String delimiter) {
		this.name = name;
		this.type = type;
		this.value = value;
		this.getter = getter;
		this.setter = setter;
		this.pre = pre;
		this.post = post;
		this.delimiter = delimiter;
	}

	@Override
	public String toString() {
		return pre + name + delimiter + type + delimiter + value + delimiter + getter + delimiter + setter + post;
	}

	public String getName() {
		return name;
	}

	public String getType() {
		return type;
	}

	public String getValue() {
		return value;
	}

	public String getGetter() {
		return getter;
	}

	public String getSetter() {
		return setter;
	}
}

class ClassInfoUtil {
	public static LinkedHashMap<String, BeanProp> getBeanProps(Object obj, String pre, String post, String delimiter) {
		LinkedHashMap<String, BeanProp> hash = new LinkedHashMap<String, BeanProp>();
		BeanInfo bi = null;
		PropertyDescriptor[] pd = null;
		try {
			bi = Introspector.getBeanInfo(obj.getClass());
			pd = bi.getPropertyDescriptors();
			for (int i = 0; i < pd.length; i++) {
				String name = pd[i].getName();
				String type = pd[i].getPropertyType().getName();
				String value = (String) pd[i].getValue(name);
				Method m = pd[i].getReadMethod();
				String getter = null;
				if (m != null)
					getter = m.getName();
				String setter = null;
				m = pd[i].getWriteMethod();
				if (m != null)
					setter = m.getName();

				BeanProp bp = new BeanProp(name, type, value, getter, setter, pre, post, delimiter);
				hash.put(name, bp);
			}
		} catch (IntrospectionException e) {
			e.printStackTrace();
			return null;
		}
		return hash;
	}
}

public class ClassInfo {
	public static String exposeAsMarkdown(Object obj) {
		StringBuilder sb = new StringBuilder();
		LinkedHashMap<String, BeanProp> hash = ClassInfoUtil.getBeanProps(obj, "|", "|", "|");

		//expose as markdown
		sb.append("|name|type|value|getter|setter|\n");
		sb.append("|:--|:--|:--|:--|:--|\n");
		for (String key : hash.keySet()) {
			BeanProp bp = hash.get(key);
			sb.append(bp.toString()+ "\n");
		}
		return sb.toString();
	}
}
```

前回はコンソール実行前提で作成しているので、`main()`部分をサーブレットにします。初めてのサーブレット作成です。Eclipseに感謝です。

```java:ExposeJDBC.java
package net.mognet.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.HashMap;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;


class JDBCType {
	private String className, jndiName;
	public JDBCType(String className, String jndiName) {
		this.className = className;
		this.jndiName = jndiName;
	}
	public String getClassName() {
		return this.className;
	}
	public String getJndiName() {
		return this.jndiName;
	}
}

@WebServlet({ "/JDBCProperty", "/*" })
public class JDBCProperty extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public JDBCProperty() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		HashMap<String, JDBCType> map = new HashMap<String, JDBCType>();
		map.put("MySQL", new JDBCType("com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource", "jdbc/mysqlmaster"));
		map.put("Db2", new JDBCType("com.ibm.db2.jcc.DB2ConnectionPoolDataSource", "jdbc/db2"));
		map.put("Oracle", new JDBCType("oracle.jdbc.pool.OracleConnectionPoolDataSource", "jdbc/oracle"));
		map.put("SQLServer", new JDBCType("com.microsoft.sqlserver.jdbc.SQLServerConnectionPoolDataSource", "jdbc/sqlserver"));
		PrintWriter out = response.getWriter();
		response.setContentType("text/html; charset=UTF-8");
		out.println("<html><head><title>jdbc property</title></head><body>");
		
		try {
			Context ctx = new InitialContext();
			for(String key : map.keySet()) {
				DataSource ds = (DataSource) ctx.lookup(map.get(key).getJndiName());
				String title = key + "(" + ds.getClass().getName() + ")";
				out.println("<h1>" + title + "</h1>");
				String prop = ClassInfo.exposeAsMarkdown(ds);
				out.println("<pre>");
				out.println("# " + title);
				out.println(prop);
				out.println("</pre>");
				
				java.sql.Connection cn = ds.getConnection();
				title = key + "(" + cn.getClass().getName() + ")";
				out.println("<h1>" + title + "</h1>");
				prop = ClassInfo.exposeAsMarkdown(cn);
				out.println("<pre>");
				out.println("# " + title);
				out.println(prop);
				out.println("</pre>");
			}
		} catch (NamingException | SQLException e) {
			out.println("<p>" + e.getMessage() + "</p>");
		}
		
		out.println("</body></html>");

	}

}
```

# 結果
結果は以下付録のようになりました。クラスがそもそもWASのものですね。他のJavaEEの実装でも試してみたいところです。
WASから`lookup()`して取得した`DataSource`も、そこから`getConnection()`した`Connection`も、みんな同じWAS実装のクラスなんですね。よく見るとDb2だけちょっとだけ独自のフィールドがあったりしますが。さらによくよく見てみれば、`Connection`オブジェクトには`Properties`型の`clientinfo`と`clientoinformation`があります。あと、値取れてません（全部`null`だけどそんなはずない）。次回はこの辺りを掘っていきます。`Reflection`で`invoke`すればいいのかしら。。。Java初心者にはそこそこ高いハードルな気がしますが、Eclipseの力を借りてやってみます。

# 付録

## Db2(com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource)
|name|type|value|getter|setter|
|:--|:--|:--|:--|:--|
|XADataSource|boolean|null|isXADataSource|null|
|active|boolean|null|isActive|null|
|class|java.lang.Class|null|getClass|null|
|connection|java.sql.Connection|null|getConnection|null|
|containerManagedConnection|java.sql.Connection|null|getContainerManagedConnection|null|
|dataStoreHelper|com.ibm.websphere.rsadapter.DataStoreHelper|null|getDataStoreHelper|null|
|heterogeneousPoolingConfigured|boolean|null|isHeterogeneousPoolingConfigured|null|
|internalDataStoreHelper|com.ibm.ws.rsadapter.spi.InternalDataStoreHelper|null|getInternalDataStoreHelper|null|
|logWriter|java.io.PrintWriter|null|getLogWriter|setLogWriter|
|loginTimeout|int|null|getLoginTimeout|setLoginTimeout|
|parentLogger|java.util.logging.Logger|null|getParentLogger|null|
|reference|javax.naming.Reference|null|getReference|setReference|

## Db2(com.ibm.ws.rsadapter.jdbc.WSJccSQLJPDQConnection)
|name|type|value|getter|setter|
|:--|:--|:--|:--|:--|
|CRI|javax.resource.spi.ConnectionRequestInfo|null|getCRI|null|
|DB2Object|java.lang.Object|null|getDB2Object|null|
|JNDIName|java.lang.String|null|getJNDIName|null|
|SQLJLogWriter|com.ibm.db2.jcc.SQLJLogWriter|null|getSQLJLogWriter|null|
|aborted|boolean|null|isAborted|setAborted|
|autoCommit|boolean|null|getAutoCommit|setAutoCommit|
|catalog|java.lang.String|null|getCatalog|setCatalog|
|class|java.lang.Class|null|getClass|null|
|clientInfo|java.util.Properties|null|getClientInfo|setClientInfo|
|clientInformation|java.util.Properties|null|getClientInformation|setClientInformation|
|closed|boolean|null|isClosed|null|
|connectionContext|sqlj.runtime.ref.DefaultContext|null|getConnectionContext|null|
|currentAutoCommit|boolean|null|null|setCurrentAutoCommit|
|currentTransactionIsolation|int|null|null|setCurrentTransactionIsolation|
|databaseName|java.lang.String|null|getDatabaseName|null|
|helper|com.ibm.websphere.rsadapter.DataStoreHelper|null|getHelper|null|
|holdability|int|null|getHoldability|setHoldability|
|internalDataStoreHelper|com.ibm.ws.rsadapter.spi.InternalDataStoreHelper|null|getInternalDataStoreHelper|null|
|isMonitoring|boolean|null|null|setIsMonitoring|
|j2EEName|com.ibm.websphere.csi.J2EEName|null|getJ2EEName|setJ2EEName|
|jccDriver|boolean|null|isJccDriver|null|
|metaData|java.sql.DatabaseMetaData|null|getMetaData|null|
|monitoring|boolean|null|isMonitoring|null|
|networkTimeout|int|null|getNetworkTimeout|null|
|readOnly|boolean|null|isReadOnly|setReadOnly|
|reserved|boolean|null|isReserved|null|
|schema|java.lang.String|null|getSchema|setSchema|
|shareable|boolean|null|isShareable|null|
|state|int|null|getState|null|
|stateString|java.lang.String|null|getStateString|null|
|systemMonitor|com.ibm.websphere.rsadapter.WSSystemMonitor|null|getSystemMonitor|null|
|tracer|com.ibm.ejs.ras.TraceComponent|null|getTracer|null|
|transactionIsolation|int|null|getTransactionIsolation|setTransactionIsolation|
|typeMap|java.util.Map|null|getTypeMap|setTypeMap|
|warnings|java.sql.SQLWarning|null|getWarnings|null|
|webSphereVersion|java.lang.String|null|getWebSphereVersion|null|

## MySQL(com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource)
|name|type|value|getter|setter|
|:--|:--|:--|:--|:--|
|XADataSource|boolean|null|isXADataSource|null|
|active|boolean|null|isActive|null|
|class|java.lang.Class|null|getClass|null|
|connection|java.sql.Connection|null|getConnection|null|
|containerManagedConnection|java.sql.Connection|null|getContainerManagedConnection|null|
|dataStoreHelper|com.ibm.websphere.rsadapter.DataStoreHelper|null|getDataStoreHelper|null|
|heterogeneousPoolingConfigured|boolean|null|isHeterogeneousPoolingConfigured|null|
|internalDataStoreHelper|com.ibm.ws.rsadapter.spi.InternalDataStoreHelper|null|getInternalDataStoreHelper|null|
|logWriter|java.io.PrintWriter|null|getLogWriter|setLogWriter|
|loginTimeout|int|null|getLoginTimeout|setLoginTimeout|
|parentLogger|java.util.logging.Logger|null|getParentLogger|null|
|reference|javax.naming.Reference|null|getReference|setReference|

## MySQL(com.ibm.ws.rsadapter.jdbc.WSJdbcConnection)
|name|type|value|getter|setter|
|:--|:--|:--|:--|:--|
|CRI|javax.resource.spi.ConnectionRequestInfo|null|getCRI|null|
|JNDIName|java.lang.String|null|getJNDIName|null|
|aborted|boolean|null|isAborted|setAborted|
|autoCommit|boolean|null|getAutoCommit|setAutoCommit|
|catalog|java.lang.String|null|getCatalog|setCatalog|
|class|java.lang.Class|null|getClass|null|
|clientInfo|java.util.Properties|null|getClientInfo|setClientInfo|
|clientInformation|java.util.Properties|null|getClientInformation|setClientInformation|
|closed|boolean|null|isClosed|null|
|helper|com.ibm.websphere.rsadapter.DataStoreHelper|null|getHelper|null|
|holdability|int|null|getHoldability|setHoldability|
|internalDataStoreHelper|com.ibm.ws.rsadapter.spi.InternalDataStoreHelper|null|getInternalDataStoreHelper|null|
|j2EEName|com.ibm.websphere.csi.J2EEName|null|getJ2EEName|setJ2EEName|
|metaData|java.sql.DatabaseMetaData|null|getMetaData|null|
|networkTimeout|int|null|getNetworkTimeout|null|
|readOnly|boolean|null|isReadOnly|setReadOnly|
|reserved|boolean|null|isReserved|null|
|schema|java.lang.String|null|getSchema|setSchema|
|shareable|boolean|null|isShareable|null|
|state|int|null|getState|null|
|stateString|java.lang.String|null|getStateString|null|
|systemMonitor|com.ibm.websphere.rsadapter.WSSystemMonitor|null|getSystemMonitor|null|
|transactionIsolation|int|null|getTransactionIsolation|setTransactionIsolation|
|typeMap|java.util.Map|null|getTypeMap|setTypeMap|
|warnings|java.sql.SQLWarning|null|getWarnings|null|

## Oracle(com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource)
|name|type|value|getter|setter|
|:--|:--|:--|:--|:--|
|XADataSource|boolean|null|isXADataSource|null|
|active|boolean|null|isActive|null|
|class|java.lang.Class|null|getClass|null|
|connection|java.sql.Connection|null|getConnection|null|
|containerManagedConnection|java.sql.Connection|null|getContainerManagedConnection|null|
|dataStoreHelper|com.ibm.websphere.rsadapter.DataStoreHelper|null|getDataStoreHelper|null|
|heterogeneousPoolingConfigured|boolean|null|isHeterogeneousPoolingConfigured|null|
|internalDataStoreHelper|com.ibm.ws.rsadapter.spi.InternalDataStoreHelper|null|getInternalDataStoreHelper|null|
|logWriter|java.io.PrintWriter|null|getLogWriter|setLogWriter|
|loginTimeout|int|null|getLoginTimeout|setLoginTimeout|
|parentLogger|java.util.logging.Logger|null|getParentLogger|null|
|reference|javax.naming.Reference|null|getReference|setReference|

## Oracle(com.ibm.ws.rsadapter.jdbc.WSJdbcConnection)
|name|type|value|getter|setter|
|:--|:--|:--|:--|:--|
|CRI|javax.resource.spi.ConnectionRequestInfo|null|getCRI|null|
|JNDIName|java.lang.String|null|getJNDIName|null|
|aborted|boolean|null|isAborted|setAborted|
|autoCommit|boolean|null|getAutoCommit|setAutoCommit|
|catalog|java.lang.String|null|getCatalog|setCatalog|
|class|java.lang.Class|null|getClass|null|
|clientInfo|java.util.Properties|null|getClientInfo|setClientInfo|
|clientInformation|java.util.Properties|null|getClientInformation|setClientInformation|
|closed|boolean|null|isClosed|null|
|helper|com.ibm.websphere.rsadapter.DataStoreHelper|null|getHelper|null|
|holdability|int|null|getHoldability|setHoldability|
|internalDataStoreHelper|com.ibm.ws.rsadapter.spi.InternalDataStoreHelper|null|getInternalDataStoreHelper|null|
|j2EEName|com.ibm.websphere.csi.J2EEName|null|getJ2EEName|setJ2EEName|
|metaData|java.sql.DatabaseMetaData|null|getMetaData|null|
|networkTimeout|int|null|getNetworkTimeout|null|
|readOnly|boolean|null|isReadOnly|setReadOnly|
|reserved|boolean|null|isReserved|null|
|schema|java.lang.String|null|getSchema|setSchema|
|shareable|boolean|null|isShareable|null|
|state|int|null|getState|null|
|stateString|java.lang.String|null|getStateString|null|
|systemMonitor|com.ibm.websphere.rsadapter.WSSystemMonitor|null|getSystemMonitor|null|
|transactionIsolation|int|null|getTransactionIsolation|setTransactionIsolation|
|typeMap|java.util.Map|null|getTypeMap|setTypeMap|
|warnings|java.sql.SQLWarning|null|getWarnings|null|

## SQLServer(com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource)
|name|type|value|getter|setter|
|:--|:--|:--|:--|:--|
|XADataSource|boolean|null|isXADataSource|null|
|active|boolean|null|isActive|null|
|class|java.lang.Class|null|getClass|null|
|connection|java.sql.Connection|null|getConnection|null|
|containerManagedConnection|java.sql.Connection|null|getContainerManagedConnection|null|
|dataStoreHelper|com.ibm.websphere.rsadapter.DataStoreHelper|null|getDataStoreHelper|null|
|heterogeneousPoolingConfigured|boolean|null|isHeterogeneousPoolingConfigured|null|
|internalDataStoreHelper|com.ibm.ws.rsadapter.spi.InternalDataStoreHelper|null|getInternalDataStoreHelper|null|
|logWriter|java.io.PrintWriter|null|getLogWriter|setLogWriter|
|loginTimeout|int|null|getLoginTimeout|setLoginTimeout|
|parentLogger|java.util.logging.Logger|null|getParentLogger|null|
|reference|javax.naming.Reference|null|getReference|setReference|

## SQLServer(com.ibm.ws.rsadapter.jdbc.WSJdbcConnection)
|name|type|value|getter|setter|
|:--|:--|:--|:--|:--|
|CRI|javax.resource.spi.ConnectionRequestInfo|null|getCRI|null|
|JNDIName|java.lang.String|null|getJNDIName|null|
|aborted|boolean|null|isAborted|setAborted|
|autoCommit|boolean|null|getAutoCommit|setAutoCommit|
|catalog|java.lang.String|null|getCatalog|setCatalog|
|class|java.lang.Class|null|getClass|null|
|clientInfo|java.util.Properties|null|getClientInfo|setClientInfo|
|clientInformation|java.util.Properties|null|getClientInformation|setClientInformation|
|closed|boolean|null|isClosed|null|
|helper|com.ibm.websphere.rsadapter.DataStoreHelper|null|getHelper|null|
|holdability|int|null|getHoldability|setHoldability|
|internalDataStoreHelper|com.ibm.ws.rsadapter.spi.InternalDataStoreHelper|null|getInternalDataStoreHelper|null|
|j2EEName|com.ibm.websphere.csi.J2EEName|null|getJ2EEName|setJ2EEName|
|metaData|java.sql.DatabaseMetaData|null|getMetaData|null|
|networkTimeout|int|null|getNetworkTimeout|null|
|readOnly|boolean|null|isReadOnly|setReadOnly|
|reserved|boolean|null|isReserved|null|
|schema|java.lang.String|null|getSchema|setSchema|
|shareable|boolean|null|isShareable|null|
|state|int|null|getState|null|
|stateString|java.lang.String|null|getStateString|null|
|systemMonitor|com.ibm.websphere.rsadapter.WSSystemMonitor|null|getSystemMonitor|null|
|transactionIsolation|int|null|getTransactionIsolation|setTransactionIsolation|
|typeMap|java.util.Map|null|getTypeMap|setTypeMap|
|warnings|java.sql.SQLWarning|null|getWarnings|null|