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