View Javadoc
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