KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > scriptella > jdbc > SqlParserBase


1 /*
2  * Copyright 2006-2007 The Scriptella Project Team.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package scriptella.jdbc;
17
18 import scriptella.configuration.ConfigurationException;
19 import scriptella.expression.PropertiesSubstitutor;
20 import scriptella.util.IOUtils;
21 import scriptella.util.StringUtils;
22
23 import java.io.IOException JavaDoc;
24 import java.io.Reader JavaDoc;
25 import java.util.regex.Matcher JavaDoc;
26
27
28 /**
29  * Customizable SQL parser.
30  * <p><u>Supported extensions</u>
31  * The parser supports extensions described in {@link PropertiesSubstitutor}.<br/>
32  * Additionally <b>?</b> prefix is used for expressions which should be injected as prepared statement parameters.
33  * <p>Example:
34  * <pre><code>
35  * var=_name
36  * id=11
37  * --------------------------------------
38  * select * FROM table${var} where id=?id
39  * --- is transformed to ---
40  * select * FROM table_name where id=? where statement parameter has value of 11
41  * </code></pre>
42  * <p><u>Notes:</u><br>
43  * <ul>
44  * <li>$ prefixed expressions are substituted in all parts except comments.
45  * <li>? prefixed expressions are not substituted inside quotes and comments.
46  * </ul>
47  * Example:
48  *
49  * <pre><code>
50  * --only ${prop} and ?surname are handled
51  * SELECT * FROM "Table" WHERE NAME="?John${prop}" and SURNAME=?surname;
52  * </code></pre>
53  * These extensions are handled by subclasses in {@link #handleParameter(String, boolean, boolean)} method.
54  *
55  *
56  * @author Fyodor Kupolov
57  * @version 1.0
58  */

59 public class SqlParserBase {
60     /**
61      * Parses SQL script.
62      *
63      * @param reader reader with SQL script.
64      */

65     public void parse(final Reader JavaDoc reader) {
66         parse(new SqlReaderTokenizer(reader));
67     }
68
69     public void parse(final SqlTokenizer tok) {
70         try {
71             for (String JavaDoc s;(s=tok.nextStatement())!=null;) {
72                 handleStatement(s, tok.getInjections());
73             }
74         } catch (IOException JavaDoc e) {
75             throw new ConfigurationException("Failed to read element content", e);
76         } finally {
77             IOUtils.closeSilently(tok);
78         }
79
80     }
81
82     private final Matcher JavaDoc m = PropertiesSubstitutor.PROP_PTR.matcher("");
83     private final Matcher JavaDoc extM = PropertiesSubstitutor.EXPR_PTR.matcher("");
84     private final StringBuilder JavaDoc tmpBuf = new StringBuilder JavaDoc();
85
86     private void handleStatement(final String JavaDoc sql,
87                                  final int[] injections) {
88         if (StringUtils.isAsciiWhitespacesOnly(sql)) {
89             return;
90         }
91
92         if (injections != null && injections.length>0) {
93             m.reset(sql);
94             extM.reset(sql);
95
96             tmpBuf.setLength(0); //clearing the string builder
97
int lastPos = 0;
98
99             for (int index : injections) {
100                 int ind = index + 1;
101                 Matcher JavaDoc found = null;
102                 boolean expr = false;
103                 if (m.find(ind) && (m.start() == ind)) { //property reference
104
found = m;
105
106                 } else if (extM.find(ind) && (extM.start() == ind)) { //expression
107
found = extM;
108                     expr = true;
109                 }
110                 if (found != null) {
111                     //? - jdbcParam, $ - insert value as text
112
boolean jdbcParam = sql.charAt(index) == '?';
113                     tmpBuf.append(sql.substring(lastPos, index));
114                     lastPos = found.end();
115                     tmpBuf.append(handleParameter(found.group(1), expr, jdbcParam));
116                 }
117
118             }
119
120             if (lastPos < sql.length()) { //Add right side
121
tmpBuf.append(sql.substring(lastPos, sql.length()));
122             }
123             statementParsed(tmpBuf.toString());
124         } else {
125             statementParsed(sql);
126         }
127
128
129     }
130
131     /**
132      * Called when parameter is encountered in SQL.
133      *
134      * @param name parameter name or expression
135      * @param expression true if specified name is an expression, not a simple property reference
136      * @param jdbcParam true if parameter value should be passed as prepared statement parameter. Othewise it's value should be inserted
137      * into statement text.
138      * @return substituion string.
139      */

140     protected String JavaDoc handleParameter(final String JavaDoc name, final boolean expression, final boolean jdbcParam) {
141         return expression ? ((jdbcParam ? "?{" : "${") + name + '}') : ((jdbcParam ? "?{" : "$") + name);
142     }
143
144     /**
145      * Invoked when SQL statement has been processed and all expressions handled.
146      *
147      * @param sql content of the preprocessed statement.
148      */

149     protected void statementParsed(final String JavaDoc sql) {
150     }
151
152 }
153
Popular Tags