| StandardCallingConvention.java |
/*
* $Id: StandardCallingConvention.java,v 1.74 2013/01/18 10:41:47 agoubard Exp $
*
* See the COPYRIGHT file for redistribution and use restrictions.
*/
package org.xins.server;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.xins.common.text.TextUtils;
import org.xins.common.xml.ElementFormatter;
/**
* Standard calling convention. The technical name for this calling convention
* is <em>_xins-std</em>.
*
* @version $Revision: 1.74 $ $Date: 2013/01/18 10:41:47 $
* @author <a href="mailto:anthony.goubard@japplis.com">Anthony Goubard</a>
* @author <a href="mailto:ernst@ernstdehaan.com">Ernst de Haan</a>
*/
public class StandardCallingConvention extends CallingConvention {
/**
* The response encoding format.
*/
protected static final String RESPONSE_ENCODING = "UTF-8";
/**
* The content type of the HTTP response.
*/
protected static final String RESPONSE_CONTENT_TYPE = "text/xml; charset=" + RESPONSE_ENCODING;
/**
* Checks if the specified request can be handled by this calling
* convention.
*
* <p>This method will not throw any exception.
*
* @param httpRequest
* the HTTP request to investigate, cannot be <code>null</code>.
*
* @return
* <code>true</code> if this calling convention is <em>possibly</em>
* able to handle this request, or <code>false</code> if it
* <em>definitely</em> not able to handle this request.
*/
protected boolean matches(HttpServletRequest httpRequest) {
// If no _function parameter is specified, then there is no match
return ! TextUtils.isEmpty(httpRequest.getParameter("_function"));
}
/**
* Converts an HTTP request to a XINS request (implementation method). This
* method should only be called from class CallingConvention. Only
* then it is guaranteed that the <code>httpRequest</code> argument is not
* <code>null</code>.
*
* @param httpRequest
* the HTTP request, will not be <code>null</code>.
*
* @return
* the XINS request object, never <code>null</code>.
*
* @throws InvalidRequestException
* if the request is considerd to be invalid.
*
* @throws FunctionNotSpecifiedException
* if the request does not indicate the name of the function to execute.
*/
protected FunctionRequest convertRequestImpl(HttpServletRequest httpRequest)
throws InvalidRequestException,
FunctionNotSpecifiedException {
// Parse the parameters in the HTTP request
Map<String, String> params = gatherParams(httpRequest);
// Remove all invalid parameters
cleanUpParameters(params);
// Determine function name
String functionName = httpRequest.getParameter("_function");
if (TextUtils.isEmpty(functionName)) {
throw new FunctionNotSpecifiedException();
}
// Get data section
String dataSectionValue = httpRequest.getParameter("_data");
Element dataElement = null;
if (dataSectionValue != null && dataSectionValue.length() > 0) {
// Parse the data section
try {
dataElement = ElementFormatter.parse(dataSectionValue);
// Parsing error
} catch (SAXException exception) {
String detail = "Cannot parse the data section.";
throw new InvalidRequestException(detail, exception);
}
}
// Define the HTTP method in the backpack
Map<String, Object> backpack = new HashMap<String, Object>();
backpack.put("_httpMethod", httpRequest.getMethod());
// Construct and return the request object
return new FunctionRequest(functionName, params, dataElement, backpack);
}
/**
* Converts a XINS result to an HTTP response (implementation method).
*
* @param xinsResult
* the XINS result object that should be converted to an HTTP response,
* will not be <code>null</code>.
*
* @param httpResponse
* the HTTP response object to configure, will not be <code>null</code>.
*
* @param backpack
* the request backpack, will not be <code>null</code>.
*
* @throws IOException
* if calling any of the methods in <code>httpResponse</code> causes an
* I/O error.
*/
protected void convertResultImpl(FunctionResult xinsResult,
HttpServletResponse httpResponse,
Map<String, Object> backpack)
throws IOException {
// Set the status code and the content type
Integer backpackStatusCode = (Integer) backpack.get(BackpackConstants.STATUS_CODE);
if (backpackStatusCode == null) {
httpResponse.setStatus(HttpServletResponse.SC_OK);
} else {
httpResponse.setStatus(backpackStatusCode);
}
httpResponse.setContentType(RESPONSE_CONTENT_TYPE);
// Determine the method
String method = (String) backpack.get("_httpMethod");
// Handle HEAD requests
if ("HEAD".equals(method)) {
StringWriter out = new StringWriter();
CallResultOutputter.output(out, xinsResult);
httpResponse.setContentLength(out.getBuffer().length());
// Handle non-HEAD requests
} else {
Writer out = httpResponse.getWriter();
CallResultOutputter.output(out, xinsResult);
out.close();
}
}
}