1 /*
2 * The Apache Software License, Version 1.1
3 *
4 * Copyright (c) 1999 The Apache Software Foundation. All rights
5 * reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * 3. The end-user documentation included with the redistribution, if
20 * any, must include the following acknowlegement:
21 * "This product includes software developed by the
22 * Apache Software Foundation (http://www.apache.org/)."
23 * Alternately, this acknowlegement may appear in the software itself,
24 * if and wherever such third-party acknowlegements normally appear.
25 *
26 * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
27 * Foundation" must not be used to endorse or promote products derived
28 * from this software without prior written permission. For written
29 * permission, please contact apache@apache.org.
30 *
31 * 5. Products derived from this software may not be called "Apache"
32 * nor may "Apache" appear in their names without prior written
33 * permission of the Apache Group.
34 *
35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46 * SUCH DAMAGE.
47 * ====================================================================
48 *
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Apache Software Foundation. For more
51 * information on the Apache Software Foundation, please see
52 * <http://www.apache.org/>.
53 *
54 */
55
56 package org.apache.commons.jelly.tags.sql;
57
58 import java.sql.*;
59 import java.util.*;
60 import javax.sql.DataSource;
61 import javax.servlet.jsp.jstl.sql.Result;
62 import javax.servlet.jsp.jstl.sql.SQLExecutionTag;
63
64 import org.apache.commons.jelly.JellyContext;
65 import org.apache.commons.jelly.JellyException;
66 import org.apache.commons.jelly.TagSupport;
67 import org.apache.commons.jelly.XMLOutput;
68 import org.apache.commons.jelly.tags.Resources;
69
70 import org.apache.commons.logging.Log;
71 import org.apache.commons.logging.LogFactory;
72
73
74 /***
75 * <p>Tag handler for <Query> in JSTL.
76 *
77 * @author Hans Bergsten
78 * @author Justyna Horwat
79 */
80
81 public class QueryTag extends SqlTagSupport {
82
83 /*** The Log to which logging calls will be made. */
84 private static final Log log = LogFactory.getLog(QueryTag.class);
85
86 /*
87 * The following properties take expression values, so the
88 * setter methods are implemented by the expression type
89 * specific subclasses.
90 */
91 protected int maxRows = -1;
92 protected boolean maxRowsSpecified;
93 protected int startRow;
94
95 /*
96 * Instance variables that are not for attributes
97 */
98 private Connection conn;
99
100 //**********************************************************************
101 // Constructor and initialization
102
103 public QueryTag() {
104 }
105
106 //*********************************************************************
107 // Accessor methods
108
109 /**
110 * The index of the first row returned can be
111 * specified using startRow.
112 */
113 public void setStartRow(int startRow) {
114 this.startRow = startRow;
115 }
116
117 /***
118 * Query result can be limited by specifying
119 * the maximum number of rows returned.
120 */
121 public void setMaxRows(int maxRows) {
122 this.maxRows = maxRows;
123 this.maxRowsSpecified = true;
124 }
125
126 //**********************************************************************
127 // Tag logic
128
129 /**
130 * <p>Execute the SQL statement, set either through the <code>sql</code>
131 * attribute or as the body, and save the result as a variable
132 * named by the <code>var</code> attribute in the scope specified
133 * by the <code>scope</code> attribute, as an object that implements
134 * the Result interface.
135 *
136 * <p>The connection used to execute the statement comes either
137 * from the <code>DataSource</code> specified by the
138 * <code>dataSource</code> attribute, provided by a parent action
139 * element, or is retrieved from a JSP scope attribute
140 * named <code>javax.servlet.jstl.sql.dataSource</code>.
141 */
142 public void doTag(XMLOutput output) throws Exception {
143
144 if (!maxRowsSpecified) {
145 Object obj = context.getVariable("org.apache.commons.jelly.sql.maxRows");
146 if (obj != null) {
147 if (obj instanceof Integer) {
148 maxRows = ((Integer) obj).intValue();
149 }
150 else if (obj instanceof String) {
151 try {
152 maxRows = Integer.parseInt((String) obj);
153 }
154 catch (NumberFormatException nfe) {
155 throw new JellyException(
156 Resources.getMessage("SQL_MAXROWS_PARSE_ERROR", (String) obj),
157 nfe);
158 }
159 }
160 else {
161 throw new JellyException(Resources.getMessage("SQL_MAXROWS_INVALID"));
162 }
163 }
164 }
165
166 Result result = null;
167 String sqlStatement = null;
168
169 log.debug( "About to lookup connection" );
170
171 try {
172 conn = getConnection();
173
174 /*
175 * Use the SQL statement specified by the sql attribute, if any,
176 * otherwise use the body as the statement.
177 */
178 if (sql != null) {
179 sqlStatement = sql;
180 }
181 else {
182 sqlStatement = getBodyText();
183 }
184 if (sqlStatement == null || sqlStatement.trim().length() == 0) {
185 throw new JellyException(Resources.getMessage("SQL_NO_STATEMENT"));
186 }
187 /*
188 * We shouldn't have a negative startRow or illegal maxrows
189 */
190 if ((startRow < 0) || (maxRows < -1)) {
191 throw new JellyException(Resources.getMessage("PARAM_BAD_VALUE"));
192 }
193
194 /*
195 * Note! We must not use the setMaxRows() method on the
196 * the statement to limit the number of rows, since the
197 * Result factory must be able to figure out the correct
198 * value for isLimitedByMaxRows(); there's no way to check
199 * if it was from the ResultSet.
200 */
201 if ( log.isDebugEnabled() ) {
202 log.debug( "About to execute query: " + sqlStatement );
203 }
204
205 ResultSet rs = null;
206 if ( hasParameters() ) {
207 PreparedStatement ps = conn.prepareStatement(sqlStatement);
208 setParameters(ps);
209 rs = ps.executeQuery();
210 }
211 else {
212 Statement statement = conn.createStatement();
213 rs = statement.executeQuery(sqlStatement);
214 }
215
216 result = new ResultImpl(rs, startRow, maxRows);
217 context.setVariable(var, result);
218 }
219 catch (SQLException e) {
220 throw new JellyException(sqlStatement + ": " + e.getMessage(), e);
221 }
222 finally {
223 if (conn != null && !isPartOfTransaction) {
224 try {
225 conn.close();
226 }
227 catch (SQLException e) {
228 } // Not much we can do
229 conn = null;
230 }
231 clearParameters();
232 }
233 }
234 }
This page was automatically generated by Maven