package railo.runtime.engine;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Iterator;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.openamf.AMFBody;
import org.openamf.AMFError;
import org.openamf.AMFMessage;
import org.openamf.ServiceRequest;
import org.openamf.io.AMFDeserializer;
import org.openamf.io.AMFSerializer;
import railo.commons.io.IOUtil;
import railo.runtime.exp.PageException;
import railo.runtime.net.amf.CFMLProxy;
import railo.runtime.net.amf.OpenAMFCaster;
/**
* AMF Engine
*/
public final class AMFEngine {
/**
* Main entry point for the servlet
* @param servlet
* @param req
* @param rsp
*
* @throws ServletException
* @throws IOException
*/
public void service(HttpServlet servlet, HttpServletRequest req, HttpServletResponse rsp) throws IOException {
AMFMessage requestMessage = null;
AMFMessage responseMessage = null;
requestMessage = deserializeAMFMessage(req);
responseMessage = processMessage(servlet, req, rsp, requestMessage);
serializeAMFMessage(rsp, responseMessage);
}
private AMFMessage deserializeAMFMessage(HttpServletRequest req) throws IOException {
DataInputStream dis = null;
try {
dis = new DataInputStream(req.getInputStream());
AMFDeserializer deserializer = new AMFDeserializer(dis);
AMFMessage message = deserializer.getAMFMessage();
return message;
}
finally {
IOUtil.closeEL(dis);
}
}
private void serializeAMFMessage(HttpServletResponse resp, AMFMessage message) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
AMFSerializer serializer = new AMFSerializer(dos);
serializer.serializeMessage(message);
resp.setContentType("application/x-amf");
resp.setContentLength(baos.size());
ServletOutputStream sos = resp.getOutputStream();
baos.writeTo(sos);
sos.flush();
}
/**
* Iterates through the request message's bodies, invokes each body and
* then, builds a message to send as the results
* @param req
* @param rsp
* @param message
* @return AMFMessage
* @throws IOException
* @throws ServletException
*/
private AMFMessage processMessage(HttpServlet servlet, HttpServletRequest req, HttpServletResponse rsp, AMFMessage message) {
AMFMessage responseMessage = new AMFMessage();
for (Iterator bodies = message.getBodies(); bodies.hasNext();) {
AMFBody requestBody = (AMFBody) bodies.next();
// invoke
Object serviceResult = invokeBody(servlet,req, rsp, requestBody);
String target = getTarget(requestBody, serviceResult);
AMFBody responseBody = new AMFBody(target, "null", serviceResult);
responseMessage.addBody(responseBody);
}
return responseMessage;
}
private Object invokeBody(HttpServlet servlet, HttpServletRequest req, HttpServletResponse rsp, AMFBody requestBody) {
try {
ServiceRequest request = new ServiceRequest(requestBody);
rsp.getOutputStream();// MUST muss das sein?
return new CFMLProxy().invokeBody(OpenAMFCaster.getInstance(),null,servlet.getServletContext(),servlet.getServletConfig(), req, rsp, request.getServiceName(), request.getServiceMethodName(), request.getParameters());
}
catch (Exception e) {
e.printStackTrace();
rsp.setStatus(200);
AMFError error=new AMFError();
e.setStackTrace(e.getStackTrace());
error.setDescription(e.getMessage());
if(e instanceof PageException){
PageException pe = (PageException)e;
error.setCode(pe.getErrorCode());
error.setCode(pe.getErrorCode());
error.setDetails(pe.getDetail());
}
return error;
}
}
private String getTarget(AMFBody requestBody, Object serviceResult) {
String target = "/onResult";
if (serviceResult instanceof AMFError) {
target = "/onStatus";
}
return requestBody.getResponse() + target;
}
}