View Javadoc

1   package com.atlassian.sal.core.rdbms;
2   
3   import com.google.common.annotations.VisibleForTesting;
4   
5   import javax.annotation.Nonnull;
6   import javax.annotation.concurrent.NotThreadSafe;
7   import java.sql.Array;
8   import java.sql.Blob;
9   import java.sql.CallableStatement;
10  import java.sql.Clob;
11  import java.sql.Connection;
12  import java.sql.DatabaseMetaData;
13  import java.sql.NClob;
14  import java.sql.PreparedStatement;
15  import java.sql.SQLClientInfoException;
16  import java.sql.SQLException;
17  import java.sql.SQLWarning;
18  import java.sql.SQLXML;
19  import java.sql.Savepoint;
20  import java.sql.Statement;
21  import java.sql.Struct;
22  import java.util.Map;
23  import java.util.Properties;
24  import java.util.concurrent.Executor;
25  
26  /**
27   * {@link java.sql.Connection} proxy, which throws {@link java.lang.UnsupportedOperationException} on invocation of:
28   * <ul>
29   * <li>{@link java.sql.Connection#setAutoCommit(boolean)}</li>
30   * <li>{@link java.sql.Connection#commit()}</li>
31   * <li>{@link java.sql.Connection#close()}</li>
32   * <li>{@link java.sql.Connection#rollback()}</li>
33   * <li>{@link java.sql.Connection#setReadOnly(boolean)}</li>
34   * <li>{@link java.sql.Connection#setReadOnly(boolean)}</li>
35   * <li>{@link java.sql.Connection#abort(java.util.concurrent.Executor)}</li>
36   * <li>{@link java.sql.Connection#setCatalog(String)}</li>
37   * <li>{@link java.sql.Connection#setSchema(String)}</li>
38   * <li>{@link java.sql.Connection#setTransactionIsolation(int)}</li>
39   * <li>{@link java.sql.Connection#setNetworkTimeout(java.util.concurrent.Executor, int)}</li>
40   * </ul>
41   * <p/>
42   * {@link #expire()} should be called after use, to prevent users from retaining and abusing the {@link
43   * java.sql.Connection}.
44   *
45   * @since 3.0
46   */
47  @NotThreadSafe
48  class WrappedConnection implements Connection {
49      @VisibleForTesting
50      Connection connection;
51  
52      public WrappedConnection(@Nonnull final Connection connection) {
53          this.connection = connection;
54      }
55  
56      void expire() {
57          connection = null;
58      }
59  
60      private Connection connection() {
61          if (connection == null) {
62              throw new IllegalStateException("Connection accessed outside the scope of a callback passed to com.atlassian.sal.api.rdbms.TransactionalExecutor");
63          } else {
64              return connection;
65          }
66      }
67  
68      /*
69       * Banned methods
70       */
71      @Override
72      public void setAutoCommit(final boolean autoCommit) throws SQLException {
73          connection();
74          throw new UnsupportedOperationException("java.sql.Connection#setAutoCommit(boolean) called from a connection provided by com.atlassian.sal.api.rdbms.TransactionalExecutor");
75      }
76  
77      @Override
78      public void commit() throws SQLException {
79          connection();
80          throw new UnsupportedOperationException("java.sql.Connection#commit() called from a connection provided by com.atlassian.sal.api.rdbms.TransactionalExecutor");
81      }
82  
83      @Override
84      public void close() {
85          connection();
86          expire();
87      }
88  
89      @Override
90      public void rollback() throws SQLException {
91          connection();
92          throw new UnsupportedOperationException("java.sql.Connection#rollback() called from a connection provided by com.atlassian.sal.api.rdbms.TransactionalExecutor");
93      }
94  
95      @Override
96      public void setReadOnly(final boolean readOnly) throws SQLException {
97          connection();
98          throw new UnsupportedOperationException("java.sql.Connection#setReadOnly(boolean) called from a connection provided by com.atlassian.sal.api.rdbms.TransactionalExecutor");
99      }
100 
101     @Override
102     public void abort(final Executor executor) throws SQLException {
103         connection();
104         throw new UnsupportedOperationException("java.sql.Connection#abort(java.util.concurrent.Executor)} called from a connection provided by com.atlassian.sal.api.rdbms.TransactionalExecutor");
105     }
106 
107     @Override
108     public void setCatalog(final String catalog) throws SQLException {
109         connection();
110         throw new UnsupportedOperationException("java.sql.Connection#setCatalog(String) called from a connection provided by com.atlassian.sal.api.rdbms.TransactionalExecutor");
111     }
112 
113     @Override
114     public void setSchema(final String schema) throws SQLException {
115         connection();
116         throw new UnsupportedOperationException("java.sql.Connection#setSchema(String) called from a connection provided by com.atlassian.sal.api.rdbms.TransactionalExecutor");
117     }
118 
119     @Override
120     public void setTransactionIsolation(final int level) throws SQLException {
121         connection();
122         throw new UnsupportedOperationException("java.sql.Connection#setTransactionIsolation(int) called from a connection provided by com.atlassian.sal.api.rdbms.TransactionalExecutor");
123     }
124 
125     @Override
126     public void setNetworkTimeout(final Executor executor, final int milliseconds) throws SQLException {
127         connection();
128         throw new UnsupportedOperationException("java.sql.Connection#setNetworkTimeout(java.util.concurrent.Executor, int)} called from a connection provided by com.atlassian.sal.api.rdbms.TransactionalExecutor");
129     }
130 
131     @Override
132     public Savepoint setSavepoint() throws SQLException {
133         connection();
134         throw new UnsupportedOperationException("java.sql.Connection#setSavepoint() called from a connection provided by com.atlassian.sal.api.rdbms.TransactionalExecutor");
135     }
136 
137     @Override
138     public Savepoint setSavepoint(final String name) throws SQLException {
139         connection();
140         throw new UnsupportedOperationException("java.sql.Connection#setSavepoint(String) called from a connection provided by com.atlassian.sal.api.rdbms.TransactionalExecutor");
141     }
142 
143     @Override
144     public void rollback(final Savepoint savepoint) throws SQLException {
145         connection();
146         throw new UnsupportedOperationException("java.sql.Connection#setSavepoint(java.sql.Savepoint) called from a connection provided by com.atlassian.sal.api.rdbms.TransactionalExecutor");
147     }
148 
149     @Override
150     public void releaseSavepoint(final Savepoint savepoint) throws SQLException {
151         connection();
152         throw new UnsupportedOperationException("java.sql.Connection#releaseSavepoint(java.sql.Savepoint) called from a connection provided by com.atlassian.sal.api.rdbms.TransactionalExecutor");
153     }
154 
155     /*
156      * Delegating methods
157      */
158     @Override
159     public boolean isWrapperFor(final Class<?> iface) throws SQLException {
160         return connection().isWrapperFor(iface);
161     }
162 
163     @Override
164     public Statement createStatement() throws SQLException {
165         return connection().createStatement();
166     }
167 
168     @Override
169     public PreparedStatement prepareStatement(final String sql) throws SQLException {
170         return connection().prepareStatement(sql);
171     }
172 
173     @Override
174     public CallableStatement prepareCall(final String sql) throws SQLException {
175         return connection().prepareCall(sql);
176     }
177 
178     @Override
179     public String nativeSQL(final String sql) throws SQLException {
180         return connection().nativeSQL(sql);
181     }
182 
183     @Override
184     public boolean getAutoCommit() throws SQLException {
185         return connection().getAutoCommit();
186     }
187 
188     @Override
189     public boolean isClosed() throws SQLException {
190         return connection().isClosed();
191     }
192 
193     @Override
194     public DatabaseMetaData getMetaData() throws SQLException {
195         return connection().getMetaData();
196     }
197 
198     @Override
199     public boolean isReadOnly() throws SQLException {
200         return connection().isReadOnly();
201     }
202 
203     @Override
204     public String getCatalog() throws SQLException {
205         return connection().getCatalog();
206     }
207 
208     @Override
209     public int getTransactionIsolation() throws SQLException {
210         return connection().getTransactionIsolation();
211     }
212 
213     @Override
214     public SQLWarning getWarnings() throws SQLException {
215         return connection().getWarnings();
216     }
217 
218     @Override
219     public void clearWarnings() throws SQLException {
220         connection().clearWarnings();
221     }
222 
223     @Override
224     public Statement createStatement(final int resultSetType, final int resultSetConcurrency) throws SQLException {
225         return connection().createStatement(resultSetType, resultSetConcurrency);
226     }
227 
228     @Override
229     public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency)
230             throws SQLException {
231         return connection().prepareStatement(sql, resultSetType, resultSetConcurrency);
232     }
233 
234     @Override
235     public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency)
236             throws SQLException {
237         return connection().prepareCall(sql, resultSetType, resultSetConcurrency);
238     }
239 
240     @Override
241     public Map<String, Class<?>> getTypeMap() throws SQLException {
242         return connection().getTypeMap();
243     }
244 
245     @Override
246     public void setTypeMap(final Map<String, Class<?>> map) throws SQLException {
247         connection().setTypeMap(map);
248     }
249 
250     @Override
251     public void setHoldability(final int holdability) throws SQLException {
252         connection().setHoldability(holdability);
253     }
254 
255     @Override
256     public int getHoldability() throws SQLException {
257         return connection().getHoldability();
258     }
259 
260     @Override
261     public Statement createStatement(final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability)
262             throws SQLException {
263         return connection().createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
264     }
265 
266     @Override
267     public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability)
268             throws SQLException {
269         return connection().prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
270     }
271 
272     @Override
273     public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability)
274             throws SQLException {
275         return connection().prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
276     }
277 
278     @Override
279     public PreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys) throws SQLException {
280         return connection().prepareStatement(sql, autoGeneratedKeys);
281     }
282 
283     @Override
284     public PreparedStatement prepareStatement(final String sql, final int[] columnIndexes) throws SQLException {
285         return connection().prepareStatement(sql, columnIndexes);
286     }
287 
288     @Override
289     public PreparedStatement prepareStatement(final String sql, final String[] columnNames) throws SQLException {
290         return connection().prepareStatement(sql, columnNames);
291     }
292 
293     @Override
294     public Clob createClob() throws SQLException {
295         return connection().createClob();
296     }
297 
298     @Override
299     public Blob createBlob() throws SQLException {
300         return connection().createBlob();
301     }
302 
303     @Override
304     public NClob createNClob() throws SQLException {
305         return connection().createNClob();
306     }
307 
308     @Override
309     public SQLXML createSQLXML() throws SQLException {
310         return connection().createSQLXML();
311     }
312 
313     @Override
314     public boolean isValid(final int timeout) throws SQLException {
315         return connection().isValid(timeout);
316     }
317 
318     @Override
319     public void setClientInfo(final String name, final String value) throws SQLClientInfoException {
320         connection().setClientInfo(name, value);
321     }
322 
323     @Override
324     public void setClientInfo(final Properties properties) throws SQLClientInfoException {
325         connection().setClientInfo(properties);
326     }
327 
328     @Override
329     public String getClientInfo(final String name) throws SQLException {
330         return connection().getClientInfo(name);
331     }
332 
333     @Override
334     public Properties getClientInfo() throws SQLException {
335         return connection().getClientInfo();
336     }
337 
338     @Override
339     public Array createArrayOf(final String typeName, final Object[] elements) throws SQLException {
340         return connection().createArrayOf(typeName, elements);
341     }
342 
343     @Override
344     public Struct createStruct(final String typeName, final Object[] attributes) throws SQLException {
345         return connection().createStruct(typeName, attributes);
346     }
347 
348     @Override
349     public String getSchema() throws SQLException {
350         return connection().getSchema();
351     }
352 
353     @Override
354     public int getNetworkTimeout() throws SQLException {
355         return connection().getNetworkTimeout();
356     }
357 
358     @Override
359     public <T> T unwrap(final Class<T> iface) throws SQLException {
360         return connection().unwrap(iface);
361     }
362 }