KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > tool > hbm2ddl > SchemaExport


1 //$Id: SchemaExport.java,v 1.10 2005/07/18 22:36:43 epbernard Exp $
2
package org.hibernate.tool.hbm2ddl;
3
4 import java.io.File JavaDoc;
5 import java.io.FileInputStream JavaDoc;
6 import java.io.FileWriter JavaDoc;
7 import java.io.IOException JavaDoc;
8 import java.sql.Connection JavaDoc;
9 import java.sql.SQLException JavaDoc;
10 import java.sql.Statement JavaDoc;
11 import java.util.ArrayList JavaDoc;
12 import java.util.List JavaDoc;
13 import java.util.Properties JavaDoc;
14 import java.util.StringTokenizer JavaDoc;
15
16 import org.apache.commons.logging.Log;
17 import org.apache.commons.logging.LogFactory;
18 import org.hibernate.HibernateException;
19 import org.hibernate.cfg.Configuration;
20 import org.hibernate.cfg.NamingStrategy;
21 import org.hibernate.cfg.Settings;
22 import org.hibernate.connection.ConnectionProvider;
23 import org.hibernate.connection.ConnectionProviderFactory;
24 import org.hibernate.dialect.Dialect;
25 import org.hibernate.util.JDBCExceptionReporter;
26 import org.hibernate.util.ReflectHelper;
27
28 /**
29  * Commandline tool to export table schema to the database. This
30  * class may also be called from inside an application.
31  *
32  * @author Daniel Bradby, Gavin King
33  */

34 public class SchemaExport {
35
36     private static final Log log = LogFactory.getLog(SchemaExport.class);
37
38     private ConnectionHelper connectionHelper;
39     private String JavaDoc[] dropSQL;
40     private String JavaDoc[] createSQL;
41     private String JavaDoc outputFile = null;
42     private Dialect dialect;
43     private String JavaDoc delimiter;
44     private List JavaDoc exceptions;
45
46     /**
47      * Create a schema exporter for the given Configuration
48      */

49     public SchemaExport(Configuration cfg) throws HibernateException {
50         this( cfg, cfg.getProperties() );
51     }
52
53     /**
54      * Create a schema exporter for the given Configuration
55      * and given settings
56      */

57     public SchemaExport(Configuration cfg, Settings settings) throws HibernateException {
58         dialect = settings.getDialect();
59         connectionHelper = new SuppliedConnectionProviderConnectionHelper( settings.getConnectionProvider() );
60         dropSQL = cfg.generateDropSchemaScript( dialect );
61         createSQL = cfg.generateSchemaCreationScript( dialect );
62         exceptions = new ArrayList JavaDoc();
63     }
64
65     /**
66      * Create a schema exporter for the given Configuration, with the given
67      * database connection properties.
68      */

69     public SchemaExport(Configuration cfg, Properties JavaDoc connectionProperties) throws HibernateException {
70         dialect = Dialect.getDialect( connectionProperties );
71
72         Properties JavaDoc props = new Properties JavaDoc();
73         props.putAll( dialect.getDefaultProperties() );
74         props.putAll( connectionProperties );
75
76         connectionHelper = new ProviderConnectionHelper( props );
77         dropSQL = cfg.generateDropSchemaScript( dialect );
78         createSQL = cfg.generateSchemaCreationScript( dialect );
79         exceptions = new ArrayList JavaDoc();
80     }
81
82     public SchemaExport(Configuration cfg, Connection JavaDoc connection) {
83         this.connectionHelper = new SuppliedConnectionHelper( connection );
84         dialect = Dialect.getDialect( cfg.getProperties() );
85         dropSQL = cfg.generateDropSchemaScript( dialect );
86         createSQL = cfg.generateSchemaCreationScript( dialect );
87         exceptions = new ArrayList JavaDoc();
88     }
89
90     /**
91      * Set an output filename. The generated script will be written to this file.
92      */

93     public SchemaExport setOutputFile(String JavaDoc filename) {
94         outputFile = filename;
95         return this;
96     }
97
98     /**
99      * Set the end of statement delimiter
100      */

101     public SchemaExport setDelimiter(String JavaDoc delimiter) {
102         this.delimiter = delimiter;
103         return this;
104     }
105
106     /**
107      * Run the schema creation script.
108      * @param script print the DDL to the console
109      * @param export export the script to the database
110      */

111     public void create(boolean script, boolean export) {
112         execute(script, export, false, true);
113     }
114
115     /**
116      * Run the drop schema script.
117      * @param script print the DDL to the console
118      * @param export export the script to the database
119      */

120     public void drop(boolean script, boolean export) {
121         execute(script, export, true, true);
122     }
123
124     private void execute(boolean script, boolean export, boolean justDrop, boolean format) {
125
126         log.info("Running hbm2ddl schema export");
127
128         Connection JavaDoc connection = null;
129         FileWriter JavaDoc fileOutput = null;
130         Statement JavaDoc statement = null;
131
132         exceptions.clear();
133
134         try {
135
136             if(outputFile != null) {
137                 log.info("writing generated schema to file: " + outputFile);
138                 fileOutput = new FileWriter JavaDoc(outputFile);
139             }
140
141             if (export) {
142                 log.info("exporting generated schema to database");
143                 connection = connectionHelper.getConnection();
144                 if ( !connection.getAutoCommit() ) {
145                     connection.commit();
146                     connection.setAutoCommit(true);
147                 }
148                 statement = connection.createStatement();
149             }
150
151             for (int i = 0; i < dropSQL.length; i++) {
152                 try {
153                     String JavaDoc formatted = dropSQL[i];
154                     if (delimiter!=null) formatted += delimiter;
155                     if (script) System.out.println(formatted);
156                     log.debug(formatted);
157                     if (outputFile != null) fileOutput.write( formatted + "\n" );
158                     if (export) statement.executeUpdate( dropSQL[i] );
159                 }
160                 catch(SQLException JavaDoc e) {
161                     exceptions.add(e);
162                     log.debug( "Unsuccessful: " + dropSQL[i] );
163                     log.debug( e.getMessage() );
164                 }
165
166             }
167
168             if (!justDrop) {
169                 for(int j = 0; j < createSQL.length; j++) {
170                     try {
171                         String JavaDoc formatted = format ? format( createSQL[j] ) : createSQL[j];
172                         if (delimiter!=null) formatted += delimiter;
173                         if (script) System.out.println(formatted);
174                         log.debug(formatted);
175                         if (outputFile != null) fileOutput.write( formatted + "\n" );
176                         if (export) statement.executeUpdate( createSQL[j] );
177                     }
178                     catch (SQLException JavaDoc e) {
179                         exceptions.add(e);
180                         log.error( "Unsuccessful: " + createSQL[j] );
181                         log.error( e.getMessage() );
182                     }
183                 }
184             }
185
186             log.info("schema export complete");
187
188         }
189
190         catch(Exception JavaDoc e) {
191             exceptions.add(e);
192             log.error("schema export unsuccessful", e);
193         }
194
195         finally {
196
197             try {
198                 if (statement!=null) statement.close();
199                 if (connection!=null) connectionHelper.release();
200             }
201             catch(Exception JavaDoc e) {
202                 exceptions.add(e);
203                 log.error( "Could not close connection", e );
204             }
205
206             try {
207                 if (fileOutput!=null) fileOutput.close();
208             }
209             catch (IOException JavaDoc ioe) {
210                 exceptions.add(ioe);
211                 log.error( "Error closing output file: " + outputFile, ioe );
212             }
213
214         }
215     }
216
217     /**
218      * Format an SQL statement using simple rules:
219      * a) Insert newline after each comma;
220      * b) Indent three spaces after each inserted newline;
221      * If the statement contains single/double quotes return unchanged,
222      * it is too complex and could be broken by simple formatting.
223      */

224     private static String JavaDoc format(String JavaDoc sql) {
225         if ( sql.toLowerCase().startsWith("create table") ) {
226             return formatCreateTable( sql );
227         }
228         else if ( sql.toLowerCase().startsWith("alter table") ) {
229             return formatAlterTable( sql );
230         }
231         else if ( sql.toLowerCase().startsWith("comment on") ) {
232             return formatCommentOn( sql );
233         }
234         else {
235             return sql;
236         }
237     }
238     
239     private static String JavaDoc formatCommentOn(String JavaDoc sql) {
240         StringBuffer JavaDoc result = new StringBuffer JavaDoc(60);
241         StringTokenizer JavaDoc tokens = new StringTokenizer JavaDoc( sql, " '[]\"", true );
242
243         boolean quoted = false;
244         while ( tokens.hasMoreTokens() ) {
245             String JavaDoc token = tokens.nextToken();
246             result.append(token);
247             if ( isQuote(token) ) {
248                 quoted = !quoted;
249             }
250             else if (!quoted) {
251                 if ( "is".equals(token) ) {
252                     result.append("\n ");
253                 }
254             }
255         }
256         
257         return result.toString();
258     }
259
260     private static String JavaDoc formatAlterTable(String JavaDoc sql) {
261         StringBuffer JavaDoc result = new StringBuffer JavaDoc(60);
262         StringTokenizer JavaDoc tokens = new StringTokenizer JavaDoc( sql, " (,)'[]\"", true );
263
264         boolean quoted = false;
265         while ( tokens.hasMoreTokens() ) {
266             String JavaDoc token = tokens.nextToken();
267             if ( isQuote(token) ) {
268                 quoted = !quoted;
269             }
270             else if (!quoted) {
271                 if ( isBreak(token) ) {
272                     result.append("\n ");
273                 }
274             }
275             result.append(token);
276         }
277         
278         return result.toString();
279     }
280
281     private static String JavaDoc formatCreateTable(String JavaDoc sql) {
282         StringBuffer JavaDoc result = new StringBuffer JavaDoc(60);
283         StringTokenizer JavaDoc tokens = new StringTokenizer JavaDoc( sql, "(,)'[]\"", true );
284
285         int depth = 0;
286         boolean quoted = false;
287         while ( tokens.hasMoreTokens() ) {
288             String JavaDoc token = tokens.nextToken();
289             if ( isQuote(token) ) {
290                 quoted = !quoted;
291                 result.append(token);
292             }
293             else if (quoted) {
294                 result.append(token);
295             }
296             else {
297                 if ( ")".equals(token) ) {
298                     depth--;
299                     if (depth==0) result.append("\n");
300                 }
301                 result.append(token);
302                 if ( ",".equals(token) && depth==1 ) result.append("\n ");
303                 if ( "(".equals(token) ) {
304                     depth++;
305                     if (depth==1) result.append("\n ");
306                 }
307             }
308         }
309         
310         return result.toString();
311     }
312
313     private static boolean isBreak(String JavaDoc token) {
314         return "add".equals(token) ||
315             "references".equals(token) ||
316             "foreign".equals(token) ||
317             "on".equals(token);
318     }
319
320     private static boolean isQuote(String JavaDoc tok) {
321         return "\"".equals(tok) ||
322                 "`".equals(tok) ||
323                 "]".equals(tok) ||
324                 "[".equals(tok) ||
325                 "'".equals(tok);
326     }
327
328     public static void main(String JavaDoc[] args) {
329         try {
330             Configuration cfg = new Configuration();
331
332             boolean script = true;
333             boolean drop = false;
334             boolean export = true;
335             String JavaDoc outFile = null;
336             String JavaDoc propFile = null;
337             boolean formatSQL = false;
338             String JavaDoc delim = null;
339
340             for ( int i=0; i<args.length; i++ ) {
341                 if( args[i].startsWith("--") ) {
342                     if( args[i].equals("--quiet") ) {
343                         script = false;
344                     }
345                     else if( args[i].equals("--drop") ) {
346                         drop = true;
347                     }
348                     else if( args[i].equals("--text") ) {
349                         export = false;
350                     }
351                     else if( args[i].startsWith("--output=") ) {
352                         outFile = args[i].substring(9);
353                     }
354                     else if( args[i].startsWith("--properties=") ) {
355                         propFile = args[i].substring(13);
356                     }
357                     else if( args[i].equals("--format") ) {
358                         formatSQL = true;
359                     }
360                     else if ( args[i].startsWith("--delimiter=") ) {
361                         delim = args[i].substring(12);
362                     }
363                     else if ( args[i].startsWith("--config=") ) {
364                         cfg.configure( args[i].substring(9) );
365                     }
366                     else if ( args[i].startsWith("--naming=") ) {
367                         cfg.setNamingStrategy(
368                             (NamingStrategy) ReflectHelper.classForName( args[i].substring(9) ).newInstance()
369                         );
370                     }
371                 }
372                 else {
373                     String JavaDoc filename = args[i];
374                     if ( filename.endsWith( ".jar" ) ) {
375                         cfg.addJar( new File JavaDoc(filename) );
376                     }
377                     else {
378                         cfg.addFile(filename);
379                     }
380                 }
381
382             }
383             if(propFile!=null) {
384                 Properties JavaDoc props = new Properties JavaDoc();
385                 props.load( new FileInputStream JavaDoc(propFile) );
386                 new SchemaExport(cfg, props)
387                     .setOutputFile(outFile)
388                     .setDelimiter(delim)
389                     .execute(script, export, drop, formatSQL);
390             }
391             else {
392                 new SchemaExport(cfg)
393                     .setOutputFile(outFile)
394                     .setDelimiter(delim)
395                     .execute(script, export, drop, formatSQL);
396             }
397         }
398         catch(Exception JavaDoc e) {
399             log.error( "Error creating schema ", e );
400             e.printStackTrace();
401         }
402     }
403
404     /**
405      * Returns a List of all Exceptions which occured during the export.
406      * @return A List containig the Exceptions occured during the export
407      */

408     public List JavaDoc getExceptions() {
409         return exceptions;
410     }
411
412     private interface ConnectionHelper {
413         Connection JavaDoc getConnection() throws SQLException JavaDoc;
414         void release() throws SQLException JavaDoc;
415     }
416
417     private class SuppliedConnectionHelper implements ConnectionHelper {
418         private Connection JavaDoc connection;
419
420         public SuppliedConnectionHelper(Connection JavaDoc connection) {
421             this.connection = connection;
422         }
423
424         public Connection JavaDoc getConnection() {
425             return connection;
426         }
427
428         public void release() {
429             JDBCExceptionReporter.logAndClearWarnings(connection);
430             connection = null;
431         }
432     }
433
434     private class SuppliedConnectionProviderConnectionHelper implements ConnectionHelper {
435         private ConnectionProvider provider;
436         private Connection JavaDoc connection;
437
438         public SuppliedConnectionProviderConnectionHelper(ConnectionProvider provider) {
439             this.provider = provider;
440         }
441
442         public Connection JavaDoc getConnection() throws SQLException JavaDoc {
443             if (connection == null) {
444                 connection = provider.getConnection();
445                 if ( !connection.getAutoCommit() ) {
446                     connection.commit();
447                     connection.setAutoCommit( true );
448                 }
449             }
450             return connection;
451         }
452
453         public void release() throws SQLException JavaDoc {
454             if (connection != null) {
455                 JDBCExceptionReporter.logAndClearWarnings(connection);
456                 provider.closeConnection( connection );
457                 connection = null;
458             }
459         }
460     }
461
462     private class ProviderConnectionHelper implements ConnectionHelper {
463         private Properties JavaDoc cfgProperties;
464         private ConnectionProvider connectionProvider;
465         private Connection JavaDoc connection;
466
467         public ProviderConnectionHelper(Properties JavaDoc cfgProperties) {
468             this.cfgProperties = cfgProperties;
469         }
470
471         public Connection JavaDoc getConnection() throws SQLException JavaDoc {
472             if ( connection == null ) {
473                 connectionProvider = ConnectionProviderFactory.newConnectionProvider( cfgProperties );
474                 connection = connectionProvider.getConnection();
475                 if ( !connection.getAutoCommit() ) {
476                     connection.commit();
477                     connection.setAutoCommit( true );
478                 }
479             }
480             return connection;
481         }
482
483         public void release() throws SQLException JavaDoc {
484             if ( connection!=null ) {
485                 JDBCExceptionReporter.logAndClearWarnings(connection);
486                 connectionProvider.closeConnection( connection );
487                 connectionProvider.close();
488             }
489             connection = null;
490         }
491     }
492 }
493
494
495
496
497
498
499
500
Popular Tags