@Override public Value createBlob(InputStream in, long maxLength) { init(); int type = Value.BLOB; if (maxLength < 0) { maxLength = Long.MAX_VALUE; } int max = (int) Math.min(maxLength, database.getMaxLengthInplaceLob()); try { if (max != 0 && max < Integer.MAX_VALUE) { BufferedInputStream b = new BufferedInputStream(in, max); b.mark(max); byte[] small = new byte[max]; int len = IOUtils.readFully(b, small, max); if (len < max) { if (len < small.length) { small = Arrays.copyOf(small, len); } return ValueLobDb.createSmallLob(type, small); } b.reset(); in = b; } if (maxLength != Long.MAX_VALUE) { in = new LimitInputStream(in, maxLength); } return createLob(in, type); } catch (IllegalStateException e) { throw DbException.get(ErrorCode.OBJECT_CLOSED, e); } catch (IOException e) { throw DbException.convertIOException(e, null); } }
@Override public Value convertPrecision(long precision, boolean force) { if (this.precision <= precision) { return this; } ValueLobDb lob; if (type == CLOB) { if (handler == null) { try { int p = MathUtils.convertLongToInt(precision); String s = IOUtils.readStringAndClose(getReader(), p); byte[] data = s.getBytes(Constants.UTF8); lob = ValueLobDb.createSmallLob(type, data, s.length()); } catch (IOException e) { throw DbException.convertIOException(e, null); } } else { lob = ValueLobDb.createTempClob(getReader(), precision, handler); } } else { if (handler == null) { try { int p = MathUtils.convertLongToInt(precision); byte[] data = IOUtils.readBytesAndClose(getInputStream(), p); lob = ValueLobDb.createSmallLob(type, data, data.length); } catch (IOException e) { throw DbException.convertIOException(e, null); } } else { lob = ValueLobDb.createTempBlob(getInputStream(), precision, handler); } } return lob; }
/** * Create a temporary BLOB value from a stream. * * @param in the input stream * @param length the number of characters to read, or -1 for no limit * @param handler the data handler * @return the lob value */ public static ValueLobDb createTempBlob(InputStream in, long length, DataHandler handler) { try { long remaining = Long.MAX_VALUE; boolean compress = handler.getLobCompressionAlgorithm(Value.BLOB) != null; if (length >= 0 && length < remaining) { remaining = length; } int len = getBufferSize(handler, compress, remaining); byte[] buff; if (len >= Integer.MAX_VALUE) { buff = IOUtils.readBytesAndClose(in, -1); len = buff.length; } else { buff = DataUtils.newBytes(len); len = IOUtils.readFully(in, buff, len); } if (len <= handler.getMaxLengthInplaceLob()) { byte[] small = DataUtils.newBytes(len); System.arraycopy(buff, 0, small, 0, len); return ValueLobDb.createSmallLob(Value.BLOB, small, small.length); } ValueLobDb lob = new ValueLobDb(handler, buff, len, in, remaining); return lob; } catch (IOException e) { throw DbException.convertIOException(e, null); } }
public OutputStream newOutputStream(boolean append) { try { return new FileChannelOutputStream(open("rw"), append); } catch (IOException e) { throw DbException.convertIOException(e, name); } }
/** * Create a temporary CLOB value from a stream. * * @param in the reader * @param length the number of characters to read, or -1 for no limit * @param handler the data handler * @return the lob value */ public static ValueLobDb createTempClob(Reader in, long length, DataHandler handler) { BufferedReader reader; if (in instanceof BufferedReader) { reader = (BufferedReader) in; } else { reader = new BufferedReader(in, Constants.IO_BUFFER_SIZE); } try { boolean compress = handler.getLobCompressionAlgorithm(Value.CLOB) != null; long remaining = Long.MAX_VALUE; if (length >= 0 && length < remaining) { remaining = length; } int len = getBufferSize(handler, compress, remaining); char[] buff; if (len >= Integer.MAX_VALUE) { String data = IOUtils.readStringAndClose(reader, -1); buff = data.toCharArray(); len = buff.length; } else { buff = new char[len]; reader.mark(len); len = IOUtils.readFully(reader, buff, len); } if (len <= handler.getMaxLengthInplaceLob()) { byte[] small = new String(buff, 0, len).getBytes(Constants.UTF8); return ValueLobDb.createSmallLob(Value.CLOB, small, len); } reader.reset(); ValueLobDb lob = new ValueLobDb(handler, reader, remaining); return lob; } catch (IOException e) { throw DbException.convertIOException(e, null); } }
public OutputStream openFileOutputStream(String fileName, boolean append) { try { return new FileObjectOutputStream(openFileObject(fileName, "rw"), append); } catch (IOException e) { throw DbException.convertIOException(e, fileName); } }
public void copy(String original, String copy) { try { OutputStream out = openFileOutputStream(copy, false); InputStream in = openFileInputStream(original); IOUtils.copyAndClose(in, out); } catch (IOException e) { rollback(); throw DbException.convertIOException(e, "Can not copy " + original + " to " + copy); } }
public boolean createNewFile(String fileName) { try { if (exists(fileName)) { return false; } openFileObject(fileName, "rw").close(); return true; } catch (IOException e) { throw DbException.convertIOException(e, fileName); } }
@Override public byte[] getBytesNoCopy() { if (type == CLOB) { // convert hex to string return super.getBytesNoCopy(); } if (small != null) { return small; } try { return IOUtils.readBytesAndClose(getInputStream(), Integer.MAX_VALUE); } catch (IOException e) { throw DbException.convertIOException(e, toString()); } }
@Override public InputStream getInputStream() { if (small != null) { return new ByteArrayInputStream(small); } else if (fileName != null) { FileStore store = handler.openFile(fileName, "r", true); boolean alwaysClose = SysProperties.lobCloseBetweenReads; return new BufferedInputStream( new FileStoreInputStream(store, handler, false, alwaysClose), Constants.IO_BUFFER_SIZE); } long byteCount = (type == Value.BLOB) ? precision : -1; try { return handler.getLobStorage().getInputStream(this, hmac, byteCount); } catch (IOException e) { throw DbException.convertIOException(e, toString()); } }
@Override public String getString() { int len = precision > Integer.MAX_VALUE || precision == 0 ? Integer.MAX_VALUE : (int) precision; try { if (type == Value.CLOB) { if (small != null) { return new String(small, Constants.UTF8); } return IOUtils.readStringAndClose(getReader(), len); } byte[] buff; if (small != null) { buff = small; } else { buff = IOUtils.readBytesAndClose(getInputStream(), len); } return StringUtils.convertBytesToHex(buff); } catch (IOException e) { throw DbException.convertIOException(e, toString()); } }
@Override public Value createClob(Reader reader, long maxLength) { init(); int type = Value.CLOB; if (maxLength < 0) { maxLength = Long.MAX_VALUE; } int max = (int) Math.min(maxLength, database.getMaxLengthInplaceLob()); try { if (max != 0 && max < Integer.MAX_VALUE) { BufferedReader b = new BufferedReader(reader, max); b.mark(max); char[] small = new char[max]; int len = IOUtils.readFully(b, small, max); if (len < max) { if (len < small.length) { small = Arrays.copyOf(small, len); } byte[] utf8 = new String(small, 0, len).getBytes(Constants.UTF8); return ValueLobDb.createSmallLob(type, utf8); } b.reset(); reader = b; } CountingReaderInputStream in = new CountingReaderInputStream(reader, maxLength); ValueLobDb lob = createLob(in, type); // the length is not correct lob = ValueLobDb.create(type, database, lob.getTableId(), lob.getLobId(), null, in.getLength()); return lob; } catch (IllegalStateException e) { throw DbException.get(ErrorCode.OBJECT_CLOSED, e); } catch (IOException e) { throw DbException.convertIOException(e, null); } }
/** * Restores database files. * * @param zipFileName the name of the backup file * @param directory the directory name * @param db the database name (null for all databases) * @throws DbException if there is an IOException */ public static void execute(String zipFileName, String directory, String db) { InputStream in = null; try { if (!FileUtils.exists(zipFileName)) { throw new IOException("File not found: " + zipFileName); } String originalDbName = null; int originalDbLen = 0; if (db != null) { originalDbName = getOriginalDbName(zipFileName, db); if (originalDbName == null) { throw new IOException("No database named " + db + " found"); } if (originalDbName.startsWith(SysProperties.FILE_SEPARATOR)) { originalDbName = originalDbName.substring(1); } originalDbLen = originalDbName.length(); } in = FileUtils.newInputStream(zipFileName); ZipInputStream zipIn = new ZipInputStream(in); while (true) { ZipEntry entry = zipIn.getNextEntry(); if (entry == null) { break; } String fileName = entry.getName(); // restoring windows backups on linux and vice versa fileName = fileName.replace('\\', SysProperties.FILE_SEPARATOR.charAt(0)); fileName = fileName.replace('/', SysProperties.FILE_SEPARATOR.charAt(0)); if (fileName.startsWith(SysProperties.FILE_SEPARATOR)) { fileName = fileName.substring(1); } boolean copy = false; if (db == null) { copy = true; } else if (fileName.startsWith(originalDbName + ".")) { fileName = db + fileName.substring(originalDbLen); copy = true; } if (copy) { OutputStream o = null; try { o = FileUtils.newOutputStream( directory + SysProperties.FILE_SEPARATOR + fileName, false); IOUtils.copy(zipIn, o); o.close(); } finally { IOUtils.closeSilently(o); } } zipIn.closeEntry(); } zipIn.closeEntry(); zipIn.close(); } catch (IOException e) { throw DbException.convertIOException(e, zipFileName); } finally { IOUtils.closeSilently(in); } }
private void connectServer(ConnectionInfo ci) { String name = ci.getName(); if (name.startsWith("//")) { name = name.substring("//".length()); } int idx = name.indexOf('/'); if (idx < 0) { throw ci.getFormatException(); } databaseName = name.substring(idx + 1); String server = name.substring(0, idx); traceSystem = new TraceSystem(null); String traceLevelFile = ci.getProperty(SetTypes.TRACE_LEVEL_FILE, null); if (traceLevelFile != null) { int level = Integer.parseInt(traceLevelFile); String prefix = getFilePrefix(SysProperties.CLIENT_TRACE_DIRECTORY); try { traceSystem.setLevelFile(level); if (level > 0 && level < 4) { String file = FileUtils.createTempFile(prefix, Constants.SUFFIX_TRACE_FILE, false, false); traceSystem.setFileName(file); } } catch (IOException e) { throw DbException.convertIOException(e, prefix); } } String traceLevelSystemOut = ci.getProperty(SetTypes.TRACE_LEVEL_SYSTEM_OUT, null); if (traceLevelSystemOut != null) { int level = Integer.parseInt(traceLevelSystemOut); traceSystem.setLevelSystemOut(level); } trace = traceSystem.getTrace(Trace.JDBC); String serverList = null; if (server.indexOf(',') >= 0) { serverList = StringUtils.quoteStringSQL(server); ci.setProperty("CLUSTER", Constants.CLUSTERING_ENABLED); } autoReconnect = Boolean.parseBoolean(ci.getProperty("AUTO_RECONNECT", "false")); // AUTO_SERVER implies AUTO_RECONNECT boolean autoServer = Boolean.parseBoolean(ci.getProperty("AUTO_SERVER", "false")); if (autoServer && serverList != null) { throw DbException.getUnsupportedException("autoServer && serverList != null"); } autoReconnect |= autoServer; if (autoReconnect) { String className = ci.getProperty("DATABASE_EVENT_LISTENER"); if (className != null) { className = StringUtils.trim(className, true, true, "'"); try { eventListener = (DatabaseEventListener) JdbcUtils.loadUserClass(className).newInstance(); } catch (Throwable e) { throw DbException.convert(e); } } } cipher = ci.getProperty("CIPHER"); if (cipher != null) { fileEncryptionKey = MathUtils.secureRandomBytes(32); } String[] servers = StringUtils.arraySplit(server, ',', true); int len = servers.length; transferList.clear(); sessionId = StringUtils.convertBytesToHex(MathUtils.secureRandomBytes(32)); // TODO cluster: support more than 2 connections boolean switchOffCluster = false; try { for (int i = 0; i < len; i++) { String s = servers[i]; try { Transfer trans = initTransfer(ci, databaseName, s); transferList.add(trans); } catch (IOException e) { if (len == 1) { throw DbException.get(ErrorCode.CONNECTION_BROKEN_1, e, e + ": " + s); } switchOffCluster = true; } } checkClosed(); if (switchOffCluster) { switchOffCluster(); } checkClusterDisableAutoCommit(serverList); } catch (DbException e) { traceSystem.close(); throw e; } }