001: /*
002: * $Id: StandardCallingConvention.java,v 1.64 2007/09/18 08:45:07 agoubard Exp $
003: *
004: * Copyright 2003-2007 Orange Nederland Breedband B.V.
005: * See the COPYRIGHT file for redistribution and use restrictions.
006: */
007: package org.xins.server;
008:
009: import java.io.IOException;
010: import java.io.StringReader;
011: import java.io.StringWriter;
012: import java.io.Writer;
013:
014: import javax.servlet.http.HttpServletRequest;
015: import javax.servlet.http.HttpServletResponse;
016:
017: import org.xins.common.Utils;
018: import org.xins.common.collections.BasicPropertyReader;
019: import org.xins.common.text.ParseException;
020: import org.xins.common.text.TextUtils;
021: import org.xins.common.xml.Element;
022: import org.xins.common.xml.ElementParser;
023:
024: /**
025: * Standard calling convention. The technical name for this calling convention
026: * is <em>_xins-std</em>.
027: *
028: * @version $Revision: 1.64 $ $Date: 2007/09/18 08:45:07 $
029: * @author <a href="mailto:anthony.goubard@japplis.com">Anthony Goubard</a>
030: * @author <a href="mailto:ernst@ernstdehaan.com">Ernst de Haan</a>
031: */
032: public class StandardCallingConvention extends CallingConvention {
033:
034: /**
035: * The response encoding format.
036: */
037: protected static final String RESPONSE_ENCODING = "UTF-8";
038:
039: /**
040: * The content type of the HTTP response.
041: */
042: protected static final String RESPONSE_CONTENT_TYPE = "text/xml; charset="
043: + RESPONSE_ENCODING;
044:
045: /**
046: * Checks if the specified request can be handled by this calling
047: * convention.
048: *
049: * <p>This method will not throw any exception.
050: *
051: * @param httpRequest
052: * the HTTP request to investigate, cannot be <code>null</code>.
053: *
054: * @return
055: * <code>true</code> if this calling convention is <em>possibly</em>
056: * able to handle this request, or <code>false</code> if it
057: * <em>definitely</em> not able to handle this request.
058: */
059: protected boolean matches(HttpServletRequest httpRequest) {
060:
061: // If no _function parameter is specified, then there is no match
062: return !TextUtils
063: .isEmpty(httpRequest.getParameter("_function"));
064: }
065:
066: /**
067: * Converts an HTTP request to a XINS request (implementation method). This
068: * method should only be called from class CallingConvention. Only
069: * then it is guaranteed that the <code>httpRequest</code> argument is not
070: * <code>null</code>.
071: *
072: * @param httpRequest
073: * the HTTP request, will not be <code>null</code>.
074: *
075: * @return
076: * the XINS request object, never <code>null</code>.
077: *
078: * @throws InvalidRequestException
079: * if the request is considerd to be invalid.
080: *
081: * @throws FunctionNotSpecifiedException
082: * if the request does not indicate the name of the function to execute.
083: */
084: protected FunctionRequest convertRequestImpl(
085: HttpServletRequest httpRequest)
086: throws InvalidRequestException,
087: FunctionNotSpecifiedException {
088:
089: // Parse the parameters in the HTTP request
090: BasicPropertyReader params = gatherParams(httpRequest);
091:
092: // Remove all invalid parameters
093: cleanUpParameters(params);
094:
095: // Determine function name
096: String functionName = httpRequest.getParameter("_function");
097: if (TextUtils.isEmpty(functionName)) {
098: throw new FunctionNotSpecifiedException();
099: }
100:
101: // Get data section
102: String dataSectionValue = httpRequest.getParameter("_data");
103: Element dataElement = null;
104: if (dataSectionValue != null && dataSectionValue.length() > 0) {
105: ElementParser parser = new ElementParser();
106:
107: // Parse the data section
108: try {
109: dataElement = parser.parse(new StringReader(
110: dataSectionValue));
111:
112: // I/O error, should never happen on a StringReader
113: } catch (IOException exception) {
114: throw Utils.logProgrammingError(exception);
115: // Parsing error
116: } catch (ParseException exception) {
117: String detail = "Cannot parse the data section.";
118: throw new InvalidRequestException(detail, exception);
119: }
120: }
121:
122: // Construct and return the request object
123: return new FunctionRequest(functionName, params, dataElement);
124: }
125:
126: /**
127: * Converts a XINS result to an HTTP response (implementation method).
128: *
129: * @param xinsResult
130: * the XINS result object that should be converted to an HTTP response,
131: * will not be <code>null</code>.
132: *
133: * @param httpResponse
134: * the HTTP response object to configure, will not be <code>null</code>.
135: *
136: * @param httpRequest
137: * the HTTP request, will not be <code>null</code>.
138: *
139: * @throws IOException
140: * if calling any of the methods in <code>httpResponse</code> causes an
141: * I/O error.
142: */
143: protected void convertResultImpl(FunctionResult xinsResult,
144: HttpServletResponse httpResponse,
145: HttpServletRequest httpRequest) throws IOException {
146:
147: // Set the status code and the content type
148: httpResponse.setStatus(HttpServletResponse.SC_OK);
149: httpResponse.setContentType(RESPONSE_CONTENT_TYPE);
150:
151: // Determine the method
152: String method = httpRequest.getMethod();
153:
154: // Handle HEAD requests
155: if ("HEAD".equals(method)) {
156: StringWriter out = new StringWriter();
157: CallResultOutputter.output(out, xinsResult);
158: httpResponse.setContentLength(out.getBuffer().length());
159:
160: // Handle non-HEAD requests
161: } else {
162: Writer out = httpResponse.getWriter();
163: CallResultOutputter.output(out, xinsResult);
164: out.close();
165: }
166: }
167: }
|