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