All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.topia.liquibase.TopiaLiquibaseServiceImpl Maven / Gradle / Ivy

There is a newer version: 4.0
Show newest version
package org.nuiton.topia.liquibase;

/*
 * #%L
 * ToPIA :: Liquibase integration service
 * $Id$
 * $HeadURL$
 * %%
 * Copyright (C) 2004 - 2014 CodeLutin
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import liquibase.Contexts;
import liquibase.Liquibase;
import liquibase.database.Database;
import liquibase.database.DatabaseFactory;
import liquibase.exception.DatabaseException;
import liquibase.exception.LiquibaseException;
import liquibase.resource.ClassLoaderResourceAccessor;
import liquibase.resource.CompositeResourceAccessor;
import liquibase.resource.FileSystemResourceAccessor;
import liquibase.resource.ResourceAccessor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.topia.persistence.TopiaApplicationContext;
import org.nuiton.topia.persistence.TopiaMigrationServiceException;
import org.nuiton.topia.persistence.jdbc.JdbcConfiguration;

import java.util.Map;

/**
 * Integration with Liquibase migration
 * framework.
 *
 * When {@link org.nuiton.topia.persistence.TopiaApplicationContext} will be started
 * all migrations will be run.
 *
 * @since 3.0
 */
public class TopiaLiquibaseServiceImpl implements TopiaLiquibaseService {

    private static final Log log = LogFactory.getLog(TopiaLiquibaseServiceImpl.class);

    protected Contexts allContexts = new Contexts("");

    /**
     * Place to find the changelog, default name has been fixed according
     * to best practices.
     */
    protected String changeLogPath = "db/changelog-master.xml";

    protected Database database;

    protected Liquibase liquibase;

    @Override
    public void initTopiaService(TopiaApplicationContext topiaApplicationContext, Map serviceConfiguration) {

        if ( ! serviceConfiguration.isEmpty()) {
            throw new UnsupportedOperationException("no configuration expected but " + serviceConfiguration + " given");
        }

        try {

            ResourceAccessor resourceAccessor = getResourceAccessor();

            database = openDatabase(topiaApplicationContext, resourceAccessor);

            liquibase = getLiquibase(database, resourceAccessor);

        } catch (LiquibaseException e) {
            close();
            throw new TopiaMigrationServiceException("unable to init liquibase", e);
        }

    }

    @Override
    public String getSchemaVersion() {

        // TODO brendan 18/07/14 use http://www.liquibase.org/documentation/changes/tag_database.html ?
        throw new UnsupportedOperationException("schema version is not made available by liquibase");

    }

    @Override
    public void initOnCreateSchema() {

        if (log.isInfoEnabled()) {
            log.info("init liquibase");
        }

        try {

            liquibase.changeLogSync(allContexts);

        } catch (LiquibaseException e) {
            close();
            throw new TopiaMigrationServiceException("unable to init liquibase", e);
        }

    }

    @Override
    public void runSchemaMigration() {

        if (log.isInfoEnabled()) {
            log.info("migrate schema with liquibase");
        }

        try {

            liquibase.update(allContexts);

        } catch (LiquibaseException e) {
            close();
            throw new TopiaMigrationServiceException("unable to update schema with liquibase", e);
        }

    }

    protected Liquibase getLiquibase(Database database, ResourceAccessor resourceAccessor) throws LiquibaseException {
        Liquibase liquibase = new Liquibase(changeLogPath, resourceAccessor, database);
        return liquibase;
    }

    /**
     * Implementation highly inspired from {@link liquibase.integration.servlet.LiquibaseServletListener}.
     */
    protected ResourceAccessor getResourceAccessor() {
        Thread currentThread = Thread.currentThread();
        ClassLoader contextClassLoader = currentThread.getContextClassLoader();
        ResourceAccessor threadClFO = new ClassLoaderResourceAccessor(contextClassLoader);
        ResourceAccessor clFO = new ClassLoaderResourceAccessor();
        ResourceAccessor fsFO = new FileSystemResourceAccessor();
        return new CompositeResourceAccessor(clFO, fsFO, threadClFO);
    }

    protected Database openDatabase(TopiaApplicationContext topiaApplicationContext, ResourceAccessor resourceAccessor) {
        JdbcConfiguration configuration = topiaApplicationContext.getConfiguration();
        String url = configuration.getJdbcConnectionUrl();
        String user = configuration.getJdbcConnectionUser();
        String password = configuration.getJdbcConnectionPassword();
        try {
            Database database = DatabaseFactory.getInstance().openDatabase(url, user, password, null, resourceAccessor);
            return database;
        } catch (DatabaseException e) {
            throw new TopiaMigrationServiceException("cannot get database for migration connection", e);
        }
    }

    protected void closeDatabase() {
        if (database != null) {
            try {
                database.close();
                database = null;
            } catch (DatabaseException e2) {
                if (log.isWarnEnabled()) {
                    log.warn("error while trying to close database after liquibase error", e2);
                }
            }
        }
    }

    @Override
    public void close() {
        closeDatabase();
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy