org.h2.command.dml.ScriptBase Maven / Gradle / Ivy
/*
* Copyright 2004-2019 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (https://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.dml;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.h2.api.ErrorCode;
import org.h2.api.JavaObjectSerializer;
import org.h2.command.Prepared;
import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.engine.SysProperties;
import org.h2.expression.Expression;
import org.h2.message.DbException;
import org.h2.pagestore.db.LobStorageBackend;
import org.h2.security.SHA256;
import org.h2.store.DataHandler;
import org.h2.store.FileStore;
import org.h2.store.FileStoreInputStream;
import org.h2.store.FileStoreOutputStream;
import org.h2.store.fs.FileUtils;
import org.h2.tools.CompressTool;
import org.h2.util.IOUtils;
import org.h2.util.SmallLRUCache;
import org.h2.util.StringUtils;
import org.h2.util.TempFileDeleter;
import org.h2.value.CompareMode;
/**
* This class is the base for RunScriptCommand and ScriptCommand.
*/
abstract class ScriptBase extends Prepared implements DataHandler {
/**
* The default name of the script file if .zip compression is used.
*/
private static final String SCRIPT_SQL = "script.sql";
/**
* The output stream.
*/
protected OutputStream out;
/**
* The input stream.
*/
protected InputStream in;
/**
* The file name (if set).
*/
private Expression fileNameExpr;
private Expression password;
private String fileName;
private String cipher;
private FileStore store;
private String compressionAlgorithm;
ScriptBase(Session session) {
super(session);
}
public void setCipher(String c) {
cipher = c;
}
private boolean isEncrypted() {
return cipher != null;
}
public void setPassword(Expression password) {
this.password = password;
}
public void setFileNameExpr(Expression file) {
this.fileNameExpr = file;
}
protected String getFileName() {
if (fileNameExpr != null && fileName == null) {
fileName = fileNameExpr.optimize(session).getValue(session).getString();
if (fileName == null || StringUtils.isWhitespaceOrEmpty(fileName)) {
fileName = "script.sql";
}
fileName = SysProperties.getScriptDirectory() + fileName;
}
return fileName;
}
@Override
public boolean isTransactional() {
return false;
}
/**
* Delete the target file.
*/
void deleteStore() {
String file = getFileName();
if (file != null) {
FileUtils.delete(file);
}
}
private void initStore() {
Database db = session.getDatabase();
byte[] key = null;
if (cipher != null && password != null) {
char[] pass = password.optimize(session).
getValue(session).getString().toCharArray();
key = SHA256.getKeyPasswordHash("script", pass);
}
String file = getFileName();
store = FileStore.open(db, file, "rw", cipher, key);
store.setCheckedWriting(false);
store.init();
}
/**
* Open the output stream.
*/
void openOutput() {
String file = getFileName();
if (file == null) {
return;
}
if (isEncrypted()) {
initStore();
out = new FileStoreOutputStream(store, this, compressionAlgorithm);
// always use a big buffer, otherwise end-of-block is written a lot
out = new BufferedOutputStream(out, Constants.IO_BUFFER_SIZE_COMPRESS);
} else {
OutputStream o;
try {
o = FileUtils.newOutputStream(file, false);
} catch (IOException e) {
throw DbException.convertIOException(e, null);
}
out = new BufferedOutputStream(o, Constants.IO_BUFFER_SIZE);
out = CompressTool.wrapOutputStream(out, compressionAlgorithm, SCRIPT_SQL);
}
}
/**
* Open the input stream.
*/
void openInput() {
String file = getFileName();
if (file == null) {
return;
}
if (isEncrypted()) {
initStore();
in = new FileStoreInputStream(store, this, compressionAlgorithm != null, false);
} else {
InputStream inStream;
try {
inStream = FileUtils.newInputStream(file);
} catch (IOException e) {
throw DbException.convertIOException(e, file);
}
in = new BufferedInputStream(inStream, Constants.IO_BUFFER_SIZE);
in = CompressTool.wrapInputStream(in, compressionAlgorithm, SCRIPT_SQL);
if (in == null) {
throw DbException.get(ErrorCode.FILE_NOT_FOUND_1, SCRIPT_SQL + " in " + file);
}
}
}
/**
* Close input and output streams.
*/
void closeIO() {
IOUtils.closeSilently(out);
out = null;
IOUtils.closeSilently(in);
in = null;
if (store != null) {
store.closeSilently();
store = null;
}
}
@Override
public boolean needRecompile() {
return false;
}
@Override
public String getDatabasePath() {
return null;
}
@Override
public FileStore openFile(String name, String mode, boolean mustExist) {
return null;
}
@Override
public void checkPowerOff() {
session.getDatabase().checkPowerOff();
}
@Override
public void checkWritingAllowed() {
session.getDatabase().checkWritingAllowed();
}
@Override
public int getMaxLengthInplaceLob() {
return session.getDatabase().getMaxLengthInplaceLob();
}
@Override
public TempFileDeleter getTempFileDeleter() {
return session.getDatabase().getTempFileDeleter();
}
@Override
public String getLobCompressionAlgorithm(int type) {
return session.getDatabase().getLobCompressionAlgorithm(type);
}
public void setCompressionAlgorithm(String algorithm) {
this.compressionAlgorithm = algorithm;
}
@Override
public Object getLobSyncObject() {
return this;
}
@Override
public SmallLRUCache getLobFileListCache() {
return null;
}
@Override
public LobStorageBackend getLobStorage() {
return null;
}
@Override
public int readLob(long lobId, byte[] hmac, long offset, byte[] buff,
int off, int length) {
throw DbException.throwInternalError();
}
@Override
public JavaObjectSerializer getJavaObjectSerializer() {
return session.getDataHandler().getJavaObjectSerializer();
}
@Override
public CompareMode getCompareMode() {
return session.getDataHandler().getCompareMode();
}
}