/*
* Copyright 2008-2012 Amazon Technologies, Inc.
*
* 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://aws.amazon.com/apache2.0
*
* This file 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 com.amazonaws.eclipse.datatools.enablement.simpledb.driver;
import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
import com.amazonaws.eclipse.datatools.enablement.simpledb.internal.driver.JdbcDatabaseMetaData;
import com.amazonaws.eclipse.datatools.enablement.simpledb.internal.driver.JdbcPreparedStatement;
import com.amazonaws.eclipse.datatools.enablement.simpledb.internal.driver.JdbcStatement;
import com.amazonaws.services.simpledb.AmazonSimpleDB;
/**
* JDBC Connection wrapper around AmazonSimpleDB driver.
*/
public class JdbcConnection implements Connection {
private JdbcDriver driver;
private String accessKey;
private String secretKey;
private boolean readOnly = false;
private boolean autoCommit = true;
private JdbcDatabaseMetaData metaData;
/** Map of domain_name to list of attribute_name, where attributes are temporary ones not yet existing in the SDB. */
private Map<String, List<String>> pendingColumns = new HashMap<String, List<String>>();
/** The SimpleDB service endpoint this JDBC driver will talk to */
private final String endpoint;
/**
* Creates a new JDBC connection to Amazon SimpleDB, using the specified
* driver to connect to the specified endpoint, and the access key and
* secret key to authenticate.
*
* @param driver
* The SimpleDB JDBC Driver object to use to communicate to
* SimpleDB.
* @param accessKey
* The AWS access key for the desired account.
* @param secretKey
* The AWS secret access key for the desired account.
* @param endpoint
* The Amazon SimpleDB endpoint to communicate with.
*/
public JdbcConnection(final JdbcDriver driver, final String accessKey, final String secretKey, final String endpoint) {
this.driver = driver;
this.accessKey = accessKey;
this.secretKey = secretKey;
this.endpoint = endpoint;
}
/**
* @return an instance of the AmazonSDB driver
*/
public AmazonSimpleDB getClient() {
try {
return this.driver.getClient(this.accessKey, this.secretKey, this.endpoint);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void clearWarnings() throws SQLException {
}
public void close() throws SQLException {
this.driver = null;
this.accessKey = null;
this.secretKey = null;
}
public void commit() throws SQLException {
assertOpen();
// close();
}
public void rollback() throws SQLException {
assertOpen();
// close();
}
private void assertCursorOptions(final int resultSetType, final int resultSetConcurrency,
final int resultSetHoldability) throws SQLException {
if (resultSetType != ResultSet.TYPE_FORWARD_ONLY) {
throw new SQLException("Only TYPE_FORWARD_ONLY cursor is supported"); //$NON-NLS-1$
}
if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY) {
throw new SQLException("Only CONCUR_READ_ONLY cursor is supported"); //$NON-NLS-1$
}
if (resultSetHoldability != ResultSet.CLOSE_CURSORS_AT_COMMIT) {
throw new SQLException("Only CLOSE_CURSORS_AT_COMMIT is supported"); //$NON-NLS-1$
}
}
private void assertOpen() throws SQLException {
if (this.driver == null) {
throw new SQLException("database connection closed"); //$NON-NLS-1$
}
}
public Statement createStatement() throws SQLException {
return createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT);
}
public Statement createStatement(final int resultSetType, final int resultSetConcurrency) throws SQLException {
return createStatement(resultSetType, resultSetConcurrency, ResultSet.CLOSE_CURSORS_AT_COMMIT);
}
public Statement createStatement(final int resultSetType, final int resultSetConcurrency,
final int resultSetHoldability) throws SQLException {
assertCursorOptions(resultSetType, resultSetConcurrency, resultSetHoldability);
return new JdbcStatement(this);
}
public boolean getAutoCommit() throws SQLException {
return this.autoCommit;
}
public String getCatalog() throws SQLException {
assertOpen();
return null;
}
public void setCatalog(final String catalog) throws SQLException {
assertOpen();
}
public int getHoldability() throws SQLException {
assertOpen();
return ResultSet.CLOSE_CURSORS_AT_COMMIT;
}
public void setHoldability(final int holdability) throws SQLException {
assertOpen();
if (holdability != ResultSet.CLOSE_CURSORS_AT_COMMIT) {
throw new SQLException("Only CLOSE_CURSORS_AT_COMMIT cursor is supported"); //$NON-NLS-1$
}
}
public DatabaseMetaData getMetaData() throws SQLException {
if (this.metaData == null) {
this.metaData = new JdbcDatabaseMetaData(this);
}
return this.metaData;
}
public SQLWarning getWarnings() throws SQLException {
return null;
}
public boolean isClosed() throws SQLException {
return this.driver == null;
}
public boolean isReadOnly() throws SQLException {
return this.readOnly;
}
public String nativeSQL(final String sql) throws SQLException {
return sql;
}
public CallableStatement prepareCall(final String sql) throws SQLException {
return prepareCall(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT);
}
public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency)
throws SQLException {
return prepareCall(sql, resultSetType, resultSetConcurrency, ResultSet.CLOSE_CURSORS_AT_COMMIT);
}
public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency,
final int resultSetHoldability) throws SQLException {
throw new SQLException("SimpleDB does not support Stored Procedures"); //$NON-NLS-1$
}
public PreparedStatement prepareStatement(final String sql) throws SQLException {
return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
ResultSet.CLOSE_CURSORS_AT_COMMIT);
}
public PreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys) throws SQLException {
// NB! ignores autoGeneratedKeys
return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
ResultSet.CLOSE_CURSORS_AT_COMMIT);
}
public PreparedStatement prepareStatement(final String sql, final int[] columnIndexes) throws SQLException {
// NB! ignores columnIndexes
return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
ResultSet.CLOSE_CURSORS_AT_COMMIT);
}
public PreparedStatement prepareStatement(final String sql, final String[] columnNames) throws SQLException {
// NB! ignores columnNames
return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
ResultSet.CLOSE_CURSORS_AT_COMMIT);
}
public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency)
throws SQLException {
return prepareStatement(sql, resultSetType, resultSetConcurrency, ResultSet.CLOSE_CURSORS_AT_COMMIT);
}
public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency,
final int resultSetHoldability) throws SQLException {
assertCursorOptions(resultSetType, resultSetConcurrency, resultSetHoldability);
return new JdbcPreparedStatement(this, sql);
}
public void setAutoCommit(final boolean autoCommit) throws SQLException {
this.autoCommit = autoCommit;
}
public void setReadOnly(final boolean readOnly) throws SQLException {
this.readOnly = readOnly;
}
public int getTransactionIsolation() {
return TRANSACTION_SERIALIZABLE;
}
public void setTransactionIsolation(final int level) throws SQLException {
if (level != TRANSACTION_SERIALIZABLE) {
throw new SQLException("SDB supports only TRANSACTION_SERIALIZABLE"); //$NON-NLS-1$
}
}
// NOT SUPPORTED ////////////////////////////////////////////////////////////
public Map<String, Class<?>> getTypeMap() throws SQLException {
throw new SQLException("unsupported by SDB yet"); //$NON-NLS-1$
}
public void setTypeMap(final Map<String, Class<?>> map) throws SQLException {
throw new SQLException("unsupported by SDB yet"); //$NON-NLS-1$
}
public Savepoint setSavepoint() throws SQLException {
throw new SQLException("unsupported by SDB yet"); //$NON-NLS-1$
}
public Savepoint setSavepoint(final String name) throws SQLException {
throw new SQLException("unsupported by SDB yet"); //$NON-NLS-1$
}
public void releaseSavepoint(final Savepoint savepoint) throws SQLException {
throw new SQLException("unsupported by SDB yet"); //$NON-NLS-1$
}
public void rollback(final Savepoint savepoint) throws SQLException {
throw new SQLException("unsupported by SDB yet"); //$NON-NLS-1$
}
//////////////////////////////////////////////////////////////////////////////
/**
* Temporarily holds an attribute which can't be added directly to SDB without a value.
*
* @param table
* domain name
* @param column
* attribute name
*/
public void addPendingColumn(final String table, final String column) {
List<String> columns = this.pendingColumns.get(table);
if (columns == null) {
columns = new ArrayList<String>();
this.pendingColumns.put(table, columns);
}
if (!columns.contains(column)) {
columns.add(column);
}
}
/**
* Removes temporary attribute when it's no longer needed.
*
* @param table
* @param column
* @return <code>true</code> if pending columns list contained the specified column
*/
public boolean removePendingColumn(final String table, final String column) {
List<String> columns = this.pendingColumns.get(table);
if (columns != null) {
boolean result = columns.remove(column);
if (columns.isEmpty()) {
this.pendingColumns.remove(table);
}
return result;
}
return false;
}
/**
* A list of temporary attributes to be returned by JDBC driver, but not existing in SDB yet since there is no values.
*
* @param table
* domain name
* @return list of attribute names
*/
public List<String> getPendingColumns(final String table) {
return this.pendingColumns.get(table);
}
public Array createArrayOf(final String typeName, final Object[] elements)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
public Blob createBlob() throws SQLException {
// TODO Auto-generated method stub
return null;
}
public Clob createClob() throws SQLException {
// TODO Auto-generated method stub
return null;
}
public NClob createNClob() throws SQLException {
// TODO Auto-generated method stub
return null;
}
public SQLXML createSQLXML() throws SQLException {
// TODO Auto-generated method stub
return null;
}
public Struct createStruct(final String typeName, final Object[] attributes)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
public Properties getClientInfo() throws SQLException {
// TODO Auto-generated method stub
return null;
}
public String getClientInfo(final String name) throws SQLException {
// TODO Auto-generated method stub
return null;
}
public boolean isValid(final int timeout) throws SQLException {
// TODO Auto-generated method stub
return false;
}
public void setClientInfo(final Properties properties)
throws SQLClientInfoException {
// TODO Auto-generated method stub
}
public void setClientInfo(final String name, final String value)
throws SQLClientInfoException {
// TODO Auto-generated method stub
}
public boolean isWrapperFor(final Class<?> arg0) throws SQLException {
// TODO Auto-generated method stub
return false;
}
public <T> T unwrap(final Class<T> arg0) throws SQLException {
// TODO Auto-generated method stub
return null;
}
public void setSchema(String schema) throws SQLException {
}
public String getSchema() throws SQLException {
return null;
}
public void abort(Executor executor) throws SQLException {
}
public void setNetworkTimeout(Executor executor, int milliseconds)
throws SQLException {
}
public int getNetworkTimeout() throws SQLException {
return 0;
}
}