View Javadoc

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 2001-2003 (C) Exoffice Technologies Inc. All Rights Reserved.
42   *
43   * $Id: RDBMSTool.java,v 1.7 2003/08/07 13:33:11 tanderson Exp $
44   */
45  
46  package org.exolab.jms.tools.db;
47  
48  import java.sql.Connection;
49  import java.sql.SQLException;
50  import java.sql.Statement;
51  
52  import org.apache.commons.logging.Log;
53  import org.apache.commons.logging.LogFactory;
54  
55  import org.exolab.jms.persistence.PersistenceException;
56  import org.exolab.jms.persistence.SQLHelper;
57  
58  
59  /***
60   * This class provides support for creating and destroying tables in RDBMS
61   * databases.
62   *
63   * @version     $Revision: 1.7 $ $Date: 2003/08/07 13:33:11 $
64   * @author      <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
65   */
66  public class RDBMSTool {
67  
68      /***
69       * The connection to the database
70       */
71      private Connection _connection = null;
72  
73      /***
74       * The schema browser
75       */
76      private SchemaBrowser _browser = null;
77  
78      /***
79       * The logger
80       */
81      private static final Log _log = LogFactory.getLog(RDBMSTool.class);
82  
83  
84      /***
85       * Construct a new <code>RDBMSTool</code>
86       *
87       * @param connection the JDBC connection
88       * @throws PersistenceException if database meta-data can't be obtained
89       */
90      public RDBMSTool(Connection connection) throws PersistenceException {
91          _connection = connection;
92          _browser = new SchemaBrowser(_connection);
93      }
94  
95      /***
96       * Creates the database
97       *
98       * @param schema the database schema
99       * @throws PersistenceException if elements cannot be created in the
100      * database
101      */
102     public void create(Database schema) throws PersistenceException {
103         Table[] tables = schema.getTable();
104         for (int i = 0; i < tables.length; ++i) {
105             create(tables[i]);
106         }
107     }
108 
109     /***
110      * Drops tables from the database
111      *
112      * @param schema the database schema
113      * @throws PersistenceException if elements cannot be dropped from the
114      * database
115      */
116     public void drop(Database schema) throws PersistenceException {
117         Table[] tables = schema.getTable();
118         for (int i = 0; i < tables.length; ++i) {
119             drop(tables[i]);
120         }
121         Deprecated[] redundant = schema.getDeprecated();
122         for (int i = 0; i < redundant.length; ++i) {
123             dropTable(redundant[i].getName());
124         }
125     }
126 
127     /***
128      * Close the connection to the database
129      */
130     public void close() {
131         SQLHelper.close(_connection);
132     }
133 
134     /***
135      * Creates a table in the database
136      *
137      * @param table the table to create
138      * @throws PersistenceException if the table exists, or cannot be created
139      */
140     public void create(Table table) throws PersistenceException {
141         String name = table.getName();
142         if (_browser.getTableExists(name)) {
143             throw new PersistenceException(
144                 "An object already exists in the database named " + name);
145         }
146 
147         StringBuffer sql = new StringBuffer("create table ");
148         sql.append(name);
149         sql.append(" (");
150 
151         _log.debug("Creating table: " + name);
152         Attribute[] attributes = table.getAttribute();
153         for (int i = 0; i < attributes.length; ++i) {
154             if (i > 0) {
155                 sql.append(", ");
156             }
157             sql.append(attributes[i].getName());
158             sql.append(" ");
159             sql.append(getSQLType(attributes[i]));
160         }
161         sql.append(")");
162 
163         _log.debug("SQL=" + sql);
164         Statement statement = null;
165         try {
166             statement = _connection.createStatement();
167             statement.executeUpdate(sql.toString());
168         } catch (SQLException exception) {
169             throw new PersistenceException("Failed to create table=" + name,
170                 exception);
171         } finally {
172             SQLHelper.close(statement);
173         }
174         createIndexes(table);
175     }
176 
177     /***
178      * Drops a table from the database. If the table doesn't exist, then
179      * it will be ignored.
180      *
181      * @param table the table to drop
182      * @throws PersistenceException for any database error
183      */
184     public void drop(Table table) throws PersistenceException {
185         dropTable(table.getName());
186     }
187 
188     /***
189      * Returns the schema browser
190      *
191      * @return the schema browser
192      */
193     public SchemaBrowser getSchemaBrowser() {
194         return _browser;
195     }
196 
197     private void createIndexes(Table table) throws PersistenceException {
198         Index[] indexes = table.getIndex();
199         for (int i = 0; i < indexes.length; ++i) {
200             Index index = indexes[i];
201             StringBuffer sql = new StringBuffer("create ");
202             if (index.getUnique()) {
203                 sql.append("unique ");
204             }
205             sql.append("index ");
206             sql.append(index.getName());
207             sql.append(" on ");
208             sql.append(table.getName());
209             sql.append("(");
210             Column[] columns = index.getColumn();
211             for (int j = 0; j < columns.length; ++j) {
212                 if (j > 0) {
213                     sql.append(", ");
214                 }
215                 sql.append(columns[j].getName());
216             }
217             sql.append(")");
218             _log.debug("SQL=" + sql);
219             Statement statement = null;
220             try {
221                 statement = _connection.createStatement();
222                 statement.executeUpdate(sql.toString());
223             } catch (SQLException exception) {
224                 throw new PersistenceException(
225                     "Failed to create index=" + index.getName() + " on table "
226                     + table.getName());
227             } finally {
228                 SQLHelper.close(statement);
229             }
230         }
231     }
232 
233     /***
234      * Drop a table
235      *
236      * @param name the name of the table to drop
237      * @throws PersistenceException if the drop fails
238      */
239     private void dropTable(String name) throws PersistenceException {
240         if (_browser.getTableExists(name)) {
241             String sql = "drop table " + name;
242             _log.debug("SQL=" + sql);
243             Statement statement = null;
244             try {
245                 statement = _connection.createStatement();
246                 statement.executeUpdate(sql);
247             } catch (SQLException exception) {
248                 throw new PersistenceException("Failed to drop table=" + name,
249                     exception);
250             } finally {
251                 SQLHelper.close(statement);
252             }
253         }
254     }
255 
256     /***
257      * Returns the SQL type for a given attribute
258      *
259      * @param attribute the attribute
260      * @return a string representation of the type
261      * @throws PersistenceException if {@link Attribute#getType} is invalid, or
262      * the RDBMS doesn't support the type
263      */
264     private String getSQLType(Attribute attribute)
265         throws PersistenceException {
266         Type result = _browser.getType(attribute);
267         _log.debug("attribute=" + attribute.getName() + "->" + result);
268         return result.getSQL();
269     }
270 
271 } //-- RDBMSTool