001 package railo.runtime.tag; 002 003 import java.io.IOException; 004 005 import javax.servlet.jsp.tagext.Tag; 006 007 import railo.commons.lang.StringUtil; 008 import railo.runtime.db.SQLCaster; 009 import railo.runtime.db.SQLItemImpl; 010 import railo.runtime.exp.ApplicationException; 011 import railo.runtime.exp.DatabaseException; 012 import railo.runtime.exp.PageException; 013 import railo.runtime.ext.tag.TagImpl; 014 import railo.runtime.op.Caster; 015 import railo.runtime.type.Array; 016 import railo.runtime.type.ArrayImpl; 017 import railo.runtime.type.util.ListUtil; 018 019 /** 020 * Checks the data type of a query parameter. The cfqueryparam tag is nested within a cfquery tag. 021 * It is embedded within the query SQL statement. If you specify its optional parameters, cfqueryparam 022 * also performs data validation. 023 * 024 * 025 * 026 **/ 027 public final class QueryParam extends TagImpl { 028 029 private SQLItemImpl item=new SQLItemImpl(); 030 031 /** Specifies the character that separates values in the list of parameter values in the value 032 ** attribute. The default is a comma. If you specify a list of values for the value attribute, you must 033 ** also specify the list attribute. */ 034 private String separator=","; 035 036 /** Yes or No. Indicates that the parameter value of the value attribute is a list of values, 037 ** separated by a separator character. The default is No */ 038 private boolean list; 039 040 041 /** Maximum length of the parameter. The default value is the length of the string specified in 042 ** the value attribute. */ 043 private double maxlength=-1; 044 045 @Override 046 public void release() { 047 separator=","; 048 list=false; 049 maxlength=-1; 050 item=new SQLItemImpl(); 051 } 052 053 054 /** set the value list 055 * Yes or No. Indicates that the parameter value of the value attribute is a list of values, 056 * separated by a separator character. The default is No 057 * @param list value to set 058 **/ 059 public void setList(boolean list) { 060 this.list=list; 061 } 062 063 /** set the value null 064 * Yes or No. Indicates whether the parameter is passed as a null. If Yes, the tag ignores the 065 * value attribute. The default is No. 066 * @param nulls value to set 067 **/ 068 public void setNull(boolean nulls) { 069 item.setNulls(nulls); 070 } 071 072 /** set the value value 073 * @param value value to set 074 **/ 075 public void setValue(Object value) { 076 item.setValue(value); 077 } 078 079 /** set the value maxlength 080 * Maximum length of the parameter. The default value is the length of the string specified in 081 * the value attribute. 082 * @param maxlength value to set 083 **/ 084 public void setMaxlength(double maxlength) { 085 this.maxlength=maxlength; 086 } 087 088 /** set the value separator 089 * Specifies the character that separates values in the list of parameter values in the value 090 * attribute. The default is a comma. If you specify a list of values for the value attribute, you must 091 * also specify the list attribute. 092 * @param separator value to set 093 **/ 094 public void setSeparator(String separator) { 095 this.separator=separator; 096 } 097 098 /** set the value scale 099 * Number of decimal places of the parameter. The default value is zero. 100 * @param scale value to set 101 **/ 102 public void setScale(double scale) { 103 item.setScale((int)scale); 104 } 105 106 /** set the value cfsqltype 107 * The SQL type that the parameter (any type) will be bound to. 108 * @param type value to set 109 * @throws DatabaseException 110 **/ 111 public void setCfsqltype(String type) throws DatabaseException { 112 item.setType(SQLCaster.toIntType(type)); 113 114 } 115 116 @Override 117 public int doStartTag() throws PageException { 118 Tag parent = getParent(); 119 while(parent!=null && !(parent instanceof Query)) { 120 parent=parent.getParent(); 121 } 122 if(parent instanceof Query) { 123 Query query = (Query)parent; 124 if(!item.isNulls() && !item.isValueSet()) 125 throw new ApplicationException("attribute value from tag queryparam is required if attribute null is false"); 126 if(list) { 127 String v = Caster.toString(item.getValue()); 128 Array arr=null; 129 if(StringUtil.isEmpty(v)){ 130 arr=new ArrayImpl(); 131 arr.append(""); 132 } 133 else arr=ListUtil.listToArrayRemoveEmpty(v,separator); 134 135 int len=arr.size(); 136 StringBuffer sb=new StringBuffer(); 137 for(int i=1;i<=len;i++) { 138 query.setParam(item.clone(check(arr.getE(i)))); 139 if(i>1)sb.append(','); 140 sb.append('?'); 141 } 142 write(sb.toString()); 143 } 144 else { 145 check(item.getValue()); 146 query.setParam(item); 147 write("?"); 148 } 149 } 150 else { 151 throw new ApplicationException("Wrong Context, tag QueryParam must be inside a Query tag"); 152 } 153 return SKIP_BODY; 154 } 155 156 private Object check(Object value) throws PageException { 157 if(maxlength!=-1) { 158 String str = Caster.toString(value); 159 if(str.length()>maxlength) 160 throw new DatabaseException("value ["+value+"] is to large, defined maxlength is ["+Caster.toString(maxlength)+"] but length of value is ["+str.length()+"]",null,null,null); 161 } 162 return value; 163 } 164 165 private void write(String str) { 166 try { 167 pageContext.write(str); 168 } 169 catch (IOException e) {} 170 } 171 172 }