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.runtime.net.amf; 020 021import java.io.ByteArrayOutputStream; 022import java.io.IOException; 023import java.io.OutputStream; 024import java.util.ArrayList; 025import java.util.List; 026import java.util.Map; 027 028import javax.servlet.ServletConfig; 029import javax.servlet.ServletContext; 030import javax.servlet.ServletException; 031import javax.servlet.http.Cookie; 032import javax.servlet.http.HttpServletRequest; 033import javax.servlet.http.HttpServletResponse; 034 035import lucee.commons.io.DevNullOutputStream; 036import lucee.commons.io.res.Resource; 037import lucee.commons.lang.Pair; 038import lucee.commons.lang.SystemOut; 039import lucee.runtime.CFMLFactory; 040import lucee.runtime.PageContext; 041import lucee.runtime.PageContextImpl; 042import lucee.runtime.PageSource; 043import lucee.runtime.config.ConfigImpl; 044import lucee.runtime.config.ConfigWebImpl; 045import lucee.runtime.engine.CFMLEngineImpl; 046import lucee.runtime.exp.PageException; 047import lucee.runtime.net.http.HttpServletRequestDummy; 048import lucee.runtime.net.http.HttpServletResponseDummy; 049import lucee.runtime.net.http.HttpUtil; 050import lucee.runtime.net.http.ReqRspUtil; 051import lucee.runtime.op.Caster; 052import lucee.runtime.type.Collection; 053import lucee.runtime.type.KeyImpl; 054import lucee.runtime.type.Struct; 055import lucee.runtime.type.StructImpl; 056import flex.messaging.config.ConfigMap; 057 058public class CFMLProxy { 059 060 private static final Collection.Key FLASH = KeyImpl.intern("flash"); 061 private static final Collection.Key PARAMS = KeyImpl.intern("params"); 062 private static final Collection.Key RESULT = KeyImpl.intern("result"); 063 private static final Collection.Key AMF_FORWARD = KeyImpl.intern("AMF-Forward"); 064 065 066 067 public Object invokeBody(AMFCaster caster,ConfigMap configMap,ServletContext context,ServletConfig config,HttpServletRequest req, 068 HttpServletResponse rsp,String serviceName,String serviceMethodName,List rawParams) throws ServletException, PageException,IOException { 069 070 //try { 071 072 073 // Forward 074 CFMLFactory factory = CFMLEngineImpl.getInstance().getCFMLFactory(context, config, req); 075 PageContext pc=null; 076 077 // CFC Files 078 String cfc; 079 Object parameters=null; 080 try { 081 cfc="/"+serviceName.replace('.','/')+".cfc"; 082 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 083 pc=createPageContext(factory,cfc,"method="+serviceMethodName,baos,req); 084 PageSource source = ((PageContextImpl)pc).getPageSourceExisting(cfc); 085 086 if(caster==null)caster=((ConfigImpl)pc.getConfig()).getAMFCaster(configMap); 087 parameters=caster.toCFMLObject(rawParams); 088 if(source!=null) { 089 print(pc,cfc+"?method="+serviceMethodName); 090 // Map 091 //print.err(parameters); 092 if(parameters instanceof Map){ 093 //print.err("map"); 094 pc.getHttpServletRequest().setAttribute("argumentCollection", parameters); 095 } 096 // List 097 else if(parameters instanceof List){ 098 //print.err("list"); 099 pc.getHttpServletRequest().setAttribute("argumentCollection", parameters); 100 } 101 else { 102 ArrayList list = new ArrayList(); 103 list.add(parameters); 104 pc.getHttpServletRequest().setAttribute("argumentCollection", list); 105 106 } 107 108 // Execute 109 pc.execute(cfc,true); 110 111 // write back response 112 writeBackResponse(pc,rsp); 113 114 // After 115 return caster.toAMFObject(pc.variablesScope().get(AMF_FORWARD,null)); 116 117 } 118 } 119 finally { 120 if(pc!=null)factory.releaseLuceePageContext(pc); 121 } 122 123 // CFML Files 124 String cfml; 125 try { 126 cfml="/"+(serviceName.replace('.','/')+'/'+serviceMethodName.replace('.','/'))+".cfm"; 127 pc=createPageContext(factory,cfml,"",null,req); 128 PageSource source = ((PageContextImpl)pc).getPageSourceExisting(cfml); 129 130 if(source!=null) { 131 print(pc,cfml); 132 // Before 133 Struct params=new StructImpl(); 134 pc.variablesScope().setEL(FLASH,params); 135 params.setEL(PARAMS,parameters); 136 137 // Execute 138 pc.execute(cfml,true); 139 140 // write back response 141 writeBackResponse(pc,rsp); 142 143 // After 144 Object flash=pc.variablesScope().get(FLASH,null); 145 if(flash instanceof Struct) { 146 return caster.toAMFObject(((Struct)flash).get(RESULT,null)); 147 } 148 return null; 149 } 150 } 151 finally { 152 if(pc!=null)factory.releaseLuceePageContext(pc); 153 } 154 155 throw new AMFException("can't find cfml ("+cfml+") or cfc ("+cfc+") matching the request"); 156 } 157 158 private PageContext createPageContext(CFMLFactory factory,String scriptName,String queryString, OutputStream os, HttpServletRequest formerReq) { 159 Resource root = factory.getConfig().getRootDirectory(); 160 if(os==null)os=DevNullOutputStream.DEV_NULL_OUTPUT_STREAM; 161 162 // Request 163 HttpServletRequestDummy req = new HttpServletRequestDummy( 164 root,"localhost",scriptName,queryString, 165 ReqRspUtil.getCookies(formerReq,((ConfigImpl)factory.getConfig())._getWebCharset()), 166 HttpUtil.cloneHeaders(formerReq), 167 HttpUtil.cloneParameters(formerReq), 168 HttpUtil.getAttributesAsStruct(formerReq),null); 169 req.addHeader("AMF-Forward", "true"); 170 HttpServletResponseDummy rsp = new HttpServletResponseDummy(os); 171 172 return factory.getLuceePageContext(factory.getServlet(), req, rsp, null, false, -1, false); 173 } 174 175 private void writeBackResponse(PageContext pc, HttpServletResponse rsp) { 176 HttpServletResponseDummy hsrd=(HttpServletResponseDummy) pc.getHttpServletResponse(); 177 178 // Cookie 179 Cookie[] cookies = hsrd.getCookies(); 180 if(cookies!=null) { 181 for(int i=0;i<cookies.length;i++) { 182 rsp.addCookie(cookies[i]); 183 } 184 } 185 186 // header 187 Pair<String,Object>[] headers = hsrd.getHeaders(); 188 Pair<String,Object> header ; 189 Object value; 190 if(headers!=null) { 191 for(int i=0;i<headers.length;i++) { 192 header=headers[i]; 193 value=header.getValue(); 194 if(value instanceof Long)rsp.addDateHeader(header.getName(), ((Long)value).longValue()); 195 else if(value instanceof Integer)rsp.addDateHeader(header.getName(), ((Integer)value).intValue()); 196 else rsp.addHeader(header.getName(), Caster.toString(header.getValue(),"")); 197 } 198 } 199 } 200 201 private void print(PageContext pc, String str) { 202 if(pc.getConfig() instanceof ConfigWebImpl) 203 SystemOut.printDate(((ConfigWebImpl)pc.getConfig()).getOutWriter(), str); 204 205 } 206}