Project: greenhouse
/*
 * Copyright 2010-2011 the original author or authors. 
 * 
 * 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. 
 */
package com.springsource.greenhouse.database; 
 
import javax.sql.DataSource; 
 
import org.springframework.core.env.Environment; 
import org.springframework.core.io.ClassPathResource; 
import org.springframework.jdbc.versioned.DatabaseChange; 
import org.springframework.jdbc.versioned.DatabaseChangeSet; 
import org.springframework.jdbc.versioned.DatabaseVersion; 
import org.springframework.jdbc.versioned.GenericDatabaseUpgrader; 
import org.springframework.jdbc.versioned.SqlDatabaseChange; 
import org.springframework.security.crypto.encrypt.TextEncryptor; 
import org.springframework.social.connect.jdbc.JdbcUsersConnectionRepository; 
 
import com.springsource.greenhouse.database.upgrade.v3.UpdateEncryptionMethod; 
 
/**
 * Performs migrations against the Greenhouse database. 
 * Allows a database migration to be automated as part of integrating a software change that impacts the schema. 
 * If the Database is at version zero(), the current version of the database will be installed. 
 * If the Database is at a version less than the current version, the database will be upgraded from that version to the current version. 
 * If the Database is already at the current version, no migration will be performed. 
 * This migration model was adapted from the <a href="http://www.liquibase.org/tutorial-using-oracle">LiquiBase Oracle tutorial</a>. 
 * @author Keith Donald 
 */
 
public class DatabaseUpgrader { 
  
 private final Environment environment; 
  
 private final TextEncryptor textEncryptor; 
 
 private final org.springframework.jdbc.versioned.DatabaseUpgrader upgrader; 
 
 public DatabaseUpgrader(DataSource dataSource, Environment environment, TextEncryptor textEncryptor) {   
  this.environment = environment; 
  this.textEncryptor = textEncryptor; 
  this.upgrader = createUpgrader(dataSource); 
 
  
 public void run() { 
  upgrader.run();   
 
 
 // subclassing hooks 
  
 protected void addInstallChanges(DatabaseChangeSet changeSet) {} 
 
 // internal helpers 
  
 private org.springframework.jdbc.versioned.DatabaseUpgrader createUpgrader(DataSource dataSource) { 
  GenericDatabaseUpgrader upgrader = new GenericDatabaseUpgrader(dataSource); 
  if (upgrader.getCurrentDatabaseVersion().equals(DatabaseVersion.zero())) { 
   addInstallChangeSet(upgrader);    
  else { 
   addUpgradeChangeSets(upgrader); 
  
  return upgrader; 
 
 
 // Called for completely fresh DB only 
 private void addInstallChangeSet(GenericDatabaseUpgrader upgrader) { 
  DatabaseChangeSet changeSet = new DatabaseChangeSet(DatabaseVersion.valueOf("4")); 
  changeSet.add(installScript("Member.sql")); 
  changeSet.add(installScript("Group.sql")); 
  changeSet.add(installScript("Activity.sql")); 
  changeSet.add(installScript("ConnectedApp.sql")); 
  changeSet.add(installScript("Reset.sql")); 
  changeSet.add(installScript("Invite.sql"));   
  changeSet.add(installScript("Venue.sql")); 
  changeSet.add(installScript("Event.sql")); 
  changeSet.add(SqlDatabaseChange.inResource(new ClassPathResource("JdbcUsersConnectionRepository.sql", JdbcUsersConnectionRepository.class))); 
  addInstallChanges(changeSet); 
  upgrader.addChangeSet(changeSet); 
 
 
 private DatabaseChange installScript(String resource) { 
  return SqlDatabaseChange.inResource(new ClassPathResource("install/" + resource, DatabaseUpgrader.class)); 
 
 
 // Called to upgrade existing DB 
 private void addUpgradeChangeSets(GenericDatabaseUpgrader upgrader) { 
  upgrader.addChangeSet(version2ChangeSet()); 
  upgrader.addChangeSet(version3ChangeSet()); 
  upgrader.addChangeSet(version4ChangeSet()); 
 
 
 private DatabaseChangeSet version2ChangeSet() {   
  DatabaseChangeSet changeSet = new DatabaseChangeSet(DatabaseVersion.valueOf("2")); 
  changeSet.add(upgradeScript("v2/AlterServiceProviderTable.sql")); 
  return changeSet; 
 
  
 private DatabaseChangeSet version3ChangeSet() { 
  DatabaseChangeSet changeSet = new DatabaseChangeSet(DatabaseVersion.valueOf("3")); 
  changeSet.add(new UpdateEncryptionMethod(environment, textEncryptor)); 
  changeSet.add(upgradeScript("v3/CreateUserConnectionTable.sql")); 
  changeSet.add(upgradeScript("v3/PopulateUserConnectionTable.sql")); 
  changeSet.add(upgradeScript("v3/DropAccountConnectionTables.sql")); 
  return changeSet; 
 
  
 private DatabaseChangeSet version4ChangeSet() { 
  DatabaseChangeSet changeSet = new DatabaseChangeSet(DatabaseVersion.valueOf("4")); 
    changeSet.add(upgradeScript("v4/CreateTimeSlotTable.sql")); 
  return changeSet;   
 
 
 private DatabaseChange upgradeScript(String resource) { 
  return SqlDatabaseChange.inResource(new ClassPathResource("upgrade/" + resource, DatabaseUpgrader.class)); 
 
  
}