001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.tag; 020 021import java.io.IOException; 022 023import javax.servlet.jsp.tagext.Tag; 024 025import lucee.commons.lang.StringUtil; 026import lucee.runtime.db.SQLCaster; 027import lucee.runtime.db.SQLItemImpl; 028import lucee.runtime.exp.ApplicationException; 029import lucee.runtime.exp.DatabaseException; 030import lucee.runtime.exp.PageException; 031import lucee.runtime.ext.tag.TagImpl; 032import lucee.runtime.op.Caster; 033import lucee.runtime.type.Array; 034import lucee.runtime.type.ArrayImpl; 035import lucee.runtime.type.util.ListUtil; 036 037/** 038* Checks the data type of a query parameter. The cfqueryparam tag is nested within a cfquery tag. 039* It is embedded within the query SQL statement. If you specify its optional parameters, cfqueryparam 040* also performs data validation. 041* 042* 043* 044**/ 045public final class QueryParam extends TagImpl { 046 047 private SQLItemImpl item=new SQLItemImpl(); 048 049 /** Specifies the character that separates values in the list of parameter values in the value 050 ** attribute. The default is a comma. If you specify a list of values for the value attribute, you must 051 ** also specify the list attribute. */ 052 private String separator=","; 053 054 /** Yes or No. Indicates that the parameter value of the value attribute is a list of values, 055 ** separated by a separator character. The default is No */ 056 private boolean list; 057 058 059 /** Maximum length of the parameter. The default value is the length of the string specified in 060 ** the value attribute. */ 061 private double maxlength=-1; 062 063 @Override 064 public void release() { 065 separator=","; 066 list=false; 067 maxlength=-1; 068 item=new SQLItemImpl(); 069 } 070 071 072 /** set the value list 073 * Yes or No. Indicates that the parameter value of the value attribute is a list of values, 074 * separated by a separator character. The default is No 075 * @param list value to set 076 **/ 077 public void setList(boolean list) { 078 this.list=list; 079 } 080 081 /** set the value null 082 * Yes or No. Indicates whether the parameter is passed as a null. If Yes, the tag ignores the 083 * value attribute. The default is No. 084 * @param nulls value to set 085 **/ 086 public void setNull(boolean nulls) { 087 item.setNulls(nulls); 088 } 089 090 /** set the value value 091 * @param value value to set 092 **/ 093 public void setValue(Object value) { 094 item.setValue(value); 095 } 096 097 /** set the value maxlength 098 * Maximum length of the parameter. The default value is the length of the string specified in 099 * the value attribute. 100 * @param maxlength value to set 101 **/ 102 public void setMaxlength(double maxlength) { 103 this.maxlength=maxlength; 104 } 105 106 /** set the value separator 107 * Specifies the character that separates values in the list of parameter values in the value 108 * attribute. The default is a comma. If you specify a list of values for the value attribute, you must 109 * also specify the list attribute. 110 * @param separator value to set 111 **/ 112 public void setSeparator(String separator) { 113 this.separator=separator; 114 } 115 116 /** set the value scale 117 * Number of decimal places of the parameter. The default value is zero. 118 * @param scale value to set 119 **/ 120 public void setScale(double scale) { 121 item.setScale((int)scale); 122 } 123 124 /** set the value cfsqltype 125 * The SQL type that the parameter (any type) will be bound to. 126 * @param type value to set 127 * @throws DatabaseException 128 **/ 129 public void setCfsqltype(String type) throws DatabaseException { 130 item.setType(SQLCaster.toSQLType(type)); 131 132 } 133 public void setSqltype(String type) throws DatabaseException { 134 item.setType(SQLCaster.toSQLType(type)); 135 136 } 137 138 @Override 139 public int doStartTag() throws PageException { 140 Tag parent = getParent(); 141 while(parent!=null && !(parent instanceof Query)) { 142 parent=parent.getParent(); 143 } 144 if(parent instanceof Query) { 145 Query query = (Query)parent; 146 if(!item.isNulls() && !item.isValueSet()) 147 throw new ApplicationException("attribute value from tag queryparam is required if attribute null is false"); 148 if(list) { 149 String v = Caster.toString(item.getValue()); 150 Array arr=null; 151 if(StringUtil.isEmpty(v)){ 152 arr=new ArrayImpl(); 153 arr.append(""); 154 } 155 else arr=ListUtil.listToArrayRemoveEmpty(v,separator); 156 157 int len=arr.size(); 158 StringBuffer sb=new StringBuffer(); 159 for(int i=1;i<=len;i++) { 160 query.setParam(item.clone(check(arr.getE(i)))); 161 if(i>1)sb.append(','); 162 sb.append('?'); 163 } 164 write(sb.toString()); 165 } 166 else { 167 check(item.getValue()); 168 query.setParam(item); 169 write("?"); 170 } 171 } 172 else { 173 throw new ApplicationException("Wrong Context, tag QueryParam must be inside a Query tag"); 174 } 175 return SKIP_BODY; 176 } 177 178 private Object check(Object value) throws PageException { 179 if(maxlength!=-1) { 180 String str = Caster.toString(value); 181 if(str.length()>maxlength) 182 throw new DatabaseException("value ["+value+"] is to large, defined maxlength is ["+Caster.toString(maxlength)+"] but length of value is ["+str.length()+"]",null,null,null); 183 } 184 return value; 185 } 186 187 private void write(String str) { 188 try { 189 pageContext.write(str); 190 } 191 catch (IOException e) {} 192 } 193 194}