1 package org.apache.ojb.broker.util.batch;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
20 import org.apache.ojb.broker.platforms.PlatformFactory;
21 import org.apache.ojb.broker.platforms.PlatformException;
22 import org.apache.ojb.broker.platforms.Platform;
23
24 import java.lang.reflect.Method;
25 import java.lang.reflect.InvocationTargetException;
26 import java.math.BigDecimal;
27 import java.sql.Connection;
28 import java.sql.PreparedStatement;
29 import java.sql.SQLException;
30 import java.util.ArrayList;
31
32
33 import java.lang.reflect.InvocationHandler;
34
35
36
37
38
39
40
41
42
43
44
45
46
47 public class PreparedStatementInvocationHandler implements InvocationHandler
48 {
49
50 private final static Integer ONE = new Integer(1);
51
52 private static Method ADD_BATCH;
53
54 private final static Method SET_BIG_DECIMAL;
55
56 static
57 {
58 Method setBigDecimal = null;
59 try
60 {
61 setBigDecimal = PreparedStatement.class.getMethod("setBigDecimal",
62 new Class[] {Integer.TYPE, BigDecimal.class});
63 }
64 catch ( Exception ex )
65 {
66
67 }
68 SET_BIG_DECIMAL = setBigDecimal;
69 }
70
71 private final BatchConnection _batchConn;
72
73 private final String _sql;
74
75 private ArrayList _methods = new ArrayList();
76
77 private ArrayList _params = new ArrayList();
78
79 private Platform m_platform = null;
80
81 public PreparedStatementInvocationHandler(BatchConnection batchConn, String sql, JdbcConnectionDescriptor jcd)
82 {
83 _batchConn = batchConn;
84 _sql = sql;
85 m_platform = PlatformFactory.getPlatformFor(jcd);
86 try
87 {
88 ADD_BATCH = m_platform.getClass().getMethod("addBatch",new Class[]{PreparedStatement.class});
89 }
90 catch ( NoSuchMethodException e )
91 {
92
93
94
95 ADD_BATCH = null;
96 }
97 catch ( SecurityException e )
98 {
99
100 }
101 }
102
103 public Object invoke(Object proxy, Method method, Object[] args)
104 throws Throwable
105 {
106 String name = method.getName();
107 if ( name.equals("executeUpdate") )
108 {
109 _methods.add(ADD_BATCH);
110 _params.add(null);
111 _batchConn.nextExecuted(_sql);
112 return ONE;
113 }
114 else if ( name.equals("doExecute") )
115 {
116 doExecute((Connection) args[0]);
117 }
118 else if ( name.startsWith("set") )
119 {
120
121 if ( name.equals("setLong") )
122 {
123 method = SET_BIG_DECIMAL;
124 args[1] = BigDecimal.valueOf(((Long) args[1]).longValue());
125 }
126 _methods.add(method);
127 _params.add(args);
128 }
129 return null;
130 }
131
132
133
134
135 private void doExecute(Connection conn) throws SQLException
136 {
137 PreparedStatement stmt;
138 int size;
139
140 size = _methods.size();
141 if ( size == 0 )
142 {
143 return;
144 }
145 stmt = conn.prepareStatement(_sql);
146 try
147 {
148 m_platform.afterStatementCreate(stmt);
149 }
150 catch ( PlatformException e )
151 {
152 if ( e.getCause() instanceof SQLException )
153 {
154 throw (SQLException)e.getCause();
155 }
156 else
157 {
158 throw new SQLException(e.getMessage());
159 }
160 }
161 try
162 {
163 m_platform.beforeBatch(stmt);
164 }
165 catch ( PlatformException e )
166 {
167 if ( e.getCause() instanceof SQLException )
168 {
169 throw (SQLException)e.getCause();
170 }
171 else
172 {
173 throw new SQLException(e.getMessage());
174 }
175 }
176 try
177 {
178 for ( int i = 0; i < size; i++ )
179 {
180 Method method = (Method) _methods.get(i);
181 try
182 {
183 if ( method.equals(ADD_BATCH) )
184 {
185
186
187
188 m_platform.addBatch(stmt);
189 }
190 else
191 {
192 method.invoke(stmt, (Object[]) _params.get(i));
193 }
194 }
195 catch (IllegalArgumentException ex)
196 {
197 StringBuffer buffer = generateExceptionMessage(i, stmt, ex);
198 throw new SQLException(buffer.toString());
199 }
200 catch ( IllegalAccessException ex )
201 {
202 StringBuffer buffer = generateExceptionMessage(i, stmt, ex);
203 throw new SQLException(buffer.toString());
204 }
205 catch ( InvocationTargetException ex )
206 {
207 Throwable th = ex.getTargetException();
208
209 if ( th == null )
210 {
211 th = ex;
212 }
213 if ( th instanceof SQLException )
214 {
215 throw ((SQLException) th);
216 }
217 else
218 {
219 throw new SQLException(th.toString());
220 }
221 }
222 catch (PlatformException e)
223 {
224 throw new SQLException(e.toString());
225 }
226 }
227 try
228 {
229
230
231
232 m_platform.executeBatch(stmt);
233 }
234 catch ( PlatformException e )
235 {
236 if ( e.getCause() instanceof SQLException )
237 {
238 throw (SQLException)e.getCause();
239 }
240 else
241 {
242 throw new SQLException(e.getMessage());
243 }
244 }
245
246 }
247 finally
248 {
249 stmt.close();
250 _methods.clear();
251 _params.clear();
252 }
253 }
254
255 private StringBuffer generateExceptionMessage(int i, PreparedStatement stmt, Exception ex)
256 {
257 StringBuffer buffer = new StringBuffer();
258 buffer.append("Method of type: ");
259 buffer.append(_methods.get(i));
260 buffer.append(" invoking on instance: ");
261 if (( _methods.get(i)).equals(ADD_BATCH))
262 buffer.append(m_platform);
263 else
264 buffer.append(stmt);
265 buffer.append(" with parameters: ");
266 if ((_methods.get(i)).equals(ADD_BATCH))
267 buffer.append(stmt);
268 else
269 buffer.append(_params.get(i));
270 buffer.append(" with root: ");
271 buffer.append(ex.toString());
272 return buffer;
273 }
274 }
275