1
2
3
4
5
6
7
8
9
10
11 package org.mule.transport.jdbc;
12
13 import org.mule.DefaultMuleMessage;
14 import org.mule.api.MuleEvent;
15 import org.mule.api.MuleMessage;
16 import org.mule.api.endpoint.ImmutableEndpoint;
17 import org.mule.api.endpoint.OutboundEndpoint;
18 import org.mule.api.transaction.Transaction;
19 import org.mule.api.transport.MessageAdapter;
20 import org.mule.transaction.TransactionCoordination;
21 import org.mule.transport.AbstractMessageDispatcher;
22 import org.mule.util.ArrayUtils;
23 import org.mule.util.StringUtils;
24
25 import java.sql.Connection;
26 import java.util.ArrayList;
27 import java.util.List;
28
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31
32
33
34
35
36 public class JdbcMessageDispatcher extends AbstractMessageDispatcher
37 {
38
39 protected static Log staticLogger = LogFactory.getLog(AbstractMessageDispatcher.class);
40
41 protected JdbcConnector connector;
42 protected static final String STORED_PROCEDURE_PREFIX = "{ ";
43 protected static final String STORED_PROCEDURE_SUFFIX = " }";
44
45 public JdbcMessageDispatcher(OutboundEndpoint endpoint)
46 {
47 super(endpoint);
48 this.connector = (JdbcConnector) endpoint.getConnector();
49 }
50
51 protected void doDispose()
52 {
53
54 }
55
56 protected Object executeWriteStatement(MuleEvent event, String writeStmt) throws Exception
57 {
58 List paramNames = new ArrayList();
59 writeStmt = connector.parseStatement(writeStmt, paramNames);
60
61 Object[] paramValues = connector.getParams(endpoint, paramNames, new DefaultMuleMessage(
62 event.transformMessage()), this.endpoint.getEndpointURI().getAddress());
63
64 Transaction tx = TransactionCoordination.getInstance().getTransaction();
65 Connection con = null;
66
67 MuleMessage message = event.getMessage();
68
69 try
70 {
71 con = this.connector.getConnection();
72
73 if ("call".equalsIgnoreCase(writeStmt.substring(0, 4)))
74 {
75 writeStmt = STORED_PROCEDURE_PREFIX + writeStmt + STORED_PROCEDURE_SUFFIX;
76 }
77
78 if (logger.isDebugEnabled())
79 {
80 logger.debug("SQL UPDATE: " + writeStmt + ", params = " + ArrayUtils.toString(paramValues));
81 }
82 int nbRows = connector.getQueryRunner().update(con, writeStmt, paramValues);
83 if (nbRows != 1)
84 {
85 logger.warn("Row count for write should be 1 and not " + nbRows);
86 }
87 if (tx == null)
88 {
89 JdbcUtils.commitAndClose(con);
90 }
91 logger.debug("MuleEvent dispatched succesfuly");
92 }
93 catch (Exception e)
94 {
95 logger.debug("Error dispatching event: " + e.getMessage(), e);
96 if (tx == null)
97 {
98 JdbcUtils.rollbackAndClose(con);
99 }
100 throw e;
101 }
102
103 return message;
104 }
105
106 protected String getStatement(ImmutableEndpoint endpoint)
107 {
108 String writeStmt = endpoint.getEndpointURI().getAddress();
109 String str;
110 if ((str = this.connector.getQuery(endpoint, writeStmt)) != null)
111 {
112 writeStmt = str;
113 }
114 writeStmt = StringUtils.trimToEmpty(writeStmt);
115 if (StringUtils.isBlank(writeStmt))
116 {
117 throw new IllegalArgumentException("Missing statement");
118 }
119
120 return writeStmt;
121 }
122
123 protected boolean isWriteStatement(String writeStmt)
124 {
125 if (!"insert".equalsIgnoreCase(writeStmt.substring(0, 6))
126 && !"update".equalsIgnoreCase(writeStmt.substring(0, 6))
127 && !"delete".equalsIgnoreCase(writeStmt.substring(0, 6))
128 && !"merge".equalsIgnoreCase(writeStmt.substring(0, 5))
129 && !"call".equalsIgnoreCase(writeStmt.substring(0, 4)))
130 {
131 return false;
132 }
133
134 return true;
135 }
136
137 protected void doDispatch(MuleEvent event) throws Exception
138 {
139 if (logger.isDebugEnabled())
140 {
141 logger.debug("Dispatch event: " + event);
142 }
143
144 String writeStmt = getStatement(event.getEndpoint());
145
146 if (!isWriteStatement(writeStmt))
147 {
148 throw new IllegalArgumentException(
149 "Write statement should be an insert / update / delete / merge sql statement, or a stored-procedure call");
150 }
151
152 this.executeWriteStatement(event, writeStmt);
153
154 }
155
156 protected MuleMessage doSend(MuleEvent event) throws Exception
157 {
158 String statement = getStatement(event.getEndpoint());
159
160 if (isWriteStatement(statement))
161 {
162 executeWriteStatement(event, statement);
163 return event.getMessage();
164 }
165
166 return executeRequest(event.getTimeout(),event, connector, endpoint);
167
168 }
169
170
171
172
173
174
175
176
177
178
179
180 protected static MuleMessage executeRequest(long timeout, MuleEvent event,
181 JdbcConnector connector, ImmutableEndpoint endpoint) throws Exception
182 {
183 if (staticLogger.isDebugEnabled())
184 {
185 staticLogger.debug("Trying to receive a message with a timeout of " + timeout);
186 }
187
188 String[] stmts = connector.getReadAndAckStatements(endpoint);
189 String readStmt = stmts[0];
190 String ackStmt = stmts[1];
191 List readParams = new ArrayList();
192 List ackParams = new ArrayList();
193 readStmt = connector.parseStatement(readStmt, readParams);
194 ackStmt = connector.parseStatement(ackStmt, ackParams);
195
196 Connection con = null;
197 long t0 = System.currentTimeMillis();
198 Transaction tx = TransactionCoordination.getInstance().getTransaction();
199 try
200 {
201 con = connector.getConnection();
202 if (timeout < 0)
203 {
204 timeout = Long.MAX_VALUE;
205 }
206 Object result;
207 do
208 {
209 Object[] params = connector.getParams(endpoint, readParams,
210 event!=null ? event.getMessage() : null,
211 endpoint.getEndpointURI().getAddress());
212 if (staticLogger.isDebugEnabled())
213 {
214 staticLogger.debug("SQL QUERY: " + readStmt + ", params = " + ArrayUtils.toString(params));
215 }
216 result = connector.getQueryRunner().query(con, readStmt, params, connector.getResultSetHandler());
217 if (result != null)
218 {
219 if (staticLogger.isDebugEnabled())
220 {
221 staticLogger.debug("Received: " + result);
222 }
223 break;
224 }
225 long sleep = Math.min(connector.getPollingFrequency(),
226 timeout - (System.currentTimeMillis() - t0));
227 if (sleep > 0)
228 {
229 if (staticLogger.isDebugEnabled())
230 {
231 staticLogger.debug("No results, sleeping for " + sleep);
232 }
233 Thread.sleep(sleep);
234 }
235 else
236 {
237 staticLogger.debug("Timeout");
238 JdbcUtils.rollbackAndClose(con);
239 return null;
240 }
241 }
242 while (true);
243 if (ackStmt != null)
244 {
245 Object[] params = connector.getParams(endpoint, ackParams, result, ackStmt);
246 if (staticLogger.isDebugEnabled())
247 {
248 staticLogger.debug("SQL UPDATE: " + ackStmt + ", params = " + ArrayUtils.toString(params));
249 }
250 int nbRows = connector.getQueryRunner().update(con, ackStmt, params);
251 if (nbRows != 1)
252 {
253 staticLogger.warn("Row count for ack should be 1 and not " + nbRows);
254 }
255 }
256 MessageAdapter msgAdapter = connector.getMessageAdapter(result);
257 MuleMessage message = new DefaultMuleMessage(msgAdapter);
258 if (tx == null)
259 {
260 JdbcUtils.commitAndClose(con);
261 }
262
263 return message;
264 }
265 catch (Exception e)
266 {
267 if (tx == null)
268 {
269 JdbcUtils.rollbackAndClose(con);
270 }
271 throw e;
272 }
273
274 }
275
276
277 protected void doConnect() throws Exception
278 {
279
280 }
281
282 protected void doDisconnect() throws Exception
283 {
284
285 }
286
287 }