001: /*
002: * $Id: RESTCallingConvention.java,v 1.4 2007/09/18 11:27:16 agoubard Exp $
003: */
004: package com.mycompany.rest.api;
005:
006: import java.io.IOException;
007: import java.io.Writer;
008: import java.util.Iterator;
009: import java.util.StringTokenizer;
010:
011: import javax.servlet.http.HttpServletRequest;
012: import javax.servlet.http.HttpServletResponse;
013:
014: import org.xins.common.MandatoryArgumentChecker;
015: import org.xins.common.Utils;
016: import org.xins.common.collections.BasicPropertyReader;
017: import org.xins.common.spec.EntityNotFoundException;
018: import org.xins.common.spec.InvalidSpecificationException;
019:
020: import org.xins.server.API;
021: import org.xins.server.CallResultOutputter;
022: import org.xins.server.CustomCallingConvention;
023: import org.xins.server.FunctionNotSpecifiedException;
024: import org.xins.server.FunctionRequest;
025: import org.xins.server.FunctionResult;
026: import org.xins.server.InvalidRequestException;
027:
028: /**
029: * The REST calling convention as describe at http://en.wikipedia.org/wiki/REST.
030: *
031: * @version $Revision: 1.4 $ $Date: 2007/09/18 11:27:16 $
032: * @author <a href="mailto:anthony.goubard@japplis.com">Anthony Goubard</a>
033: */
034: public class RESTCallingConvention extends CustomCallingConvention {
035:
036: /**
037: * The response encoding format.
038: */
039: static final String RESPONSE_ENCODING = "UTF-8";
040:
041: /**
042: * The content type of the HTTP response.
043: */
044: static final String RESPONSE_CONTENT_TYPE = "text/xml; charset="
045: + RESPONSE_ENCODING;
046:
047: /**
048: * The API using this calling convention.
049: */
050: private final API _api;
051:
052: /**
053: * Constructs a new <code>addUserImpl</code> instance.
054: *
055: * @param api
056: * the API, using this calling convention, cannot be <code>null</code>.
057: *
058: * @throws IllegalArgumentException
059: * if <code>api == null</code>.
060: */
061: public RESTCallingConvention(API api)
062: throws IllegalArgumentException {
063: MandatoryArgumentChecker.check("api", api);
064: _api = api;
065: }
066:
067: protected String[] getSupportedMethods() {
068: return new String[] { "GET", "POST", "PUT", "DELETE" };
069: }
070:
071: protected boolean matches(HttpServletRequest httpRequest)
072: throws Exception {
073:
074: return httpRequest.getQueryString() == null;
075: }
076:
077: protected FunctionRequest convertRequestImpl(
078: HttpServletRequest httpRequest)
079: throws InvalidRequestException,
080: FunctionNotSpecifiedException {
081: String restMethod = "";
082: String httpMethod = httpRequest.getMethod().toLowerCase();
083: if (httpMethod.equals("post")) {
084: restMethod = "Update";
085: } else if (httpMethod.equals("put")) {
086: restMethod = "Add";
087: } else if (httpMethod.equals("get")) {
088: restMethod = "Get";
089: } else if (httpMethod.equals("delete")) {
090: restMethod = "Delete";
091: } else {
092: throw Utils.logProgrammingError("Unauthorized method: "
093: + httpMethod);
094: }
095: String path = httpRequest.getContextPath();
096:
097: // Get the first path to know the resource wanted
098: String resourceName = "";
099: StringTokenizer stPaths = new StringTokenizer(path, "/");
100: if (stPaths.hasMoreTokens()) {
101: resourceName = stPaths.nextToken();
102: }
103: String functionName = restMethod
104: + resourceName.substring(0, 1).toUpperCase()
105: + resourceName.substring(1);
106: if (functionName.endsWith("s")) {
107: functionName = functionName.substring(0, functionName
108: .length() - 1);
109: }
110:
111: // Get the arguments of the functions
112: BasicPropertyReader params = new BasicPropertyReader();
113: try {
114: Iterator itInputParameters = _api.getAPISpecification()
115: .getFunction(functionName).getInputParameters()
116: .keySet().iterator();
117: while (itInputParameters.hasNext()
118: && stPaths.hasMoreTokens()) {
119: String nextParamName = (String) itInputParameters
120: .next();
121: String nextArg = stPaths.nextToken();
122: params.set(nextParamName, nextArg);
123: }
124: } catch (InvalidSpecificationException isex) {
125: Utils.logIgnoredException(isex);
126: } catch (EntityNotFoundException enfex) {
127: throw new FunctionNotSpecifiedException();
128: }
129: return new FunctionRequest(functionName, params, null);
130: }
131:
132: protected void convertResultImpl(FunctionResult xinsResult,
133: HttpServletResponse httpResponse,
134: HttpServletRequest httpRequest) throws IOException {
135:
136: // Set the status code and the content type
137: httpResponse.setStatus(HttpServletResponse.SC_OK);
138: httpResponse.setContentType(RESPONSE_CONTENT_TYPE);
139:
140: Writer out = httpResponse.getWriter();
141: CallResultOutputter.output(out, xinsResult);
142: out.close();
143: }
144: }
|