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

alpine.server.upgrade.UpgradeExecutor Maven / Gradle / Ivy

/*
 * This file is part of Alpine.
 *
 * 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.
 *
 * SPDX-License-Identifier: Apache-2.0
 * Copyright (c) Steve Springett. All Rights Reserved.
 */
package alpine.server.upgrade;

import alpine.common.logging.Logger;
import alpine.common.util.VersionComparator;
import alpine.persistence.AlpineQueryManager;
import alpine.server.util.DbUtil;

import javax.jdo.datastore.JDOConnection;
import java.lang.reflect.Constructor;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

/**
 * Executes upgrades by first checking if execution is necessary and if the specific upgrade
 * has already been executed. If an upgrade is necessary and the specific upgrade being requested
 * has not previously executed, the upgrade will be processed and the schema version will be upgraded.
 *
 * @author Steve Springett
 * @since 1.2.0
 */
@SuppressWarnings("unused")
public class UpgradeExecutor {

    private final static Logger LOGGER = Logger.getLogger(UpgradeExecutor.class);

    private final AlpineQueryManager qm;

    /**
     * Constructs a new UpgradeExecutor object.
     *
     * @param qm an AlpineQueryManager (or superclass) object
     * @since 1.2.0
     */
    public UpgradeExecutor(final AlpineQueryManager qm) {
        this.qm = qm;
    }

    /**
     * Performs the execution of upgrades in the order defined by the specified array.
     *
     * @param classes the upgrade classes
     * @throws UpgradeException if errors are encountered
     * @since 1.2.0
     */
    public void executeUpgrades(final List> classes) throws UpgradeException {
        final Connection connection = getConnection(qm);
        final UpgradeMetaProcessor installedUpgrades = new UpgradeMetaProcessor(connection);
        DbUtil.initPlatformName(connection); // Initialize DbUtil

        // First, we need to ensure the schema table is populated on a clean install
        // But we do so without passing any version.
        try {
            installedUpgrades.updateSchemaVersion(null);
        } catch (SQLException e) {
            LOGGER.error("Failed to update schema version", e);
            return;
        }

        for (final Class upgradeClass : classes) {
            try {
                @SuppressWarnings("unchecked")
                final Constructor constructor = upgradeClass.getConstructor();
                final UpgradeItem upgradeItem = (UpgradeItem) constructor.newInstance();

                if (upgradeItem.shouldUpgrade(qm, connection)) {
                    if (!installedUpgrades.hasUpgradeRan(upgradeClass)) {
                        LOGGER.info("Upgrade class " + upgradeClass.getName() + " about to run.");
                        final long startTime = System.currentTimeMillis();
                        upgradeItem.executeUpgrade(qm, connection);
                        final long endTime = System.currentTimeMillis();
                        installedUpgrades.installUpgrade(upgradeClass, startTime, endTime);
                        installedUpgrades.updateSchemaVersion(new VersionComparator(upgradeItem.getSchemaVersion()));
                        LOGGER.info("Completed running upgrade class " + upgradeClass.getName() + " in " + (endTime - startTime) + " ms.");
                    } else {
                        LOGGER.debug("Upgrade class " + upgradeClass.getName() + " has already ran, skipping.");
                    }
                } else {
                    LOGGER.debug("Upgrade class " + upgradeClass.getName() + " does not need to run.");
                }
            } catch (Exception e) {
                DbUtil.rollback(connection);
                LOGGER.error("Error in executing upgrade class: " + upgradeClass.getName(), e);
                throw new UpgradeException(e);
            }
        }
    }

    /**
     * This connection should never be closed.
     */
    private Connection getConnection(AlpineQueryManager aqm) {
        final JDOConnection jdoConnection = aqm.getPersistenceManager().getDataStoreConnection();
        if (jdoConnection != null) {
            if (jdoConnection.getNativeConnection() instanceof Connection) {
                return (Connection)jdoConnection.getNativeConnection();
            }
        }
        return null;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy