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 }