]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-5978: RunSqlScript init handler now reads and executes SQL script files from...
authorAron Roberts <aron@socrates.berkeley.edu>
Tue, 23 Apr 2013 03:07:12 +0000 (20:07 -0700)
committerAron Roberts <aron@socrates.berkeley.edu>
Tue, 23 Apr 2013 03:07:12 +0000 (20:07 -0700)
services/common-api/src/main/java/org/collectionspace/services/common/api/FileTools.java
services/common/src/main/cspace/config/services/resources/db/mysql/.gitignore [new file with mode: 0644]
services/common/src/main/cspace/config/services/resources/db/postgresql/.gitignore [new file with mode: 0644]
services/common/src/main/java/org/collectionspace/services/common/ServiceMain.java
services/common/src/main/java/org/collectionspace/services/common/init/RunSqlScripts.java

index 3e4f04ca1fad933e87aa6234d7bb3efe39b7260d..6b6eacab12d0e9e7913dd5b91aba6d0b0f30db30 100644 (file)
@@ -146,8 +146,13 @@ public class FileTools {
     }\r
 \r
     public static String readFile(String dir, String relPath){\r
+        File theFile = new File(dir, relPath);\r
+        return readFile(theFile);\r
+\r
+    }\r
+    \r
+    public static String readFile(File theFile){\r
         try {\r
-            File theFile = new File(dir, relPath);\r
             FileInputStream fis = new FileInputStream(theFile);\r
             byte[] theData = new byte[(int) theFile.length()];\r
             // need to check the number of bytes read here\r
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 (file)
index 0000000..e69de29
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 (file)
index 0000000..e69de29
index def363563e0538a2e93a5969aa8469def4c0f5fc..17b249a6fffd40589597e09cd097d238c28b761e 100644 (file)
@@ -366,12 +366,15 @@ public class ServiceMain {
         return serverRootDir;\r
     }\r
     \r
+    /**\r
+     * @return the server resources path\r
+     */\r
+    public String getServerResourcesPath() {\r
+        return getServerRootDir() + File.separator + ConfigReader.RESOURCES_DIR_PATH + File.separator;\r
+    }\r
+    \r
     public InputStream getResourceAsStream(String resourceName) throws FileNotFoundException {\r
-       InputStream result = null;\r
-       \r
-       String resourcePath = getServerRootDir() + File.separator + ConfigReader.RESOURCES_DIR_PATH + File.separator + resourceName;\r
-       result = new FileInputStream(new File(resourcePath));\r
-       \r
+       InputStream result = new FileInputStream(new File(getServerResourcesPath() + resourceName));\r
        return result;\r
     }\r
 \r
index f6baf86f5d2a5902f97ee06164ae7bb3fd2d4ab9..0ac977b5e330d0594f3a736d8bc486747cd7ee4a 100644 (file)
 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<String> 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<File> 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<File>() {
+            @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<String> getSqlScriptNames(List<Property> properties) {
-        String scriptName = "";
-        List<String> scriptNames = new ArrayList<String>();
+        String scriptName;
+        List<String> 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<File> getSqlScriptFiles(String dataSourceName, String repositoryName) throws Exception {
+        List<File> 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);
             }
         }
     }