KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > exolab > jms > tools > db > SchemaBrowser


1 /**
2  * Redistribution and use of this software and associated documentation
3  * ("Software"), with or without modification, are permitted provided
4  * that the following conditions are met:
5  *
6  * 1. Redistributions of source code must retain copyright
7  * statements and notices. Redistributions must also contain a
8  * copy of this document.
9  *
10  * 2. Redistributions in binary form must reproduce the
11  * above copyright notice, this list of conditions and the
12  * following disclaimer in the documentation and/or other
13  * materials provided with the distribution.
14  *
15  * 3. The name "Exolab" must not be used to endorse or promote
16  * products derived from this Software without prior written
17  * permission of Exoffice Technologies. For written permission,
18  * please contact info@exolab.org.
19  *
20  * 4. Products derived from this Software may not be called "Exolab"
21  * nor may "Exolab" appear in their names without prior written
22  * permission of Exoffice Technologies. Exolab is a registered
23  * trademark of Exoffice Technologies.
24  *
25  * 5. Due credit should be given to the Exolab Project
26  * (http://www.exolab.org/).
27  *
28  * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29  * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30  * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32  * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39  * OF THE POSSIBILITY OF SUCH DAMAGE.
40  *
41  * Copyright 2002-2003 (C) Exoffice Technologies Inc. All Rights Reserved.
42  *
43  * $Id: SchemaBrowser.java,v 1.1 2004/11/26 01:51:15 tanderson Exp $
44  */

45
46 package org.exolab.jms.tools.db;
47
48 import java.sql.Connection JavaDoc;
49 import java.sql.DatabaseMetaData JavaDoc;
50 import java.sql.PreparedStatement JavaDoc;
51 import java.sql.ResultSet JavaDoc;
52 import java.sql.ResultSetMetaData JavaDoc;
53 import java.sql.SQLException JavaDoc;
54
55 import org.apache.commons.logging.Log;
56 import org.apache.commons.logging.LogFactory;
57
58 import org.exolab.jms.persistence.PersistenceException;
59 import org.exolab.jms.persistence.SQLHelper;
60
61
62 /**
63  * This class provides methods for examining a database schema
64  *
65  * @version $Revision: 1.1 $ $Date: 2004/11/26 01:51:15 $
66  * @author <a HREF="mailto:tima@intalio.com">Tim Anderson</a>
67  */

68 public class SchemaBrowser {
69
70     /**
71      * The connection to the database
72      */

73     private Connection JavaDoc _connection = null;
74
75     /**
76      * The set of data types supported by the RDBMS
77      */

78     private TypeSet _types = null;
79
80     /**
81      * The type mapper, used to convert between the type requested by
82      * the schema, and those supported by the RDBMS
83      */

84     private TypeMapper _mapper = null;
85
86     /**
87      * The logger
88      */

89     private static final Log _log = LogFactory.getLog(SchemaBrowser.class);
90
91
92     /**
93      * Construct a new <code>SchemaBrowser</code>
94      *
95      * @param connection the JDBC connection
96      * @throws PersistenceException if database meta-data can't be obtained
97      */

98     public SchemaBrowser(Connection JavaDoc connection) throws PersistenceException {
99         _connection = connection;
100
101         // get the types supported by the database
102
_types = new TypeSet(_connection);
103         _mapper = new TypeMapper(_types);
104     }
105
106     /**
107      * Returns the schema for the specified table
108      *
109      * @param name the table name
110      * @return the schema for the table identified by <code>name</code>
111      * @throws PersistenceException if the named table doesn't exist, or the
112      * schema cannot be obtained
113      */

114     public Table getTable(String JavaDoc name) throws PersistenceException {
115         Table result = new Table();
116
117         result.setName(name);
118
119         // determine the column types. Another approach would be to use
120
// DatabaseMetaData.getColumns() - except that not all JDBC drivers
121
// seem to support this (e.g, Sybase)
122
PreparedStatement JavaDoc select = null;
123         try {
124             select = _connection.prepareStatement(
125                 "select * from " + name + " where 1 = 0");
126             ResultSet JavaDoc set = select.executeQuery();
127             ResultSetMetaData JavaDoc metaData = set.getMetaData();
128
129             for (int i = 1; i <= metaData.getColumnCount(); ++i) {
130                 String JavaDoc columnName = metaData.getColumnName(i);
131                 int dataType = metaData.getColumnType(i);
132                 long precision = metaData.getPrecision(i);
133                 int nullable = metaData.isNullable(i);
134                 String JavaDoc typeName = metaData.getColumnTypeName(i);
135                 Type type = _mapper.getType(dataType, precision);
136                 if (type == null) {
137                     // this will only occur if the JDBC driver is buggy, as the
138
// database meta data is inconsistent with the column meta
139
// data
140
// Try and get the nearest precision equivalent
141
type = _types.getNearestType(dataType, precision);
142                     if (type == null) {
143                         // getColumns() refers to type not included in
144
// database meta data
145
throw new InvalidTypeException(
146                             "JDBC driver error. Type=" + dataType
147                             + ", precision=" + precision + "(SQL type="
148                             + typeName + ") isn't supported by "
149                             + "Connection.getMetaData().getTypeInfo(), but is "
150                             + "referred to by "
151                             + "Connection.getMetaData().getColumns()");
152                     }
153                 }
154
155                 Attribute attribute = new Attribute();
156                 attribute.setName(columnName);
157                 attribute.setType(type.getSymbolicType());
158                 if (nullable == DatabaseMetaData.columnNoNulls) {
159                     attribute.setNot_null(true);
160                 } else {
161                     attribute.setNot_null(false);
162                 }
163                 result.addAttribute(attribute);
164             }
165         } catch (SQLException JavaDoc exception) {
166             throw new PersistenceException(
167                 "Failed to determine the schema of table=" + name,
168                 exception);
169         } finally {
170             SQLHelper.close(select);
171         }
172         return result;
173     }
174
175     /**
176      * Returns the {@link Type} for an {@link Attribute}
177      *
178      * @param attribute the attribute
179      * @return the type
180      * @throws PersistenceException if {@link Attribute#getType} is invalid, or
181      * the RDBMS doesn't support the type
182      */

183     public Type getType(Attribute attribute) throws PersistenceException {
184         Type result = null;
185         Type type = Type.getType(attribute.getType());
186         Type map = _mapper.getType(type.getType(), type.getPrecision());
187         if (map == null) {
188             throw new PersistenceException(
189                 "Database does not support type=" + attribute.getType());
190         }
191
192         if (type.getType() != map.getType()) {
193             result = map;
194         } else {
195             boolean parameters = type.getParameters();
196             long precision = type.getPrecision();
197             if (precision <= map.getPrecision()) {
198                 if (precision == -1) {
199                     precision = map.getPrecision();
200                     parameters = map.getParameters();
201                 }
202                 result = new Type(map.getType(), map.getName(),
203                     precision, parameters);
204             } else {
205                 throw new PersistenceException(
206                     attribute.getName() + type + " exceeds precision for "
207                     + map + " precision=" + map.getPrecision());
208             }
209         }
210         return result;
211     }
212
213     /**
214      * Returns true if a table exists
215      *
216      * @param table the name of the table
217      */

218     public boolean getTableExists(String JavaDoc table) throws PersistenceException {
219         boolean result = false;
220
221         String JavaDoc name = table;
222         ResultSet JavaDoc set = null;
223         try {
224             DatabaseMetaData JavaDoc metaData = _connection.getMetaData();
225             if (metaData.storesUpperCaseIdentifiers()) {
226                 name = name.toUpperCase();
227             }
228
229             set = metaData.getTables(_connection.getCatalog(), null,
230                 name, null);
231             if (set.next()) {
232                 result = true;
233             }
234         } catch (SQLException JavaDoc exception) {
235             throw new PersistenceException("Failed to determine if table="
236                 + table + " exists", exception);
237         } finally {
238             SQLHelper.close(set);
239         }
240         return result;
241     }
242
243 } //-- SchemaBrowser
244
Popular Tags