View Javadoc

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