001: /*
002: * $Id: XMLCallingConvention.java,v 1.48 2007/09/18 08:45:03 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.PrintWriter;
011:
012: import java.util.Iterator;
013: import java.util.List;
014:
015: import javax.servlet.http.HttpServletRequest;
016: import javax.servlet.http.HttpServletResponse;
017:
018: import org.xins.common.collections.BasicPropertyReader;
019: import org.xins.common.text.TextUtils;
020: import org.xins.common.xml.Element;
021:
022: /**
023: * XML calling convention.
024: *
025: * @version $Revision: 1.48 $ $Date: 2007/09/18 08:45:03 $
026: * @author <a href="mailto:anthony.goubard@japplis.com">Anthony Goubard</a>
027: */
028: public class XMLCallingConvention extends CallingConvention {
029:
030: /**
031: * The response encoding format.
032: */
033: protected static final String RESPONSE_ENCODING = "UTF-8";
034:
035: /**
036: * The content type of the HTTP response.
037: */
038: protected static final String RESPONSE_CONTENT_TYPE = "text/xml; charset="
039: + RESPONSE_ENCODING;
040:
041: protected String[] getSupportedMethods() {
042: return new String[] { "POST" };
043: }
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: * @throws Exception
060: * if analysis of the request causes an exception;
061: * <code>false</code> will be assumed.
062: */
063: protected boolean matches(HttpServletRequest httpRequest)
064: throws Exception {
065:
066: // Parse the XML in the request (if any)
067: Element element = parseXMLRequest(httpRequest);
068:
069: return element.getLocalName().equals("request")
070: && element.getAttribute("function") != null;
071: }
072:
073: /**
074: * Converts an HTTP request to a XINS request (implementation method). This
075: * method should only be called from class CallingConvention. Only
076: * then it is guaranteed that the <code>httpRequest</code> argument is not
077: * <code>null</code>.
078: *
079: * @param httpRequest
080: * the HTTP request, will not be <code>null</code>.
081: *
082: * @return
083: * the XINS request object, never <code>null</code>.
084: *
085: * @throws InvalidRequestException
086: * if the request is considerd to be invalid.
087: *
088: * @throws FunctionNotSpecifiedException
089: * if the request does not indicate the name of the function to execute.
090: */
091: protected FunctionRequest convertRequestImpl(
092: HttpServletRequest httpRequest)
093: throws InvalidRequestException,
094: FunctionNotSpecifiedException {
095:
096: Element requestElem = parseXMLRequest(httpRequest);
097:
098: String functionName = requestElem.getAttribute("function");
099:
100: // Determine function parameters
101: BasicPropertyReader functionParams = new BasicPropertyReader();
102: Iterator parameters = requestElem.getChildElements("param")
103: .iterator();
104: while (parameters.hasNext()) {
105: Element nextParam = (Element) parameters.next();
106: String name = nextParam.getAttribute("name");
107: String value = nextParam.getText();
108: functionParams.set(name, value);
109: }
110:
111: // Check if function is specified
112: if (TextUtils.isEmpty(functionName)) {
113: throw new FunctionNotSpecifiedException();
114: }
115:
116: // Remove all invalid parameters
117: cleanUpParameters(functionParams);
118:
119: // Get data section
120: Element dataElement = null;
121: List dataElementList = requestElem.getChildElements("data");
122: if (dataElementList.size() == 1) {
123: dataElement = (Element) dataElementList.get(0);
124: } else if (dataElementList.size() > 1) {
125: throw new InvalidRequestException(
126: "Found multiple data sections.");
127: }
128:
129: return new FunctionRequest(functionName, functionParams,
130: dataElement);
131: }
132:
133: /**
134: * Converts a XINS result to an HTTP response (implementation method).
135: *
136: * @param xinsResult
137: * the XINS result object that should be converted to an HTTP response,
138: * will not be <code>null</code>.
139: *
140: * @param httpResponse
141: * the HTTP response object to configure, will not be <code>null</code>.
142: *
143: * @param httpRequest
144: * the HTTP request, will not be <code>null</code>.
145: *
146: * @throws IOException
147: * if calling any of the methods in <code>httpResponse</code> causes an
148: * I/O error.
149: */
150: protected void convertResultImpl(FunctionResult xinsResult,
151: HttpServletResponse httpResponse,
152: HttpServletRequest httpRequest) throws IOException {
153:
154: // Send the XML output to the stream and flush
155: httpResponse.setContentType(RESPONSE_CONTENT_TYPE);
156: PrintWriter out = httpResponse.getWriter();
157: httpResponse.setStatus(HttpServletResponse.SC_OK);
158: CallResultOutputter.output(out, xinsResult);
159: out.close();
160: }
161: }
|