File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\upgrade\DbUpgrade.java.html

1 /*
2 * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
3 * Version 1.0, and under the Eclipse Public License, Version 1.0
4 * (http://h2database.com/html/license.html).
5 * Initial Developer: H2 Group
6 */
7 package org.h2.upgrade;
8
9 import java.io.File;
10 import java.sql.Connection;
11 import java.sql.DriverManager;
12 import java.sql.SQLException;
13 import java.sql.Statement;
14 import java.util.Properties;
15 import java.util.UUID;
16 import org.h2.engine.ConnectionInfo;
17 import org.h2.jdbc.JdbcConnection;
18 import org.h2.message.DbException;
19 import org.h2.store.fs.FileUtils;
20 import org.h2.util.StringUtils;
21 import org.h2.util.Utils;
22
23 /**
24 * This class starts the conversion from older database versions to the current
25 * version if the respective classes are found.
26 */
27 public class DbUpgrade {
28
29 private static final boolean UPGRADE_CLASSES_PRESENT;
30
31 private static boolean scriptInTempDir;
32 private static boolean deleteOldDb;
33
34 static {
35 UPGRADE_CLASSES_PRESENT = Utils.isClassPresent("org.h2.upgrade.v1_1.Driver");
36 }
37
38 /**
39 * If the upgrade classes are present, upgrade the database, or connect
40 * using the old version (if the parameter NO_UPGRADE is set to true). If
41 * the database is upgraded, or if no upgrade is possible or needed, this
42 * methods returns null.
43 *
44 * @param url the database URL
45 * @param info the properties
46 * @return the connection if connected with the old version (NO_UPGRADE)
47 */
48 public static Connection connectOrUpgrade(String url, Properties info) throws SQLException {
49 if (!UPGRADE_CLASSES_PRESENT) {
50 return null;
51 }
52 Properties i2 = new Properties();
53 i2.putAll(info);
54 // clone so that the password (if set as a char array) is not cleared
55 Object o = info.get("password");
56 if (o instanceof char[]) {
57 i2.put("password", StringUtils.cloneCharArray((char[]) o));
58 }
59 info = i2;
60 ConnectionInfo ci = new ConnectionInfo(url, info);
61 if (ci.isRemote() || !ci.isPersistent()) {
62 return null;
63 }
64 String name = ci.getName();
65 if (FileUtils.exists(name + ".h2.db")) {
66 return null;
67 }
68 if (!FileUtils.exists(name + ".data.db")) {
69 return null;
70 }
71 if (ci.removeProperty("NO_UPGRADE", false)) {
72 return connectWithOldVersion(url, info);
73 }
74 synchronized (DbUpgrade.class) {
75 upgrade(ci, info);
76 return null;
77 }
78 }
79
80 /**
81 * The conversion script file will per default be created in the db
82 * directory. Use this method to change the directory to the temp
83 * directory.
84 *
85 * @param scriptInTempDir true if the conversion script should be
86 * located in the temp directory.
87 */
88 public static void setScriptInTempDir(boolean scriptInTempDir) {
89 DbUpgrade.scriptInTempDir = scriptInTempDir;
90 }
91
92 /**
93 * Old files will be renamed to .backup after a successful conversion. To
94 * delete them after the conversion, use this method with the parameter
95 * 'true'.
96 *
97 * @param deleteOldDb if true, the old db files will be deleted.
98 */
99 public static void setDeleteOldDb(boolean deleteOldDb) {
100 DbUpgrade.deleteOldDb = deleteOldDb;
101 }
102
103 private static Connection connectWithOldVersion(String url, Properties info) throws SQLException {
104 url = "jdbc:h2v1_1:" + url.substring("jdbc:h2:".length()) + ";IGNORE_UNKNOWN_SETTINGS=TRUE";
105 return DriverManager.getConnection(url, info);
106 }
107
108 private static void upgrade(ConnectionInfo ci, Properties info) throws SQLException {
109 String name = ci.getName();
110 String data = name + ".data.db";
111 String index = name + ".index.db";
112 String lobs = name + ".lobs.db";
113 String backupData = data + ".backup";
114 String backupIndex = index + ".backup";
115 String backupLobs = lobs + ".backup";
116 String script = null;
117 try {
118 if (scriptInTempDir) {
119 new File(Utils.getProperty("java.io.tmpdir", ".")).mkdirs();
120 script = File.createTempFile("h2dbmigration", "backup.sql").getAbsolutePath();
121 } else {
122 script = name + ".script.sql";
123 }
124 String oldUrl = "jdbc:h2v1_1:" + name + ";UNDO_LOG=0;LOG=0;LOCK_MODE=0";
125 String cipher = ci.getProperty("CIPHER", null);
126 if (cipher != null) {
127 oldUrl += ";CIPHER=" + cipher;
128 }
129 Connection conn = DriverManager.getConnection(oldUrl, info);
130 Statement stat = conn.createStatement();
131 String uuid = UUID.randomUUID().toString();
132 if (cipher != null) {
133 stat.execute("script to '" + script + "' cipher aes password '" + uuid + "' --hide--");
134 } else {
135 stat.execute("script to '" + script + "'");
136 }
137 conn.close();
138 FileUtils.moveTo(data, backupData);
139 FileUtils.moveTo(index, backupIndex);
140 if (FileUtils.exists(lobs)) {
141 FileUtils.moveTo(lobs, backupLobs);
142 }
143 ci.removeProperty("IFEXISTS", false);
144 conn = new JdbcConnection(ci, true);
145 stat = conn.createStatement();
146 if (cipher != null) {
147 stat.execute("runscript from '" + script + "' cipher aes password '" + uuid + "' --hide--");
148 } else {
149 stat.execute("runscript from '" + script + "'");
150 }
151 stat.execute("analyze");
152 stat.execute("shutdown compact");
153 stat.close();
154 conn.close();
155 if (deleteOldDb) {
156 FileUtils.delete(backupData);
157 FileUtils.delete(backupIndex);
158 FileUtils.deleteRecursive(backupLobs, false);
159 }
160 } catch (Exception e) {
161 if (FileUtils.exists(backupData)) {
162 FileUtils.moveTo(backupData, data);
163 }
164 if (FileUtils.exists(backupIndex)) {
165 FileUtils.moveTo(backupIndex, index);
166 }
167 if (FileUtils.exists(backupLobs)) {
168 FileUtils.moveTo(backupLobs, lobs);
169 }
170 FileUtils.delete(name + ".h2.db");
171 throw DbException.toSQLException(e);
172 } finally {
173 if (script != null) {
174 FileUtils.delete(script);
175 }
176 }
177 }
178
179 }
180