KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > continuent > sequoia > controller > requests > RequestFactory


1 /**
2  * Sequoia: Database clustering technology.
3  * Copyright (C) 2005 AmicoSoft, Inc. dba Emic Networks
4  * Contact: sequoia@continuent.org
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * Initial developer(s): Emmanuel Cecchet.
19  * Contributor(s): ______________________.
20  */

21
22 package org.continuent.sequoia.controller.requests;
23
24 import java.sql.Connection JavaDoc;
25
26 /**
27  * This class defines a RequestFactory.<br>
28  * Given a SQL query, it creates a full request of the correct type. These
29  * request types are defined by the implementing classes, as well as the regular
30  * expressions to be used for the SQL query parsing
31  *
32  * @author <a HREF="mailto:emmanuel.cecchet@emicnetworks.com">Emmanuel Cecchet</a>
33  * @author <a HREF="mailto:gilles.rayrat@continuent.com">Gilles Rayrat</a>
34  * @version 2.0
35  */

36 public abstract class RequestFactory
37 {
38   /** Reqular expressions to be used for request parsing */
39   private RequestRegExp driverRegExp = null;
40
41   /**
42    * Sets the custom regular expressions
43    *
44    * @param regexp regular expression to be used for request parsing
45    */

46   protected RequestFactory(RequestRegExp regexp)
47   {
48     driverRegExp = regexp;
49   }
50
51   /**
52    * Parses the given string:
53    * <ul>
54    * <li>if a read query is identified, creates and returns the appropriate
55    * read request
56    * <li>else if a write query is identified, creates and returns an unknown
57    * write request
58    * <li>else returns null
59    * </ul>
60    *
61    * @param sqlQuery sql statement to parse
62    * @param escapeProcessing query parameter to set
63    * @param timeout query parameter to set
64    * @param lineSeparator query parameter to set
65    * @return a <code>SelectRequest</code>, an <code>UnknownReadRequest</code>,
66    * an <code>UnknownWriteRequest</code> or <code>null</code>
67    */

68   protected AbstractRequest decodeReadRequestFromString(String JavaDoc sqlQuery,
69       boolean escapeProcessing, int timeout, String JavaDoc lineSeparator)
70   {
71     AbstractRequest decodedRequest = null;
72     if (driverRegExp.getSelectRequestPattern().matcher(sqlQuery).matches())
73     {
74       decodedRequest = getSelectRequest(sqlQuery, escapeProcessing, timeout,
75           lineSeparator);
76       if (driverRegExp.getSelectForUpdatePattern().matcher(sqlQuery).matches())
77         ((SelectRequest) decodedRequest).setMustBroadcast(true);
78     }
79     if (driverRegExp.getUnknownWriteRequestPattern().matcher(sqlQuery)
80         .matches())
81     {
82       decodedRequest = getUnknownWriteRequest(sqlQuery, escapeProcessing,
83           timeout, lineSeparator);
84     }
85     else if (driverRegExp.getUnknownReadRequestPattern().matcher(sqlQuery)
86         .matches())
87     {
88       decodedRequest = getUnknownReadRequest(sqlQuery, escapeProcessing,
89           timeout, lineSeparator);
90       if (driverRegExp.getSelectForUpdatePattern().matcher(sqlQuery).matches())
91         ((SelectRequest) decodedRequest).setMustBroadcast(true);
92     }
93     return decodedRequest;
94   }
95
96   /**
97    * Parses the given string and creates/returns the appropriate write request,
98    * stored procedure or <code>null</code> if no write query was identified
99    *
100    * @param sqlQuery sql statement to parse
101    * @param escapeProcessing query parameter to set
102    * @param timeout query parameter to set
103    * @param lineSeparator query parameter to set
104    * @return an <code>InsertRequest</code>, an <code>UpdateRequest</code>,
105    * a <code>DeleteRequest</code>, a <code>CreateRequest</code>, a
106    * <code>DropRequest</code>, an <code>AlterRequest</code>, a
107    * <code>StoredProcedure</code> or <code>null</code>
108    */

109   protected AbstractRequest decodeWriteRequestFromString(String JavaDoc sqlQuery,
110       boolean escapeProcessing, int timeout, String JavaDoc lineSeparator)
111   {
112     AbstractRequest decodedRequest = null;
113     if (driverRegExp.getInsertQueryPattern().matcher(sqlQuery).matches())
114     {
115       decodedRequest = getInsertRequest(sqlQuery, escapeProcessing, timeout,
116           lineSeparator);
117     }
118     else if (driverRegExp.getUpdateRequestPattern().matcher(sqlQuery).matches())
119     {
120       decodedRequest = getUpdateRequest(sqlQuery, escapeProcessing, timeout,
121           lineSeparator);
122     }
123     else if (driverRegExp.getDeleteRequestPattern().matcher(sqlQuery).matches())
124     {
125       decodedRequest = getDeleteRequest(sqlQuery, escapeProcessing, timeout,
126           lineSeparator);
127     }
128     else if (driverRegExp.getCreateRequestPattern().matcher(sqlQuery).matches())
129     {
130       decodedRequest = getCreateRequest(sqlQuery, escapeProcessing, timeout,
131           lineSeparator);
132     }
133     else if (driverRegExp.getDropRequestPattern().matcher(sqlQuery).matches())
134     {
135       decodedRequest = getDropRequest(sqlQuery, escapeProcessing, timeout,
136           lineSeparator);
137     }
138     else if (driverRegExp.getAlterRequestPattern().matcher(sqlQuery).matches())
139     {
140       decodedRequest = getAlterRequest(sqlQuery, escapeProcessing, timeout,
141           lineSeparator);
142     }
143     else if (driverRegExp.getStoredProcedurePattern().matcher(sqlQuery)
144         .matches())
145     {
146       decodedRequest = getStoredProcedure(sqlQuery, escapeProcessing, timeout,
147           lineSeparator);
148     }
149     return decodedRequest;
150   }
151
152   /**
153    * Given a sql statement string, creates the appropriate read or write
154    * request, or <code>null</code> if no sql query could be identified.
155    * Priority of the parsing and the parameters of the request to be created are
156    * configurable tries to identify read or write first)
157    *
158    * @param sqlQuery sql statement to parse
159    * @param isProbablyAReadRequest set to true if the given sql query is
160    * probably a read statement. This will give priority to the parsing
161    * of read requests
162    * @param escapeProcessing query parameter to set
163    * @param timeout query parameter to set
164    * @param lineSeparator query parameter to set
165    * @return an <code>InsertRequest</code>, an <code>UpdateRequest</code>,
166    * a <code>DeleteRequest</code>, a <code>CreateRequest</code>, a
167    * <code>DropRequest</code>, an <code>AlterRequest</code>, a
168    * <code>StoredProcedure</code>, a <code>SelectRequest</code>,
169    * an <code>UnknownReadRequest</code>, an
170    * <code>UnknownWriteRequest</code> or <code>null</code>
171    */

172   public AbstractRequest requestFromString(String JavaDoc sqlQuery,
173       boolean isProbablyAReadRequest, boolean escapeProcessing, int timeout,
174       String JavaDoc lineSeparator)
175   {
176     AbstractRequest decodedRequest = null;
177     if (isProbablyAReadRequest)
178     {
179       // more probably a read, let's try it first
180
decodedRequest = decodeReadRequestFromString(sqlQuery, escapeProcessing,
181           timeout, lineSeparator);
182     }
183     if (decodedRequest == null || decodedRequest instanceof UnknownWriteRequest)
184     {
185       // either isProbablyAReadRequest == false or decodeRead found an unknown
186
// write
187
decodedRequest = decodeWriteRequestFromString(sqlQuery, escapeProcessing,
188           timeout, lineSeparator);
189     }
190     if (decodedRequest == null && !isProbablyAReadRequest)
191     {
192       // decodeWrite didn't find anything, let's try decodeRead
193
decodedRequest = decodeReadRequestFromString(sqlQuery, escapeProcessing,
194           timeout, lineSeparator);
195     }
196     else if (decodedRequest == null)
197     {
198       // nothing found, safer to say that it is an unknown read
199
decodedRequest = getUnknownReadRequest(sqlQuery, escapeProcessing,
200           timeout, lineSeparator);
201     }
202     return decodedRequest;
203   }
204
205   /**
206    * Returns true if the query has to be executed with statement.execute() or if
207    * it contains an inline batch such as "SELECT xxx ; INSERT xxx ; DROP xxx ;
208    * ..."
209    *
210    * @param request the request to check
211    * @return true if the request has to be executed with statement.execute() or
212    * contains an inline batch
213    */

214   public boolean requestNeedsExecute(AbstractRequest request)
215   {
216     // Check if the request match the StatementExecuteRequest pattern
217
if (driverRegExp.getStatementExecuteRequestPattern().matcher(
218         request.getSqlOrTemplate()).matches())
219       return true;
220
221     // Otherwise, check if the query contains an inline batch such as "SELECT
222
// xxx ; INSERT xxx ; DROP xxx ; ..."
223
String JavaDoc sql = request.getSqlOrTemplate();
224     int semiColonIdx = sql.indexOf(';');
225
226     // Test for no semicolon
227
if (semiColonIdx == -1)
228       return false;
229
230     // Test for multiple semicolons
231
// TODO: Check that semicolon does not belong to a parameter
232
if (sql.indexOf(';', semiColonIdx) != -1)
233       return true;
234
235     // Single semicolon, check that this was not just appended at the end of a
236
// single query
237
if (sql.trim().endsWith(";"))
238       return false; // query ends by semicolon
239
else
240       return true;
241   }
242
243   /**
244    * Check whether the given sql is authorized to execute on the cluster or not.
245    *
246    * @param sql the SQL statement to check
247    * @return false if the statement is not authorized and must be blocked, true
248    * otherwise
249    */

250   public boolean isAuthorizedRequest(String JavaDoc sql)
251   {
252     return !driverRegExp.getUnauthorizedRequestsPattern().matcher(sql)
253         .matches();
254   }
255
256   /**
257    *
258    * Determines whether or not a select statement should be broadcast
259    * based on the setting of the transaction isolation level. By
260    * default request at transaction isolation level serializable are
261    * broadcast.
262    *
263    * @param transactionIsolationLevel the transaction isolation level
264    * for the current request.
265    *
266    * @return true if the select should be broadcast.
267    */

268   public boolean isBroadcastRequired(int transactionIsolationLevel)
269   {
270     return transactionIsolationLevel == Connection.TRANSACTION_SERIALIZABLE;
271   }
272   
273   /**
274    * @see AlterRequest#AlterRequest(String, boolean, int, String)
275    */

276   protected abstract AlterRequest getAlterRequest(String JavaDoc sqlQuery,
277       boolean escapeProcessing, int timeout, String JavaDoc lineSeparator);
278
279   /**
280    * @see CreateRequest#CreateRequest(String, boolean, int, String)
281    */

282   protected abstract CreateRequest getCreateRequest(String JavaDoc sqlQuery,
283       boolean escapeProcessing, int timeout, String JavaDoc lineSeparator);
284
285   /**
286    * @see DeleteRequest#DeleteRequest(String, boolean, int, String)
287    */

288   protected abstract DeleteRequest getDeleteRequest(String JavaDoc sqlQuery,
289       boolean escapeProcessing, int timeout, String JavaDoc lineSeparator);
290
291   /**
292    * @see DropRequest#DropRequest(String, boolean, int, String)
293    */

294   protected abstract DropRequest getDropRequest(String JavaDoc sqlQuery,
295       boolean escapeProcessing, int timeout, String JavaDoc lineSeparator);
296
297   /**
298    * @see InsertRequest#InsertRequest(String, boolean, int, String)
299    */

300   protected abstract InsertRequest getInsertRequest(String JavaDoc sqlQuery,
301       boolean escapeProcessing, int timeout, String JavaDoc lineSeparator);
302
303   /**
304    * @see SelectRequest#SelectRequest(String, boolean, int, String)
305    */

306   protected abstract SelectRequest getSelectRequest(String JavaDoc sqlQuery,
307       boolean escapeProcessing, int timeout, String JavaDoc lineSeparator);
308
309   /**
310    * @see StoredProcedure#StoredProcedure(String, boolean, int, String)
311    */

312   protected abstract StoredProcedure getStoredProcedure(String JavaDoc sqlQuery,
313       boolean escapeProcessing, int timeout, String JavaDoc lineSeparator);
314
315   /**
316    * @see UnknownReadRequest#UnknownReadRequest(String, boolean, int, String)
317    */

318   protected abstract UnknownReadRequest getUnknownReadRequest(String JavaDoc sqlQuery,
319       boolean escapeProcessing, int timeout, String JavaDoc lineSeparator);
320
321   /**
322    * @see UnknownWriteRequest#UnknownWriteRequest(String, boolean, int, String)
323    */

324   protected abstract UnknownWriteRequest getUnknownWriteRequest(
325       String JavaDoc sqlQuery, boolean escapeProcessing, int timeout,
326       String JavaDoc lineSeparator);
327
328   /**
329    * @see UpdateRequest#UpdateRequest(String, boolean, int, String)
330    */

331   protected abstract UpdateRequest getUpdateRequest(String JavaDoc sqlQuery,
332       boolean escapeProcessing, int timeout, String JavaDoc lineSeparator);
333 }
334
Popular Tags