1 package com.atlassian.activeobjects.spi;
2
3 import java.lang.reflect.InvocationHandler;
4 import java.lang.reflect.InvocationTargetException;
5 import java.lang.reflect.Method;
6 import java.lang.reflect.Proxy;
7 import java.sql.Connection;
8 import java.sql.SQLException;
9
10 import static com.google.common.base.Preconditions.checkNotNull;
11
12
13
14
15
16
17 public final class ConnectionHandler implements InvocationHandler {
18 private final Connection delegate;
19 private final Closeable closeable;
20
21 public ConnectionHandler(Connection delegate, Closeable closeable) {
22 this.delegate = checkNotNull(delegate);
23 this.closeable = checkNotNull(closeable);
24 }
25
26 @Override
27 public Object invoke(Object proxy, Method method, Object[] args) throws SQLException {
28 if (isCloseMethod(method)) {
29 closeable.close();
30 return Void.TYPE;
31 }
32
33 return delegate(method, args);
34 }
35
36 private Object delegate(Method method, Object[] args) throws SQLException {
37 try {
38 return method.invoke(delegate, args);
39 } catch (IllegalAccessException e) {
40 throw new IllegalStateException(e);
41 } catch (InvocationTargetException e) {
42 Throwable cause = e.getCause();
43
44 if (cause instanceof SQLException) {
45 throw (SQLException) cause;
46 }
47
48 if (cause instanceof RuntimeException) {
49 throw (RuntimeException) cause;
50 }
51
52 if (cause instanceof Error) {
53 throw (Error) cause;
54 }
55
56 throw new RuntimeException("Unexpected checked exception", cause);
57 }
58 }
59
60 public static Connection newInstance(Connection c) {
61 return newInstance(c, new Closeable() {
62 @Override
63 public void close() throws SQLException {
64 }
65 });
66 }
67
68 public static Connection newInstance(Connection c, Closeable closeable) {
69 return (Connection) Proxy.newProxyInstance(
70 ConnectionHandler.class.getClassLoader(),
71 new Class[]{Connection.class},
72 new ConnectionHandler(c, closeable));
73 }
74
75 private static boolean isCloseMethod(Method method) {
76 return method.getName().equals("close")
77 && method.getParameterTypes().length == 0;
78 }
79
80 public static interface Closeable {
81 void close() throws SQLException;
82 }
83 }
84