001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.geronimo.console.internaldb; 019 020 import org.apache.commons.logging.Log; 021 import org.apache.commons.logging.LogFactory; 022 023 import java.sql.Connection; 024 import java.sql.DatabaseMetaData; 025 import java.sql.ResultSet; 026 import java.sql.ResultSetMetaData; 027 import java.sql.SQLException; 028 import java.util.Hashtable; 029 import java.util.Map; 030 031 public class InternalDBHelper { 032 private final static Log log = LogFactory.getLog(InternalDBHelper.class); 033 034 private static final int RDBMS_DERBY = 1; 035 036 private static final int RDBMS_MSSQL = 2; 037 038 private static final String JNDI_DERBY = "java:comp/env/SystemDatasource"; 039 040 private static final Map derbyDBInfo = new Hashtable(); 041 042 /** 043 * Returns the database metadata as a map. 044 */ 045 public Map getDBInfo() { 046 derbyDBInfo.clear(); 047 Connection conn = null; 048 try { 049 conn = DerbyConnectionUtil.getSystemDBConnection(); 050 DatabaseMetaData dbMD = (DatabaseMetaData) conn.getMetaData(); 051 052 // DB 053 derbyDBInfo.put("URL", removeNull(dbMD.getURL())); 054 derbyDBInfo.put("Username", removeNull(dbMD.getUserName())); 055 derbyDBInfo.put("Read Only", removeNull(String.valueOf(dbMD 056 .isReadOnly()))); 057 derbyDBInfo.put("DB Product Name", removeNull(dbMD 058 .getDatabaseProductName())); 059 derbyDBInfo.put("DB Product Version", removeNull(dbMD 060 .getDatabaseProductVersion())); 061 derbyDBInfo.put("DB Major Version", removeNull(String.valueOf(dbMD 062 .getDatabaseMajorVersion()))); 063 derbyDBInfo.put("DB Minor Version", removeNull(String.valueOf(dbMD 064 .getDatabaseMinorVersion()))); 065 066 // Driver 067 derbyDBInfo.put("Driver Name", removeNull(dbMD.getDriverName())); 068 derbyDBInfo.put("Driver Version", removeNull(dbMD 069 .getDriverVersion())); 070 derbyDBInfo.put("Driver Major Version", removeNull(String 071 .valueOf(dbMD.getDriverMajorVersion()))); 072 derbyDBInfo.put("Driver Minor Version", removeNull(String 073 .valueOf(dbMD.getDriverMinorVersion()))); 074 075 // JDBC 076 derbyDBInfo.put("JDBC Major Version", removeNull(String 077 .valueOf(dbMD.getJDBCMajorVersion()))); 078 derbyDBInfo.put("JDBC Minor Version", removeNull(String 079 .valueOf(dbMD.getJDBCMinorVersion()))); 080 081 // Functions 082 derbyDBInfo.put("Numeric Functions", removeNull(dbMD 083 .getNumericFunctions())); 084 derbyDBInfo.put("String Functions", removeNull(dbMD 085 .getStringFunctions())); 086 derbyDBInfo.put("System Functions", removeNull(dbMD 087 .getSystemFunctions())); 088 derbyDBInfo.put("Time Date Functions", removeNull(dbMD 089 .getTimeDateFunctions())); 090 091 // Etc 092 derbyDBInfo.put("Supported SQL Keywords", removeNull(dbMD 093 .getSQLKeywords().replace(',', ' '))); 094 derbyDBInfo.put("Supported Types", removeNull(getColumnData(dbMD 095 .getTypeInfo(), "TYPE_NAME"))); 096 derbyDBInfo.put("Table Types", removeNull(getColumnData(dbMD 097 .getTableTypes(), "TABLE_TYPE"))); 098 derbyDBInfo.put("Schemas", removeNull(getColumnData(dbMD 099 .getSchemas(), "TABLE_SCHEM"))); 100 String tx = null; 101 102 switch (dbMD.getDefaultTransactionIsolation()) { 103 case Connection.TRANSACTION_NONE: 104 tx = "not supported"; 105 break; 106 case Connection.TRANSACTION_READ_COMMITTED: 107 tx = "dirty reads are prevented; non-repeatable reads and phantom reads can occur"; 108 break; 109 case Connection.TRANSACTION_READ_UNCOMMITTED: 110 tx = "dirty reads, non-repeatable reads and phantom reads can occur"; 111 break; 112 case Connection.TRANSACTION_REPEATABLE_READ: 113 tx = "dirty reads and non-repeatable reads are prevented; phantom reads can occur"; 114 break; 115 case Connection.TRANSACTION_SERIALIZABLE: 116 tx = "dirty reads, non-repeatable reads and phantom reads are prevented"; 117 break; 118 default: 119 tx = ""; 120 break; 121 } 122 123 derbyDBInfo.put("Default Transaction Isolation", removeNull(tx)); 124 String holdability = null; 125 126 switch (dbMD.getResultSetHoldability()) { 127 case ResultSet.HOLD_CURSORS_OVER_COMMIT: 128 holdability = "hold cursors over commit"; 129 break; 130 case ResultSet.CLOSE_CURSORS_AT_COMMIT: 131 holdability = "close cursors at commit"; 132 break; 133 default: 134 holdability = ""; 135 break; 136 } 137 derbyDBInfo.put("Result Set Holdability", removeNull(holdability)); 138 String sqlStateType = null; 139 140 switch (dbMD.getSQLStateType()) { 141 case DatabaseMetaData.sqlStateXOpen: 142 sqlStateType = "X/Open SQL CLI"; 143 break; 144 case DatabaseMetaData.sqlStateSQL99: 145 sqlStateType = "SQL99"; 146 break; 147 default: 148 sqlStateType = ""; 149 break; 150 } 151 derbyDBInfo.put("SQL State Type", removeNull(sqlStateType)); 152 } catch (SQLException e) { 153 printSQLError((SQLException) e); 154 } finally { 155 // close DB connection 156 try { 157 if (conn != null) { 158 conn.close(); 159 } 160 } catch (SQLException e) { 161 // problem closing DB connection 162 } 163 } 164 165 return derbyDBInfo; 166 } 167 168 private String removeNull(String s) { 169 return ((s == null) ? "" : s); 170 } 171 172 /** 173 * Get a specific column data as a string separated by ','. 174 */ 175 private String getColumnData(ResultSet rs, String colName) { 176 StringBuffer result = new StringBuffer(); 177 try { 178 ResultSetMetaData rsmd = rs.getMetaData(); 179 180 // 1) Get column number 181 int selectedCol = -1; 182 int numberOfColumns = rsmd.getColumnCount(); 183 for (int i = 1; i <= numberOfColumns; i++) { 184 String columnName = rsmd.getColumnName(i); 185 if (columnName.equals(colName)) { 186 selectedCol = i; 187 break; 188 } 189 } 190 191 // 2) Get data 192 boolean firstData = true; 193 while (rs.next()) { 194 for (int i = 1; i <= numberOfColumns; i++) { 195 if (i == selectedCol) { 196 if (firstData) { 197 firstData = false; 198 } else { 199 result.append(','); 200 } 201 String columnValue = rs.getString(i); 202 result.append(columnValue); 203 } 204 } 205 } 206 } catch (SQLException e) { 207 printSQLError((SQLException) e); 208 } 209 210 return result.toString(); 211 } 212 213 /** 214 * Print the SQL exception including chained exceptions 215 * if there is one. 216 * 217 * @param e 218 */ 219 private void printSQLError(SQLException e) { 220 while (e != null) { 221 log.error(e.toString(), e); 222 e = e.getNextException(); 223 } 224 } 225 226 }