src/org/objectweb/cjdbc/controller/backend/DatabaseBackendMetaData.java

説明を見る。
00001 00025 package org.objectweb.cjdbc.controller.backend; 00026 00027 import java.sql.Connection; 00028 import java.sql.DatabaseMetaData; 00029 import java.sql.ResultSet; 00030 import java.sql.SQLException; 00031 00032 import org.objectweb.cjdbc.common.i18n.Translate; 00033 import org.objectweb.cjdbc.common.log.Trace; 00034 import org.objectweb.cjdbc.common.sql.schema.DatabaseColumn; 00035 import org.objectweb.cjdbc.common.sql.schema.DatabaseProcedure; 00036 import org.objectweb.cjdbc.common.sql.schema.DatabaseProcedureParameter; 00037 import org.objectweb.cjdbc.common.sql.schema.DatabaseSchema; 00038 import org.objectweb.cjdbc.common.sql.schema.DatabaseTable; 00039 import org.objectweb.cjdbc.controller.connection.AbstractConnectionManager; 00040 00052 public class DatabaseBackendMetaData 00053 { 00055 private AbstractConnectionManager connectionManager; 00056 00058 private Trace logger; 00059 00061 private DatabaseSchema databaseSchema; 00062 00064 private int dynamicPrecision; 00065 00067 private boolean gatherSystemTables = false; 00068 00081 public DatabaseBackendMetaData(AbstractConnectionManager connectionManager, 00082 Trace logger, int dynamicPrecision, boolean gatherSystemTables) 00083 { 00084 this.connectionManager = connectionManager; 00085 this.dynamicPrecision = dynamicPrecision; 00086 this.logger = logger; 00087 this.gatherSystemTables = gatherSystemTables; 00088 } 00089 00096 private void createDatabaseSchemaDynamically() throws SQLException 00097 { 00098 if (dynamicPrecision == DatabaseBackendSchemaConstants.DynamicPrecisionStatic) 00099 return; 00100 Connection connection = null; 00101 boolean wasInitialized = connectionManager.isInitialized(); 00102 ResultSet rs = null; 00103 00104 try 00105 { 00106 if (!wasInitialized) 00107 connectionManager.initializeConnections(); 00108 00109 connection = connectionManager.getConnection(); 00110 if (connection == null) 00111 { 00112 String msg = Translate.get("backend.meta.connection.failed"); 00113 logger.error(msg); 00114 throw new SQLException(msg); 00115 } 00116 00117 // Get DatabaseMetaData 00118 DatabaseMetaData metaData = connection.getMetaData(); 00119 if (metaData == null) 00120 { 00121 logger.warn(Translate.get("backend.meta.received.null")); 00122 return; 00123 } 00124 00125 databaseSchema = new DatabaseSchema(); 00126 00127 // Check if we should get system tables or not 00128 String[] types; 00129 if (gatherSystemTables) 00130 types = new String[]{"TABLE", "VIEW", "SYSTEM TABLE", "SYSTEM VIEW"}; 00131 else 00132 types = new String[]{"TABLE", "VIEW"}; 00133 00134 // Get tables meta data 00135 // getTables() gets a description of tables matching the catalog, schema, 00136 // table name pattern and type. Sending in null for catalog and schema 00137 // drops them from the selection criteria. The table name pattern "%" 00138 // means match any substring of 0 or more characters. 00139 // Last argument allows to obtain only database tables 00140 try 00141 { 00142 rs = metaData.getTables(null, null, "%", types); 00143 } 00144 catch (Exception e) 00145 { 00146 // VIEWS cannot be retrieved with this backend 00147 logger.error(Translate.get("backend.meta.view.not.supported"), e); 00148 rs = metaData.getTables(null, null, "%", new String[]{"TABLE"}); 00149 } 00150 00151 if (rs == null) 00152 { 00153 logger.warn(Translate.get("backend.meta.received.null")); 00154 return; 00155 } 00156 00157 String tableName; 00158 DatabaseTable table = null; 00159 while (rs.next()) 00160 { 00161 // 1 is table catalog, 2 is table schema, 3 is table name, 4 is type 00162 tableName = rs.getString(3); 00163 if (logger.isDebugEnabled()) 00164 logger.debug(Translate.get("backend.meta.found.table", tableName)); 00165 00166 // Create a new table and add it to the database schema 00167 table = new DatabaseTable(tableName); 00168 databaseSchema.addTable(table); 00169 00170 if (dynamicPrecision >= DatabaseBackendSchemaConstants.DynamicPrecisionColumn) 00171 { 00172 // Get information about this table columns 00173 getColumns(metaData, table); 00174 // Get information about this table primary keys 00175 getPrimaryKeys(metaData, table); 00176 } 00177 } 00178 00179 // Get Procedures for this database 00180 if (dynamicPrecision >= DatabaseBackendSchemaConstants.DynamicPrecisionProcedures) 00181 getProcedures(metaData, databaseSchema); 00182 } 00183 catch (Exception e) 00184 { 00185 if (e instanceof RuntimeException) 00186 logger.error(Translate.get("backend.meta.runtime.error"), e); 00187 throw new SQLException(Translate.get("backend.meta.failed.get.info", e)); 00188 } 00189 finally 00190 { 00191 if (connection != null) 00192 connectionManager.releaseConnection(connection); 00193 00194 if (!wasInitialized) 00195 connectionManager.finalizeConnections(); 00196 00197 try 00198 { 00199 rs.close(); 00200 } 00201 catch (Exception ignore) 00202 { 00203 } 00204 } 00205 } 00206 00211 private void getProcedures(DatabaseMetaData metaData, DatabaseSchema schema) 00212 { 00213 if (logger.isDebugEnabled()) 00214 logger.debug(Translate.get("backend.meta.get.procedures")); 00215 ResultSet rs = null; 00216 ResultSet rs2 = null; 00217 try 00218 { 00219 // Get Procedures meta data 00220 rs = metaData.getProcedures(null, null, "%"); 00221 00222 if (rs == null) 00223 { 00224 logger.warn(Translate.get("backend.meta.get.procedures.failed", 00225 metaData.getConnection().getCatalog())); 00226 return; 00227 } 00228 00229 while (rs.next()) 00230 { 00231 // Each row is a procedure description 00232 // 3 = PROCEDURE_NAME 00233 // 7 = REMARKS 00234 // 8 = PROCEDURE_TYPE 00235 DatabaseProcedure procedure = new DatabaseProcedure(rs.getString(3), rs 00236 .getString(7), rs.getShort(8)); 00237 00238 if (schema.getProcedure(procedure.getName()) != null) 00239 { 00240 if (logger.isDebugEnabled()) 00241 logger.debug(Translate 00242 .get("backend.meta.procedure.already.in.schema", procedure 00243 .getName())); 00244 continue; 00245 } 00246 else 00247 { 00248 if (logger.isDebugEnabled()) 00249 logger.debug(Translate.get("backend.meta.found.procedure", 00250 procedure.getName())); 00251 } 00252 00253 // TODO: Current limitation is that we don't distinguish 2 procedures 00254 // with the same name but different signatures 00255 00256 if (dynamicPrecision < DatabaseBackendSchemaConstants.DynamicPrecisionProcedures) 00257 continue; 00258 // This is a new stored procedure, get the column information 00259 rs2 = metaData 00260 .getProcedureColumns(null, null, procedure.getName(), "%"); 00261 if (rs2 == null) 00262 logger.warn(Translate.get("backend.meta.get.procedure.params.failed", 00263 procedure.getName())); 00264 else 00265 { 00266 while (rs2.next()) 00267 { 00268 // Each row is a parameter description for the current procedure 00269 // 4 = COLUMN_NAME 00270 // 5 = COLUMN_TYPE 00271 // 6 = DATA_TYPE 00272 // 7 = TYPE_NAME 00273 // 8 = PRECISION 00274 // 9 = LENGTH 00275 // 10 = SCALE 00276 // 11 = RADIX 00277 // 12 = NULLABLE 00278 // 13 = REMARKS 00279 DatabaseProcedureParameter param = new DatabaseProcedureParameter( 00280 rs2.getString(4), rs2.getInt(5), rs2.getInt(6), rs2 00281 .getString(7), rs2.getFloat(8), rs2.getInt(9), rs2 00282 .getInt(10), rs2.getInt(11), rs2.getInt(12), rs2 00283 .getString(13)); 00284 // TO CHECK: 00285 // This cannot happen since we don't allow 2 procedures with the 00286 // same name. 00287 // It seems useless to test if a parameter already exist since it 00288 // should never happen. 00289 // We will need to reuse some pieces of this code when we will 00290 // implement support for 00291 // stored procedures of the same name with different signatures. 00292 // ArrayList parameters = procedure.getParameters(); 00293 // for (int i = 0; i < parameters.size(); i++) 00294 // { 00295 // String name = 00296 // ((DatabaseProcedureParameter) parameters.get(i)).getName(); 00297 // if (name.equals(param.getName())) 00298 // break; 00299 // } 00300 procedure.addParameter(param); 00301 } 00302 rs2.close(); 00303 } 00304 00305 schema.addProcedure(procedure); 00306 } 00307 } 00308 catch (Exception e) 00309 { 00310 logger.error(Translate.get("backend.meta.get.procedures.failed", e 00311 .getMessage())); 00312 } 00313 finally 00314 { 00315 try 00316 { 00317 rs.close(); 00318 } 00319 catch (Exception ignore) 00320 { 00321 } 00322 try 00323 { 00324 rs2.close(); 00325 } 00326 catch (Exception ignoreAsWell) 00327 { 00328 } 00329 } 00330 } 00331 00340 private void getColumns(DatabaseMetaData metaData, DatabaseTable table) 00341 throws SQLException 00342 { 00343 ResultSet rs = null; 00344 try 00345 { 00346 // Get columns meta data 00347 // getColumns() gets a description of columns matching the catalog, 00348 // schema, table name and column name pattern. Sending in null for 00349 // catalog and schema drops them from the selection criteria. The 00350 // column pattern "%" allows to obtain all columns. 00351 rs = metaData.getColumns(null, null, table.getName(), "%"); 00352 00353 if (rs == null) 00354 { 00355 logger.warn(Translate.get("backend.meta.get.columns.failed", table 00356 .getName())); 00357 return; 00358 } 00359 00360 DatabaseColumn column = null; 00361 int type; 00362 while (rs.next()) 00363 { 00364 // 1 is table catalog, 2 is table schema, 3 is table name, 00365 // 4 is column name, 5 is data type 00366 type = rs.getShort(5); 00367 column = new DatabaseColumn(rs.getString(4), false, type); 00368 table.addColumn(column); 00369 00370 if (logger.isDebugEnabled()) 00371 logger.debug(Translate.get("backend.meta.found.column", rs 00372 .getString(4))); 00373 } 00374 } 00375 catch (SQLException e) 00376 { 00377 throw new SQLException(Translate.get("backend.meta.get.columns.failed", 00378 table.getName())); 00379 } 00380 finally 00381 { 00382 try 00383 { 00384 rs.close(); 00385 } 00386 catch (Exception ignore) 00387 { 00388 } 00389 } 00390 } 00391 00400 private void getPrimaryKeys(DatabaseMetaData metaData, DatabaseTable table) 00401 throws SQLException 00402 { 00403 ResultSet rs = null; 00404 try 00405 { 00406 // Get primary keys meta data 00407 // getPrimaryKeys() gets a description of primary keys matching the 00408 // catalog, schema, and table name. Sending in null for catalog and 00409 // schema drop them from the selection criteria. 00410 00411 rs = metaData.getPrimaryKeys(null, null, table.getName()); 00412 00413 if (rs == null) 00414 { 00415 logger.warn(Translate.get("backend.meta.get.primary.keys.failed", table 00416 .getName())); 00417 return; 00418 } 00419 00420 String columnName = null; 00421 while (rs.next()) 00422 { 00423 00424 // 1 is table catalog, 2 is table schema, 3 is table name, 4 is column 00425 // name 00426 columnName = rs.getString(4); 00427 if (columnName == null) 00428 continue; 00429 if (logger.isDebugEnabled()) 00430 logger.debug(Translate.get("backend.meta.found.primary.key", 00431 columnName)); 00432 00433 // Set the column to unique 00434 table.getColumn(columnName).setIsUnique(true); 00435 } 00436 } 00437 catch (SQLException e) 00438 { 00439 throw new SQLException(Translate.get( 00440 "backend.meta.get.primary.keys.failed", table.getName())); 00441 } 00442 finally 00443 { 00444 try 00445 { 00446 rs.close(); 00447 } 00448 catch (Exception ignore) 00449 { 00450 } 00451 } 00452 } 00453 00466 public DatabaseSchema getDatabaseSchema() throws SQLException 00467 { 00468 if (databaseSchema == null) 00469 createDatabaseSchemaDynamically(); 00470 return databaseSchema; 00471 } 00472 }

CJDBCversion1.0.4に対してTue Oct 12 15:16:00 2004に生成されました。 doxygen 1.3.8