1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shindig.social.opensocial.service;
19
20 import org.apache.shindig.auth.SecurityToken;
21 import org.apache.shindig.common.util.JsonConversionUtil;
22 import org.apache.shindig.social.ResponseError;
23 import org.apache.shindig.social.opensocial.spi.DataCollection;
24 import org.apache.shindig.social.opensocial.spi.RestfulCollection;
25
26 import com.google.common.collect.Lists;
27 import org.apache.commons.io.IOUtils;
28 import org.apache.commons.lang.StringUtils;
29 import org.json.JSONArray;
30 import org.json.JSONException;
31 import org.json.JSONObject;
32
33 import java.io.IOException;
34 import java.util.List;
35 import java.util.concurrent.Future;
36 import javax.servlet.ServletException;
37 import javax.servlet.http.HttpServletRequest;
38 import javax.servlet.http.HttpServletResponse;
39
40 /***
41 * JSON-RPC handler servlet.
42 */
43 public class JsonRpcServlet extends ApiServlet {
44
45 @Override
46 protected void doGet(HttpServletRequest servletRequest,
47 HttpServletResponse servletResponse)
48 throws ServletException, IOException {
49 SecurityToken token = getSecurityToken(servletRequest);
50 if (token == null) {
51 sendSecurityError(servletResponse);
52 return;
53 }
54
55 try {
56 setCharacterEncodings(servletRequest, servletResponse);
57 JSONObject request = JsonConversionUtil.fromRequest(servletRequest);
58 dispatch(request, servletRequest, servletResponse, token);
59 } catch (JSONException je) {
60
61 }
62 }
63
64 @Override
65 protected void doPost(HttpServletRequest servletRequest,
66 HttpServletResponse servletResponse)
67 throws ServletException, IOException {
68 SecurityToken token = getSecurityToken(servletRequest);
69 if (token == null) {
70 sendSecurityError(servletResponse);
71 return;
72 }
73
74 setCharacterEncodings(servletRequest, servletResponse);
75 servletResponse.setContentType("application/json");
76
77 try {
78 String content = IOUtils.toString(servletRequest.getInputStream(),
79 servletRequest.getCharacterEncoding());
80 if ((content.indexOf('[') != -1) && content.indexOf('[') < content.indexOf('{')) {
81
82 JSONArray batch = new JSONArray(content);
83 dispatchBatch(batch, servletRequest, servletResponse, token);
84 } else {
85 JSONObject request = new JSONObject(content);
86 dispatch(request, servletRequest, servletResponse, token);
87 }
88 } catch (JSONException je) {
89 sendBadRequest(je, servletResponse);
90 }
91 }
92
93 protected void dispatchBatch(JSONArray batch, HttpServletRequest servletRequest,
94 HttpServletResponse servletResponse, SecurityToken token) throws JSONException, IOException {
95
96 List<Future<?>> responses = Lists.newArrayListWithExpectedSize(batch.length());
97
98
99
100
101
102 for (int i = 0; i < batch.length(); i++) {
103 JSONObject batchObj = batch.getJSONObject(i);
104 RpcRequestItem requestItem = new RpcRequestItem(batchObj, token, jsonConverter);
105 responses.add(handleRequestItem(requestItem, servletRequest));
106 }
107
108
109
110 JSONArray result = new JSONArray();
111 for (int i = 0; i < batch.length(); i++) {
112 JSONObject batchObj = batch.getJSONObject(i);
113 String key = null;
114 if (batchObj.has("id")) {
115 key = batchObj.getString("id");
116 }
117 result.put(getJSONResponse(key, getResponseItem(responses.get(i))));
118 }
119 servletResponse.getWriter().write(result.toString());
120 }
121
122 protected void dispatch(JSONObject request, HttpServletRequest servletRequest,
123 HttpServletResponse servletResponse, SecurityToken token) throws JSONException, IOException {
124 String key = null;
125 if (request.has("id")) {
126 key = request.getString("id");
127 }
128 RpcRequestItem requestItem = new RpcRequestItem(request, token, jsonConverter);
129
130
131
132 ResponseItem response = getResponseItem(handleRequestItem(requestItem, servletRequest));
133 JSONObject result = getJSONResponse(key, response);
134 servletResponse.getWriter().write(result.toString());
135 }
136
137 private JSONObject getJSONResponse(String key, ResponseItem responseItem) throws JSONException {
138 JSONObject result = new JSONObject();
139 if (key != null) {
140 result.put("id", key);
141 }
142 if (responseItem.getError() != null) {
143 result.put("error", getErrorJson(responseItem));
144 } else {
145 Object response = responseItem.getResponse();
146 JSONObject converted = (JSONObject) jsonConverter.convertToJson(response);
147
148 if (response instanceof RestfulCollection) {
149
150 converted.put("list", converted.remove("entry"));
151 result.put("data", converted);
152 } else if (response instanceof DataCollection) {
153 if (converted.has("entry")) {
154 result.put("data", converted.get("entry"));
155 }
156 } else {
157 result.put("data", converted);
158 }
159 }
160 return result;
161 }
162
163
164
165
166 private JSONObject getErrorJson(ResponseItem responseItem) throws JSONException {
167 JSONObject error = new JSONObject();
168 error.put("code", responseItem.getError().getHttpErrorCode());
169
170 String message = responseItem.getError().toString();
171 if (StringUtils.isNotBlank(responseItem.getErrorMessage())) {
172 message += ": " + responseItem.getErrorMessage();
173 }
174 error.put("message", message);
175 return error;
176 }
177
178 @Override
179 protected void sendError(HttpServletResponse servletResponse, ResponseItem responseItem)
180 throws IOException {
181 try {
182 JSONObject error = getErrorJson(responseItem);
183 servletResponse.getWriter().write(error.toString());
184 } catch (JSONException je) {
185
186 servletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
187 "Error generating error response " + je.getMessage());
188 }
189 }
190
191 private void sendBadRequest(Throwable t, HttpServletResponse response) throws IOException {
192 sendError(response, new ResponseItem(ResponseError.BAD_REQUEST,
193 "Invalid batch - " + t.getMessage()));
194 }
195 }