1 package org.hibernate.tool.hbm2ddl; 3 4 import java.io.File ; 5 import java.io.FileInputStream ; 6 import java.io.FileWriter ; 7 import java.io.IOException ; 8 import java.sql.Connection ; 9 import java.sql.SQLException ; 10 import java.sql.Statement ; 11 import java.util.ArrayList ; 12 import java.util.List ; 13 import java.util.Properties ; 14 import java.util.StringTokenizer ; 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 34 public class SchemaExport { 35 36 private static final Log log = LogFactory.getLog(SchemaExport.class); 37 38 private ConnectionHelper connectionHelper; 39 private String [] dropSQL; 40 private String [] createSQL; 41 private String outputFile = null; 42 private Dialect dialect; 43 private String delimiter; 44 private List exceptions; 45 46 49 public SchemaExport(Configuration cfg) throws HibernateException { 50 this( cfg, cfg.getProperties() ); 51 } 52 53 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 (); 63 } 64 65 69 public SchemaExport(Configuration cfg, Properties connectionProperties) throws HibernateException { 70 dialect = Dialect.getDialect( connectionProperties ); 71 72 Properties props = new Properties (); 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 (); 80 } 81 82 public SchemaExport(Configuration cfg, Connection 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 (); 88 } 89 90 93 public SchemaExport setOutputFile(String filename) { 94 outputFile = filename; 95 return this; 96 } 97 98 101 public SchemaExport setDelimiter(String delimiter) { 102 this.delimiter = delimiter; 103 return this; 104 } 105 106 111 public void create(boolean script, boolean export) { 112 execute(script, export, false, true); 113 } 114 115 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 connection = null; 129 FileWriter fileOutput = null; 130 Statement 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 (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 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 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 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 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 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 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 ioe) { 210 exceptions.add(ioe); 211 log.error( "Error closing output file: " + outputFile, ioe ); 212 } 213 214 } 215 } 216 217 224 private static String format(String 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 formatCommentOn(String sql) { 240 StringBuffer result = new StringBuffer (60); 241 StringTokenizer tokens = new StringTokenizer ( sql, " '[]\"", true ); 242 243 boolean quoted = false; 244 while ( tokens.hasMoreTokens() ) { 245 String 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 formatAlterTable(String sql) { 261 StringBuffer result = new StringBuffer (60); 262 StringTokenizer tokens = new StringTokenizer ( sql, " (,)'[]\"", true ); 263 264 boolean quoted = false; 265 while ( tokens.hasMoreTokens() ) { 266 String 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 formatCreateTable(String sql) { 282 StringBuffer result = new StringBuffer (60); 283 StringTokenizer tokens = new StringTokenizer ( sql, "(,)'[]\"", true ); 284 285 int depth = 0; 286 boolean quoted = false; 287 while ( tokens.hasMoreTokens() ) { 288 String 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 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 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 [] args) { 329 try { 330 Configuration cfg = new Configuration(); 331 332 boolean script = true; 333 boolean drop = false; 334 boolean export = true; 335 String outFile = null; 336 String propFile = null; 337 boolean formatSQL = false; 338 String 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 filename = args[i]; 374 if ( filename.endsWith( ".jar" ) ) { 375 cfg.addJar( new File (filename) ); 376 } 377 else { 378 cfg.addFile(filename); 379 } 380 } 381 382 } 383 if(propFile!=null) { 384 Properties props = new Properties (); 385 props.load( new FileInputStream (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 e) { 399 log.error( "Error creating schema ", e ); 400 e.printStackTrace(); 401 } 402 } 403 404 408 public List getExceptions() { 409 return exceptions; 410 } 411 412 private interface ConnectionHelper { 413 Connection getConnection() throws SQLException ; 414 void release() throws SQLException ; 415 } 416 417 private class SuppliedConnectionHelper implements ConnectionHelper { 418 private Connection connection; 419 420 public SuppliedConnectionHelper(Connection connection) { 421 this.connection = connection; 422 } 423 424 public Connection 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 connection; 437 438 public SuppliedConnectionProviderConnectionHelper(ConnectionProvider provider) { 439 this.provider = provider; 440 } 441 442 public Connection getConnection() throws SQLException { 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 { 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 cfgProperties; 464 private ConnectionProvider connectionProvider; 465 private Connection connection; 466 467 public ProviderConnectionHelper(Properties cfgProperties) { 468 this.cfgProperties = cfgProperties; 469 } 470 471 public Connection getConnection() throws SQLException { 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 { 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 |