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 }