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