Package railo.runtime

Source Code of railo.runtime.ComponentPage

package railo.runtime;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import railo.commons.io.CharsetUtil;
import railo.commons.io.IOUtil;
import railo.commons.io.res.Resource;
import railo.commons.io.res.util.ResourceUtil;
import railo.commons.lang.CFTypes;
import railo.commons.lang.ExceptionUtil;
import railo.commons.lang.StringUtil;
import railo.commons.lang.mimetype.MimeType;
import railo.runtime.config.ConfigImpl;
import railo.runtime.config.ConfigWebImpl;
import railo.runtime.converter.BinaryConverter;
import railo.runtime.converter.ConverterException;
import railo.runtime.converter.JSONConverter;
import railo.runtime.converter.JavaConverter;
import railo.runtime.converter.ScriptConverter;
import railo.runtime.converter.WDDXConverter;
import railo.runtime.converter.XMLConverter;
import railo.runtime.converter.bin.ImageConverter;
import railo.runtime.dump.DumpUtil;
import railo.runtime.dump.DumpWriter;
import railo.runtime.exp.ApplicationException;
import railo.runtime.exp.ExpressionException;
import railo.runtime.exp.PageException;
import railo.runtime.gateway.GatewayEngineImpl;
import railo.runtime.interpreter.CFMLExpressionInterpreter;
import railo.runtime.interpreter.JSONExpressionInterpreter;
import railo.runtime.net.http.ReqRspUtil;
import railo.runtime.net.rpc.server.ComponentController;
import railo.runtime.net.rpc.server.RPCServer;
import railo.runtime.op.Caster;
import railo.runtime.op.Constants;
import railo.runtime.op.Decision;
import railo.runtime.rest.RestUtil;
import railo.runtime.rest.Result;
import railo.runtime.rest.path.Path;
import railo.runtime.type.Array;
import railo.runtime.type.ArrayImpl;
import railo.runtime.type.Collection;
import railo.runtime.type.Collection.Key;
import railo.runtime.type.FunctionArgument;
import railo.runtime.type.KeyImpl;
import railo.runtime.type.Struct;
import railo.runtime.type.StructImpl;
import railo.runtime.type.UDF;
import railo.runtime.type.UDFPlus;
import railo.runtime.type.cfc.ComponentAccess;
import railo.runtime.type.scope.Scope;
import railo.runtime.type.util.ArrayUtil;
import railo.runtime.type.util.CollectionUtil;
import railo.runtime.type.util.ComponentUtil;
import railo.runtime.type.util.KeyConstants;
import railo.runtime.type.util.ListUtil;
import railo.runtime.type.util.StructUtil;
import railo.runtime.type.util.UDFUtil;

/**
* A Page that can produce Components
*/
public abstract class ComponentPage extends PagePlus  {
 
  public static final Collection.Key ACCEPT_ARG_COLL_FORMATS = KeyImpl.getInstance("acceptedArgumentCollectionFormats");

 
  private static final long serialVersionUID = -3483642653131058030L;

  public static final railo.runtime.type.Collection.Key REMOTE_PERSISTENT_ID = KeyImpl.intern("Id16hohohh");

  private long lastCheck=-1;
 
 
  public abstract ComponentImpl newInstance(PageContext pc,String callPath,boolean isRealPath)
    throws railo.runtime.exp.PageException;
 
  @Override
  public void call(PageContext pc) throws PageException {
    // remote persistent (only type server is supported)
    String strRemotePersisId = Caster.toString(getURLorForm(pc,REMOTE_PERSISTENT_ID,null),null);//Caster.toString(pc.urlFormScope().get(REMOTE_PERSISTENT_ID,null),null);
   
    if(!StringUtil.isEmpty(strRemotePersisId,true)) {
      strRemotePersisId=strRemotePersisId.trim();
    }
    else strRemotePersisId=null;
   
    HttpServletRequest req = pc.getHttpServletRequest();
    // client
    String client = Caster.toString(req.getAttribute("client"),null);
    // call type (invocation, store-only)
    String callType = Caster.toString(req.getAttribute("call-type"),null);
    boolean fromGateway="railo-gateway-1-0".equals(client);
    boolean fromRest="railo-rest-1-0".equals(client);
    Component component;
    try {
      pc.setSilent();
      // load the cfc
      try {
              if(fromGateway && strRemotePersisId!=null) {
                ConfigWebImpl config=(ConfigWebImpl) pc.getConfig();
                GatewayEngineImpl engine = config.getGatewayEngine();
                component=engine.getPersistentRemoteCFC(strRemotePersisId);
               
                if(component==null) {
                  component=newInstance(pc,getPageSource().getComponentName(),false);
                  if(!fromGateway)component=ComponentWrap.toComponentWrap(Component.ACCESS_REMOTE,component);
                 
                  engine.setPersistentRemoteCFC(strRemotePersisId,component);
                }
               
              }
              else {
                component=newInstance(pc,getPageSource().getComponentName(),false);
                if(!fromGateway)component=ComponentWrap.toComponentWrap(Component.ACCESS_REMOTE,component);
              }
            }
            finally {
                pc.unsetSilent();
            }
           
            // Only get the Component, no invocation
            if("store-only".equals(callType)) {
              req.setAttribute("component", component);
              return;
            }
           
           
           
            // METHOD INVOCATION
      String qs=ReqRspUtil.getQueryString(pc.getHttpServletRequest());
            if(pc.getBasePageSource()==this.getPageSource() && pc.getConfig().debug())
              pc.getDebugger().setOutput(false);
            boolean isPost=pc.getHttpServletRequest().getMethod().equalsIgnoreCase("POST");
           
            boolean suppressContent = ((ConfigImpl)pc.getConfig()).isSuppressContent();
            if(suppressContent)pc.clear();
            Object method;
           
            if(fromRest){
             
              callRest(pc,component,Caster.toString(req.getAttribute("rest-path"),""),(Result)req.getAttribute("rest-result"),suppressContent);
              return;
            }
           
           
           
            // POST
            if(isPost) {
              // Soap
              if(isSoap(pc)) {
                callWebservice(pc,component);
                //close(pc);
                    return;
              }
          // WDDX
                else if((method=getURLorForm(pc, KeyConstants._method, null))!=null) {
                  callWDDX(pc,component,KeyImpl.toKey(method),suppressContent);
                //close(pc);
                    return;
                }
             
            }
           
            // GET
            else {
              // WSDL
                if(qs!=null && qs.trim().equalsIgnoreCase("wsdl")) {
                    callWSDL(pc,component);
                //close(pc);
                    return;
                }
          // WDDX
                else if((method=getURLorForm(pc, KeyConstants._method, null))!=null) {
                    callWDDX(pc,component,KeyImpl.toKey(method),suppressContent);
                    //close(pc);
                    return;
                }
               
                if(qs!=null) {
                  int rf = UDFUtil.toReturnFormat(qs.trim(),-1);
                  if(rf!=-1) callCFCMetaData(pc,component,rf);
                //close(pc);
                    return;
                }
            }
           
           
            // Include MUST
            Array path = pc.getTemplatePath();
            //if(path.size()>1 ) {
            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
             
              ComponentWrap c = ComponentWrap.toComponentWrap(Component.ACCESS_PRIVATE,ComponentUtil.toComponentAccess(component));
              Key[] keys = c.keys();
              Object el;
              Scope var = pc.variablesScope();
              for(int i=0;i<keys.length;i++) {
                el=c.get(keys[i],null);
                if(el instanceof UDF)
                  var.set(keys[i], el);
               
              }
               
              return;
            }
          
           
      // DUMP
      //TODO component.setAccess(pc,Component.ACCESS_PUBLIC);
      String cdf = pc.getConfig().getComponentDumpTemplate();
     
      if(cdf!=null && cdf.trim().length()>0) {
          pc.variablesScope().set(KeyConstants._component,component);
          pc.doInclude(cdf);
      }
      else pc.write(pc.getConfig().getDefaultDumpWriter(DumpWriter.DEFAULT_RICH).toString(pc,component.toDumpData(pc,9999,DumpUtil.toDumpProperties() ),true));
     
    }
    catch(Throwable t) {
      throw Caster.toPageException(t);//Exception Handler.castAnd Stack(t, this, pc);
    }
  }
 
  private Object getURLorForm(PageContext pc, Key key, Object defaultValue) {
    Object res = pc.formScope().get(key,null);
    if(res!=null) return res;
    return pc.urlScope().get(key,defaultValue);
  }

  private void callRest(PageContext pc, Component component, String path, Result result, boolean suppressContent) throws IOException, ConverterException {
    String method = pc.getHttpServletRequest().getMethod();
    String[] subPath = result.getPath();
    Struct cMeta;
    try {
      cMeta = component.getMetaData(pc);
    } catch (PageException pe) {
      throw ExceptionUtil.toIOException(pe);
    }
   

    // Consumes
    MimeType[] cConsumes=null;
    String strMimeType = Caster.toString(cMeta.get(KeyConstants._consumes,null),null);
    if(!StringUtil.isEmpty(strMimeType,true)){
      cConsumes = MimeType.getInstances(strMimeType,',');
    }
   
    // Produces
    MimeType[] cProduces=null;
    strMimeType = Caster.toString(cMeta.get(KeyConstants._produces,null),null);
    if(!StringUtil.isEmpty(strMimeType,true)){
      cProduces = MimeType.getInstances(strMimeType,',');
    }
   
   
   
    Iterator<Entry<Key, Object>> it = component.entryIterator();
    Entry<Key, Object> e;
    Object value;
    UDF udf;
    Struct meta;
    int status=404;
    MimeType bestP,bestC;
    while(it.hasNext()){
      e = it.next();
      value=e.getValue();
      if(value instanceof UDF){
        udf=(UDF)value;
        try {
          meta = udf.getMetaData(pc);
         
          // check if http method match
          String httpMethod = Caster.toString(meta.get(KeyConstants._httpmethod,null),null);
          if(StringUtil.isEmpty(httpMethod) || !httpMethod.equalsIgnoreCase(method)) continue;
         

          // get consumes mimetype
          MimeType[] consumes;
          strMimeType = Caster.toString(meta.get(KeyConstants._consumes,null),null);
          if(!StringUtil.isEmpty(strMimeType,true)){
            consumes = MimeType.getInstances(strMimeType,',');
          }
          else
            consumes=cConsumes;
         
         
          // get produces mimetype
          MimeType[] produces;
          strMimeType = Caster.toString(meta.get(KeyConstants._produces,null),null);
          if(!StringUtil.isEmpty(strMimeType,true)){
            produces = MimeType.getInstances(strMimeType,',');
          }
          else
            produces=cProduces;
         
         
         
         
          String restPath = Caster.toString(meta.get(KeyConstants._restPath,null),null);
         
          // no rest path
          if(StringUtil.isEmpty(restPath)){
            if(ArrayUtil.isEmpty(subPath)) {
              bestC = best(consumes,result.getContentType());
              bestP = best(produces,result.getAccept());
              if(bestC==null) status=405;
              else if(bestP==null) status=406;
              else {
                status=200;
                _callRest(pc, component, udf, path, result.getVariables(),result,bestP,produces, suppressContent,e.getKey());
                break;
              }
            }
          }
          else {
            Struct var = result.getVariables();
            int index=RestUtil.matchPath(var, Path.init(restPath)/*TODO cache this*/, result.getPath());
            if(index>=0 && index+1==result.getPath().length) {
              bestC = best(consumes,result.getContentType());
              bestP = best(produces,result.getAccept());
             
              if(bestC==null) status=405;
              else if(bestP==null) status=406;
              else {
                status=200;
                _callRest(pc, component, udf, path, var,result,bestP,produces, suppressContent,e.getKey());
                break;
              }
            }
          }
        }
        catch (PageException pe) {}
      }
    }
    if(status==404)
      RestUtil.setStatus(pc,404,"no rest service for ["+path+"] found");
    else if(status==405)
      RestUtil.setStatus(pc,405,"Unsupported Media Type");
    else if(status==406)
      RestUtil.setStatus(pc,406,"Not Acceptable");
   
     
  }

  private MimeType best(MimeType[] produces, MimeType... accept) {
    if(ArrayUtil.isEmpty(produces)){
      if(accept.length>0) return accept[0];
      return MimeType.ALL;
    }
   
    MimeType best=null,tmp;
   
    for(int a=0;a<accept.length;a++){
      tmp=accept[a].bestMatch(produces);
      if(tmp!=null && !accept[a].hasWildCards() && tmp.hasWildCards()){
        tmp=accept[a];
      }
      if(tmp!=null &&
          (best==null ||
           best.getQuality()<tmp.getQuality() ||
           (best.getQuality()==tmp.getQuality() && best.hasWildCards() && !tmp.hasWildCards())))
        best=tmp;
    }
   
   
   
    return best;
  }

  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 {
    FunctionArgument[] fa=udf.getFunctionArguments();
    Struct args=new StructImpl(),meta;
   
    Key name;
    String restArgName,restArgSource,value;
    for(int i=0;i<fa.length;i++){
      name = fa[i].getName();
      meta=fa[i].getMetaData();
      restArgSource=meta==null?"":Caster.toString(meta.get(KeyConstants._restArgSource,""),"");
     
      if("path".equalsIgnoreCase(restArgSource))
        setValue(fa[i],args,name, variables.get(name,null));
      if("query".equalsIgnoreCase(restArgSource) || "url".equalsIgnoreCase(restArgSource))
        setValue(fa[i],args,name, pc.urlScope().get(name,null));
      if("form".equalsIgnoreCase(restArgSource))
        setValue(fa[i],args,name, pc.formScope().get(name,null));
      if("cookie".equalsIgnoreCase(restArgSource))
        setValue(fa[i],args,name, pc.cookieScope().get(name,null));
      if("header".equalsIgnoreCase(restArgSource) || "head".equalsIgnoreCase(restArgSource)) {
        restArgName=meta==null?"":Caster.toString(meta.get(KeyConstants._restArgName,""),"");
        if(StringUtil.isEmpty(restArgName))restArgName=name.getString();
        value=ReqRspUtil.getHeaderIgnoreCase(pc, restArgName, null);
        setValue(fa[i],args,name,value);
      }
      if("matrix".equalsIgnoreCase(restArgSource))
        setValue(fa[i],args,name, result.getMatrix().get(name,null));
     
      if("body".equalsIgnoreCase(restArgSource) || StringUtil.isEmpty(restArgSource,true)){
        boolean isSimple=CFTypes.isSimpleType(fa[i].getType());
        Object body = ReqRspUtil.getRequestBody(pc,true,null);
        if(isSimple && !Decision.isSimpleValue(body))
          body= ReqRspUtil.getRequestBody(pc,false,null);
        setValue(fa[i],args,name, body);
      }
     
    }
    Object rtn=null;
    try{
        if(suppressContent)pc.setSilent();
      rtn = component.callWithNamedValues(pc, methodName, args);
    }
    catch (PageException e) {
      RestUtil.setStatus(pc, 500, ExceptionUtil.getMessage(e));
    }
      finally {
        if(suppressContent)pc.unsetSilent();
      }
     
      // custom response
    Struct sct = result.getCustomResponse();
    boolean hasContent=false;
      if(sct!=null){
      HttpServletResponse rsp = pc.getHttpServletResponse();
        // status
        int status = Caster.toIntValue(sct.get(KeyConstants._status,Constants.DOUBLE_ZERO),0);
        if(status>0)rsp.setStatus(status);
     
        // content
        Object o=sct.get(KeyConstants._content,null);
        if(o!=null) {
          String content=Caster.toString(o,null);
          if(content!=null) {
              try {
            pc.forceWrite(content);
            hasContent=true;
          }
              catch (IOException e) {}
          }
        }
       
        // headers
        Struct headers=Caster.toStruct(sct.get(KeyConstants._headers,null),null);
        if(headers!=null){
          //Key[] keys = headers.keys();
          Iterator<Entry<Key, Object>> it = headers.entryIterator();
          Entry<Key, Object> e;
          String n,v;
          Object tmp;
          while(it.hasNext()){
            e = it.next();
            n=e.getKey().getString();
            tmp=e.getValue();
            v=Caster.toString(tmp,null);
            if(tmp!=null && v==null) v=tmp.toString();
            rsp.setHeader(n, v);
         
        }
    }
      // convert result
    if(rtn!=null && !hasContent){
      Props props = new Props();
          props.format=result.getFormat();
          Charset cs = getCharset(pc);
          if(result.hasFormatExtension()){
            //setFormat(pc.getHttpServletResponse(), props.format,cs);
          _writeOut(pc, props, null, rtn,cs);
          }
          else {
            if(best!=null && !MimeType.ALL.same(best)) {
                int f = MimeType.toFormat(best, -1);
                if(f!=-1) {
                  props.format=f;
                  //setFormat(pc.getHttpServletResponse(), f,cs);
                  _writeOut(pc, props, null, rtn,cs);
                }
                else {
                  writeOut(pc,props,rtn,best);
                }
              }
            else {
              _writeOut(pc, props, null, rtn,cs);
            }
          }
         
         
        }
   
  }

  private void setValue(FunctionArgument fa, Struct args, Key name, Object value) {
    if(value==null){
      Struct meta = fa.getMetaData();
      if(meta!=null)value=meta.get(KeyConstants._default,null);
    }
    args.setEL(name, value);
  }

  private void writeOut(PageContext pc, Props props, Object obj, MimeType mt) throws PageException, IOException, ConverterException {
    // TODO miemtype mapping with converter defintion from external file
    // Images
    if(mt.same(MimeType.IMAGE_GIF)) writeOut(pc,obj,mt,new ImageConverter("gif"));
    else if(mt.same(MimeType.IMAGE_JPG)) writeOut(pc,obj,mt,new ImageConverter("jpeg"));
    else if(mt.same(MimeType.IMAGE_PNG)) writeOut(pc,obj,mt,new ImageConverter("png"));
    else if(mt.same(MimeType.IMAGE_TIFF)) writeOut(pc,obj,mt,new ImageConverter("tiff"));
    else if(mt.same(MimeType.IMAGE_BMP)) writeOut(pc,obj,mt,new ImageConverter("bmp"));
    else if(mt.same(MimeType.IMAGE_WBMP)) writeOut(pc,obj,mt,new ImageConverter("wbmp"));
    else if(mt.same(MimeType.IMAGE_FBX)) writeOut(pc,obj,mt,new ImageConverter("fbx"));
    else if(mt.same(MimeType.IMAGE_FBX)) writeOut(pc,obj,mt,new ImageConverter("fbx"));
    else if(mt.same(MimeType.IMAGE_PNM)) writeOut(pc,obj,mt,new ImageConverter("pnm"));
    else if(mt.same(MimeType.IMAGE_PGM)) writeOut(pc,obj,mt,new ImageConverter("pgm"));
    else if(mt.same(MimeType.IMAGE_PBM)) writeOut(pc,obj,mt,new ImageConverter("pbm"));
    else if(mt.same(MimeType.IMAGE_ICO)) writeOut(pc,obj,mt,new ImageConverter("ico"));
    else if(mt.same(MimeType.IMAGE_PSD)) writeOut(pc,obj,mt,new ImageConverter("psd"));
    else if(mt.same(MimeType.IMAGE_ASTERIX)) writeOut(pc,obj,MimeType.IMAGE_PNG,new ImageConverter("png"));
   
    // Application
    else if(mt.same(MimeType.APPLICATION_JAVA)) writeOut(pc,obj,mt,new JavaConverter());
    //if("application".equalsIgnoreCase(mt.getType()))
   
   
    else _writeOut(pc, props, null, obj,null);
  }

  private static void writeOut(PageContext pc, Object obj, MimeType mt,BinaryConverter converter) throws ConverterException, IOException {
    pc.getResponse().setContentType(mt.toString());
   
    OutputStream os=null;
    try{
      converter.writeOut(pc, obj, os=pc.getResponseStream());
    }
    finally{
      IOUtil.closeEL(os);
    }
  }

  public static  boolean isSoap(PageContext pc) {
    HttpServletRequest req = pc.getHttpServletRequest();
    InputStream is=null;
    try {
      is=req.getInputStream();
     
      String input = IOUtil.toString(is,CharsetUtil.ISO88591);
      return
      StringUtil.indexOfIgnoreCase(input, "soap:Envelope")!=-1 ||
      StringUtil.indexOfIgnoreCase(input, "soapenv:Envelope")!=-1 ||
        StringUtil.indexOfIgnoreCase(input, "SOAP-ENV:Envelope")!=-1;
    }
    catch (IOException e) {
      return false;
    }
    finally {
      IOUtil.closeEL(is);
    }
  }
 
 
  private void callWDDX(PageContext pc, Component component, Collection.Key methodName, boolean suppressContent) throws IOException, ConverterException, PageException {
    //Struct url = StructUtil.duplicate(pc.urlFormScope(),true);
    Struct url=StructUtil.merge(new Struct[]{pc.formScope(),pc.urlScope()});
    // define args
    url.removeEL(KeyConstants._fieldnames);
    url.removeEL(KeyConstants._method);
    Object args=url.get(KeyConstants._argumentCollection,null);
    String strArgCollFormat=Caster.toString(url.get("argumentCollectionFormat",null),null);
   
   
    // url.returnFormat
    int urlReturnFormat=-1;
    Object oReturnFormatFromURL=url.get(KeyConstants._returnFormat,null);
    if(oReturnFormatFromURL!=null)urlReturnFormat=UDFUtil.toReturnFormat(Caster.toString(oReturnFormatFromURL,null),-1);
   
    // request header "accept"
    List<MimeType> accept = ReqRspUtil.getAccept(pc);
    int headerReturnFormat = MimeType.toFormat(accept,UDF.RETURN_FORMAT_XML, -1);
   
   
        Object queryFormat=url.get(KeyConstants._queryFormat,null);
       
       
       
        if(args==null){
          args=pc.getHttpServletRequest().getAttribute("argumentCollection");
        }
        if(StringUtil.isEmpty(strArgCollFormat)) {
          strArgCollFormat=Caster.toString(pc.getHttpServletRequest().getAttribute("argumentCollectionFormat"),null);
        }
       
      //content-type
        Charset cs = getCharset(pc);
        Object o = component.get(pc,methodName,null);
        Props props = getProps(pc, o, urlReturnFormat,headerReturnFormat);
       
        if(!props.output) setFormat(pc.getHttpServletResponse(),props.format,cs);
         
       
        Object rtn=null;
        try{
        if(suppressContent)pc.setSilent();
       
         
          if(args==null){
            url=translate(component,methodName.getString(),url);
            rtn = component.callWithNamedValues(pc, methodName, url);
          }
          else if(args instanceof String){
            String str=(String)args;
            int format = UDFUtil.toReturnFormat(strArgCollFormat,-1);
           
              // CFML
              if(UDF.RETURN_FORMAT_SERIALIZE==format)  {
                 // do not catch exception when format is defined
                args=new CFMLExpressionInterpreter().interpret(pc, str);
              }
              // JSON
              if(UDF.RETURN_FORMAT_JSON==format)  {
                 // do not catch exception when format is defined
                args=new JSONExpressionInterpreter(false).interpret(pc, str);
              }
              // default
              else {
                 // catch exception when format is not defined, then in this case the string can also be a simple argument
                try {
                  args=new JSONExpressionInterpreter(false).interpret(pc, str);
                }
                catch (PageException pe) {
                  try {
                    args=new CFMLExpressionInterpreter().interpret(pc, str);
                  }
                  catch (PageException _pe) {}
            }
              }
        }

          // call
          if(args!=null) {
            if(Decision.isCastableToStruct(args)){
              rtn = component.callWithNamedValues(pc, methodName, Caster.toStruct(args,false));
            }
            else if(Decision.isCastableToArray(args)){
              rtn = component.call(pc, methodName, Caster.toNativeArray(args));
            }
            else {
              Object[] ac=new Object[1];
              ac[0]=args;
              rtn = component.call(pc, methodName, ac);
            }
          }
        }
      finally {
        if(suppressContent)pc.unsetSilent();
      }
        // convert result
        if(rtn!=null){
          if(pc.getHttpServletRequest().getHeader("AMF-Forward")!=null) {
            pc.variablesScope().setEL("AMF-Forward", rtn);
          }
          else {
            _writeOut(pc, props, queryFormat, rtn,cs);
          }
        }
       
    }
   
  private static void setFormat(HttpServletResponse rsp, int format, Charset charset) {
      String strCS;
    if(charset==null) strCS="";
      else strCS="; charset="+charset.displayName();
   
    switch(format){
        case UDF.RETURN_FORMAT_WDDX:
          rsp.setContentType("text/xml"+strCS);
          rsp.setHeader("Return-Format", "wddx");
        break;
        case UDF.RETURN_FORMAT_JSON:
          rsp.setContentType("application/json"+strCS);
          rsp.setHeader("Return-Format", "json");
        break;
        case UDF.RETURN_FORMAT_PLAIN:
          rsp.setContentType("text/plain"+strCS);
          rsp.setHeader("Return-Format", "plain");
        break;
        case UDF.RETURN_FORMAT_XML:
          rsp.setContentType("text/xml"+strCS);
          rsp.setHeader("Return-Format", "xml");
        break;
        case UDF.RETURN_FORMAT_SERIALIZE:
          rsp.setContentType("application/cfml"+strCS);
          rsp.setHeader("Return-Format", "cfml");
        break;
        case UDFPlus.RETURN_FORMAT_JAVA:
          rsp.setContentType("application/java"); // no charset this is a binary format
          rsp.setHeader("Return-Format", "java");
        break;
        }
  }

  private static Props getProps(PageContext pc, Object o,int urlReturnFormat,int headerReturnFormat) {
      Props props = new Props();
     
    props.strType="any";
    props.secureJson=pc.getApplicationContext().getSecureJson();
    int udfReturnFormat=-1;
    if(o instanceof UDFPlus) {
      UDFPlus udf = ((UDFPlus)o);
      udfReturnFormat=udf.getReturnFormat(-1);
      props.type=udf.getReturnType();
      props.strType=udf.getReturnTypeAsString();
      props.output=udf.getOutput();
      if(udf.getSecureJson()!=null)props.secureJson=udf.getSecureJson().booleanValue();
    }

    // format
    if(isValid(urlReturnFormat)) props.format=urlReturnFormat;
    else if(isValid(udfReturnFormat)) props.format=udfReturnFormat;
    else if(isValid(headerReturnFormat)) props.format=headerReturnFormat;
    else props.format=UDF.RETURN_FORMAT_WDDX;
   
    // return type XML ignore WDDX
    if(props.type==CFTypes.TYPE_XML) {
      if(UDF.RETURN_FORMAT_WDDX==props.format)
        props.format=UDF.RETURN_FORMAT_PLAIN;
    }
     
     
     
      return props;
    }
   
    private static boolean isValid(int returnFormat) {
    return returnFormat!=-1 && returnFormat!=UDF.RETURN_FORMAT_XML;
  }

  public static void writeToResponseStream(PageContext pc,Component component, String methodName,int urlReturnFormat,int headerReturnFormat,Object queryFormat,Object rtn) throws ConverterException, PageException, IOException {
      Object o = component.get(KeyImpl.init(methodName),null);
      Props p = getProps(pc, o, urlReturnFormat,headerReturnFormat);
      _writeOut(pc, p, queryFormat, rtn,null);
    }
   
    private static void _writeOut(PageContext pc,Props props,Object queryFormat,Object rtn,Charset cs) throws ConverterException, PageException, IOException {
      // return type XML ignore WDDX
    if(props.type==CFTypes.TYPE_XML) {
      //if(UDF.RETURN_FORMAT_WDDX==format) format=UDF.RETURN_FORMAT_PLAIN;
      rtn=Caster.toString(Caster.toXML(rtn));
    }
    // function does no real cast, only check it
    else rtn=Caster.castTo(pc, (short)props.type, props.strType, rtn);
     
    setFormat(pc.getHttpServletResponse(), props.format, cs);
   
      // WDDX
    if(UDF.RETURN_FORMAT_WDDX==props.format) {
      WDDXConverter converter = new WDDXConverter(pc.getTimeZone(),false,false);
            converter.setTimeZone(pc.getTimeZone());
            pc.forceWrite(converter.serialize(rtn));
    }
    // JSON
    else if(UDF.RETURN_FORMAT_JSON==props.format) {
      boolean byColumn = false;
        if(queryFormat instanceof String){
          String strQF=((String) queryFormat).trim();
          if(strQF.equalsIgnoreCase("row"));
          else if(strQF.equalsIgnoreCase("column"))byColumn=true;
          else throw new ApplicationException("invalid queryformat definition ["+strQF+"], valid formats are [row,column]");
        }
        JSONConverter converter = new JSONConverter(false);
        String prefix="";
        if(props.secureJson) {
          prefix=pc.getApplicationContext().getSecureJsonPrefix();
          if(prefix==null)prefix="";
        }
        pc.forceWrite(prefix+converter.serialize(pc,rtn,byColumn));
    }
    // CFML
    else if(UDF.RETURN_FORMAT_SERIALIZE==props.format) {
      ScriptConverter converter = new ScriptConverter(false);
      pc.forceWrite(converter.serialize(rtn));
    }
      // XML
    else if(UDF.RETURN_FORMAT_XML==props.format) {
      XMLConverter converter = new XMLConverter(pc.getTimeZone(),false);
            converter.setTimeZone(pc.getTimeZone());
            pc.forceWrite(converter.serialize(rtn));
    }
    // Plain
    else if(UDF.RETURN_FORMAT_PLAIN==props.format) {
      pc.forceWrite(Caster.toString(rtn));
    }

    // JAVA
    else if(UDFPlus.RETURN_FORMAT_JAVA==props.format) {
      writeOut(pc,rtn,MimeType.APPLICATION_JAVA,new JavaConverter());
    }
    else throw new IOException("invalid return format defintion:"+props.format);
  }

  public static Struct translate(Component c, String strMethodName, Struct params) {
    Collection.Key methodName=KeyImpl.init(strMethodName);
    Key[] keys = CollectionUtil.keys(params);
    FunctionArgument[] args=null;
    int index=-1;
    Object value;
      for(int i=0;i<keys.length;i++){
        index=Caster.toIntValue(keys[i].getString(),0);
        if(index>0)  {
          if(args==null)args=_getArgs(c,methodName);
          if(args!=null && index<=args.length) {
            value=params.removeEL(keys[i]);
            if(value!=null)params.setEL(args[index-1].getName(), value);
          }
        }
       
      }
      return params;
  }

  private static FunctionArgument[] _getArgs(Component c, Collection.Key methodName) {
    Object o=c.get(methodName,null);
    if(o instanceof UDF) return ((UDF) o).getFunctionArguments();
    return null;
  }
 
  private void callCFCMetaData(PageContext pc, Component cfc, int format) throws IOException, PageException, ConverterException {
    ComponentAccess ca = ComponentUtil.toComponentAccess(cfc);
    ComponentWrap cw = new ComponentWrap(Component.ACCESS_REMOTE,ca)
    ComponentScope scope = cw.getComponentScope();
    Struct udfs=new StructImpl(),sctUDF,sctArg;
    Array arrArg;
    Iterator<Object> it = scope.valueIterator();
    Object v;
    UDF udf;
    FunctionArgument[] args;
    while(it.hasNext()){
        v=it.next();
          // UDF
        if(v instanceof UDF) {
          udf=(UDF) v;
            sctUDF=new StructImpl();
            arrArg=new ArrayImpl();
            udfs.setEL(udf.getFunctionName(), sctUDF);
            args = udf.getFunctionArguments();
            for(int i=0;i<args.length;i++){
              sctArg=new StructImpl();
              arrArg.appendEL(sctArg);
              sctArg.setEL(KeyConstants._name, args[i].getName().getString());
              sctArg.setEL(KeyConstants._type, args[i].getTypeAsString());
              sctArg.setEL(KeyConstants._required, args[i].isRequired());
              if(!StringUtil.isEmpty(args[i].getHint()))sctArg.setEL(KeyConstants._hint, args[i].getHint());
            }
            sctUDF.set(KeyConstants._arguments, arrArg);
            sctUDF.set(KeyConstants._returntype, udf.getReturnTypeAsString());
           
          }
    }
    Struct rtn=new StructImpl();
    rtn.set(KeyConstants._functions, udfs);
    rtn.set(ACCEPT_ARG_COLL_FORMATS, "cfml,json");
   
       
        InputStream is;
        Charset cs=null;
    // WDDX
    if(UDF.RETURN_FORMAT_WDDX==format) {
      WDDXConverter converter = new WDDXConverter(pc.getTimeZone(),false,false);
            converter.setTimeZone(pc.getTimeZone());
            String str = converter.serialize(rtn);
            cs = getCharset(pc);
            is = new ByteArrayInputStream(str.getBytes(cs));
    }
   
        // JSON
    else if(UDF.RETURN_FORMAT_JSON==format) {
          boolean byColumn = false;
        JSONConverter converter = new JSONConverter(false);
        String str = converter.serialize(pc,rtn,byColumn);
            cs = getCharset(pc);
            is = new ByteArrayInputStream(str.getBytes(cs));
       
        }
        // CFML
    else if(UDF.RETURN_FORMAT_SERIALIZE==format) {
      ScriptConverter converter = new ScriptConverter(false);
      String str=converter.serialize(rtn);
            cs = getCharset(pc);
            is = new ByteArrayInputStream(str.getBytes(cs));
    }
      // XML
    else if(UDF.RETURN_FORMAT_XML==format) {
      XMLConverter converter = new XMLConverter(pc.getTimeZone(),false);
            converter.setTimeZone(pc.getTimeZone());
            String str=converter.serialize(rtn);
            cs = getCharset(pc);
            is = new ByteArrayInputStream(str.getBytes(cs));
    }
    // Plain
    else if(UDF.RETURN_FORMAT_PLAIN==format) {
      String str= Caster.toString(rtn);
            cs = getCharset(pc);
            is = new ByteArrayInputStream(str.getBytes(cs));
    }
    // Java
    else if(UDFPlus.RETURN_FORMAT_JAVA==format) {
      byte[] bytes = JavaConverter.serializeAsBinary(rtn);
      is = new ByteArrayInputStream(bytes);
     
    }
    else throw new IOException("invalid format defintion:"+format);
       
       
       
       
    OutputStream os=null;
    try {
      os=pc.getResponseStream();
      setFormat(pc.getHttpServletResponse(), format, cs);
      IOUtil.copy(is, os, false,false);
     
    }
    finally {
      IOUtil.flushEL(os);
            IOUtil.closeEL(os);
            ((PageContextImpl)pc).getRootOut().setClosed(true);
    }
  }

  private Charset getCharset(PageContext pc) {
    HttpServletResponse rsp = pc.getHttpServletResponse();
        String str = ReqRspUtil.getCharacterEncoding(pc,rsp);
        if(StringUtil.isEmpty(str)) str=pc.getConfig().getWebCharset();
        return CharsetUtil.toCharset(str, CharsetUtil.UTF8);
  }

  private void callWSDL(PageContext pc, Component component) throws ServletException, IOException, ExpressionException {
      // take wsdl file defined by user
      String wsdl = component.getWSDLFile();
      if(!StringUtil.isEmpty(wsdl)) {
       
        OutputStream os=null;
        Resource input = ResourceUtil.toResourceExisting(pc, wsdl);
        try {
          os=pc.getResponseStream();
        pc.getResponse().setContentType("text/xml; charset=utf-8");
          IOUtil.copy(input, os, false);
         
        }
        finally {
          IOUtil.flushEL(os);
                IOUtil.closeEL(os);
                ((PageContextImpl)pc).getRootOut().setClosed(true);
        }
      }
      // create a wsdl file
      else {
        RPCServer.getInstance(pc.getId(),pc.getServletContext())
            .doGet(pc.getHttpServletRequest(), pc. getHttpServletResponse(), component);
      }
    }
   
    private void callWebservice(PageContext pc, Component component) throws IOException, ServletException {
      ComponentController.set(pc, component);
      try {
          RPCServer.getInstance(pc.getId(),pc.getServletContext())
            .doPost(pc.getHttpServletRequest(), pc. getHttpServletResponse(), component);
      }
      finally {
        ComponentController.release();
      }
    }
   

    public abstract void initComponent(PageContext pc,ComponentImpl c) throws PageException;

  public void ckecked() {
    lastCheck=System.currentTimeMillis();
  }

  public long lastCheck() {
    return lastCheck;
  }
 
}
  class Props {

    public String strType="any";
    public boolean secureJson;
    public int type=CFTypes.TYPE_ANY;
    public int format=UDF.RETURN_FORMAT_WDDX;
    public boolean output=true;
   
  }
TOP

Related Classes of railo.runtime.ComponentPage

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.