KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > taglibs > standard > tag > common > sql > QueryTagSupport


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
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
17 package org.apache.taglibs.standard.tag.common.sql;
18
19 import java.sql.Connection JavaDoc;
20 import java.sql.PreparedStatement JavaDoc;
21 import java.sql.ResultSet JavaDoc;
22 import java.sql.SQLException JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.List JavaDoc;
25
26 import javax.servlet.jsp.JspException JavaDoc;
27 import javax.servlet.jsp.JspTagException JavaDoc;
28 import javax.servlet.jsp.PageContext JavaDoc;
29 import javax.servlet.jsp.jstl.core.Config;
30 import javax.servlet.jsp.jstl.sql.Result;
31 import javax.servlet.jsp.jstl.sql.SQLExecutionTag;
32 import javax.servlet.jsp.tagext.BodyTagSupport JavaDoc;
33 import javax.servlet.jsp.tagext.TryCatchFinally JavaDoc;
34 import javax.sql.DataSource JavaDoc;
35
36 import org.apache.taglibs.standard.resources.Resources;
37 import org.apache.taglibs.standard.tag.common.core.Util;
38
39
40 /**
41  * <p>Tag handler for &lt;Query&gt; in JSTL.
42  *
43  * @author Hans Bergsten
44  * @author Justyna Horwat
45  */

46
47 public abstract class QueryTagSupport extends BodyTagSupport JavaDoc
48     implements TryCatchFinally JavaDoc, SQLExecutionTag {
49
50     private String JavaDoc var;
51     private int scope;
52
53     /*
54      * The following properties take expression values, so the
55      * setter methods are implemented by the expression type
56      * specific subclasses.
57      */

58     protected Object JavaDoc rawDataSource;
59     protected boolean dataSourceSpecified;
60     protected String JavaDoc sql;
61     protected int maxRows;
62     protected boolean maxRowsSpecified;
63     protected int startRow;
64
65     /*
66      * Instance variables that are not for attributes
67      */

68     private Connection JavaDoc conn;
69     private List JavaDoc parameters;
70     private boolean isPartOfTransaction;
71
72
73     //*********************************************************************
74
// Constructor and initialization
75

76     public QueryTagSupport() {
77         super();
78         init();
79     }
80
81     private void init() {
82         startRow = 0;
83         maxRows = -1;
84     maxRowsSpecified = dataSourceSpecified = false;
85     isPartOfTransaction = false;
86     conn = null;
87     rawDataSource = null;
88     parameters = null;
89     sql = null;
90     var = null;
91         scope = PageContext.PAGE_SCOPE;
92     }
93
94
95     //*********************************************************************
96
// Accessor methods
97

98     /**
99      * Setter method for the name of the variable to hold the
100      * result.
101      */

102     public void setVar(String JavaDoc var) {
103     this.var = var;
104     }
105
106     /**
107      * Setter method for the scope of the variable to hold the
108      * result.
109      */

110     public void setScope(String JavaDoc scopeName) {
111         scope = Util.getScope(scopeName);
112     }
113
114     //*********************************************************************
115
// Public utility methods
116

117     /**
118      * Called by nested parameter elements to add PreparedStatement
119      * parameter values.
120      */

121     public void addSQLParameter(Object JavaDoc o) {
122     if (parameters == null) {
123         parameters = new ArrayList JavaDoc();
124     }
125     parameters.add(o);
126     }
127
128     //*********************************************************************
129
// Tag logic
130

131     /**
132      * Prepares for execution by setting the initial state, such as
133      * getting the <code>Connection</code>
134      */

135     public int doStartTag() throws JspException JavaDoc {
136
137         if (!maxRowsSpecified) {
138         Object JavaDoc obj = Config.find(pageContext, Config.SQL_MAX_ROWS);
139         if (obj != null) {
140         if (obj instanceof Integer JavaDoc) {
141             maxRows = ((Integer JavaDoc) obj).intValue();
142         } else if (obj instanceof String JavaDoc) {
143             try {
144             maxRows = Integer.parseInt((String JavaDoc) obj);
145             } catch (NumberFormatException JavaDoc nfe) {
146             throw new JspException JavaDoc(
147                 Resources.getMessage("SQL_MAXROWS_PARSE_ERROR",
148                          (String JavaDoc) obj),
149                 nfe);
150             }
151         } else {
152             throw new JspException JavaDoc(
153                         Resources.getMessage("SQL_MAXROWS_INVALID"));
154         }
155             }
156         }
157
158     try {
159         conn = getConnection();
160     } catch (SQLException JavaDoc e) {
161         throw new JspException JavaDoc(sql + ": " + e.getMessage(), e);
162     }
163
164     return EVAL_BODY_BUFFERED;
165     }
166
167     /**
168      * <p>Execute the SQL statement, set either through the <code>sql</code>
169      * attribute or as the body, and save the result as a variable
170      * named by the <code>var</code> attribute in the scope specified
171      * by the <code>scope</code> attribute, as an object that implements
172      * the Result interface.
173      *
174      * <p>The connection used to execute the statement comes either
175      * from the <code>DataSource</code> specified by the
176      * <code>dataSource</code> attribute, provided by a parent action
177      * element, or is retrieved from a JSP scope attribute
178      * named <code>javax.servlet.jstl.sql.dataSource</code>.
179      */

180     public int doEndTag() throws JspException JavaDoc {
181     /*
182      * Use the SQL statement specified by the sql attribute, if any,
183      * otherwise use the body as the statement.
184      */

185     String JavaDoc sqlStatement = null;
186     if (sql != null) {
187         sqlStatement = sql;
188     }
189     else if (bodyContent != null) {
190         sqlStatement = bodyContent.getString();
191     }
192     if (sqlStatement == null || sqlStatement.trim().length() == 0) {
193         throw new JspTagException JavaDoc(
194                 Resources.getMessage("SQL_NO_STATEMENT"));
195     }
196         /*
197          * We shouldn't have a negative startRow or illegal maxrows
198          */

199         if ((startRow < 0) || (maxRows < -1)) {
200             throw new JspException JavaDoc(
201                 Resources.getMessage("PARAM_BAD_VALUE"));
202         }
203
204     Result result = null;
205     /*
206      * Note! We must not use the setMaxRows() method on the
207      * the statement to limit the number of rows, since the
208      * Result factory must be able to figure out the correct
209      * value for isLimitedByMaxRows(); there's no way to check
210      * if it was from the ResultSet.
211           */

212     PreparedStatement JavaDoc ps = null;
213     try {
214         ps = conn.prepareStatement(sqlStatement);
215         setParameters(ps, parameters);
216         ResultSet JavaDoc rs = ps.executeQuery();
217         result = new ResultImpl(rs, startRow, maxRows);
218     }
219     catch (Throwable JavaDoc e) {
220         throw new JspException JavaDoc(sqlStatement + ": " + e.getMessage(), e);
221     } finally {
222         if (ps != null) {
223         try {
224             ps.close();
225         } catch (SQLException JavaDoc sqe) {
226             throw new JspException JavaDoc(sqe.getMessage(), sqe);
227         }
228         }
229     }
230     pageContext.setAttribute(var, result, scope);
231     return EVAL_PAGE;
232     }
233
234     /**
235      * Just rethrows the Throwable.
236      */

237     public void doCatch(Throwable JavaDoc t) throws Throwable JavaDoc {
238     throw t;
239     }
240
241     /**
242      * Close the <code>Connection</code>, unless this action is used
243      * as part of a transaction.
244      */

245     public void doFinally() {
246     if (conn != null && !isPartOfTransaction) {
247         try {
248         conn.close();
249         } catch (SQLException JavaDoc e) {} // Not much we can do
250
}
251
252     conn = null;
253     parameters = null;
254     }
255
256
257     //*********************************************************************
258
// Private utility methods
259

260     private Connection JavaDoc getConnection() throws JspException JavaDoc, SQLException JavaDoc {
261     // Fix: Add all other mechanisms
262
Connection JavaDoc conn = null;
263     isPartOfTransaction = false;
264
265     TransactionTagSupport parent = (TransactionTagSupport)
266         findAncestorWithClass(this, TransactionTagSupport.class);
267     if (parent != null) {
268             if (dataSourceSpecified) {
269                 throw new JspTagException JavaDoc(
270                     Resources.getMessage("ERROR_NESTED_DATASOURCE"));
271             }
272         conn = parent.getSharedConnection();
273             isPartOfTransaction = true;
274     } else {
275         if ((rawDataSource == null) && dataSourceSpecified) {
276         throw new JspException JavaDoc(
277             Resources.getMessage("SQL_DATASOURCE_NULL"));
278         }
279         DataSource JavaDoc dataSource = DataSourceUtil.getDataSource(rawDataSource,
280                                  pageContext);
281             try {
282             conn = dataSource.getConnection();
283             } catch (Exception JavaDoc ex) {
284                 throw new JspException JavaDoc(
285                     Resources.getMessage("DATASOURCE_INVALID",
286                                          ex.toString()));
287             }
288     }
289
290     return conn;
291     }
292
293     private void setParameters(PreparedStatement JavaDoc ps, List JavaDoc parameters)
294         throws SQLException JavaDoc
295     {
296     if (parameters != null) {
297         for (int i = 0; i < parameters.size(); i++) {
298                 /* The first parameter has index 1. If a null
299                  * is passed to setObject the parameter will be
300                  * set to JDBC null so an explicit call to
301                  * ps.setNull is not required.
302                  */

303         ps.setObject(i + 1, parameters.get(i));
304         }
305     }
306     }
307 }
308
Popular Tags