1
22
23 package com.liferay.portal.poller;
24
25 import com.liferay.portal.NoSuchLayoutException;
26 import com.liferay.portal.kernel.json.JSONArray;
27 import com.liferay.portal.kernel.json.JSONFactoryUtil;
28 import com.liferay.portal.kernel.json.JSONObject;
29 import com.liferay.portal.kernel.log.Log;
30 import com.liferay.portal.kernel.log.LogFactoryUtil;
31 import com.liferay.portal.kernel.poller.PollerHeader;
32 import com.liferay.portal.kernel.poller.PollerProcessor;
33 import com.liferay.portal.kernel.poller.PollerRequest;
34 import com.liferay.portal.kernel.poller.PollerResponse;
35 import com.liferay.portal.kernel.util.ContentTypes;
36 import com.liferay.portal.kernel.util.GetterUtil;
37 import com.liferay.portal.kernel.util.ParamUtil;
38 import com.liferay.portal.kernel.util.StringPool;
39 import com.liferay.portal.kernel.util.StringUtil;
40 import com.liferay.portal.kernel.util.Validator;
41 import com.liferay.portal.model.BrowserTracker;
42 import com.liferay.portal.model.Company;
43 import com.liferay.portal.service.BrowserTrackerLocalServiceUtil;
44 import com.liferay.portal.service.CompanyLocalServiceUtil;
45 import com.liferay.portal.util.PortalUtil;
46 import com.liferay.util.Encryptor;
47 import com.liferay.util.servlet.ServletResponseUtil;
48
49 import java.io.IOException;
50
51 import java.util.HashMap;
52 import java.util.HashSet;
53 import java.util.Map;
54 import java.util.Set;
55
56 import javax.servlet.ServletException;
57 import javax.servlet.http.HttpServlet;
58 import javax.servlet.http.HttpServletRequest;
59 import javax.servlet.http.HttpServletResponse;
60
61
67 public class PollerServlet extends HttpServlet {
68
69 public void service(
70 HttpServletRequest request, HttpServletResponse response)
71 throws IOException, ServletException {
72
73 try {
74 String content = getContent(request);
75
76 if (content == null) {
77 PortalUtil.sendError(
78 HttpServletResponse.SC_NOT_FOUND,
79 new NoSuchLayoutException(), request, response);
80 }
81 else {
82 response.setContentType(ContentTypes.TEXT_PLAIN_UTF8);
83
84 ServletResponseUtil.write(
85 response, content.getBytes(StringPool.UTF8));
86 }
87 }
88 catch (Exception e) {
89 _log.error(e, e);
90
91 PortalUtil.sendError(
92 HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e, request,
93 response);
94 }
95 }
96
97 protected String getContent(HttpServletRequest request) throws Exception {
98 String pollerRequest = getPollerRequest(request);
99
100 if (Validator.isNull(pollerRequest)) {
101 return null;
102 }
103
104 Map<String, Object>[] pollerRequestChunks =
105 (Map<String, Object>[])JSONFactoryUtil.deserialize(pollerRequest);
106
107 PollerHeader pollerHeader = getPollerHeader(pollerRequestChunks);
108
109 if (pollerHeader == null) {
110 return null;
111 }
112
113 boolean doReceive = isDoReceive(request);
114
115 JSONArray pollerResponseChunksJSON = null;
116 Set<String> portletIdsWithChunks = null;
117
118 if (doReceive) {
119 pollerResponseChunksJSON = JSONFactoryUtil.createJSONArray();
120 portletIdsWithChunks = new HashSet<String>();
121
122 boolean suspendPolling = false;
123
124 if (pollerHeader.isStartPolling()) {
125 BrowserTrackerLocalServiceUtil.updateBrowserTracker(
126 pollerHeader.getUserId(), pollerHeader.getBrowserKey());
127 }
128 else {
129 BrowserTracker browserTracker =
130 BrowserTrackerLocalServiceUtil.getBrowserTracker(
131 pollerHeader.getUserId(), pollerHeader.getBrowserKey());
132
133 if (browserTracker.getBrowserKey() !=
134 pollerHeader.getBrowserKey()) {
135
136 suspendPolling = true;
137 }
138 }
139
140 JSONObject pollerResponseChunkJSON =
141 JSONFactoryUtil.createJSONObject();
142
143 pollerResponseChunkJSON.put("userId", pollerHeader.getUserId());
144 pollerResponseChunkJSON.put(
145 "initialRequest", pollerHeader.isInitialRequest());
146 pollerResponseChunkJSON.put("suspendPolling", suspendPolling);
147
148 pollerResponseChunksJSON.put(pollerResponseChunkJSON);
149 }
150
151 for (int i = 1; i < pollerRequestChunks.length; i++) {
152 Map<String, Object> pollerRequestChunk = pollerRequestChunks[i];
153
154 String portletId = (String)pollerRequestChunk.get("portletId");
155 Map<String, String> parameterMap = getData(pollerRequestChunk);
156 String chunkId = (String)pollerRequestChunk.get("chunkId");
157
158 try {
159 process(
160 doReceive, pollerResponseChunksJSON, portletIdsWithChunks,
161 pollerHeader, portletId, parameterMap, chunkId);
162 }
163 catch (Exception e) {
164 _log.error(e, e);
165 }
166 }
167
168 if (!doReceive) {
169 return StringPool.BLANK;
170 }
171
172 for (String portletId : pollerHeader.getPortletIds()) {
173 if (portletIdsWithChunks.contains(portletId)) {
174 continue;
175 }
176
177 try {
178 process(
179 doReceive, pollerResponseChunksJSON, portletIdsWithChunks,
180 pollerHeader, portletId, new HashMap<String, String>(),
181 null);
182 }
183 catch (Exception e) {
184 _log.error(e, e);
185 }
186 }
187
188 return pollerResponseChunksJSON.toString();
189 }
190
191 protected Map<String, String> getData(
192 Map<String, Object> pollerRequestChunk)
193 throws Exception {
194
195 Map<String, Object> oldParameterMap =
196 (Map<String, Object>)pollerRequestChunk.get("data");
197
198 Map<String, String> newParameterMap = new HashMap<String, String>();
199
200 if (oldParameterMap == null) {
201 return newParameterMap;
202 }
203
204 for (Map.Entry<String, Object> entry : oldParameterMap.entrySet()) {
205 newParameterMap.put(
206 entry.getKey(), String.valueOf(entry.getValue()));
207 }
208
209 return newParameterMap;
210 }
211
212 protected PollerHeader getPollerHeader(
213 Map<String, Object>[] pollerRequestChunks)
214 throws Exception {
215
216 if (pollerRequestChunks.length < 1) {
217 return null;
218 }
219
220 Map<String, Object> pollerRequestChunk = pollerRequestChunks[0];
221
222 long companyId = GetterUtil.getLong(
223 String.valueOf(pollerRequestChunk.get("companyId")));
224 String userIdString = GetterUtil.getString(
225 String.valueOf(pollerRequestChunk.get("userId")));
226 long browserKey = GetterUtil.getLong(
227 String.valueOf(pollerRequestChunk.get("browserKey")));
228 String[] portletIds = StringUtil.split(
229 String.valueOf(pollerRequestChunk.get("portletIds")));
230 boolean initialRequest = GetterUtil.getBoolean(
231 String.valueOf(pollerRequestChunk.get("initialRequest")));
232 boolean startPolling = GetterUtil.getBoolean(
233 String.valueOf(pollerRequestChunk.get("startPolling")));
234
235 long userId = getUserId(companyId, userIdString);
236
237 if (userId == 0) {
238 return null;
239 }
240
241 return new PollerHeader(
242 userId, browserKey, portletIds, initialRequest, startPolling);
243 }
244
245 protected String getPollerRequest(HttpServletRequest request)
246 throws Exception {
247
248 String pollerRequest = ParamUtil.getString(request, "pollerRequest");
249
250 if (Validator.isNull(pollerRequest)) {
251 return null;
252 }
253
254 return StringUtil.replace(
255 pollerRequest,
256 new String[] {
257 StringPool.OPEN_CURLY_BRACE,
258 StringPool.CLOSE_CURLY_BRACE,
259 _ESCAPED_OPEN_CURLY_BRACE,
260 _ESCAPED_CLOSE_CURLY_BRACE
261 },
262 new String[] {
263 _OPEN_HASH_MAP_WRAPPER,
264 StringPool.DOUBLE_CLOSE_CURLY_BRACE,
265 StringPool.OPEN_CURLY_BRACE,
266 StringPool.CLOSE_CURLY_BRACE
267 });
268 }
269
270 protected long getUserId(long companyId, String userIdString) {
271 long userId = 0;
272
273 try {
274 Company company = CompanyLocalServiceUtil.getCompany(companyId);
275
276 userId = GetterUtil.getLong(
277 Encryptor.decrypt(company.getKeyObj(), userIdString));
278 }
279 catch (Exception e) {
280 _log.error(
281 "Invalid credentials for company id " + companyId +
282 " and user id " + userIdString);
283 }
284
285 return userId;
286 }
287
288 protected boolean isDoReceive(HttpServletRequest request)
289 throws Exception {
290
291 String path = GetterUtil.getString(request.getPathInfo());
292
293 if (path.endsWith("/receive")) {
294 return true;
295 }
296 else {
297 return false;
298 }
299 }
300
301 protected void process(
302 boolean doReceive, JSONArray pollerResponseChunksJSON,
303 Set<String> portletIdsWithChunks, PollerHeader pollerHeader,
304 String portletId, Map<String, String> parameterMap, String chunkId)
305 throws Exception {
306
307 PollerProcessor pollerProcessor =
308 PollerProcessorUtil.getPollerProcessor(portletId);
309
310 if (pollerProcessor == null) {
311 _log.error("Poller processor not found for portlet " + portletId);
312
313 return;
314 }
315
316 PollerRequest pollerRequest = new PollerRequest(
317 pollerHeader, portletId, parameterMap, chunkId);
318
319 if (doReceive) {
320 PollerResponse pollerResponse = new PollerResponse(
321 portletId, chunkId);
322
323 pollerProcessor.receive(pollerRequest, pollerResponse);
324
325 pollerResponseChunksJSON.put(pollerResponse.toJSONObject());
326 portletIdsWithChunks.add(portletId);
327 }
328 else {
329 pollerProcessor.send(pollerRequest);
330 }
331 }
332
333 private static final String _ESCAPED_CLOSE_CURLY_BRACE =
334 "[$CLOSE_CURLY_BRACE$]";
335
336 private static final String _ESCAPED_OPEN_CURLY_BRACE =
337 "[$OPEN_CURLY_BRACE$]";
338
339 private static final String _OPEN_HASH_MAP_WRAPPER =
340 "{\"javaClass\":\"java.util.HashMap\",\"map\":{";
341
342 private static Log _log = LogFactoryUtil.getLog(PollerServlet.class);
343
344 }