1 19 20 package com.sslexplorer.jdbc; 21 22 import java.io.BufferedReader ; 23 import java.io.File ; 24 import java.io.FileInputStream ; 25 import java.io.FileOutputStream ; 26 import java.io.IOException ; 27 import java.io.InputStream ; 28 import java.io.InputStreamReader ; 29 import java.io.OutputStream ; 30 import java.io.PrintWriter ; 31 import java.sql.SQLException ; 32 import java.util.ArrayList ; 33 import java.util.Collections ; 34 import java.util.HashMap ; 35 import java.util.Iterator ; 36 import java.util.List ; 37 import java.util.Properties ; 38 import java.util.prefs.Preferences ; 39 40 import org.apache.commons.logging.Log; 41 import org.apache.commons.logging.LogFactory; 42 43 import com.sslexplorer.boot.ContextHolder; 44 import com.sslexplorer.boot.Util; 45 import com.sslexplorer.boot.VersionInfo; 46 47 59 public class DBUpgrader { 60 61 final static Log log = LogFactory.getLog(DBUpgrader.class); 62 63 private static HashMap removed = new HashMap (); 65 private static HashMap removeProcessed = new HashMap (); 66 67 69 private JDBCDatabaseEngine engine; 70 private File dbDir; 71 private VersionInfo.Version newDbVersion; 72 private File upgradeDir; 73 private File versionsFile; 74 private boolean useDbNameForVersionCheck; 75 76 84 public DBUpgrader(VersionInfo.Version newDbVersion, JDBCDatabaseEngine engine, File dbDir, File upgradeDir) { 85 this(null, newDbVersion, engine, dbDir, upgradeDir); 86 } 87 88 97 public DBUpgrader(File versionsFile, VersionInfo.Version newDbVersion, JDBCDatabaseEngine engine, File dbDir, File upgradeDir) { 98 this(versionsFile, newDbVersion, engine, dbDir, upgradeDir, false); 99 } 100 101 112 public DBUpgrader(File versionsFile, VersionInfo.Version newDbVersion, JDBCDatabaseEngine engine, File dbDir, File upgradeDir, 113 boolean useDbNameForVersionCheck) { 114 super(); 115 this.versionsFile = versionsFile; 116 this.upgradeDir = upgradeDir; 117 this.engine = engine; 118 this.dbDir = dbDir; 119 this.newDbVersion = newDbVersion; 120 this.useDbNameForVersionCheck = useDbNameForVersionCheck; 121 } 122 123 128 public void upgrade() throws Exception { 129 Properties versions = null; 130 if (versionsFile == null) { 131 134 versionsFile = new File (ContextHolder.getContext().getDBDirectory(), "versions.log"); 135 Preferences p = ContextHolder.getContext().getPreferences().node("dbupgrader"); 136 if (p.nodeExists("currentDataVersion")) { 137 log.warn("Migrating database versions from preferences to properties file in " 138 + ContextHolder.getContext().getDBDirectory().getAbsolutePath() + "."); 139 versions = new Properties (); 140 p = p.node("currentDataVersion"); 141 String [] c = p.keys(); 142 for (int i = 0; i < c.length; i++) { 143 versions.put(c[i], p.get(c[i], "")); 144 } 145 FileOutputStream fos = new FileOutputStream (versionsFile); 146 try { 147 versions.store(fos, "SSL-Explorer Database versions"); 148 } finally { 149 Util.closeStream(fos); 150 } 151 p.removeNode(); 152 } 153 } 154 155 if (versions == null) { 157 versions = new Properties (); 158 if (versionsFile.exists()) { 159 FileInputStream fin = new FileInputStream (versionsFile); 160 try { 161 versions.load(fin); 162 } finally { 163 Util.closeStream(fin); 164 } 165 } 166 } 167 168 try { 169 String dbCheckName = useDbNameForVersionCheck ? engine.getDatabase() : engine.getAlias(); 170 171 if ((!engine.isDatabaseExists() || removed.containsKey(engine.getDatabase())) 172 && !removeProcessed.containsKey(dbCheckName)) { 173 versions.remove(dbCheckName); 174 removeProcessed.put(dbCheckName, Boolean.TRUE); 175 if (log.isInfoEnabled()) 176 log.info("Database for " + dbCheckName + " (" + engine.getDatabase() 177 + ") has been removed, assuming this is a re-install."); 178 removed.put(engine.getDatabase(), Boolean.TRUE); 179 } 180 181 VersionInfo.Version currentDataVersion = new VersionInfo.Version(versions.getProperty(dbCheckName, "0.0.0")); 184 if (log.isInfoEnabled()) { 185 log.info("New logical database version for " + engine.getAlias() + " is " + newDbVersion); 186 log.info("Current logical database version for " + engine.getAlias() + " is " + currentDataVersion); 187 log.info("Upgrade script directory is " + upgradeDir.getAbsolutePath()); 189 } 190 List upgrades = getSortedUpgrades(upgradeDir); 191 File oldLog = new File (upgradeDir, "upgrade.log"); 192 if (!dbDir.exists()) { 193 if (!dbDir.mkdirs()) { 194 throw new Exception ("Failed to create database directory " + dbDir.getAbsolutePath()); 195 } 196 } 197 File logFile = new File (dbDir, "upgrade.log"); 198 if (oldLog.exists()) { 199 if (log.isInfoEnabled()) 200 log.info("Moving upgrade.log to new location (as of version 0.1.5 it resides in the db directory."); 201 if (!oldLog.renameTo(logFile)) { 202 throw new Exception ("Failed to move upgrade log file from " + oldLog.getAbsolutePath() + " to " 203 + logFile.getAbsolutePath()); 204 } 205 } 206 HashMap completedUpgrades = new HashMap (); 207 if (!logFile.exists()) { 208 OutputStream out = null; 209 try { 210 out = new FileOutputStream (logFile); 211 PrintWriter writer = new PrintWriter (out, true); 212 writer.println("# This file contains a list of database upgrades"); 213 writer.println("# that have completed correctly."); 214 } finally { 215 if (out != null) { 216 out.flush(); 217 out.close(); 218 } 219 } 220 } else { 221 InputStream in = null; 222 try { 223 in = new FileInputStream (logFile); 224 BufferedReader reader = new BufferedReader (new InputStreamReader (in)); 225 String line = null; 226 while ((line = reader.readLine()) != null) { 227 line = line.trim(); 228 if (!line.equals("") && !line.startsWith("#")) { 229 completedUpgrades.put(line, line); 230 } 231 } 232 } finally { 233 if (in != null) { 234 in.close(); 235 } 236 } 237 } 238 OutputStream out = null; 239 try { 240 out = new FileOutputStream (logFile, true); 241 PrintWriter writer = new PrintWriter (out, true); 242 Class.forName("org.hsqldb.jdbcDriver"); for (Iterator i = upgrades.iterator(); i.hasNext();) { 247 DBUpgradeOp upgrade = (DBUpgradeOp) i.next(); 248 boolean runBefore = completedUpgrades.containsKey(upgrade.getFile().getName()); 249 if (log.isInfoEnabled()) 250 log.info("Checking if upgrade " + upgrade.getFile() + " [" + upgrade.getVersion() 251 + "] needs to be run. Run before = " + runBefore + ". Current data version = " 252 + currentDataVersion + ", upgrade version = " + upgrade.getVersion()); 253 if ((!runBefore || (currentDataVersion.getMajor() == 0 && currentDataVersion.getMinor() == 0 && currentDataVersion 254 .getBuild() == 0)) 255 && upgrade.getVersion().compareTo(currentDataVersion) >= 0 256 && upgrade.getVersion().compareTo(newDbVersion) < 0) { 257 if (log.isInfoEnabled()) 258 log.info("Running script " + upgrade.getName() + " [" + upgrade.getVersion() + "] on database " 259 + engine.getDatabase()); 260 261 JDBCConnectionImpl conx = engine.aquireConnection(); 263 try { 264 runSQLScript(conx, upgrade.getFile()); 265 completedUpgrades.put(upgrade.getFile().getName(), upgrade.getFile().getName()); 266 writer.println(upgrade.getFile().getName()); 267 } finally { 268 engine.releaseConnection(conx); 269 } 270 } 271 } 272 versions.put(dbCheckName, newDbVersion.toString()); 273 274 if (log.isInfoEnabled()) 275 log.info("Logical database " + engine.getAlias() + " (" + engine.getDatabase() + ") is now at version " 276 + newDbVersion); 277 } finally { 278 if (out != null) { 279 out.flush(); 280 out.close(); 281 } 282 } 283 } finally { 284 FileOutputStream fos = new FileOutputStream (versionsFile); 285 try { 286 versions.store(fos, "SSL-Explorer Database versions"); 287 } finally { 288 Util.closeStream(fos); 289 } 290 } 291 } 292 293 private List getSortedUpgrades(File upgradeDir) { 294 List sortedUpgrades = new ArrayList (); 295 File [] files = upgradeDir.listFiles(); 296 for (int i = 0; files != null && i < files.length; i++) { 297 String n = files[i].getName(); 298 if (n.endsWith(engine.getAlias() + ".sql")) { 299 sortedUpgrades.add(new DBUpgradeOp(files[i])); 300 } else { 301 if (log.isDebugEnabled()) 302 log.debug("Skipping script " + n); 303 } 304 305 } 306 Collections.sort(sortedUpgrades); 307 return sortedUpgrades; 308 } 309 310 private void runSQLScript(JDBCConnectionImpl con, File sqlFile) throws SQLException , IllegalStateException , IOException { 311 312 InputStream in = null; 313 try { 314 in = new FileInputStream (sqlFile); 315 BufferedReader reader = new BufferedReader (new InputStreamReader (in)); 316 String line = null; 317 StringBuffer cmdBuffer = new StringBuffer (); 318 boolean quoted = false; 319 char ch; 320 while ((line = reader.readLine()) != null) { 321 line = line.trim(); 322 if (!line.equals("") && !line.startsWith("//") && !line.startsWith("--") && !line.startsWith("#")) { 323 quoted = false; 324 for (int i = 0; i < line.length(); i++) { 325 ch = line.charAt(i); 326 if (ch == '\'') { 327 if (quoted) { 328 if ((i + 1) < line.length() && line.charAt(i + 1) == '\'') { 329 i++; 330 cmdBuffer.append(ch); 331 } else { 332 quoted = false; 333 } 334 } else { 335 quoted = true; 336 } 337 cmdBuffer.append(ch); 338 } else if (ch == ';' && !quoted) { 339 if (cmdBuffer.length() > 0) { 340 executeSQLStatement(con, cmdBuffer.toString()); 341 cmdBuffer.setLength(0); 342 } 343 } else { 344 if (i == 0 && ch != ' ' && cmdBuffer.length() > 0 && !quoted) { 345 cmdBuffer.append(' '); 346 } 347 cmdBuffer.append(ch); 348 } 349 } 350 } 351 } 352 if (cmdBuffer.length() > 0) { 353 executeSQLStatement(con, cmdBuffer.toString()); 354 cmdBuffer.setLength(0); 355 } 356 } finally { 357 if (in != null) { 358 in.close(); 359 } 360 } 361 } 362 363 private void executeSQLStatement(JDBCConnectionImpl con, String cmd) throws SQLException { 364 380 if (cmd.startsWith("CREATE ALIAS ")) { 381 int idx = cmd.indexOf("com.sslexplorer.DBFunctions."); 382 if (idx != -1) { 383 cmd = cmd.substring(0, idx) + "com.sslexplorer.server.hsqldb.DBFunctions." + cmd.substring(idx + 28); 384 } 385 idx = cmd.indexOf("com.sslexplorer.server.hsqldb.DBFunctions."); 386 if (idx != -1) { 387 cmd = cmd.substring(0, idx) + "com.sslexplorer.jdbc.hsqldb.DBFunctions." + cmd.substring(idx + 42); 388 } 389 390 } 391 392 if (log.isDebugEnabled()) 393 log.debug("Executing \"" + cmd + "\""); 394 con.execute(cmd); 395 } 396 397 } 398 | Popular Tags |