package org.codehaus.mojo.dbupgrade.file; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import org.apache.commons.dbutils.DbUtils; import org.codehaus.mojo.dbupgrade.DBUpgradeException; import org.codehaus.mojo.dbupgrade.DBUpgradeLifecycle; import org.codehaus.mojo.dbupgrade.sqlexec.DefaultSQLExec; import org.codehaus.plexus.util.IOUtil; import org.codehaus.plexus.util.StringUtils; /* * Copyright 2000-2010 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ /** * This class hooks up user's sql upgrade script locations contained in a text file ( ie the text file contains a list of SQL script paths ). * After a SQL script is executed, its names is stored in your configurable database version table. DBUpgrade uses * database version's value ( a SQL script name ) to pickup the next upgrade script, if any. */ public class FileDBUpgradeLifecycle implements DBUpgradeLifecycle { private DefaultSQLExec sqlexec; private FileListDBUpgradeConfiguration config; private String initialDBVersion = null; public FileDBUpgradeLifecycle( FileListDBUpgradeConfiguration config ) throws DBUpgradeException { this.config = config; this.sqlexec = new DefaultSQLExec( config ); this.initializeDBVersion(); } /** * Execute DB Upgrade lifecycle phases */ public int upgrade() throws DBUpgradeException { int upgraderCount = 0; FileReader fileReader = null; try { fileReader = new FileReader( config.getUpgradeFile() ); BufferedReader reader = new BufferedReader( fileReader ); String line = null; //find where we left off last upgrade if ( !StringUtils.isBlank( this.initialDBVersion ) ) { while ( ( line = this.readLine( reader ) ) != null ) { if ( !StringUtils.isBlank( line ) ) { File upgradeFile = new File( config.getScriptDirectory(), line ); if ( !upgradeFile.exists() ) { throw new DBUpgradeException( upgradeFile.getAbsolutePath() + " not found." ); } if ( initialDBVersion.equals( line ) ) { break; //so that we can continue with upgrade } } } if ( line == null ) { throw new DBUpgradeException( "Database version value: " + initialDBVersion + " not found in the list. Are you upgrading the right database?" ); } } //continue on with last upgrade while ( ( line = this.readLine( reader ) ) != null ) { if ( !StringUtils.isBlank( line ) ) { upgrade( config.getScriptDirectory(), line.trim() ); upgraderCount++; } } } catch ( IOException e ) { throw new DBUpgradeException( "Unable to perform file upgrade: " + this.config.getUpgradeFile(), e ); } finally { IOUtil.close( fileReader ); } return upgraderCount; } private String readLine( BufferedReader reader ) throws IOException { String line = reader.readLine(); if ( line != null ) { line = line.trim(); if ( StringUtils.isBlank( line ) || line.startsWith( "#" ) ) { line = ""; } } return line; } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private Connection getConnection() throws DBUpgradeException { try { return sqlexec.getConnection(); } catch ( SQLException e ) { throw new DBUpgradeException( e.getMessage(), e ); } } private void initializeVersionTable() throws DBUpgradeException { try { this.createVersionTable(); this.createInitialVersion(); } catch ( SQLException e ) { throw new DBUpgradeException( "Unable to create version table:" + config.getVersionTableName() + ".", e ); } } private void initializeDBVersion() throws DBUpgradeException { Statement stm = null; ResultSet rs = null; try { stm = sqlexec.getConnection().createStatement(); rs = stm.executeQuery( "SELECT " + config.getVersionColumnName() + " FROM " + config.getVersionTableName() ); if ( !rs.next() ) { this.createInitialVersion(); } } catch ( SQLException e ) { initializeVersionTable(); } finally { DbUtils.closeQuietly( rs ); DbUtils.closeQuietly( stm ); } this.initialDBVersion = this.getDBVersion(); } private void createVersionTable() throws SQLException { sqlexec.execute( "create table " + config.getVersionTableName() + " ( " + config.getVersionColumnName() + " varchar(256) )" ); sqlexec.commit(); } private void createInitialVersion() throws SQLException { sqlexec.execute( "insert into " + config.getVersionTableName() + " ( " + config.getVersionColumnName() + " ) values ( '' )" ); sqlexec.commit(); } private String getDBVersion() throws DBUpgradeException { Statement statement = null; String version; ResultSet rs = null; Connection connection = getConnection(); try { statement = connection.createStatement(); rs = statement.executeQuery( "SELECT distinct(" + config.getVersionColumnName() + ") FROM " + config.getVersionTableName() ); if ( rs.next() ) { version = rs.getString( 1 ); if ( rs.next() ) { throw new DBUpgradeException( "Multiple versions found in " + config.getVersionTableName() + " table." ); } } else { throw new DBUpgradeException( "Version row not found in: " + config.getVersionTableName() + " table." ); } } catch ( SQLException e ) { sqlexec.rollbackQuietly(); throw new DBUpgradeException( "Version row not found in: " + config.getVersionTableName() + " table." ); } finally { DbUtils.closeQuietly( rs ); DbUtils.closeQuietly( statement ); } return version; } private void upgrade( File scriptDirectory, String upgradeFileName ) throws DBUpgradeException { File upgradeFile = new File( scriptDirectory, upgradeFileName ); if ( this.config.isVerbose() ) { System.out.println( "Executing: " + upgradeFile + " ..." ); } try { sqlexec.execute( upgradeFile, config.isDisableSQLParser() ); if ( ! StringUtils.isBlank( config.getPostIncrementalStatement() ) ) { sqlexec.execute( config.getPostIncrementalStatement() ); } sqlexec.execute( "update " + this.config.getVersionTableName() + " set " + this.config.getVersionColumnName() + " ='" + upgradeFileName + "'" ); sqlexec.commit(); } catch ( Exception e ) { sqlexec.rollbackQuietly(); throw new DBUpgradeException( "Unable to perform file upgrade: " + upgradeFile + ".", e ); } } }