/* * 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)); } }