/* * Copyright 2012 pcal.net * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.pcal.sqlsheet; import org.apache.poi.ss.usermodel.Workbook; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.nio.channels.FileChannel; import java.sql.*; import java.util.Map; import java.util.Properties; import java.util.concurrent.Executor; import java.util.logging.Level; import java.util.logging.Logger; /** * SqlSheet implementation of java.sql.Connection. * * @author <a href='http://www.pcal.net'>pcal</a> * @author <a href='http://code.google.com/p/sqlsheet'>sqlsheet</a> */ class XlsConnection implements Connection { private static final Logger logger = Logger.getLogger(XlsConnection.class.getName()); private Workbook workbook; private File saveFile; private Properties info; private boolean writeRequired; XlsConnection(Workbook workbook, Properties info) { this(workbook, null, info); } XlsConnection(Workbook workbook, File saveFile, Properties info) { if (workbook == null) { throw new IllegalArgumentException(); } this.workbook = workbook; this.saveFile = saveFile; this.info = info; } int getInt(String key, int defaultValue) { Object value = info.get(key); if (value == null) { logger.fine(String.format("Key [%s] not present.", key)); return defaultValue; } return Integer.parseInt(value.toString()); } Workbook getWorkBook() { return workbook; } public Statement createStatement() throws SQLException { return new XlsStatement(this); } public PreparedStatement prepareStatement(String sql) throws SQLException { return new XlsPreparedStatement(this, sql); } public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { return prepareStatement(sql); } public void close() throws SQLException { if (saveFile == null || !writeRequired) { return; } try { OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(saveFile)); workbook.write(outputStream); outputStream.close(); } catch (IOException exception) { throw new SQLException("Error while persisting changes.", exception); } } public void _close() throws SQLException { if (saveFile != null && writeRequired) { FileOutputStream fileOut; try { File newFile = File.createTempFile("xlsdriver", "xlsx"); fileOut = new FileOutputStream(newFile); workbook.write(fileOut); if (fileOut != null) { try { fileOut.close(); } catch (IOException e) { logger.log(Level.WARNING, e.getMessage(), e); } } //Move already existing data to not corrupt on fail File backup = backupFile(saveFile); logger.log(Level.INFO, "Created backup:" + backup.getAbsolutePath()); //Try to override file with new content //backup should rename file or copy content into new one, handle second condition if (saveFile.exists() && !saveFile.delete()) { logger.log(Level.WARNING, "Unable to delete file:" + saveFile.getAbsolutePath() + ", you may lose the results."); } moveFile(newFile, saveFile); } catch (IOException ioe) { SQLException sqe = new SQLException(ioe.getMessage()); sqe.initCause(sqe); throw sqe; } } } private File backupFile(File input) throws IOException { File output = null; if (input != null) { output = File.createTempFile(input.getName() + ".", ".bkp", null); moveFile(input, output); } return output; } private void moveFile(File sourceFile, File destFile) throws IOException { boolean moved; moved = sourceFile.renameTo(destFile); if (!moved) { logger.log(Level.WARNING, "Unable to rename file during move:" + sourceFile.getAbsolutePath()+" to "+destFile.getAbsolutePath()+", performing full copy of data."); FileChannel source = null; FileChannel destination = null; try { source = new FileInputStream(sourceFile).getChannel(); destination = new FileOutputStream(destFile).getChannel(); // previous code: destination.transferFrom(source, 0, source.size()); // to avoid infinite loops, should be: long count = 0; long size = source.size(); do { count += destination.transferFrom(source, 0, size - count); } while (count < size); } finally { if (source != null) { source.close(); } if (destination != null) { destination.close(); } } } } public boolean getAutoCommit() { return false; } public void setAutoCommit(boolean autoCommit) throws SQLException { nyi(); } public boolean isClosed() { return false; } public boolean isReadOnly() { return true; } public void setReadOnly(boolean readOnly) throws SQLException { nyi(); } public String getCatalog() { return null; } public void setCatalog(String catalog) throws SQLException { nyi(); } public int getTransactionIsolation() { return Connection.TRANSACTION_NONE; } public void setTransactionIsolation(int level) throws SQLException { nyi(); } public SQLWarning getWarnings() { return null; } @SuppressWarnings("unchecked") public Map getTypeMap() throws SQLException { return null; } public void setTypeMap(Map<String, Class<?>> map) throws SQLException { nyi(); } public void commit() throws SQLException { } public void rollback() throws SQLException { } public void clearWarnings() throws SQLException { } public DatabaseMetaData getMetaData() throws SQLException { return new XlsDatabaseMetaData(); } public CallableStatement prepareCall(String sql) throws SQLException { nyi(); return null; } public String nativeSQL(String sql) throws SQLException { nyi(); return null; } public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { nyi(); return null; } public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { nyi(); return null; } public int getHoldability() throws SQLException { nyi(); return -1; } public void setHoldability(int param) throws SQLException { nyi(); } public CallableStatement prepareCall(String str, int param, int param2, int param3) throws SQLException { nyi(); return null; } public PreparedStatement prepareStatement(String str, int param) throws SQLException { nyi(); return null; } public PreparedStatement prepareStatement(String str, int[] values) throws SQLException { nyi(); return null; } public PreparedStatement prepareStatement(String str, String[] str1) throws SQLException { nyi(); return null; } public Clob createClob() throws SQLException { nyi(); return null; } public Blob createBlob() throws SQLException { nyi(); return null; } public NClob createNClob() throws SQLException { nyi(); return null; } public SQLXML createSQLXML() throws SQLException { nyi(); return null; } public boolean isValid(int timeout) throws SQLException { nyi(); return false; } public void setClientInfo(String name, String value) throws SQLClientInfoException { } public String getClientInfo(String name) throws SQLException { nyi(); return null; } public Properties getClientInfo() throws SQLException { nyi(); return null; } public void setClientInfo(Properties properties) throws SQLClientInfoException { } public Array createArrayOf(String typeName, Object[] elements) throws SQLException { nyi(); return null; } public Struct createStruct(String typeName, Object[] attributes) throws SQLException { nyi(); return null; } public PreparedStatement prepareStatement(String str, int param, int param2, int param3) throws SQLException { nyi(); return null; } public void releaseSavepoint(Savepoint savepoint) throws SQLException { nyi(); } public void rollback(Savepoint savepoint) throws SQLException { nyi(); } public Savepoint setSavepoint() throws SQLException { nyi(); return null; } public Savepoint setSavepoint(String str) throws SQLException { nyi(); return null; } public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { nyi(); return null; } private void nyi() throws SQLException { throw new SQLException("NYI"); } public <T> T unwrap(Class<T> iface) throws SQLException { nyi(); return null; } public boolean isWrapperFor(Class<?> iface) throws SQLException { nyi(); return false; } public Boolean getWriteRequired() { return writeRequired; } public void setWriteRequired(Boolean writeRequired) { this.writeRequired = writeRequired; } public String getSchema() throws SQLException { throw new UnsupportedOperationException("Not supported yet."); } public void setSchema(String string) throws SQLException { throw new UnsupportedOperationException("Not supported yet."); } public void abort(Executor exctr) throws SQLException { throw new UnsupportedOperationException("Not supported yet."); } public void setNetworkTimeout(Executor exctr, int i) throws SQLException { throw new UnsupportedOperationException("Not supported yet."); } public int getNetworkTimeout() throws SQLException { throw new UnsupportedOperationException("Not supported yet."); } }