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.transformer.library.function; 020 021import java.io.IOException; 022import java.util.ArrayList; 023import java.util.Iterator; 024 025import lucee.commons.lang.CFTypes; 026import lucee.commons.lang.ClassException; 027import lucee.commons.lang.ClassUtil; 028import lucee.commons.lang.ExceptionUtil; 029import lucee.commons.lang.Md5; 030import lucee.commons.lang.StringUtil; 031import lucee.runtime.exp.PageRuntimeException; 032import lucee.runtime.exp.TemplateException; 033import lucee.runtime.functions.BIF; 034import lucee.runtime.functions.BIFProxy; 035import lucee.runtime.reflection.Reflector; 036import lucee.runtime.type.util.ListUtil; 037import lucee.transformer.bytecode.BytecodeException; 038import lucee.transformer.cfml.evaluator.FunctionEvaluator; 039import lucee.transformer.library.tag.TagLib; 040 041 042 043/** 044 * Eine FunctionLibFunction repraesentiert eine einzelne Funktion innerhalb einer FLD. 045 */ 046public final class FunctionLibFunction { 047 048 /** 049 * Dynamischer Argument Typ 050 */ 051 public static final int ARG_DYNAMIC = 0; 052 /** 053 * statischer Argument Typ 054 */ 055 public static final int ARG_FIX = 1; 056 057 058 private FunctionLib functionLib; 059 private String name; 060 private ArrayList<FunctionLibFunctionArg> argument=new ArrayList<FunctionLibFunctionArg>(); 061 062 private int argMin=0; 063 private int argMax=-1; 064 private int argType=ARG_FIX; 065 066 067 private String strReturnType; 068 069 private String cls=""; 070 private Class clazz; 071 private String description; 072 private boolean hasDefaultValues; 073 private FunctionEvaluator eval; 074 private String tteClass; 075 private short status=TagLib.STATUS_IMPLEMENTED; 076 private String[] memberNames; 077 private int memberPosition=1; 078 private short memberType=CFTypes.TYPE_UNKNOW; 079 private boolean memberChaining; 080 private BIF bif; 081 private String[] keywords; 082 083 084 /** 085 * Geschuetzer Konstruktor ohne Argumente. 086 */ 087 public FunctionLibFunction() { 088 } 089 public FunctionLibFunction(FunctionLib functionLib) { 090 this.functionLib=functionLib; 091 } 092 093 /** 094 * Gibt den Namen der Funktion zurueck. 095 * @return name Name der Funktion. 096 */ 097 public String getName() { 098 return name; 099 } 100 101 /** 102 * Gibt alle Argumente einer Funktion als ArrayList zurueck. 103 * @return Argumente der Funktion. 104 */ 105 public ArrayList<FunctionLibFunctionArg> getArg() { 106 return argument; 107 } 108 109 /** 110 * Gibt zurueck wieviele Argumente eine Funktion minimal haben muss. 111 * @return Minimale Anzahl Argumente der Funktion. 112 */ 113 public int getArgMin() { 114 return argMin; 115 } 116 117 /** 118 * Gibt zurueck wieviele Argumente eine Funktion minimal haben muss. 119 * @return Maximale Anzahl Argumente der Funktion. 120 */ 121 public int getArgMax() { 122 return argMax; 123 } 124 125 /** 126 * @return the status (TagLib.,TagLib.STATUS_IMPLEMENTED,TagLib.STATUS_DEPRECATED,TagLib.STATUS_UNIMPLEMENTED) 127 */ 128 public short getStatus() { 129 return status; 130 } 131 132 133 /** 134 * @param status the status to set (TagLib.,TagLib.STATUS_IMPLEMENTED,TagLib.STATUS_DEPRECATED,TagLib.STATUS_UNIMPLEMENTED) 135 */ 136 public void setStatus(short status) { 137 this.status = status; 138 } 139 140 141 /** 142 * Gibt die argument art zurueck. 143 * @return argument art 144 */ 145 public int getArgType() { 146 return argType; 147 } 148 149 /** 150 * Gibt die argument art als String zurueck. 151 * @return argument art 152 */ 153 public String getArgTypeAsString() { 154 if(argType==ARG_DYNAMIC) return "dynamic"; 155 return "fixed"; 156 } 157 158 /** 159 * Gibt zurueck von welchem Typ der Rueckgabewert dieser Funktion sein muss (query, string, struct, number usw.). 160 * @return Typ des Rueckgabewert. 161 */ 162 public String getReturnTypeAsString() { 163 return strReturnType; 164 } 165 166 /** 167 * Gibt die Klassendefinition als Zeichenkette zurueck, welche diese Funktion implementiert. 168 * @return Klassendefinition als Zeichenkette. 169 */ 170 public String getCls() { 171 return cls; 172 } 173 174 /** 175 * Gibt die Klasse zurueck, welche diese Funktion implementiert. 176 * @return Klasse der Function. 177 * @throws ClassException 178 */ 179 public Class getClazz() throws TemplateException { 180 if(clazz==null) { 181 try { 182 clazz=ClassUtil.loadClass(cls); 183 } 184 catch (ClassException e) { 185 throw new BytecodeException(e, null); 186 } 187 } 188 189 return clazz; 190 } 191 192 public Class getClazz(Class defaultValue) { 193 if(clazz==null) { 194 clazz=ClassUtil.loadClass(cls,defaultValue); 195 } 196 197 return clazz; 198 } 199 200 /** 201 * Gibt die Beschreibung der Funktion zurueck. 202 * @return String 203 */ 204 public String getDescription() { 205 return description; 206 } 207 208 /** 209 * Gibt die FunctionLib zurueck, zu der die Funktion gehoert. 210 * @return Zugehoerige FunctionLib. 211 */ 212 public FunctionLib getFunctionLib() { 213 return functionLib; 214 } 215 216 /** 217 * Setzt den Namen der Funktion. 218 * @param name Name der Funktion. 219 */ 220 public void setName(String name) { 221 this.name = name.toLowerCase(); 222 } 223 224 /** 225 * Fuegt der Funktion ein Argument hinzu. 226 * @param arg Argument zur Funktion. 227 */ 228 public void addArg(FunctionLibFunctionArg arg) { 229 arg.setFunction(this); 230 argument.add(arg); 231 if(arg.getDefaultValue()!=null) 232 hasDefaultValues=true; 233 } 234 235 /** 236 * Fuegt der Funktion ein Argument hinzu, alias fuer addArg. 237 * @param arg Argument zur Funktion. 238 */ 239 public void setArg(FunctionLibFunctionArg arg) { 240 addArg(arg); 241 } 242 243 244 /** 245 * Setzt wieviele Argumente eine Funktion minimal haben muss. 246 * @param argMin Minimale Anzahl Argumente der Funktion. 247 */ 248 public void setArgMin(int argMin) { 249 this.argMin = argMin; 250 } 251 252 /** 253 * Setzt wieviele Argumente eine Funktion minimal haben muss. 254 * @param argMax Maximale Anzahl Argumente der Funktion. 255 */ 256 public void setArgMax(int argMax) { 257 this.argMax = argMax; 258 } 259 260 /** 261 * Setzt den Rueckgabewert der Funktion (query,array,string usw.) 262 * @param value 263 */ 264 public void setReturn(String value) { 265 strReturnType=value; 266 } 267 268 /** 269 * Setzt die Klassendefinition als Zeichenkette, welche diese Funktion implementiert. 270 * @param value Klassendefinition als Zeichenkette. 271 */ 272 public void setCls(String value) { 273 cls+=value; 274 275 } 276 277 /** 278 * Setzt die Beschreibung der Funktion. 279 * @param description Beschreibung der Funktion. 280 */ 281 public void setDescription(String description) { 282 this.description = description; 283 } 284 285 /** 286 * Setzt die zugehoerige FunctionLib. 287 * @param functionLib Zugehoerige FunctionLib. 288 */ 289 public void setFunctionLib(FunctionLib functionLib) { 290 this.functionLib=functionLib; 291 } 292 293 /** 294 * sets the argument type of the function 295 * @param argType 296 */ 297 public void setArgType(int argType) { 298 this.argType=argType; 299 } 300 301 302 public String getHash() { 303 StringBuffer sb=new StringBuffer(); 304 sb.append(this.getArgMax()); 305 sb.append(this.getArgMin()); 306 sb.append(this.getArgType()); 307 sb.append(this.getArgTypeAsString()); 308 sb.append(this.getCls()); 309 sb.append(this.getName()); 310 sb.append(this.getReturnTypeAsString()); 311 312 Iterator it = this.getArg().iterator(); 313 FunctionLibFunctionArg arg; 314 while(it.hasNext()){ 315 arg=(FunctionLibFunctionArg) it.next(); 316 sb.append(arg.getHash()); 317 } 318 319 try { 320 return Md5.getDigestAsString(sb.toString()); 321 } catch (IOException e) { 322 return ""; 323 } 324 } 325 public boolean hasDefaultValues() { 326 return hasDefaultValues; 327 } 328 329 public boolean hasTteClass() { 330 return tteClass !=null && tteClass.length()>0; 331 } 332 333 public FunctionEvaluator getEvaluator() throws TemplateException { 334 if(!hasTteClass()) return null; 335 if(eval!=null) return eval; 336 try { 337 eval = (FunctionEvaluator) ClassUtil.loadInstance(tteClass); 338 } 339 catch (ClassException e) { 340 throw new TemplateException(e.getMessage()); 341 } 342 return eval; 343 } 344 public void setTteClass(String tteClass) { 345 this.tteClass=tteClass; 346 } 347 public void setMemberName(String memberNames) { 348 if(StringUtil.isEmpty(memberNames,true)) return; 349 this.memberNames=ListUtil.trimItems(ListUtil.listToStringArray(memberNames, ',')); 350 } 351 public String[] getMemberNames() { 352 return memberNames; 353 } 354 355 356 public void setKeywords(String keywords) { 357 this.keywords=ListUtil.trimItems(ListUtil.listToStringArray(keywords, ',')); 358 } 359 public String[] getKeywords() { 360 return keywords; 361 } 362 363 public void setMemberPosition(int pos) { 364 this.memberPosition=pos; 365 } 366 public int getMemberPosition() { 367 return memberPosition; 368 } 369 370 public void setMemberChaining(boolean memberChaining) { 371 this.memberChaining=memberChaining; 372 } 373 public boolean getMemberChaining() { 374 return memberChaining; 375 } 376 377 public short getMemberType() { 378 if(memberNames!=null && memberType==CFTypes.TYPE_UNKNOW){ 379 ArrayList<FunctionLibFunctionArg> args = getArg(); 380 if(args.size()>=1){ 381 memberType=CFTypes.toShortStrict(args.get(getMemberPosition()-1).getTypeAsString(),CFTypes.TYPE_UNKNOW); 382 } 383 } 384 return memberType; 385 } 386 public String getMemberTypeAsString() { 387 return CFTypes.toString(getMemberType(),"any"); 388 } 389 public BIF getBIF() { 390 if(bif!=null) return bif; 391 392 Class clazz=null; 393 try { 394 clazz = getClazz(); 395 } 396 catch (TemplateException e) { 397 throw new PageRuntimeException(e); 398 } 399 400 if(Reflector.isInstaneOf(clazz, BIF.class)) { 401 try { 402 bif=(BIF)clazz.newInstance(); 403 } 404 catch (Throwable t) { 405 ExceptionUtil.rethrowIfNecessary(t); 406 throw new RuntimeException(t); 407 } 408 } 409 else { 410 return new BIFProxy(clazz); 411 } 412 return bif; 413 } 414}