You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by cl...@apache.org on 2020/02/20 19:30:52 UTC
[activemq-artemis] branch master updated: [ARTEMIS-2626]:
Postgresql Journal implementation requires direct access to PostgeSQL
driver internal classes.
This is an automated email from the ASF dual-hosted git repository.
clebertsuconic pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/activemq-artemis.git
The following commit(s) were added to refs/heads/master by this push:
new ac98cda [ARTEMIS-2626]: Postgresql Journal implementation requires direct access to PostgeSQL driver internal classes.
new d3efc24 This closes #2987
ac98cda is described below
commit ac98cda22451f0aaf6e70ded9aca4e234449b0b7
Author: Emmanuel Hugonnet <eh...@redhat.com>
AuthorDate: Thu Feb 20 19:01:38 2020 +0100
[ARTEMIS-2626]: Postgresql Journal implementation requires direct access to PostgeSQL driver internal classes.
Issue: The BLOB manipulation is done using PostgreSQL internal classes starting from PGConnection.
This leads to ClasCastExceptions if the connection is wrapped in a pool or if the driver is in a different classloader (WildFly).
Fix: unwrap the connection and if the PostgreSQL classes are not directly available uses reflection to manipulate the BLOBs.
Jira: https://issues.apache.org/jira/browse/ARTEMIS-2626
---
.../store/file/PostgresLargeObjectManager.java | 209 ++++++++++++
.../PostgresSequentialSequentialFileDriver.java | 46 ++-
.../file/JDBCSequentialFileFactoryTest.java | 4 +-
.../store/file/PostgresLargeObjectManagerTest.java | 362 +++++++++++++++++++++
4 files changed, 592 insertions(+), 29 deletions(-)
diff --git a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/PostgresLargeObjectManager.java b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/PostgresLargeObjectManager.java
new file mode 100644
index 0000000..3167c54
--- /dev/null
+++ b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/PostgresLargeObjectManager.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2019 The Apache Software Foundation.
+ *
+ * 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 org.apache.activemq.artemis.jdbc.store.file;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.sql.Connection;
+import java.sql.SQLException;
+import org.postgresql.PGConnection;
+import org.postgresql.largeobject.LargeObject;
+
+/**
+ * Helper class for when the postresql driver is not directly availalbe.
+ */
+public class PostgresLargeObjectManager {
+
+ /**
+ * This mode indicates we want to write to an object
+ */
+ public static final int WRITE = 0x00020000;
+
+ /**
+ * This mode indicates we want to read an object
+ */
+ public static final int READ = 0x00040000;
+
+ /**
+ * This mode is the default. It indicates we want read and write access to
+ * a large object
+ */
+ public static final int READWRITE = READ | WRITE;
+
+ private final Connection realConnection;
+ private boolean shouldUseReflection;
+
+ public PostgresLargeObjectManager(Connection connection) throws SQLException {
+ this.realConnection = unwrap(connection);
+ try {
+ this.getClass().getClassLoader().loadClass("org.postgresql.PGConnection");
+ shouldUseReflection = false;
+ } catch (ClassNotFoundException ex) {
+ shouldUseReflection = true;
+ }
+ }
+
+ public final Long createLO() throws SQLException {
+ if (shouldUseReflection) {
+ Object largeObjectManager = getLargeObjectManager();
+ try {
+ Method method = largeObjectManager.getClass().getMethod("createLO");
+ return (Long) method.invoke(largeObjectManager);
+ } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+ throw new SQLException("Couldn't access org.postgresql.largeobject.LargeObjectManager", ex);
+ }
+ } else {
+ return ((PGConnection) realConnection).getLargeObjectAPI().createLO();
+ }
+ }
+
+ public Object open(long oid, int mode) throws SQLException {
+ if (shouldUseReflection) {
+ Object largeObjectManager = getLargeObjectManager();
+ try {
+ Method method = largeObjectManager.getClass().getMethod("open", long.class, int.class);
+ return method.invoke(largeObjectManager, oid, mode);
+ } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+ throw new SQLException("Couldn't access org.postgresql.largeobject.LargeObjectManager", ex);
+ }
+ } else {
+ return ((PGConnection) realConnection).getLargeObjectAPI().open(oid, mode);
+ }
+ }
+
+ public int size(Object largeObject) throws SQLException {
+ if (shouldUseReflection) {
+ try {
+ Method method = largeObject.getClass().getMethod("size");
+ return (int) method.invoke(largeObject);
+ } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+ throw new SQLException("Couldn't access org.postgresql.largeobject.LargeObject", ex);
+ }
+ } else {
+ return ((LargeObject) largeObject).size();
+ }
+ }
+
+ public void close(Object largeObject) throws SQLException {
+ if (shouldUseReflection) {
+ try {
+ Method method = largeObject.getClass().getMethod("close");
+ method.invoke(largeObject);
+ } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+ throw new SQLException("Couldn't access org.postgresql.largeobject.LargeObject", ex);
+ }
+ } else {
+ ((LargeObject) largeObject).close();
+ }
+ }
+
+ public byte[] read(Object largeObject, int length) throws SQLException {
+ if (shouldUseReflection) {
+ try {
+ Method method = largeObject.getClass().getMethod("read", int.class);
+ return (byte[]) method.invoke(largeObject, length);
+ } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+ throw new SQLException("Couldn't access org.postgresql.largeobject.LargeObject", ex);
+ }
+ } else {
+ return ((LargeObject) largeObject).read(length);
+ }
+ }
+
+ public void write(Object largeObject, byte[] data) throws SQLException {
+ if (shouldUseReflection) {
+ try {
+ Method method = largeObject.getClass().getMethod("write", byte[].class);
+ method.invoke(largeObject, data);
+ } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+ throw new SQLException("Couldn't access org.postgresql.largeobject.LargeObject", ex);
+ }
+ } else {
+ ((LargeObject) largeObject).write(data);
+ }
+ }
+
+ public void seek(Object largeObject, int position) throws SQLException {
+ if (shouldUseReflection) {
+ try {
+ Method method = largeObject.getClass().getMethod("seek", Integer.class);
+ method.invoke(largeObject, position);
+ } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+ throw new SQLException("Couldn't access org.postgresql.largeobject.LargeObject", ex);
+ }
+ } else {
+ ((LargeObject) largeObject).seek(position);
+ }
+ }
+
+ public void truncate(Object largeObject, int position) throws SQLException {
+ if (shouldUseReflection) {
+ try {
+ Method method = largeObject.getClass().getMethod("truncate", Integer.class);
+ method.invoke(largeObject, position);
+ } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+ throw new SQLException("Couldn't access org.postgresql.largeobject.LargeObject", ex);
+ }
+ } else {
+ ((LargeObject) largeObject).truncate(position);
+ }
+ }
+
+ private Object getLargeObjectManager() throws SQLException {
+ if (shouldUseReflection) {
+ try {
+ Method method = realConnection.getClass().getMethod("getLargeObjectAPI");
+ return method.invoke(realConnection);
+ } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+ throw new SQLException("Couldn't access org.postgresql.largeobject.LargeObjectManager", ex);
+ }
+ } else {
+ return ((PGConnection) realConnection).getLargeObjectAPI();
+ }
+ }
+
+ public final Connection unwrap(Connection connection) throws SQLException {
+ Connection conn = connection.unwrap(Connection.class);
+ return unwrapIronJacamar(unwrapDbcp(unwrapSpring(conn)));
+ }
+
+ private Connection unwrapIronJacamar(Connection conn) {
+ try {
+ Method method = conn.getClass().getMethod("getUnderlyingConnection");
+ return (Connection) method.invoke(conn);
+ } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+ return conn;
+ }
+ }
+
+ private Connection unwrapDbcp(Connection conn) {
+ try {
+ Method method = conn.getClass().getMethod("getDelegate");
+ return (Connection) method.invoke(conn);
+ } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+ return conn;
+ }
+ }
+
+ private Connection unwrapSpring(Connection conn) {
+ try {
+ Method method = conn.getClass().getMethod("getTargetConnection");
+ return (Connection) method.invoke(conn);
+ } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+ return conn;
+ }
+ }
+}
diff --git a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/PostgresSequentialSequentialFileDriver.java b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/PostgresSequentialSequentialFileDriver.java
index 3c68781..7d439da 100644
--- a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/PostgresSequentialSequentialFileDriver.java
+++ b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/PostgresSequentialSequentialFileDriver.java
@@ -23,9 +23,6 @@ import java.sql.SQLException;
import java.sql.Statement;
import org.apache.activemq.artemis.jdbc.store.sql.SQLProvider;
-import org.postgresql.PGConnection;
-import org.postgresql.largeobject.LargeObject;
-import org.postgresql.largeobject.LargeObjectManager;
import javax.sql.DataSource;
@@ -33,6 +30,7 @@ import javax.sql.DataSource;
public final class PostgresSequentialSequentialFileDriver extends JDBCSequentialFileFactoryDriver {
private static final String POSTGRES_OID_KEY = "POSTGRES_OID_KEY";
+ private PostgresLargeObjectManager largeObjectManager;
public PostgresSequentialSequentialFileDriver() throws SQLException {
super();
@@ -52,6 +50,7 @@ public final class PostgresSequentialSequentialFileDriver extends JDBCSequential
@Override
protected void prepareStatements() throws SQLException {
+ this.largeObjectManager = new PostgresLargeObjectManager(connection);
this.deleteFile = connection.prepareStatement(sqlProvider.getDeleteFileSQL());
this.createFile = connection.prepareStatement(sqlProvider.getInsertFileSQL(), Statement.RETURN_GENERATED_KEYS);
this.selectFileByFileName = connection.prepareStatement(sqlProvider.getSelectFileByFileName());
@@ -67,9 +66,7 @@ public final class PostgresSequentialSequentialFileDriver extends JDBCSequential
synchronized (connection) {
try {
connection.setAutoCommit(false);
-
- LargeObjectManager lobjManager = ((PGConnection) connection).getLargeObjectAPI();
- long oid = lobjManager.createLO();
+ Long oid = largeObjectManager.createLO();
createFile.setString(1, file.getFileName());
createFile.setString(2, file.getExtension());
@@ -109,20 +106,19 @@ public final class PostgresSequentialSequentialFileDriver extends JDBCSequential
@Override
public int writeToFile(JDBCSequentialFile file, byte[] data, boolean append) throws SQLException {
synchronized (connection) {
- LargeObjectManager lobjManager = ((PGConnection) connection).getLargeObjectAPI();
- LargeObject largeObject = null;
+ Object largeObject = null;
Long oid = getOID(file);
try {
connection.setAutoCommit(false);
- largeObject = lobjManager.open(oid, LargeObjectManager.WRITE);
+ largeObject = largeObjectManager.open(oid, PostgresLargeObjectManager.WRITE);
if (append) {
- largeObject.seek(largeObject.size());
+ largeObjectManager.seek(largeObject, largeObjectManager.size(largeObject));
} else {
- largeObject.truncate(0);
+ largeObjectManager.truncate(largeObject, 0);
}
- largeObject.write(data);
- largeObject.close();
+ largeObjectManager.write(largeObject, data);
+ largeObjectManager.close(largeObject);
connection.commit();
} catch (Exception e) {
connection.rollback();
@@ -134,23 +130,23 @@ public final class PostgresSequentialSequentialFileDriver extends JDBCSequential
@Override
public int readFromFile(JDBCSequentialFile file, ByteBuffer bytes) throws SQLException {
- LargeObjectManager lobjManager = ((PGConnection) connection).getLargeObjectAPI();
- LargeObject largeObject = null;
+ Object largeObject = null;
long oid = getOID(file);
synchronized (connection) {
try {
connection.setAutoCommit(false);
- largeObject = lobjManager.open(oid, LargeObjectManager.READ);
- int readLength = (int) calculateReadLength(largeObject.size(), bytes.remaining(), file.position());
+ largeObject = largeObjectManager.open(oid, PostgresLargeObjectManager.READ);
+ int readLength = (int) calculateReadLength(largeObjectManager.size(largeObject), bytes.remaining(), file.position());
if (readLength > 0) {
- if (file.position() > 0)
- largeObject.seek((int) file.position());
- byte[] data = largeObject.read(readLength);
+ if (file.position() > 0) {
+ largeObjectManager.seek(largeObject, (int) file.position());
+ }
+ byte[] data = largeObjectManager.read(largeObject, readLength);
bytes.put(data);
}
- largeObject.close();
+ largeObjectManager.close(largeObject);
connection.commit();
return readLength;
@@ -185,17 +181,15 @@ public final class PostgresSequentialSequentialFileDriver extends JDBCSequential
}
private int getPostGresLargeObjectSize(JDBCSequentialFile file) throws SQLException {
- LargeObjectManager lobjManager = ((PGConnection) connection).getLargeObjectAPI();
-
int size = 0;
Long oid = getOID(file);
if (oid != null) {
synchronized (connection) {
try {
connection.setAutoCommit(false);
- LargeObject largeObject = lobjManager.open(oid, LargeObjectManager.READ);
- size = largeObject.size();
- largeObject.close();
+ Object largeObject = largeObjectManager.open(oid, PostgresLargeObjectManager.READ);
+ size = largeObjectManager.size(largeObject);
+ largeObjectManager.close(largeObject);
connection.commit();
} catch (SQLException e) {
connection.rollback();
diff --git a/artemis-jdbc-store/src/test/java/org/apache/activemq/artemis/jdbc/file/JDBCSequentialFileFactoryTest.java b/artemis-jdbc-store/src/test/java/org/apache/activemq/artemis/jdbc/store/file/JDBCSequentialFileFactoryTest.java
similarity index 98%
rename from artemis-jdbc-store/src/test/java/org/apache/activemq/artemis/jdbc/file/JDBCSequentialFileFactoryTest.java
rename to artemis-jdbc-store/src/test/java/org/apache/activemq/artemis/jdbc/store/file/JDBCSequentialFileFactoryTest.java
index d74a76c..fef665c 100644
--- a/artemis-jdbc-store/src/test/java/org/apache/activemq/artemis/jdbc/file/JDBCSequentialFileFactoryTest.java
+++ b/artemis-jdbc-store/src/test/java/org/apache/activemq/artemis/jdbc/store/file/JDBCSequentialFileFactoryTest.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.activemq.artemis.jdbc.file;
+package org.apache.activemq.artemis.jdbc.store.file;
import java.nio.ByteBuffer;
import java.sql.DriverManager;
@@ -37,8 +37,6 @@ import org.apache.activemq.artemis.core.io.IOCallback;
import org.apache.activemq.artemis.core.io.IOCriticalErrorListener;
import org.apache.activemq.artemis.core.io.SequentialFile;
import org.apache.activemq.artemis.jdbc.store.drivers.JDBCUtils;
-import org.apache.activemq.artemis.jdbc.store.file.JDBCSequentialFile;
-import org.apache.activemq.artemis.jdbc.store.file.JDBCSequentialFileFactory;
import org.apache.activemq.artemis.jdbc.store.sql.SQLProvider;
import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
import org.apache.activemq.artemis.utils.ThreadLeakCheckRule;
diff --git a/artemis-jdbc-store/src/test/java/org/apache/activemq/artemis/jdbc/store/file/PostgresLargeObjectManagerTest.java b/artemis-jdbc-store/src/test/java/org/apache/activemq/artemis/jdbc/store/file/PostgresLargeObjectManagerTest.java
new file mode 100644
index 0000000..886ce10
--- /dev/null
+++ b/artemis-jdbc-store/src/test/java/org/apache/activemq/artemis/jdbc/store/file/PostgresLargeObjectManagerTest.java
@@ -0,0 +1,362 @@
+/*
+ * Copyright 2020 The Apache Software Foundation.
+ *
+ * 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 org.apache.activemq.artemis.jdbc.store.file;
+
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
+import java.net.URLClassLoader;
+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.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.Map;
+import java.util.Properties;
+import java.util.concurrent.Executor;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import org.junit.Test;
+
+public class PostgresLargeObjectManagerTest {
+
+ @Test
+ public void testShouldNotUseReflection() throws SQLException {
+ PostgresLargeObjectManager manager = new PostgresLargeObjectManager(new MockConnection());
+ try {
+ manager.createLO();
+ fail("Shouldn't be using reflection");
+ } catch (ClassCastException ex) {
+ }
+ }
+
+ @Test
+ public void testShouldUseReflection() throws SQLException, ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
+ ClassLoader loader = new FunkyClassLoader();
+ Class funkyClass = loader.loadClass("org.apache.activemq.artemis.jdbc.store.file.PostgresLargeObjectManager");
+ Object manager = funkyClass.getConstructor(Connection.class).newInstance(new MockConnection());
+ try {
+ funkyClass.getMethod("createLO").invoke(manager);
+ fail("Shouldn't be using reflection");
+ } catch (java.lang.reflect.InvocationTargetException ex) {
+ assertEquals("Couldn't access org.postgresql.largeobject.LargeObjectManager", ex.getCause().getMessage());
+ }
+ }
+
+ private static final class FunkyClassLoader extends URLClassLoader {
+
+ private FunkyClassLoader() {
+ super(new URL[]{
+ FunkyClassLoader.class.getProtectionDomain().getCodeSource().getLocation(),
+ PostgresLargeObjectManager.class.getProtectionDomain().getCodeSource().getLocation()
+ },
+ ClassLoader.getSystemClassLoader());
+ }
+
+ @Override
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ if ("org.postgresql.PGConnection".equals(name)) {
+ throw new ClassNotFoundException(name);
+ }
+ if ("org.apache.activemq.artemis.jdbc.store.file.PostgresLargeObjectManager".equals(name)) {
+ return this.findClass(name);
+ }
+ return super.loadClass(name);
+ }
+ }
+
+ private static final class MockConnection implements Connection {
+
+ @Override
+ public Statement createStatement() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public CallableStatement prepareCall(String sql) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public String nativeSQL(String sql) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void setAutoCommit(boolean autoCommit) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public boolean getAutoCommit() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void commit() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void rollback() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void close() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public boolean isClosed() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public DatabaseMetaData getMetaData() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void setReadOnly(boolean readOnly) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public boolean isReadOnly() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void setCatalog(String catalog) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public String getCatalog() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void setTransactionIsolation(int level) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public int getTransactionIsolation() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public SQLWarning getWarnings() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void clearWarnings() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public Map<String, Class<?>> getTypeMap() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void setHoldability(int holdability) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public int getHoldability() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public Savepoint setSavepoint() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public Savepoint setSavepoint(String name) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void rollback(Savepoint savepoint) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void releaseSavepoint(Savepoint savepoint) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public Clob createClob() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public Blob createBlob() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public NClob createNClob() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public SQLXML createSQLXML() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public boolean isValid(int timeout) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void setClientInfo(String name, String value) throws SQLClientInfoException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void setClientInfo(Properties properties) throws SQLClientInfoException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public String getClientInfo(String name) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public Properties getClientInfo() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void setSchema(String schema) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public String getSchema() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void abort(Executor executor) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public int getNetworkTimeout() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ return (T) this;
+ }
+
+ @Override
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+ return false;
+ }
+ }
+}