001 package railo.runtime; 002 003 import java.io.IOException; 004 import java.io.InputStream; 005 import java.io.OutputStream; 006 import java.util.Iterator; 007 import java.util.Map.Entry; 008 009 import javax.servlet.ServletException; 010 import javax.servlet.http.HttpServletRequest; 011 import javax.servlet.http.HttpServletResponse; 012 013 import railo.commons.io.IOUtil; 014 import railo.commons.io.res.Resource; 015 import railo.commons.io.res.util.ResourceUtil; 016 import railo.commons.lang.CFTypes; 017 import railo.commons.lang.ExceptionUtil; 018 import railo.commons.lang.StringUtil; 019 import railo.commons.lang.mimetype.MimeType; 020 import railo.runtime.config.ConfigImpl; 021 import railo.runtime.config.ConfigWebImpl; 022 import railo.runtime.converter.BinaryConverter; 023 import railo.runtime.converter.ConverterException; 024 import railo.runtime.converter.JSONConverter; 025 import railo.runtime.converter.JavaConverter; 026 import railo.runtime.converter.ScriptConverter; 027 import railo.runtime.converter.WDDXConverter; 028 import railo.runtime.converter.XMLConverter; 029 import railo.runtime.converter.bin.ImageConverter; 030 import railo.runtime.dump.DumpUtil; 031 import railo.runtime.dump.DumpWriter; 032 import railo.runtime.exp.ApplicationException; 033 import railo.runtime.exp.ExpressionException; 034 import railo.runtime.exp.PageException; 035 import railo.runtime.gateway.GatewayEngineImpl; 036 import railo.runtime.interpreter.JSONExpressionInterpreter; 037 import railo.runtime.net.http.ReqRspUtil; 038 import railo.runtime.net.rpc.server.ComponentController; 039 import railo.runtime.net.rpc.server.RPCServer; 040 import railo.runtime.op.Caster; 041 import railo.runtime.op.Constants; 042 import railo.runtime.op.Decision; 043 import railo.runtime.rest.RestUtil; 044 import railo.runtime.rest.Result; 045 import railo.runtime.rest.path.Path; 046 import railo.runtime.type.Array; 047 import railo.runtime.type.Collection; 048 import railo.runtime.type.Collection.Key; 049 import railo.runtime.type.FunctionArgument; 050 import railo.runtime.type.KeyImpl; 051 import railo.runtime.type.Struct; 052 import railo.runtime.type.StructImpl; 053 import railo.runtime.type.UDF; 054 import railo.runtime.type.UDFImpl; 055 import railo.runtime.type.scope.Scope; 056 import railo.runtime.type.util.ArrayUtil; 057 import railo.runtime.type.util.CollectionUtil; 058 import railo.runtime.type.util.ComponentUtil; 059 import railo.runtime.type.util.KeyConstants; 060 import railo.runtime.type.util.ListUtil; 061 import railo.runtime.type.util.StructUtil; 062 063 /** 064 * A Page that can produce Components 065 */ 066 public abstract class ComponentPage extends PagePlus { 067 068 private static final long serialVersionUID = -3483642653131058030L; 069 070 public static final railo.runtime.type.Collection.Key METHOD = KeyConstants._method; 071 public static final railo.runtime.type.Collection.Key REMOTE_PERSISTENT_ID = KeyImpl.intern("Id16hohohh"); 072 073 private long lastCheck=-1; 074 075 076 public abstract ComponentImpl newInstance(PageContext pc,String callPath,boolean isRealPath) 077 throws railo.runtime.exp.PageException; 078 079 @Override 080 public void call(PageContext pc) throws PageException { 081 // remote persistent (only type server is supported) 082 String strRemotePersisId = Caster.toString(getURLorForm(pc,REMOTE_PERSISTENT_ID,null),null);//Caster.toString(pc.urlFormScope().get(REMOTE_PERSISTENT_ID,null),null); 083 084 if(!StringUtil.isEmpty(strRemotePersisId,true)) { 085 strRemotePersisId=strRemotePersisId.trim(); 086 } 087 else strRemotePersisId=null; 088 089 HttpServletRequest req = pc.getHttpServletRequest(); 090 // client 091 String client = Caster.toString(req.getAttribute("client"),null); 092 // call type (invocation, store-only) 093 String callType = Caster.toString(req.getAttribute("call-type"),null); 094 boolean fromGateway="railo-gateway-1-0".equals(client); 095 boolean fromRest="railo-rest-1-0".equals(client); 096 Component component; 097 try { 098 pc.setSilent(); 099 // load the cfc 100 try { 101 if(fromGateway && strRemotePersisId!=null) { 102 ConfigWebImpl config=(ConfigWebImpl) pc.getConfig(); 103 GatewayEngineImpl engine = config.getGatewayEngine(); 104 component=engine.getPersistentRemoteCFC(strRemotePersisId); 105 106 if(component==null) { 107 component=newInstance(pc,getPageSource().getComponentName(),false); 108 if(!fromGateway)component=ComponentWrap.toComponentWrap(Component.ACCESS_REMOTE,component); 109 110 engine.setPersistentRemoteCFC(strRemotePersisId,component); 111 } 112 113 } 114 else { 115 component=newInstance(pc,getPageSource().getComponentName(),false); 116 if(!fromGateway)component=ComponentWrap.toComponentWrap(Component.ACCESS_REMOTE,component); 117 } 118 } 119 finally { 120 pc.unsetSilent(); 121 } 122 123 // Only get the Component, no invocation 124 if("store-only".equals(callType)) { 125 req.setAttribute("component", component); 126 return; 127 } 128 129 130 131 // METHOD INVOCATION 132 String qs=ReqRspUtil.getQueryString(pc.getHttpServletRequest()); 133 if(pc.getBasePageSource()==this.getPageSource()) 134 pc.getDebugger().setOutput(false); 135 boolean isPost=pc.getHttpServletRequest().getMethod().equalsIgnoreCase("POST"); 136 137 boolean suppressContent = ((ConfigImpl)pc.getConfig()).isSuppressContent(); 138 if(suppressContent)pc.clear(); 139 Object method; 140 141 if(fromRest){ 142 143 callRest(pc,component,Caster.toString(req.getAttribute("rest-path"),""),(Result)req.getAttribute("rest-result"),suppressContent); 144 return; 145 } 146 147 148 149 // POST 150 if(isPost) { 151 // Soap 152 if(isSoap(pc)) { 153 callWebservice(pc,component); 154 //close(pc); 155 return; 156 } 157 // WDDX 158 else if((method=getURLorForm(pc, KeyConstants._method, null))!=null) { 159 callWDDX(pc,component,KeyImpl.toKey(method),suppressContent); 160 //close(pc); 161 return; 162 } 163 164 } 165 166 // GET 167 else { 168 // WSDL 169 if(qs!=null && qs.trim().equalsIgnoreCase("wsdl")) { 170 callWSDL(pc,component); 171 //close(pc); 172 return; 173 } 174 // WDDX 175 else if((method=getURLorForm(pc, KeyConstants._method, null))!=null) { 176 callWDDX(pc,component,KeyImpl.toKey(method),suppressContent); 177 //close(pc); 178 return; 179 } 180 } 181 182 183 // Include MUST 184 Array path = pc.getTemplatePath(); 185 //if(path.size()>1 ) { 186 if(path.size()>1 && !(path.size()==3 && ListUtil.last(path.getE(2).toString(),"/\\",true).equalsIgnoreCase(railo.runtime.config.Constants.APP_CFC)) ) {// MUSTMUST bad impl -> check with and without application.cfc 187 188 ComponentWrap c = ComponentWrap.toComponentWrap(Component.ACCESS_PRIVATE,ComponentUtil.toComponentAccess(component)); 189 Key[] keys = c.keys(); 190 Object el; 191 Scope var = pc.variablesScope(); 192 for(int i=0;i<keys.length;i++) { 193 el=c.get(keys[i],null); 194 if(el instanceof UDF) 195 var.set(keys[i], el); 196 197 } 198 199 return; 200 } 201 202 203 // DUMP 204 //TODO component.setAccess(pc,Component.ACCESS_PUBLIC); 205 String cdf = pc.getConfig().getComponentDumpTemplate(); 206 207 if(cdf!=null && cdf.trim().length()>0) { 208 pc.variablesScope().set(KeyConstants._component,component); 209 pc.doInclude(cdf); 210 } 211 else pc.write(pc.getConfig().getDefaultDumpWriter(DumpWriter.DEFAULT_RICH).toString(pc,component.toDumpData(pc,9999,DumpUtil.toDumpProperties() ),true)); 212 213 } 214 catch(Throwable t) { 215 throw Caster.toPageException(t);//Exception Handler.castAnd Stack(t, this, pc); 216 } 217 } 218 219 private Object getURLorForm(PageContext pc, Key key, Object defaultValue) { 220 Object res = pc.formScope().get(key,null); 221 if(res!=null) return res; 222 return pc.urlScope().get(key,defaultValue); 223 } 224 225 private void callRest(PageContext pc, Component component, String path, Result result, boolean suppressContent) throws IOException, ConverterException { 226 String method = pc.getHttpServletRequest().getMethod(); 227 String[] subPath = result.getPath(); 228 Struct cMeta; 229 try { 230 cMeta = component.getMetaData(pc); 231 } catch (PageException pe) { 232 throw ExceptionUtil.toIOException(pe); 233 } 234 235 236 // Consumes 237 MimeType[] cConsumes=null; 238 String strMimeType = Caster.toString(cMeta.get(KeyConstants._consumes,null),null); 239 if(!StringUtil.isEmpty(strMimeType,true)){ 240 cConsumes = MimeType.getInstances(strMimeType,','); 241 } 242 243 // Produces 244 MimeType[] cProduces=null; 245 strMimeType = Caster.toString(cMeta.get(KeyConstants._produces,null),null); 246 if(!StringUtil.isEmpty(strMimeType,true)){ 247 cProduces = MimeType.getInstances(strMimeType,','); 248 } 249 250 251 252 Iterator<Entry<Key, Object>> it = component.entryIterator(); 253 Entry<Key, Object> e; 254 Object value; 255 UDF udf; 256 Struct meta; 257 int status=405; 258 MimeType bestP,bestC; 259 while(it.hasNext()){ 260 e = it.next(); 261 value=e.getValue(); 262 if(value instanceof UDF){ 263 udf=(UDF)value; 264 try { 265 meta = udf.getMetaData(pc); 266 267 // check if http method match 268 String httpMethod = Caster.toString(meta.get(KeyConstants._httpmethod,null),null); 269 if(StringUtil.isEmpty(httpMethod) || !httpMethod.equalsIgnoreCase(method)) continue; 270 271 272 // get consumes mimetype 273 MimeType[] consumes; 274 strMimeType = Caster.toString(meta.get(KeyConstants._consumes,null),null); 275 if(!StringUtil.isEmpty(strMimeType,true)){ 276 consumes = MimeType.getInstances(strMimeType,','); 277 } 278 else 279 consumes=cConsumes; 280 281 282 // get produces mimetype 283 MimeType[] produces; 284 strMimeType = Caster.toString(meta.get(KeyConstants._produces,null),null); 285 if(!StringUtil.isEmpty(strMimeType,true)){ 286 produces = MimeType.getInstances(strMimeType,','); 287 } 288 else 289 produces=cProduces; 290 291 292 293 294 String restPath = Caster.toString(meta.get(KeyConstants._restPath,null),null); 295 296 // no rest path 297 if(StringUtil.isEmpty(restPath)){ 298 if(ArrayUtil.isEmpty(subPath)) { 299 bestC = best(consumes,result.getContentType()); 300 bestP = best(produces,result.getAccept()); 301 if(bestC==null) status=405; 302 else if(bestP==null) status=406; 303 else { 304 status=200; 305 _callRest(pc, component, udf, path, result.getVariables(),result,bestP,produces, suppressContent,e.getKey()); 306 break; 307 } 308 } 309 } 310 else { 311 Struct var = result.getVariables(); 312 int index=RestUtil.matchPath(var, Path.init(restPath)/*TODO cache this*/, result.getPath()); 313 if(index>=0 && index+1==result.getPath().length) { 314 bestC = best(consumes,result.getContentType()); 315 bestP = best(produces,result.getAccept()); 316 317 if(bestC==null) status=405; 318 else if(bestP==null) status=406; 319 else { 320 status=200; 321 _callRest(pc, component, udf, path, var,result,bestP,produces, suppressContent,e.getKey()); 322 break; 323 } 324 } 325 } 326 } 327 catch (PageException pe) {} 328 } 329 } 330 if(status==404) 331 RestUtil.setStatus(pc,404,"no rest service for ["+path+"] found"); 332 else if(status==405) 333 RestUtil.setStatus(pc,405,"Unsupported Media Type"); 334 else if(status==406) 335 RestUtil.setStatus(pc,406,"Not Acceptable"); 336 337 338 } 339 340 private MimeType best(MimeType[] produces, MimeType... accept) { 341 if(ArrayUtil.isEmpty(produces)){ 342 if(accept.length>0) return accept[0]; 343 return MimeType.ALL; 344 } 345 346 MimeType best=null,tmp; 347 348 for(int a=0;a<accept.length;a++){ 349 tmp=accept[a].bestMatch(produces); 350 if(tmp!=null && !accept[a].hasWildCards() && tmp.hasWildCards()){ 351 tmp=accept[a]; 352 } 353 if(tmp!=null && 354 (best==null || 355 best.getQuality()<tmp.getQuality() || 356 (best.getQuality()==tmp.getQuality() && best.hasWildCards() && !tmp.hasWildCards()))) 357 best=tmp; 358 } 359 360 361 362 return best; 363 } 364 365 private void _callRest(PageContext pc, Component component, UDF udf,String path, Struct variables, Result result, MimeType best,MimeType[] produces, boolean suppressContent, Key methodName) throws PageException, IOException, ConverterException { 366 FunctionArgument[] fa=udf.getFunctionArguments(); 367 Struct args=new StructImpl(),meta; 368 369 Key name; 370 String restArgName,restArgSource,value; 371 for(int i=0;i<fa.length;i++){ 372 name = fa[i].getName(); 373 meta=fa[i].getMetaData(); 374 restArgSource=meta==null?"":Caster.toString(meta.get(KeyConstants._restArgSource,""),""); 375 376 if("path".equalsIgnoreCase(restArgSource)) 377 setValue(fa[i],args,name, variables.get(name,null)); 378 if("query".equalsIgnoreCase(restArgSource) || "url".equalsIgnoreCase(restArgSource)) 379 setValue(fa[i],args,name, pc.urlScope().get(name,null)); 380 if("form".equalsIgnoreCase(restArgSource)) 381 setValue(fa[i],args,name, pc.formScope().get(name,null)); 382 if("cookie".equalsIgnoreCase(restArgSource)) 383 setValue(fa[i],args,name, pc.cookieScope().get(name,null)); 384 if("header".equalsIgnoreCase(restArgSource) || "head".equalsIgnoreCase(restArgSource)) { 385 restArgName=meta==null?"":Caster.toString(meta.get(KeyConstants._restArgName,""),""); 386 if(StringUtil.isEmpty(restArgName))restArgName=name.getString(); 387 value=ReqRspUtil.getHeaderIgnoreCase(pc, restArgName, null); 388 setValue(fa[i],args,name,value); 389 } 390 if("matrix".equalsIgnoreCase(restArgSource)) 391 setValue(fa[i],args,name, result.getMatrix().get(name,null)); 392 393 if("body".equalsIgnoreCase(restArgSource) || StringUtil.isEmpty(restArgSource,true)){ 394 boolean isSimple=CFTypes.isSimpleType(fa[i].getType()); 395 Object body = ReqRspUtil.getRequestBody(pc,true,null); 396 if(isSimple && !Decision.isSimpleValue(body)) 397 body= ReqRspUtil.getRequestBody(pc,false,null); 398 setValue(fa[i],args,name, body); 399 } 400 401 } 402 Object rtn=null; 403 try{ 404 if(suppressContent)pc.setSilent(); 405 rtn = component.callWithNamedValues(pc, methodName, args); 406 } 407 catch (PageException e) { 408 RestUtil.setStatus(pc, 500, ExceptionUtil.getMessage(e)); 409 } 410 finally { 411 if(suppressContent)pc.unsetSilent(); 412 } 413 414 // custom response 415 Struct sct = result.getCustomResponse(); 416 boolean hasContent=false; 417 if(sct!=null){ 418 HttpServletResponse rsp = pc.getHttpServletResponse(); 419 // status 420 int status = Caster.toIntValue(sct.get(KeyConstants._status,Constants.DOUBLE_ZERO),0); 421 if(status>0)rsp.setStatus(status); 422 423 // content 424 Object o=sct.get(KeyConstants._content,null); 425 if(o!=null) { 426 String content=Caster.toString(o,null); 427 if(content!=null) { 428 try { 429 pc.forceWrite(content); 430 hasContent=true; 431 } 432 catch (IOException e) {} 433 } 434 } 435 436 // headers 437 Struct headers=Caster.toStruct(sct.get(KeyConstants._headers,null),null); 438 if(headers!=null){ 439 //Key[] keys = headers.keys(); 440 Iterator<Entry<Key, Object>> it = headers.entryIterator(); 441 Entry<Key, Object> e; 442 String n,v; 443 Object tmp; 444 while(it.hasNext()){ 445 e = it.next(); 446 n=e.getKey().getString(); 447 tmp=e.getValue(); 448 v=Caster.toString(tmp,null); 449 if(tmp!=null && v==null) v=tmp.toString(); 450 rsp.setHeader(n, v); 451 } 452 } 453 } 454 // convert result 455 if(rtn!=null && !hasContent){ 456 Props props = new Props(); 457 props.format=result.getFormat(); 458 459 if(result.hasFormatExtension()){ 460 setFormat(pc.getHttpServletResponse(), props.format); 461 pc.forceWrite(convertResult(pc, props, null, rtn)); 462 } 463 else { 464 if(best!=null && !MimeType.ALL.same(best)) { 465 int f = MimeType.toFormat(best, -1); 466 if(f!=-1) { 467 props.format=f; 468 setFormat(pc.getHttpServletResponse(), f); 469 pc.forceWrite(convertResult(pc, props, null, rtn)); 470 } 471 else { 472 writeOut(pc,props,rtn,best); 473 } 474 } 475 else pc.forceWrite(convertResult(pc, props, null, rtn)); 476 } 477 478 479 } 480 481 } 482 483 private void setValue(FunctionArgument fa, Struct args, Key name, Object value) { 484 if(value==null){ 485 Struct meta = fa.getMetaData(); 486 if(meta!=null)value=meta.get(KeyConstants._default,null); 487 } 488 args.setEL(name, value); 489 } 490 491 private void writeOut(PageContext pc, Props props, Object obj, MimeType mt) throws PageException, IOException, ConverterException { 492 // TODO miemtype mapping with converter defintion from external file 493 // Images 494 if(mt.same(MimeType.IMAGE_GIF)) writeOut(pc,obj,mt,new ImageConverter("gif")); 495 else if(mt.same(MimeType.IMAGE_JPG)) writeOut(pc,obj,mt,new ImageConverter("jpeg")); 496 else if(mt.same(MimeType.IMAGE_PNG)) writeOut(pc,obj,mt,new ImageConverter("png")); 497 else if(mt.same(MimeType.IMAGE_TIFF)) writeOut(pc,obj,mt,new ImageConverter("tiff")); 498 else if(mt.same(MimeType.IMAGE_BMP)) writeOut(pc,obj,mt,new ImageConverter("bmp")); 499 else if(mt.same(MimeType.IMAGE_WBMP)) writeOut(pc,obj,mt,new ImageConverter("wbmp")); 500 else if(mt.same(MimeType.IMAGE_FBX)) writeOut(pc,obj,mt,new ImageConverter("fbx")); 501 else if(mt.same(MimeType.IMAGE_FBX)) writeOut(pc,obj,mt,new ImageConverter("fbx")); 502 else if(mt.same(MimeType.IMAGE_PNM)) writeOut(pc,obj,mt,new ImageConverter("pnm")); 503 else if(mt.same(MimeType.IMAGE_PGM)) writeOut(pc,obj,mt,new ImageConverter("pgm")); 504 else if(mt.same(MimeType.IMAGE_PBM)) writeOut(pc,obj,mt,new ImageConverter("pbm")); 505 else if(mt.same(MimeType.IMAGE_ICO)) writeOut(pc,obj,mt,new ImageConverter("ico")); 506 else if(mt.same(MimeType.IMAGE_PSD)) writeOut(pc,obj,mt,new ImageConverter("psd")); 507 else if(mt.same(MimeType.IMAGE_ASTERIX)) writeOut(pc,obj,MimeType.IMAGE_PNG,new ImageConverter("png")); 508 509 // Application 510 else if(mt.same(MimeType.APPLICATION_JAVA)) writeOut(pc,obj,mt,new JavaConverter()); 511 //if("application".equalsIgnoreCase(mt.getType())) 512 513 514 else pc.forceWrite(convertResult(pc, props, null, obj)); 515 } 516 517 private void writeOut(PageContext pc, Object obj, MimeType mt,BinaryConverter converter) throws ConverterException, IOException { 518 pc.getResponse().setContentType(mt.toString()); 519 520 OutputStream os=null; 521 try{ 522 converter.writeOut(pc, obj, os=pc.getResponseStream()); 523 } 524 finally{ 525 IOUtil.closeEL(os); 526 } 527 } 528 529 public static boolean isSoap(PageContext pc) { 530 HttpServletRequest req = pc.getHttpServletRequest(); 531 InputStream is=null; 532 try { 533 is=req.getInputStream(); 534 535 String input = IOUtil.toString(is,"iso-8859-1"); 536 return 537 StringUtil.indexOfIgnoreCase(input, "soap:Envelope")!=-1 || 538 StringUtil.indexOfIgnoreCase(input, "soapenv:Envelope")!=-1 || 539 StringUtil.indexOfIgnoreCase(input, "SOAP-ENV:Envelope")!=-1; 540 } 541 catch (IOException e) { 542 return false; 543 } 544 finally { 545 IOUtil.closeEL(is); 546 } 547 } 548 549 550 private void callWDDX(PageContext pc, Component component, Collection.Key methodName, boolean suppressContent) throws IOException, ConverterException, PageException { 551 //Struct url = StructUtil.duplicate(pc.urlFormScope(),true); 552 Struct url=StructUtil.merge(new Struct[]{pc.formScope(),pc.urlScope()}); 553 // define args 554 url.removeEL(KeyConstants._fieldnames); 555 url.removeEL(METHOD); 556 Object args=url.get(KeyConstants._argumentCollection,null); 557 Object returnFormat=url.get(KeyConstants._returnFormat,null); 558 Object queryFormat=url.get(KeyConstants._queryFormat,null); 559 560 if(args==null){ 561 args=pc.getHttpServletRequest().getAttribute("argumentCollection"); 562 } 563 564 //content-type 565 Object o = component.get(pc,methodName,null); 566 Props props = getProps(pc, o, returnFormat); 567 if(!props.output) setFormat(pc.getHttpServletResponse(),props.format); 568 569 570 Object rtn=null; 571 try{ 572 if(suppressContent)pc.setSilent(); 573 574 575 if(args==null){ 576 url=translate(component,methodName.getString(),url); 577 rtn = component.callWithNamedValues(pc, methodName, url); 578 } 579 else if(args instanceof String){ 580 try { 581 args=new JSONExpressionInterpreter().interpret(pc, (String)args); 582 583 } catch (PageException e) {} 584 } 585 586 // call 587 if(args!=null) { 588 if(Decision.isCastableToStruct(args)){ 589 rtn = component.callWithNamedValues(pc, methodName, Caster.toStruct(args,false)); 590 } 591 else if(Decision.isCastableToArray(args)){ 592 rtn = component.call(pc, methodName, Caster.toNativeArray(args)); 593 } 594 else { 595 Object[] ac=new Object[1]; 596 ac[0]=args; 597 rtn = component.call(pc, methodName, ac); 598 } 599 } 600 } 601 finally { 602 if(suppressContent)pc.unsetSilent(); 603 } 604 // convert result 605 if(rtn!=null){ 606 if(pc.getHttpServletRequest().getHeader("AMF-Forward")!=null) { 607 pc.variablesScope().setEL("AMF-Forward", rtn); 608 } 609 else { 610 pc.forceWrite(convertResult(pc, props, queryFormat, rtn)); 611 } 612 } 613 614 } 615 616 private void setFormat(HttpServletResponse rsp, int format) { 617 switch(format){ 618 case UDF.RETURN_FORMAT_WDDX: 619 rsp.setContentType("text/xml; charset=UTF-8"); 620 rsp.setHeader("Return-Format", "wddx"); 621 break; 622 case UDF.RETURN_FORMAT_JSON: 623 rsp.setContentType("application/json"); 624 rsp.setHeader("Return-Format", "json"); 625 break; 626 case UDF.RETURN_FORMAT_PLAIN: 627 rsp.setContentType("text/plain; charset=UTF-8"); 628 rsp.setHeader("Return-Format", "plain"); 629 break; 630 case UDF.RETURN_FORMAT_XML: 631 rsp.setContentType("text/xml; charset=UTF-8"); 632 rsp.setHeader("Return-Format", "xml"); 633 break; 634 case UDF.RETURN_FORMAT_SERIALIZE: 635 rsp.setContentType("text/plain; charset=UTF-8"); 636 rsp.setHeader("Return-Format", "cfml"); 637 break; 638 } 639 } 640 641 private static Props getProps(PageContext pc, Object o,Object returnFormat) throws PageException { 642 Props props = new Props(); 643 644 props.strType="any"; 645 props.secureJson=pc.getApplicationContext().getSecureJson(); 646 if(o instanceof UDF) { 647 UDF udf = ((UDF)o); 648 props.format=udf.getReturnFormat(); 649 props.type=udf.getReturnType(); 650 props.strType=udf.getReturnTypeAsString(); 651 props.output=udf.getOutput(); 652 if(udf.getSecureJson()!=null)props.secureJson=udf.getSecureJson().booleanValue(); 653 } 654 if(!StringUtil.isEmpty(returnFormat)){ 655 props.format=UDFImpl.toReturnFormat(Caster.toString(returnFormat)); 656 } 657 658 // return type XML ignore WDDX 659 if(props.type==CFTypes.TYPE_XML) { 660 if(UDF.RETURN_FORMAT_WDDX==props.format) 661 props.format=UDF.RETURN_FORMAT_PLAIN; 662 } 663 664 665 666 return props; 667 } 668 669 public static String convertResult(PageContext pc,Component component, String methodName,Object returnFormat,Object queryFormat,Object rtn) throws ConverterException, PageException { 670 Object o = component.get(KeyImpl.init(methodName),null); 671 Props p = getProps(pc, o, returnFormat); 672 return convertResult(pc, p, queryFormat, rtn); 673 } 674 675 private static String convertResult(PageContext pc,Props props,Object queryFormat,Object rtn) throws ConverterException, PageException { 676 // return type XML ignore WDDX 677 if(props.type==CFTypes.TYPE_XML) { 678 //if(UDF.RETURN_FORMAT_WDDX==format) format=UDF.RETURN_FORMAT_PLAIN; 679 rtn=Caster.toString(Caster.toXML(rtn)); 680 } 681 // function does no real cast, only check it 682 else rtn=Caster.castTo(pc, (short)props.type, props.strType, rtn); 683 684 // WDDX 685 if(UDF.RETURN_FORMAT_WDDX==props.format) { 686 WDDXConverter converter = new WDDXConverter(pc.getTimeZone(),false,false); 687 converter.setTimeZone(pc.getTimeZone()); 688 return converter.serialize(rtn); 689 } 690 // JSON 691 else if(UDF.RETURN_FORMAT_JSON==props.format) { 692 boolean byColumn = false; 693 if(queryFormat instanceof String){ 694 String strQF=((String) queryFormat).trim(); 695 if(strQF.equalsIgnoreCase("row")); 696 else if(strQF.equalsIgnoreCase("column"))byColumn=true; 697 else throw new ApplicationException("invalid queryformat definition ["+strQF+"], valid formats are [row,column]"); 698 } 699 JSONConverter converter = new JSONConverter(false); 700 String prefix=""; 701 if(props.secureJson) { 702 prefix=pc.getApplicationContext().getSecureJsonPrefix(); 703 if(prefix==null)prefix=""; 704 } 705 return prefix+converter.serialize(pc,rtn,byColumn); 706 } 707 // Serialize 708 else if(UDF.RETURN_FORMAT_SERIALIZE==props.format) { 709 ScriptConverter converter = new ScriptConverter(false); 710 return converter.serialize(rtn); 711 } 712 // XML 713 if(UDF.RETURN_FORMAT_XML==props.format) { 714 XMLConverter converter = new XMLConverter(pc.getTimeZone(),false); 715 converter.setTimeZone(pc.getTimeZone()); 716 return converter.serialize(rtn); 717 } 718 // Plain 719 else if(UDF.RETURN_FORMAT_PLAIN==props.format) { 720 return Caster.toString(rtn); 721 } 722 return null; 723 } 724 725 public static Struct translate(Component c, String strMethodName, Struct params) { 726 Collection.Key methodName=KeyImpl.init(strMethodName); 727 Key[] keys = CollectionUtil.keys(params); 728 FunctionArgument[] args=null; 729 int index=-1; 730 Object value; 731 for(int i=0;i<keys.length;i++){ 732 index=Caster.toIntValue(keys[i].getString(),0); 733 if(index>0) { 734 if(args==null)args=_getArgs(c,methodName); 735 if(args!=null && index<=args.length) { 736 value=params.removeEL(keys[i]); 737 if(value!=null)params.setEL(args[index-1].getName(), value); 738 } 739 } 740 741 } 742 return params; 743 } 744 745 private static FunctionArgument[] _getArgs(Component c, Collection.Key methodName) { 746 Object o=c.get(methodName,null); 747 if(o instanceof UDF) return ((UDF) o).getFunctionArguments(); 748 return null; 749 } 750 751 private void callWSDL(PageContext pc, Component component) throws ServletException, IOException, ExpressionException { 752 // take wsdl file defined by user 753 String wsdl = component.getWSDLFile(); 754 if(!StringUtil.isEmpty(wsdl)) { 755 756 OutputStream os=null; 757 Resource input = ResourceUtil.toResourceExisting(pc, wsdl); 758 try { 759 os=pc.getResponseStream(); 760 pc.getResponse().setContentType("text/xml; charset=utf-8"); 761 IOUtil.copy(input, os, false); 762 763 } 764 finally { 765 IOUtil.flushEL(os); 766 IOUtil.closeEL(os); 767 ((PageContextImpl)pc).getRootOut().setClosed(true); 768 } 769 } 770 // create a wsdl file 771 else { 772 RPCServer.getInstance(pc.getId(),pc.getServletContext()) 773 .doGet(pc.getHttpServletRequest(), pc. getHttpServletResponse(), component); 774 } 775 } 776 777 private void callWebservice(PageContext pc, Component component) throws IOException, ServletException { 778 ComponentController.set(pc, component); 779 try { 780 RPCServer.getInstance(pc.getId(),pc.getServletContext()) 781 .doPost(pc.getHttpServletRequest(), pc. getHttpServletResponse(), component); 782 } 783 finally { 784 ComponentController.release(); 785 } 786 } 787 788 789 public abstract void initComponent(PageContext pc,ComponentImpl c) throws PageException; 790 791 public void ckecked() { 792 lastCheck=System.currentTimeMillis(); 793 } 794 795 public long lastCheck() { 796 return lastCheck; 797 } 798 799 } 800 class Props { 801 802 public String strType="any"; 803 public boolean secureJson; 804 public int type=CFTypes.TYPE_ANY; 805 public int format=UDF.RETURN_FORMAT_WDDX; 806 public boolean output=true; 807 808 }