package pt.utl.ist.codeGenerator.database; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.util.regex.Matcher; public class Upgrade { private static final String CRLF = System.getProperty("line.separator"); private UpgradeType upgradeType = UpgradeType.UPGRADE_DIRECT_SIMPLE; private File sqlFile = null; private String upgradeComment = null; private static String dbName = null; private static String user = null; private static String password = null; private static String dbDDLClientSchemaExecute = "mysql -u${username} -f -p${password} ${dbname} < ${file}"; private static String dbDDLClientSchemaExecuteToTempFile = "mysql -u${username} -f -p${password} ${dbname} < ${file} > ${tempfile};"; private static boolean keepDDLTempFile = false; public Upgrade(UpgradeType upgradeType, File sqlFile, String upgradeComment) { this.sqlFile = sqlFile; this.upgradeComment = upgradeComment; } public void execUpgrade() throws IOException, InterruptedException { if (this.upgradeComment != null && upgradeComment.length() > 0) System.out.print(" Executing upgrade " + upgradeComment + " Result: "); else System.out.print(" Executing sql upgrade " + sqlFile.getName() + " Result: "); if (upgradeType == UpgradeType.UPGRADE_DIRECT_SIMPLE) System.out .println(executeDDLDirect(dbName, user, password, sqlFile) ? "OK" : "Failed"); else if (upgradeType == UpgradeType.UPGRADE_DIRECT_WITH_TEMP_FILE) System.out.println(executeDDLDirectToTempFile(dbName, user, password, sqlFile) ? "OK" : "Failed"); else { System.out.println("Failed!"); System.out .println(" Don't know how to execute upgrade of type " + upgradeType); } } private boolean executeDDLDirect(String dbname, String username, String password, File ddlFile) throws IOException, InterruptedException { String ddlExecuteLine = dbDDLClientSchemaExecute.replaceAll( "\\$\\{username\\}", Matcher.quoteReplacement(username)) .replaceAll("\\$\\{password\\}", Matcher.quoteReplacement(password)).replaceAll( "\\$\\{dbname\\}", Matcher.quoteReplacement(dbname)) .replaceAll("\\$\\{file\\}", Matcher.quoteReplacement(ddlFile.getAbsolutePath())); String[] command = ddlExecuteLine.split(" "); ProcessBuilder pBuild = new ProcessBuilder(command); pBuild.directory(new File(System.getProperty("temp.dir"))); ProcessRunner pRunner = new ProcessRunner(pBuild); if (!pRunner.exitedOK()) pRunner.writeOutProcess(); return pRunner.exitedOK(); } private boolean executeDDLDirectToTempFile(String dbname, String username, String password, File ddlFile) throws IOException, InterruptedException { File generateDir = ddlFile.getParentFile(); File tempFile = File.createTempFile("", "_generated_from_" + ddlFile.getName(), generateDir); String ddlExecuteLine = dbDDLClientSchemaExecuteToTempFile.replaceAll( "\\$\\{username\\}", Matcher.quoteReplacement(username)) .replaceAll("\\$\\{password\\}", Matcher.quoteReplacement(password)).replaceAll( "\\$\\{dbname\\}", Matcher.quoteReplacement(dbname)) .replaceAll("\\$\\{file\\}", Matcher.quoteReplacement(ddlFile.getAbsolutePath())) .replaceAll("\\$\\{tempfile\\}", Matcher.quoteReplacement(tempFile.getAbsolutePath())); String[] command = ddlExecuteLine.split(" "); ProcessBuilder pBuild = new ProcessBuilder(command); pBuild.directory(new File(System.getProperty("temp.dir"))); ProcessRunner pRunner = new ProcessRunner(pBuild); if (!pRunner.exitedOK()) pRunner.writeOutProcess(); boolean execResult = pRunner.exitedOK(); if (execResult) { execResult = executeDDLDirect(dbname, username, password, tempFile); } if (!keepDDLTempFile && tempFile.exists() && tempFile.canWrite()) tempFile.delete(); return execResult; } private class ProcessRunner { private Process p = null; private BufferedReader errorReader = null; private BufferedReader inReader = null; private int exitValue = 0; private StringBuffer errorDesc = new StringBuffer(""); private StringBuffer output = new StringBuffer(""); public ProcessRunner(ProcessBuilder pBuild) throws IOException, InterruptedException { pBuild.redirectErrorStream(false); p = pBuild.start(); errorReader = new BufferedReader(new InputStreamReader(p .getErrorStream())); inReader = new BufferedReader(new InputStreamReader(p .getInputStream())); exitValue = p.waitFor(); String lineTemp = null; while ((lineTemp = errorReader.readLine()) != null) errorDesc.append(lineTemp).append(CRLF); while ((lineTemp = inReader.readLine()) != null) output.append(lineTemp).append(CRLF); } public boolean exitedOK() { return exitValue == 0; } public String getError() { return errorDesc.toString(); } public String getOuput() { return output.toString(); } public boolean isErrorAvailable() { return errorDesc.length() != 0; } public boolean isOutputAvailable() { return output.length() != 0; } public void writeOutProcess() { System.out.println("The process " + (exitedOK() ? " executed correctly" : " had a problem executing") + "!"); if (!exitedOK()) { System.out.println("The exit value from the process was " + exitValue); if (isErrorAvailable()) { System.out .println("Error description returned by the process was: "); System.out.println(getError()); } else System.out .println("No further error descriptions from the process"); } if (isOutputAvailable()) { System.out .println("The process also returned this information:"); System.out.println(getOuput()); } } } private enum UpgradeType { UPGRADE_DIRECT_SIMPLE("execute"), UPGRADE_DIRECT_WITH_TEMP_FILE( "executeWithTempFile"); private String functionName = null; private UpgradeType(String functionName) { this.functionName = functionName; } public static UpgradeType findUpgradeTypeFromExecLine(String execLine) { for (UpgradeType type : UpgradeType.values()) if (execLine.startsWith(type.functionName + " ")) return type; return null; } } public static Upgrade parseUpgradeFromExecLine(File baseDir, String execLine) { UpgradeType type = UpgradeType.findUpgradeTypeFromExecLine(execLine); String fileName = ""; if (type != null) { String[] commandLine = execLine.split(" "); if (commandLine.length >= 2) { // The type is the first String... // The file is the last fileName = commandLine[commandLine.length - 1]; File sqlFile = new File(baseDir, fileName); if (!sqlFile.exists() || !sqlFile.canRead() || !sqlFile.isFile()) return null; // The rest of the command line... join in again - it is a comment... String comment = ""; for (int i = 1; i < commandLine.length - 1; i++) { comment += " " + commandLine[i]; } comment = comment.trim(); return new Upgrade(type, sqlFile, comment); } } return null; } public static String getDbDDLClientSchemaExecute() { return dbDDLClientSchemaExecute; } public static void setDbDDLClientSchemaExecute(String dbDDLClientSchemaExecute) { Upgrade.dbDDLClientSchemaExecute = dbDDLClientSchemaExecute; } public static String getDbDDLClientSchemaExecuteToTempFile() { return dbDDLClientSchemaExecuteToTempFile; } public static void setDbDDLClientSchemaExecuteToTempFile( String dbDDLClientSchemaExecuteToTempFile) { Upgrade.dbDDLClientSchemaExecuteToTempFile = dbDDLClientSchemaExecuteToTempFile; } public static String getDbName() { return dbName; } public static void setDbName(String dbName) { Upgrade.dbName = dbName; } public static String getPassword() { return password; } public static void setPassword(String password) { Upgrade.password = password; } public static String getUser() { return user; } public static void setUser(String user) { Upgrade.user = user; } public static boolean isKeepDDLTempFile() { return keepDDLTempFile; } public static void setKeepDDLTempFile(boolean keepDDLTempFile) { Upgrade.keepDDLTempFile = keepDDLTempFile; } }