From: Aron Roberts Date: Tue, 23 Apr 2013 03:07:12 +0000 (-0700) Subject: CSPACE-5978: RunSqlScript init handler now reads and executes SQL script files from... X-Git-Url: https://git.aero2k.de/?a=commitdiff_plain;h=736ce635ae02a497ded89647c6736130cbe8014e;p=tmp%2Fjakarta-migration.git CSPACE-5978: RunSqlScript init handler now reads and executes SQL script files from within a server directory, as well as from within its own JAR-packaged resources directory. SQL scripts in its own resources directory are run first, in the order they are specified in the services tenant bindings file. Thereafter, SQL scripts in the server directory are run in ascending filename order. --- diff --git a/services/common-api/src/main/java/org/collectionspace/services/common/api/FileTools.java b/services/common-api/src/main/java/org/collectionspace/services/common/api/FileTools.java index 3e4f04ca1..6b6eacab1 100644 --- a/services/common-api/src/main/java/org/collectionspace/services/common/api/FileTools.java +++ b/services/common-api/src/main/java/org/collectionspace/services/common/api/FileTools.java @@ -146,8 +146,13 @@ public class FileTools { } public static String readFile(String dir, String relPath){ + File theFile = new File(dir, relPath); + return readFile(theFile); + + } + + public static String readFile(File theFile){ try { - File theFile = new File(dir, relPath); FileInputStream fis = new FileInputStream(theFile); byte[] theData = new byte[(int) theFile.length()]; // need to check the number of bytes read here diff --git a/services/common/src/main/cspace/config/services/resources/db/mysql/.gitignore b/services/common/src/main/cspace/config/services/resources/db/mysql/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/services/common/src/main/cspace/config/services/resources/db/postgresql/.gitignore b/services/common/src/main/cspace/config/services/resources/db/postgresql/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/services/common/src/main/java/org/collectionspace/services/common/ServiceMain.java b/services/common/src/main/java/org/collectionspace/services/common/ServiceMain.java index def363563..17b249a6f 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/ServiceMain.java +++ b/services/common/src/main/java/org/collectionspace/services/common/ServiceMain.java @@ -366,12 +366,15 @@ public class ServiceMain { return serverRootDir; } + /** + * @return the server resources path + */ + public String getServerResourcesPath() { + return getServerRootDir() + File.separator + ConfigReader.RESOURCES_DIR_PATH + File.separator; + } + public InputStream getResourceAsStream(String resourceName) throws FileNotFoundException { - InputStream result = null; - - String resourcePath = getServerRootDir() + File.separator + ConfigReader.RESOURCES_DIR_PATH + File.separator + resourceName; - result = new FileInputStream(new File(resourcePath)); - + InputStream result = new FileInputStream(new File(getServerResourcesPath() + resourceName)); return result; } diff --git a/services/common/src/main/java/org/collectionspace/services/common/init/RunSqlScripts.java b/services/common/src/main/java/org/collectionspace/services/common/init/RunSqlScripts.java index f6baf86f5..0ac977b5e 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/init/RunSqlScripts.java +++ b/services/common/src/main/java/org/collectionspace/services/common/init/RunSqlScripts.java @@ -17,12 +17,18 @@ package org.collectionspace.services.common.init; import java.io.BufferedReader; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; +import java.text.Collator; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; +import org.collectionspace.services.common.ServiceMain; +import org.collectionspace.services.common.api.FileTools; import org.collectionspace.services.common.api.Tools; import org.collectionspace.services.common.storage.JDBCTools; import org.collectionspace.services.config.service.InitHandler.Params.Field; @@ -39,6 +45,10 @@ public class RunSqlScripts extends InitHandler implements IInitHandler { private final static String LINE_SEPARATOR = System.getProperty("line.separator"); private final static String CANNOT_PERFORM_TASKS_MESSAGE = "Will not be able to perform tasks within the RunSqlScript init handler."; + // Resource paths use a forward slash ('/') as a separator + // http://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html#getResource%28java.lang.String%29 + private final static String RESOURCE_PATH_SEPARATOR = "/"; + private static String serverResourcesPath; /** * See the class javadoc for this class: it shows the syntax supported in @@ -56,6 +66,11 @@ public class RunSqlScripts extends InitHandler implements IInitHandler { logger.warn(CANNOT_PERFORM_TASKS_MESSAGE); return; } + + // First, run a sequence of SQL scripts, where those scripts may + // optionally be packaged in a resources directory within the + // current code's packaged JAR file. + String scriptContents; List scriptNames = getSqlScriptNames(properties); if (scriptNames == null || scriptNames.isEmpty()) { logger.warn("Could not obtain the name of any SQL script to run."); @@ -69,19 +84,45 @@ public class RunSqlScripts extends InitHandler implements IInitHandler { logger.warn(CANNOT_PERFORM_TASKS_MESSAGE); continue; } - String scriptContents = getSqlScriptContents(scriptPath); + scriptContents = getSqlScriptContents(scriptPath); if (Tools.isBlank(scriptContents)) { - logger.warn("Could not get contents of SQL script."); + logger.warn("Could not get contents of SQL script from resource " + scriptPath); logger.warn(CANNOT_PERFORM_TASKS_MESSAGE); continue; } - runScript(dataSourceName, repositoryName, scriptContents, scriptPath); + runScript(dataSourceName, repositoryName, scriptContents, "resource path " + scriptPath); } + + // Next, run a second sequence of SQL scripts, where those scripts may be + // stored on disk, in a resources directory within the server directory. + List scriptFiles = getSqlScriptFiles(dataSourceName, repositoryName); + // Run these scripts in a sequence based on the ascending order of their filenames. + // FIXME: consider adding functionality to specify the locale for filename + // sorting here. (The current sort order is based on the system's default locale.) + Collections.sort(scriptFiles, new Comparator() { + @Override + public int compare(File f1, File f2) { + return Collator.getInstance().compare(f1.getName(), f2.getName()); + } + }); + + for (File scriptFile : scriptFiles) { + logger.trace("Reading script file " + scriptFile.getCanonicalPath()); + scriptContents = FileTools.readFile(scriptFile); + if (Tools.isBlank(scriptContents)) { + logger.warn("Could not get contents of SQL script from file " + scriptFile.getCanonicalPath()); + logger.warn(CANNOT_PERFORM_TASKS_MESSAGE); + continue; + } + runScript(dataSourceName, repositoryName, scriptContents, "file " + scriptFile.getName()); + } + } private List getSqlScriptNames(List properties) { - String scriptName = ""; - List scriptNames = new ArrayList(); + String scriptName; + List scriptNames = new ArrayList<>(); + // Get SQL script names from tenant bindings configuration for (Property property : properties) { if (property.getKey().equals(SQL_SCRIPT_NAME_PROPERTY)) { scriptName = property.getValue(); @@ -96,13 +137,46 @@ public class RunSqlScripts extends InitHandler implements IInitHandler { private String getSqlScriptPath(String dataSourceName, String repositoryName, String scriptName) throws Exception { String scriptPath = DATABASE_RESOURCE_DIRECTORY_NAME - + "/" + + RESOURCE_PATH_SEPARATOR + JDBCTools.getDatabaseProductType(dataSourceName, repositoryName) - + "/" + + RESOURCE_PATH_SEPARATOR + scriptName; return scriptPath; } + private String getSqlScriptDirectoryPath(String dataSourceName, String repositoryName) throws Exception { + String scriptDirectoryPath = + getServerResourcesDirectoryPath() + + DATABASE_RESOURCE_DIRECTORY_NAME + + File.separator + + JDBCTools.getDatabaseProductType(dataSourceName, repositoryName) + + File.separator; + return scriptDirectoryPath; + } + + private String getServerResourcesDirectoryPath() { + if (Tools.isBlank(serverResourcesPath)) { + serverResourcesPath = ServiceMain.getInstance().getServerResourcesPath(); + } + return serverResourcesPath; + } + + private List getSqlScriptFiles(String dataSourceName, String repositoryName) throws Exception { + List sqlScriptFiles = new ArrayList<>(); + File folder = new File(getSqlScriptDirectoryPath(dataSourceName, repositoryName)); + if (!folder.isDirectory() || !folder.canRead()) { + return sqlScriptFiles; // Return an empty list of files + } + File[] files = folder.listFiles(); + for (File file : files) { + if (file.isFile() && file.canRead()) { + sqlScriptFiles.add(file); + } + // FIXME: Optionally filter by filename extension here, etc. + } + return sqlScriptFiles; + } + private String getSqlScriptContents(String scriptPath) throws Exception { return getStringFromResource(scriptPath); } @@ -167,16 +241,16 @@ public class RunSqlScripts extends InitHandler implements IInitHandler { try { rows = JDBCTools.executeUpdate(dataSourceName, repositoryName, scriptContents); } catch (Throwable e) { - logger.warn("Running SQL script " + scriptPath + " resulted in error: ", e.getMessage()); + logger.warn("Running SQL script from " + scriptPath + " resulted in error: ", e.getMessage()); rows = -1; } // FIXME: Verify which row values represent failure; should there always // be one and only one row returned in a successful response from executeUpdate? if (rows < 0) { - logger.warn("Running SQL script " + scriptPath + " failed to return expected results."); + logger.warn("Running SQL script from " + scriptPath + " failed to return expected results."); } else { if (logger.isInfoEnabled()) { - logger.info("Successfully ran SQL script: " + scriptPath); + logger.info("Successfully ran SQL script from " + scriptPath); } } }