001    package railo.runtime.engine;
002    
003    import java.io.ByteArrayOutputStream;
004    import java.io.DataInputStream;
005    import java.io.DataOutputStream;
006    import java.io.IOException;
007    import java.util.Iterator;
008    
009    import javax.servlet.ServletException;
010    import javax.servlet.ServletOutputStream;
011    import javax.servlet.http.HttpServlet;
012    import javax.servlet.http.HttpServletRequest;
013    import javax.servlet.http.HttpServletResponse;
014    
015    import org.openamf.AMFBody;
016    import org.openamf.AMFError;
017    import org.openamf.AMFMessage;
018    import org.openamf.ServiceRequest;
019    import org.openamf.io.AMFDeserializer;
020    import org.openamf.io.AMFSerializer;
021    
022    import railo.commons.io.IOUtil;
023    import railo.runtime.exp.PageException;
024    import railo.runtime.net.amf.CFMLProxy;
025    import railo.runtime.net.amf.OpenAMFCaster;
026    
027    
028    /**
029     * AMF Engine
030     */
031    public final class AMFEngine {
032        
033    
034    
035        /**
036         * Main entry point for the servlet
037         * @param servlet 
038         * @param req 
039         * @param rsp 
040         *
041         * @throws ServletException
042         * @throws IOException
043         */
044        public void service(HttpServlet servlet, HttpServletRequest req, HttpServletResponse rsp) throws IOException {
045            
046            AMFMessage requestMessage = null;
047            AMFMessage responseMessage = null;
048            requestMessage = deserializeAMFMessage(req);
049            responseMessage = processMessage(servlet, req, rsp, requestMessage);
050            serializeAMFMessage(rsp, responseMessage);
051        }
052    
053        private AMFMessage deserializeAMFMessage(HttpServletRequest req) throws IOException {
054            DataInputStream dis = null;
055            try {
056                    dis = new DataInputStream(req.getInputStream());
057                    AMFDeserializer deserializer = new AMFDeserializer(dis);
058                    AMFMessage message = deserializer.getAMFMessage();
059                    return message;
060            }
061            finally {
062                    IOUtil.closeEL(dis);
063            }
064        }
065    
066        private void serializeAMFMessage(HttpServletResponse resp, AMFMessage message) throws IOException {
067            ByteArrayOutputStream baos = new ByteArrayOutputStream();
068            DataOutputStream dos = new DataOutputStream(baos);
069            AMFSerializer serializer = new AMFSerializer(dos);
070            serializer.serializeMessage(message);
071            resp.setContentType("application/x-amf");
072            resp.setContentLength(baos.size());
073            ServletOutputStream sos = resp.getOutputStream(); 
074            baos.writeTo(sos);
075            sos.flush();
076        }
077    
078        /**
079         * Iterates through the request message's bodies, invokes each body and
080         * then, builds a message to send as the results
081         * @param req 
082         * @param rsp 
083         * @param message 
084         * @return AMFMessage
085         * @throws IOException 
086         * @throws ServletException 
087         */
088        private AMFMessage processMessage(HttpServlet servlet, HttpServletRequest req, HttpServletResponse rsp, AMFMessage message)  {
089            AMFMessage responseMessage = new AMFMessage();
090            for (Iterator bodies = message.getBodies(); bodies.hasNext();) {
091                AMFBody requestBody = (AMFBody) bodies.next();
092                // invoke
093                Object serviceResult = invokeBody(servlet,req, rsp, requestBody);
094                String target = getTarget(requestBody, serviceResult);
095                AMFBody responseBody = new AMFBody(target, "null", serviceResult);
096                responseMessage.addBody(responseBody);
097            }
098            return responseMessage;
099        }
100    
101        
102        private Object invokeBody(HttpServlet servlet, HttpServletRequest req, HttpServletResponse rsp, AMFBody requestBody) { 
103            try {
104                    ServiceRequest request = new ServiceRequest(requestBody);
105                    rsp.getOutputStream();// MUST muss das sein?
106                   
107                    return new CFMLProxy().invokeBody(OpenAMFCaster.getInstance(),null,servlet.getServletContext(),servlet.getServletConfig(), req, rsp, request.getServiceName(), request.getServiceMethodName(), request.getParameters());
108                    } 
109            catch (Exception e) {
110                    e.printStackTrace();
111                rsp.setStatus(200);
112                AMFError error=new AMFError();
113                e.setStackTrace(e.getStackTrace());
114                error.setDescription(e.getMessage());
115                            
116                            if(e instanceof PageException){
117                                    PageException pe = (PageException)e;
118                        error.setCode(pe.getErrorCode());
119                        error.setCode(pe.getErrorCode());
120                        error.setDetails(pe.getDetail());
121                            }
122                            
123                            return error;
124                    } 
125        }
126    
127        private String getTarget(AMFBody requestBody, Object serviceResult) {
128            String target = "/onResult";
129            if (serviceResult instanceof AMFError) {
130                target = "/onStatus";
131            }
132            return requestBody.getResponse() + target;
133        }
134    }