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    }