File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\command\dml\BackupCommand.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.command.dml;
8
9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.io.OutputStream;
12 import java.util.ArrayList;
13 import java.util.zip.ZipEntry;
14 import java.util.zip.ZipOutputStream;
15 import org.h2.api.DatabaseEventListener;
16 import org.h2.command.CommandInterface;
17 import org.h2.command.Prepared;
18 import org.h2.constant.ErrorCode;
19 import org.h2.engine.Constants;
20 import org.h2.engine.Database;
21 import org.h2.engine.Session;
22 import org.h2.expression.Expression;
23 import org.h2.message.DbException;
24 import org.h2.result.ResultInterface;
25 import org.h2.store.FileLister;
26 import org.h2.store.PageStore;
27 import org.h2.store.fs.FileUtils;
28 import org.h2.util.IOUtils;
29
30 /**
31 * This class represents the statement
32 * BACKUP
33 */
34 public class BackupCommand extends Prepared {
35
36 private Expression fileNameExpr;
37
38 public BackupCommand(Session session) {
39 super(session);
40 }
41
42 public void setFileName(Expression fileName) {
43 this.fileNameExpr = fileName;
44 }
45
46 public int update() {
47 String name = fileNameExpr.getValue(session).getString();
48 session.getUser().checkAdmin();
49 backupTo(name);
50 return 0;
51 }
52
53 private void backupTo(String fileName) {
54 Database db = session.getDatabase();
55 if (!db.isPersistent()) {
56 throw DbException.get(ErrorCode.DATABASE_IS_NOT_PERSISTENT);
57 }
58 try {
59 String name = db.getName();
60 name = FileUtils.getName(name);
61 OutputStream zip = FileUtils.newOutputStream(fileName, false);
62 ZipOutputStream out = new ZipOutputStream(zip);
63 db.flush();
64 String fn = db.getName() + Constants.SUFFIX_PAGE_FILE;
65 backupPageStore(out, fn, db.getPageStore());
66 // synchronize on the database, to avoid concurrent temp file
67 // creation / deletion / backup
68 String base = FileUtils.getParent(fn);
69 synchronized (db.getLobSyncObject()) {
70 String prefix = db.getDatabasePath();
71 String dir = FileUtils.getParent(prefix);
72 dir = FileLister.getDir(dir);
73 ArrayList<String> fileList = FileLister.getDatabaseFiles(dir, name, true);
74 for (String n : fileList) {
75 if (n.endsWith(Constants.SUFFIX_LOB_FILE)) {
76 backupFile(out, base, n);
77 }
78 }
79 }
80 out.close();
81 zip.close();
82 } catch (IOException e) {
83 throw DbException.convertIOException(e, fileName);
84 }
85 }
86
87 private void backupPageStore(ZipOutputStream out, String fileName, PageStore store) throws IOException {
88 Database db = session.getDatabase();
89 fileName = FileUtils.getName(fileName);
90 out.putNextEntry(new ZipEntry(fileName));
91 int pos = 0;
92 try {
93 store.setBackup(true);
94 while (true) {
95 pos = store.copyDirect(pos, out);
96 if (pos < 0) {
97 break;
98 }
99 int max = store.getPageCount();
100 db.setProgress(DatabaseEventListener.STATE_BACKUP_FILE, fileName, pos, max);
101 }
102 } finally {
103 store.setBackup(false);
104 }
105 out.closeEntry();
106 }
107
108 private static void backupFile(ZipOutputStream out, String base, String fn) throws IOException {
109 String f = FileUtils.toRealPath(fn);
110 base = FileUtils.toRealPath(base);
111 if (!f.startsWith(base)) {
112 DbException.throwInternalError(f + " does not start with " + base);
113 }
114 f = f.substring(base.length());
115 f = correctFileName(f);
116 out.putNextEntry(new ZipEntry(f));
117 InputStream in = FileUtils.newInputStream(fn);
118 IOUtils.copyAndCloseInput(in, out);
119 out.closeEntry();
120 }
121
122 public boolean isTransactional() {
123 return true;
124 }
125
126 /**
127 * Fix the file name, replacing backslash with slash.
128 *
129 * @param f the file name
130 * @return the corrected file name
131 */
132 public static String correctFileName(String f) {
133 f = f.replace('\\', '/');
134 if (f.startsWith("/")) {
135 f = f.substring(1);
136 }
137 return f;
138 }
139
140 public boolean needRecompile() {
141 return false;
142 }
143
144 public ResultInterface queryMeta() {
145 return null;
146 }
147
148 public int getType() {
149 return CommandInterface.BACKUP;
150 }
151
152 }
153