001/* 002 * Copyright 2011 Atteo. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 005 * in compliance with the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License 010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 011 * or implied. See the License for the specific language governing permissions and limitations under 012 * the License. 013 */ 014package org.atteo.moonshine.liquibase; 015 016import java.sql.SQLException; 017 018import javax.inject.Inject; 019import javax.sql.DataSource; 020 021import liquibase.Liquibase; 022import liquibase.database.DatabaseConnection; 023import liquibase.database.jvm.JdbcConnection; 024import liquibase.exception.DatabaseException; 025import liquibase.exception.LiquibaseException; 026import liquibase.resource.ClassLoaderResourceAccessor; 027import liquibase.resource.ResourceAccessor; 028 029/** 030 * Liquibase facade for migrations execution. 031 * <p> 032 * Usage: 033 * <pre> 034 * @ImportService 035 * private DatabaseService database; 036 * 037 * ... 038 * 039 * database.registerMigration(new DatabaseMigration() { 040 * @Override 041 * public void execute(DataSource dataSource) { 042 * new LiquibaseFacade(datasource).migrate("/migrations/migration01.xml"); 043 * } 044 * } 045 * </pre> 046 * </p> 047 */ 048public class LiquibaseFacade { 049 private static final String BEFORE_LAST_UPDATE = "BEFORE_LAST_UPDATE"; 050 051 private final DataSource dataSource; 052 053 @Inject 054 public LiquibaseFacade(DataSource dataSource) { 055 this.dataSource = dataSource; 056 } 057 058 /** 059 * Migrate using given migration. 060 * @param changelog resource with the migration 061 */ 062 public void migrate(String changelog) { 063 migrate(changelog, null); 064 } 065 066 /** 067 * Migrate using given migration. 068 * @param changelog resource with the migration 069 * @param contexts contexts, see {@link Liquibase#update(String)}. 070 */ 071 public void migrate(String changelog, String contexts) { 072 ResourceAccessor resourceAccessor = new ClassLoaderResourceAccessor(); 073 074 DatabaseConnection databaseConnection = null; 075 changelog = normalizeName(changelog); 076 077 try { 078 databaseConnection = new JdbcConnection(dataSource.getConnection()); 079 Liquibase liquibase = new Liquibase(changelog, resourceAccessor, databaseConnection); 080 liquibase.tag(BEFORE_LAST_UPDATE); 081 liquibase.update(contexts); 082 } catch (LiquibaseException | SQLException e) { 083 throw new RuntimeException(e); 084 } finally { 085 try { 086 if (databaseConnection != null && !databaseConnection.isClosed()) 087 databaseConnection.close(); 088 } catch (DatabaseException e) { 089 throw new RuntimeException(e); 090 } 091 } 092 } 093 094 /** 095 * Rollbacks last update. 096 * @param changelog resource with the migration 097 */ 098 public void rollbackLastUpdate(String changelog) { 099 rollback(changelog, null, BEFORE_LAST_UPDATE); 100 } 101 102 /** 103 * Rollbacks last update. 104 * @param changelog resource with the migration 105 * @param contexts contexts, see {@link Liquibase#update(String)}. 106 */ 107 public void rollbackLastUpdate(String changelog, String contexts) { 108 rollback(changelog, contexts, BEFORE_LAST_UPDATE) ; 109 } 110 111 /** 112 * Rollbacks given changelog to given tag. 113 * @param changelog resource with the migration 114 * @param contexts contexts, see {@link Liquibase#update(String)}. 115 * @param tag tag to rollback to 116 */ 117 private void rollback(String changelog, String contexts, String tag) { 118 changelog = normalizeName(changelog); 119 120 ResourceAccessor resourceAccessor = new ClassLoaderResourceAccessor(); 121 122 DatabaseConnection databaseConnection = null; 123 124 try { 125 databaseConnection = new JdbcConnection(dataSource.getConnection()); 126 Liquibase liquibase = new Liquibase(changelog, resourceAccessor, databaseConnection); 127 liquibase.rollback(tag, contexts); 128 } catch (LiquibaseException | SQLException e) { 129 throw new RuntimeException(e); 130 } finally { 131 try { 132 if (databaseConnection != null && !databaseConnection.isClosed()) { 133 databaseConnection.close(); 134 } 135 } catch (DatabaseException e) { 136 throw new RuntimeException(e); 137 } 138 } 139 } 140 141 public void dropAll() { 142 ResourceAccessor resourceAccessor = new ClassLoaderResourceAccessor(); 143 144 DatabaseConnection databaseConnection = null; 145 146 try { 147 databaseConnection = new JdbcConnection(dataSource.getConnection()); 148 Liquibase liquibase = new Liquibase(null, resourceAccessor, databaseConnection); 149 liquibase.dropAll(); 150 } catch (LiquibaseException | SQLException e) { 151 throw new RuntimeException(e); 152 } finally { 153 try { 154 if (databaseConnection != null && !databaseConnection.isClosed()) 155 databaseConnection.close(); 156 } catch (DatabaseException e) { 157 throw new RuntimeException(e); 158 } 159 } 160 } 161 162 private String normalizeName(String changelog) { 163 if (changelog.startsWith("/") ){ 164 changelog = changelog.substring(1); 165 } 166 return changelog; 167 } 168}