/*
* � Copyright IBM Corp. 2010, 2014
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.ibm.xsp.extlib.relational.debug;
import java.lang.reflect.Method;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.ibm.commons.util.QuickSort;
import com.ibm.xsp.extlib.relational.RelationalLogger;
import com.ibm.xsp.extlib.util.debug.BasicDumpFactory;
import com.ibm.xsp.extlib.util.debug.DumpAccessor;
import com.ibm.xsp.extlib.util.debug.DumpAccessorFactory;
import com.ibm.xsp.extlib.util.debug.DumpContext;
/**
* Default Java Factory.
*/
public class JdbcDumpFactory implements DumpAccessorFactory {
public JdbcDumpFactory() {
}
public DumpAccessor find(DumpContext dumpContext, Object o) {
if(o instanceof DatabaseMetaData) {
return new DatabaseMetaDataMap(dumpContext,(DatabaseMetaData)o);
}
if(o instanceof ResultSet) {
return new ResultSetGrid(dumpContext,(ResultSet)o);
}
if(o instanceof ResultSetMetaData) {
return new ResultSetMetaDataGrid(dumpContext,(ResultSetMetaData)o);
}
return null;
}
public static class DatabaseMetaDataMap extends BasicDumpFactory.PropertyMap {
public DatabaseMetaDataMap(DumpContext dumpContext, DatabaseMetaData d) {
super(dumpContext,"Database Meta Data"); // $NON-NLS-1$
try {
addCategory("Database & Driver"); // $NLS-JdbcDumpFactory.DatabaseDriver-1$
addValue("getDatabaseProductName()", d.getDatabaseProductName()); // $NON-NLS-1$
addValue("getDatabaseProductVersion()", d.getDatabaseProductVersion()); // $NON-NLS-1$
addValue("getDriverName()", d.getDriverName()); // $NON-NLS-1$
addValue("getDriverVersion()", d.getDriverVersion()); // $NON-NLS-1$
addCategory("All Properties"); // $NLS-JdbcDumpFactory.AllProperties-1$
// Read all the methods from this class that don't take a parameter and return a simple type
// then add them as a property
Method[] allMethods = d.getClass().getMethods();
(new QuickSort.ObjectArray(allMethods) {
@Override
public int compare(Object o1, Object o2) {
Method m1 = (Method)o1;
Method m2 = (Method)o2;
return m1.getName().compareTo(m2.getName());
}
}).sort();
for(int i=0; i<allMethods.length; i++) {
Method m = allMethods[i];
if(m.getParameterTypes().length!=0) {
continue;
}
Class<?> ret = m.getReturnType();
if(ret==String.class || ret==Boolean.TYPE || ret==Integer.TYPE || ret==Long.TYPE) {
String name = m.getName();
if(name.equals("getClass") || name.equals("hashCode") || name.equals("toString")) { // $NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$
continue;
}
Object value = m.invoke(d);
addValue(m.getName(), value);
}
}
} catch(Exception ex) {
if(RelationalLogger.RELATIONAL.isErrorEnabled()) {
RelationalLogger.RELATIONAL.errorp(this, "DatabaseMetaDataMap", ex, "Exception during creation of DatabaseMetaDataMap"); // $NON-NLS-1$ $NLE-JdbcDumpFactory.ExceptionduringcreationofDatabase-2$
}
addValue("Exception", ex.getMessage()); // $NON-NLS-1$
}
}
}
public static class ResultSetGrid extends DumpAccessor.Grid {
ResultSet rs;
int ncol;
public ResultSetGrid(DumpContext dumpContext, ResultSet rs) {
super(dumpContext);
try {
this.rs = rs;
ResultSetMetaData meta = rs.getMetaData();
ncol = meta.getColumnCount();
} catch(SQLException ex) {
if(RelationalLogger.RELATIONAL.isErrorEnabled()) {
RelationalLogger.RELATIONAL.errorp(this, "ResultSetGrid", ex, "SQLException during creation of ResultSetGrid"); // $NON-NLS-1$ $NLE-JdbcDumpFactory.SQLExceptionduringcreationofResul-2$
}
}
}
@Override
public String[] getColumns() {
try {
ResultSetMetaData meta = rs.getMetaData();
ArrayList<String> cols = new ArrayList<String>();
ncol = meta.getColumnCount();
for(int i=0; i<ncol; i++) {
cols.add(meta.getColumnLabel(i+1));
}
return cols.toArray(new String[cols.size()]);
} catch(SQLException ex) {
if(RelationalLogger.RELATIONAL.isErrorEnabled()) {
RelationalLogger.RELATIONAL.errorp(this, "ResultSetGrid.getColumns", ex, "SQLException caused when retrieving columns"); // $NON-NLS-1$ $NLE-JdbcDumpFactory.SQLExceptioncausedwhenretrievingc-2$
}
}
return null;
}
@Override
public Object getValue(Object object, int col) {
return ((String[])object)[col];
}
@Override
public Iterator<Object> objectIterator(int first, final int count) {
try {
if(count<0) {
return null;
}
if(first>0) {
if(!rs.relative(first)) {
return null;
}
}
Iterator<Object> it = new Iterator<Object>() {
String[] values;
int n;
public boolean hasNext() {
return values!=null;
}
public Object next() {
String[] result = values;
values = null;
if(n<count) {
try {
if(rs.next()) {
n++;
values = new String[ncol];
for(int i=0; i<ncol; i++) {
try {
values[i] = rs.getString(i+1);
} catch(SQLException ex) {
if(RelationalLogger.RELATIONAL.isErrorEnabled()) {
RelationalLogger.RELATIONAL.errorp(this, "ResultSetGrid.objectIterator.next", ex, "SQLException caused when retrieving values "); // $NON-NLS-1$ $NLE-JdbcDumpFactory.SQLExceptioncausedwhenretrievingv-2$
}
return ex.toString();
}
}
}
} catch(SQLException ex) {
if(RelationalLogger.RELATIONAL.isErrorEnabled()) {
RelationalLogger.RELATIONAL.errorp(this, "ResultSetGrid.objectIterator.next", ex, "SQLException retrieving next Object from Iterator"); // $NON-NLS-1$ $NLE-JdbcDumpFactory.SQLExceptionretrievingnextObjectf-2$
}
return ex.toString();
}
}
return result;
}
public void remove() {
}
};
it.next();
return it;
} catch(SQLException ex) {
if(RelationalLogger.RELATIONAL.isErrorEnabled()) {
RelationalLogger.RELATIONAL.errorp(this, "ResultSetGrid.objectIterator", ex, "SQLException creating Iterator"); // $NON-NLS-1$ $NLE-JdbcDumpFactory.SQLExceptioncreatingIterator-2$
}
}
return null;
}
@Override
public String getTypeAsString() {
return "ResultSet"; // $NON-NLS-1$
}
}
public static class ResultSetMetaDataGrid extends DumpAccessor.Grid {
ResultSetMetaData meta;
List<Method> columnList;
public ResultSetMetaDataGrid(DumpContext dumpContext, ResultSetMetaData meta) {
super(dumpContext);
this.meta = meta;
Method[] allMethods = meta.getClass().getMethods();
(new QuickSort.ObjectArray(allMethods) {
@Override
public int compare(Object o1, Object o2) {
String m1 = getName((Method)o1);
String m2 = getName((Method)o2);
return m1.compareTo(m2);
}
private String getName(Method m) {
String name = m.getName();
// Remove the get/is getter prefix
if(name.startsWith("get")) { // $NON-NLS-1$
name = name.substring(3);
} else if(name.startsWith("is")) { // $NON-NLS-1$
name = name.substring(2);
}
// Force some columns to be the first ones, the rest will be in alpahbetic order
if(name.equals("SchemaName")) { // $NON-NLS-1$
return "!001";
}
if(name.equals("TableName")) { // $NON-NLS-1$
return "!002";
}
if(name.equals("ColumnName")) { // $NON-NLS-1$
return "!003";
}
if(name.equals("ColumnTypeName")) { // $NON-NLS-1$
return "!004";
}
if(name.equals("Precision")) { // $NON-NLS-1$
return "!005";
}
if(name.equals("Scale")) { // $NON-NLS-1$
return "!006";
}
if(name.equals("ColumnType")) { // $NON-NLS-1$
return "!007";
}
if(name.equals("ColumnClassName")) { // $NON-NLS-1$
return "!008";
}
return name;
}
}).sort();
columnList = new ArrayList<Method>(allMethods.length);
for(int i=0; i<allMethods.length; i++) {
Method m = allMethods[i];
if(m.getParameterTypes().length!=1 || m.getParameterTypes()[0]!=Integer.TYPE) {
continue;
}
columnList.add(m);
}
}
@Override
public String[] getColumns() {
String[] allCols = new String[columnList.size()];
for(int i=0; i<columnList.size(); i++) {
String col = columnList.get(i).getName();
if(col.startsWith("get")) { // $NON-NLS-1$
col = col.substring(3);
} else if(col.startsWith("is")) { // $NON-NLS-1$
col = col.substring(2);
}
allCols[i] = col;
}
return allCols;
}
@Override
public Object getValue(Object object, int col) {
try {
Method m = columnList.get(col);
return m.invoke(meta, (Integer)object);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public Iterator<Object> objectIterator(final int first, final int count) {
int colCount = 0;
try {
colCount = Math.min(first+count, meta.getColumnCount());
} catch (SQLException ex) {
if(RelationalLogger.RELATIONAL.isErrorEnabled()) {
RelationalLogger.RELATIONAL.errorp(this, "ResultSetMetaDataGrid.objectIterator", ex, "SQLException when calculating column count"); // $NON-NLS-1$ $NLE-JdbcDumpFactory.SQLExceptionwhencalculatingcolumn-2$
}
}
final int max = Math.min(first+count, colCount);
Iterator<Object> it = new Iterator<Object>() {
int n = first;
public boolean hasNext() {
return n<max;
}
public Object next() {
return (n++)+1; // Add one because of JDBC indexes
}
public void remove() {
}
};
return it;
}
@Override
public String getTypeAsString() {
return "ResultSetMetaData"; // $NON-NLS-1$
}
}
}