com.concursive.connect.web.modules.upgrade.utils.UpgradeUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.concursive.connect.web.modules.upgrade.utils.UpgradeUtils.java

Source

/*
 * ConcourseConnect
 * Copyright 2009 Concursive Corporation
 * http://www.concursive.com
 *
 * This file is part of ConcourseConnect, an open source social business
 * software and community platform.
 *
 * Concursive ConcourseConnect is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, version 3 of the License.
 *
 * Under the terms of the GNU Affero General Public License you must release the
 * complete source code for any application that uses any part of ConcourseConnect
 * (system header files and libraries used by the operating system are excluded).
 * These terms must be included in any work that has ConcourseConnect components.
 * If you are developing and distributing open source applications under the
 * GNU Affero General Public License, then you are free to use ConcourseConnect
 * under the GNU Affero General Public License.
 *
 * If you are deploying a web site in which users interact with any portion of
 * ConcourseConnect over a network, the complete source code changes must be made
 * available.  For example, include a link to the source archive directly from
 * your web site.
 *
 * For OEMs, ISVs, SIs and VARs who distribute ConcourseConnect with their
 * products, and do not license and distribute their source code under the GNU
 * Affero General Public License, Concursive provides a flexible commercial
 * license.
 *
 * To anyone in doubt, we recommend the commercial license. Our commercial license
 * is competitively priced and will eliminate any confusion about how
 * ConcourseConnect can be used and distributed.
 *
 * ConcourseConnect 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 Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with ConcourseConnect.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Attribution Notice: ConcourseConnect is an Original Work of software created
 * by Concursive Corporation
 */

package com.concursive.connect.web.modules.upgrade.utils;

import bsh.Interpreter;
import com.concursive.commons.db.DatabaseUtils;
import com.concursive.commons.text.StringUtils;
import com.concursive.connect.config.ApplicationPrefs;
import com.concursive.connect.Constants;

import javax.servlet.ServletContext;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Utilities for working with upgrade scripts
 *
 * @author matt rajkowski
 * @created February 6, 2009
 */
public class UpgradeUtils {

    private static Log LOG = LogFactory.getLog(UpgradeUtils.class);

    /**
     * Iterates through and executes available database upgrade scripts
     *
     * @param db
     * @param context
     * @return
     * @throws Exception
     */
    public static ArrayList<String> performUpgrade(Connection db, ServletContext context) throws Exception {
        ArrayList<String> installLog = new ArrayList<String>();
        // Load the database versions to check...
        ArrayList<String> versionList = UpgradeUtils
                .retrieveDatabaseVersions(context.getResourceAsStream("/WEB-INF/database/database_versions.txt"));
        for (String version : versionList) {
            if (version.length() == 10) {
                install(context, db, version, installLog);
            }
        }
        return installLog;
    }

    /**
     * Loads the list of available database upgrade scripts
     *
     * @param is
     * @return
     * @throws Exception
     */
    public static ArrayList<String> retrieveDatabaseVersions(InputStream is) throws Exception {
        // The versions are stored in a file
        ArrayList<String> versionList = new ArrayList<String>();
        StringUtils.loadText(is, versionList, true);
        return versionList;
    }

    /**
     * Queries the database to see if the script has already been executed
     *
     * @param db      Description of the Parameter
     * @param version Description of the Parameter
     * @return The installed value
     * @throws java.sql.SQLException Description of the Exception
     */
    public static boolean isInstalled(Connection db, String version) throws SQLException {
        boolean isInstalled = false;
        // Query the installed version
        PreparedStatement pst = db.prepareStatement(
                "SELECT script_version " + "FROM database_version " + "WHERE script_version = ? ");
        pst.setString(1, version);
        ResultSet rs = pst.executeQuery();
        if (rs.next()) {
            isInstalled = true;
        }
        rs.close();
        pst.close();
        return isInstalled;
    }

    /**
     * Records a database version as being executed
     *
     * @param db      The feature to be added to the Version attribute
     * @param version The feature to be added to the Version attribute
     * @throws SQLException Description of the Exception
     */
    public static void addVersion(Connection db, String version) throws SQLException {
        // Add the specified version
        PreparedStatement pst = db.prepareStatement(
                "INSERT INTO database_version " + "(script_filename, script_version) VALUES (?, ?) ");
        pst.setString(1, DatabaseUtils.getTypeName(db) + "_" + version);
        pst.setString(2, version);
        pst.execute();
        pst.close();
    }

    /**
     * Processes the upgrade script if it is not already installed
     *
     * @param context
     * @param db
     * @param versionToInstall
     * @param installLog
     * @throws Exception
     */
    private static void install(ServletContext context, Connection db, String versionToInstall,
            ArrayList<String> installLog) throws Exception {
        if (!isInstalled(db, versionToInstall)) {
            upgradeTXT(context, db, versionToInstall + ".txt");
            installLog.add(versionToInstall + " database changes installed");
            addVersion(db, versionToInstall);
        }
    }

    /**
     * Processes the filenames listed in the specified .txt file and executes either
     * BSH or SQL
     *
     * @param context  the web context to use for finding the file resource
     * @param db       the database connection to use for executing the script against
     * @param baseName The resource filename
     * @throws SQLException Description of the Exception
     */
    private static void upgradeTXT(ServletContext context, Connection db, String baseName) throws Exception {
        String yearString = baseName.substring(0, 4) + "/";
        ArrayList<String> files = new ArrayList<String>();
        StringUtils.loadText(
                context.getResourceAsStream("/WEB-INF/database/upgrade/" + yearString + "upgrade_" + baseName),
                files, true);
        LOG.info("Scripts to process: " + files.size());
        for (String thisFile : files) {
            if (thisFile.endsWith(".bsh")) {
                // Try to run a specified bean shell script if found
                upgradeBSH(context, db, thisFile);
            } else if (thisFile.endsWith(".sql")) {
                // Try to run the specified sql file
                upgradeSQL(context, db, thisFile);
            }
        }
    }

    /**
     * Executes SQL scripts
     *
     * @param context  the web context to use for finding the file resource
     * @param db       the database connection to use for executing the script against
     * @param baseName The resource filename
     * @throws SQLException Description of the Exception
     */
    private static void upgradeSQL(ServletContext context, Connection db, String baseName) throws Exception {
        String dbType = null;
        switch (DatabaseUtils.getType(db)) {
        case DatabaseUtils.POSTGRESQL:
            dbType = "postgresql";
            break;
        case DatabaseUtils.MSSQL:
            dbType = "mssql";
            break;
        default:
            throw new Exception("Upgrade-> * Database could not be determined: " + DatabaseUtils.getType(db));
        }
        String pathString = baseName.substring(0, 4);
        LOG.info("Executing " + dbType + " script: " + baseName);
        DatabaseUtils.executeSQL(db, context.getResourceAsStream(
                "/WEB-INF/database/" + dbType + "/upgrade/" + pathString + "/" + baseName), true);
    }

    /**
     * Executes BSH scripts
     *
     * @param context    the web context to use for finding the file resource
     * @param db         the database connection to use for executing the script against
     * @param scriptName The resource filename
     * @throws Exception Description of the Exception
     */
    private static void upgradeBSH(ServletContext context, Connection db, String scriptName) throws Exception {
        LOG.info("Executing BeanShell script " + scriptName);
        // Prepare bean shell script, if needed
        Interpreter script = new Interpreter();
        script.set("db", db);
        // Add the ApplicationPrefs...
        ApplicationPrefs prefs = (ApplicationPrefs) context.getAttribute(Constants.APPLICATION_PREFS);
        script.set("prefs", prefs);
        // Read the script
        String pathString = scriptName.substring(0, 4);
        String setupPath = "/WEB-INF/database/common/" + pathString + "/";
        InputStream source = context.getResourceAsStream(setupPath + scriptName);
        BufferedReader in = new BufferedReader(new InputStreamReader(source));
        // Execute the script
        script.eval(in);
        in.close();
    }

}