001 package railo.runtime.type; 002 003 import railo.commons.lang.CFTypes; 004 import railo.commons.lang.StringUtil; 005 import railo.runtime.Component; 006 import railo.runtime.ComponentImpl; 007 import railo.runtime.Page; 008 import railo.runtime.PageContext; 009 import railo.runtime.PageSource; 010 import railo.runtime.dump.DumpData; 011 import railo.runtime.dump.DumpProperties; 012 import railo.runtime.exp.DeprecatedException; 013 import railo.runtime.exp.ExpressionException; 014 import railo.runtime.exp.PageException; 015 import railo.runtime.exp.PageRuntimeException; 016 import railo.runtime.exp.UDFCasterException; 017 import railo.runtime.functions.decision.IsValid; 018 import railo.runtime.op.Caster; 019 import railo.runtime.op.Decision; 020 import railo.runtime.type.util.ComponentUtil; 021 import railo.runtime.type.util.KeyConstants; 022 023 public abstract class UDFGSProperty extends UDFImpl { 024 025 private static final Collection.Key MIN_LENGTH = KeyImpl.intern("minLength"); 026 private static final Collection.Key MAX_LENGTH = KeyImpl.intern("maxLength"); 027 028 protected final FunctionArgument[] arguments; 029 protected final String name; 030 protected final ComponentImpl component; 031 032 public UDFGSProperty(ComponentImpl component,String name,FunctionArgument[] arguments,short rtnType,String rtnFormat) { 033 super(UDFProperties( 034 component.getPageSource(), 035 arguments, 036 -1, 037 name, 038 rtnType, 039 rtnFormat, 040 false, 041 true, 042 "public", 043 "", 044 "", 045 "", 046 Boolean.FALSE, 047 Boolean.FALSE, 048 0L, 049 null, 050 new StructImpl() 051 052 )); 053 054 this.name=name; 055 this.arguments=arguments; 056 this.component=component; 057 } 058 059 private static UDFPropertiesImpl UDFProperties(PageSource pageSource, 060 FunctionArgument[] arguments, 061 int index, 062 String functionName, 063 short returnType, 064 String strReturnFormat, 065 boolean output, 066 Boolean bufferOutput, 067 String strAccess, 068 String displayName, 069 String description, 070 String hint, 071 Boolean secureJson, 072 Boolean verifyClient, 073 long cachedWithin, 074 Integer localMode, 075 StructImpl meta) { 076 try { 077 return new UDFPropertiesImpl( pageSource, 078 arguments, 079 index, 080 functionName, 081 returnType, 082 strReturnFormat, 083 output, 084 ComponentUtil.toIntAccess(strAccess), 085 bufferOutput, 086 displayName, 087 description, 088 hint, 089 secureJson, 090 verifyClient, 091 cachedWithin, 092 localMode, 093 meta); 094 } catch (ExpressionException e) { 095 return new UDFPropertiesImpl(); 096 } 097 } 098 099 @Override 100 public FunctionArgument[] getFunctionArguments() { 101 return arguments; 102 } 103 104 @Override 105 public String getFunctionName() { 106 return name; 107 } 108 109 @Override 110 public Component getOwnerComponent() { 111 return component; 112 } 113 114 public Page getPage() { 115 throw new PageRuntimeException(new DeprecatedException("method getPage():Page is no longer suppoted, use instead getPageSource():PageSource")); 116 } 117 118 @Override 119 public boolean getOutput() { 120 return false; 121 } 122 123 @Override 124 public int getAccess() { 125 return Component.ACCESS_PUBLIC; 126 } 127 128 @Override 129 public String getDisplayName() { 130 return ""; 131 } 132 133 @Override 134 public String getDescription() { 135 return ""; 136 } 137 138 @Override 139 public String getHint() { 140 return ""; 141 } 142 143 @Override 144 public int getReturnFormat() { 145 return UDFImpl.RETURN_FORMAT_WDDX; 146 } 147 148 @Override 149 public int getReturnType() { 150 return CFTypes.toShortStrict(getReturnTypeAsString(),CFTypes.TYPE_UNKNOW); 151 } 152 153 @Override 154 public Object getValue() { 155 return this; 156 } 157 158 @Override 159 public Boolean getSecureJson() { 160 return null; 161 } 162 163 @Override 164 public Boolean getVerifyClient() { 165 return null; 166 } 167 168 @Override 169 public DumpData toDumpData(PageContext pageContext, int maxlevel,DumpProperties properties) { 170 return UDFImpl.toDumpData(pageContext, maxlevel, properties, this,false); 171 } 172 173 @Override 174 public Struct getMetaData(PageContext pc) throws PageException { 175 return super.getMetaData(pc); 176 //return UDFImpl.getMetaData(pc, this); 177 } 178 179 180 181 final Object cast(FunctionArgument arg,Object value, int index) throws PageException { 182 if(value==null || Decision.isCastableTo(arg.getType(),arg.getTypeAsString(),value)) 183 return value; 184 throw new UDFCasterException(this,arg,value,index); 185 } 186 187 final static void validate(String validate, Struct validateParams, Object obj) throws PageException { 188 if(StringUtil.isEmpty(validate,true)) return; 189 validate=validate.trim().toLowerCase(); 190 191 if(!validate.equals("regex") && !Decision.isValid(validate, obj)) 192 throw new ExpressionException(createMessage(validate, obj)); 193 194 195 // range 196 if(validateParams==null) return; 197 198 if(validate.equals("integer") || validate.equals("numeric") || validate.equals("number")){ 199 double min=Caster.toDoubleValue(validateParams.get(KeyConstants._min,null),Double.NaN); 200 double max=Caster.toDoubleValue(validateParams.get(KeyConstants._max,null),Double.NaN); 201 double d=Caster.toDoubleValue(obj); 202 if(!Double.isNaN(min) && d<min) 203 throw new ExpressionException(validate+" ["+Caster.toString(d)+"] is out of range, value must be more than or equal to ["+min+"]"); 204 if(!Double.isNaN(max) && d>max) 205 throw new ExpressionException(validate+" ["+Caster.toString(d)+"] is out of range, value must be less than or equal to ["+max+"]"); 206 } 207 else if(validate.equals("string")){ 208 double min=Caster.toDoubleValue(validateParams.get(MIN_LENGTH,null),Double.NaN); 209 double max=Caster.toDoubleValue(validateParams.get(MAX_LENGTH,null),Double.NaN); 210 String str=Caster.toString(obj); 211 int l=str.length(); 212 if(!Double.isNaN(min) && l<((int)min)) 213 throw new ExpressionException("string ["+str+"] is to short ["+l+"], the string must be at least ["+min+"] characters"); 214 if(!Double.isNaN(max) && l>((int)max)) 215 throw new ExpressionException("string ["+str+"] is to long ["+l+"], the string can have a maximum length of ["+max+"] characters"); 216 } 217 else if(validate.equals("regex")){ 218 String pattern=Caster.toString(validateParams.get(KeyConstants._pattern,null),null); 219 String value=Caster.toString(obj); 220 if(!StringUtil.isEmpty(pattern,true) && !IsValid.regex(value, pattern)) 221 throw new ExpressionException("the string ["+value+"] does not match the regular expression pattern ["+pattern+"]"); 222 } 223 } 224 225 226 private static String createMessage(String format, Object value) { 227 if(Decision.isSimpleValue(value)) return "the value ["+Caster.toString(value,null)+"] is not in ["+format+"] format"; 228 return "cannot convert object from type ["+Caster.toTypeName(value)+"] to a ["+format+"] format"; 229 } 230 231 }