001: /*
002: * $Id: JSONCallingConvention.java,v 1.6 2007/09/18 08:45:06 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 javax.servlet.http.HttpServletRequest;
013: import javax.servlet.http.HttpServletResponse;
014:
015: import org.json.JSONException;
016: import org.json.JSONObject;
017: import org.json.XML;
018:
019: import org.xins.common.collections.BasicPropertyReader;
020: import org.xins.common.text.ParseException;
021: import org.xins.common.text.TextUtils;
022: import org.xins.common.xml.Element;
023: import org.xins.common.xml.ElementParser;
024:
025: /**
026: * The JSON calling convention.
027: *
028: * This version support Yahoo style JSON calls.
029: * For the definition of the calling convention, look at
030: * http://developer.yahoo.com/common/json.html
031: *
032: * This calling convention could be used for example with Google Web Toolkit.
033: * For an example, look at
034: * http://code.google.com/webtoolkit/documentation/examples/jsonrpc/
035: *
036: * @since XINS 2.0.
037: * @version $Revision: 1.6 $ $Date: 2007/09/18 08:45:06 $
038: * @author <a href="mailto:anthony.goubard@japplis.com">Anthony Goubard</a>
039: */
040: public class JSONCallingConvention extends CallingConvention {
041:
042: /**
043: * The response encoding format.
044: */
045: protected static final String RESPONSE_ENCODING = "UTF-8";
046:
047: /**
048: * The content type of the HTTP response.
049: */
050: protected static final String RESPONSE_CONTENT_TYPE = "text/javascript; charset="
051: + RESPONSE_ENCODING + "";
052:
053: protected String[] getSupportedMethods() {
054: return new String[] { "GET", "POST" };
055: }
056:
057: protected boolean matches(HttpServletRequest httpRequest) {
058:
059: String pathInfo = httpRequest.getPathInfo();
060: return "json".equals(httpRequest.getParameter("output"))
061: && !TextUtils.isEmpty(pathInfo)
062: && !pathInfo.endsWith("/");
063: }
064:
065: protected FunctionRequest convertRequestImpl(
066: HttpServletRequest httpRequest)
067: throws InvalidRequestException,
068: FunctionNotSpecifiedException {
069:
070: // Parse the parameters in the HTTP request
071: BasicPropertyReader params = gatherParams(httpRequest);
072:
073: // Remove all invalid parameters
074: cleanUpParameters(params);
075:
076: // Determine function name
077: String pathInfo = httpRequest.getPathInfo();
078: if (TextUtils.isEmpty(pathInfo) || pathInfo.endsWith("/")) {
079: throw new FunctionNotSpecifiedException();
080: }
081: String functionName = pathInfo.substring(pathInfo
082: .lastIndexOf("/") + 1);
083:
084: Element dataElement = null;
085: String dataString = httpRequest.getParameter("_data");
086: if (!TextUtils.isEmpty(dataString)) {
087: try {
088: JSONObject dataSectionObject = new JSONObject(
089: dataString);
090: String dataSectionString = XML
091: .toString(dataSectionObject);
092: dataElement = new ElementParser()
093: .parse(dataSectionString);
094: } catch (JSONException jsonex) {
095: throw new InvalidRequestException(
096: "Invalid JSON input data section.", jsonex);
097: } catch (ParseException pex) {
098: throw new InvalidRequestException(
099: "Invalid XML created from JSON object.", pex);
100: }
101: }
102:
103: return new FunctionRequest(functionName, params, dataElement);
104: }
105:
106: protected void convertResultImpl(FunctionResult xinsResult,
107: HttpServletResponse httpResponse,
108: HttpServletRequest httpRequest) throws IOException {
109:
110: // Send the XML output to the stream and flush
111: httpResponse.setContentType(RESPONSE_CONTENT_TYPE);
112: PrintWriter out = httpResponse.getWriter();
113: httpResponse.setStatus(HttpServletResponse.SC_OK);
114:
115: try {
116: JSONObject jsonResult = JSONRPCCallingConvention
117: .createResultObject(xinsResult);
118: if (xinsResult.getErrorCode() != null) {
119: jsonResult.put("errorCode", xinsResult.getErrorCode());
120: }
121: String callback = httpRequest.getParameter("callback");
122: if (!TextUtils.isEmpty(callback)) {
123: out.print(callback + "(");
124: }
125: String jsonString = jsonResult.toString();
126: out.print(jsonString);
127: if (!TextUtils.isEmpty(callback)) {
128: out.print(")");
129: }
130: } catch (JSONException jsonex) {
131: throw new IOException(jsonex.getMessage());
132: }
133:
134: out.close();
135: }
136: }
|