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 for (Map.Entry<String, Object> entry : oldParameterMap.entrySet()) {
201 newParameterMap.put(
202 entry.getKey(), String.valueOf(entry.getValue()));
203 }
204
205 return newParameterMap;
206 }
207
208 protected PollerHeader getPollerHeader(
209 Map<String, Object>[] pollerRequestChunks)
210 throws Exception {
211
212 if (pollerRequestChunks.length < 1) {
213 return null;
214 }
215
216 Map<String, Object> pollerRequestChunk = pollerRequestChunks[0];
217
218 long companyId = GetterUtil.getLong(
219 String.valueOf(pollerRequestChunk.get("companyId")));
220 String userIdString = GetterUtil.getString(
221 String.valueOf(pollerRequestChunk.get("userId")));
222 long browserKey = GetterUtil.getLong(
223 String.valueOf(pollerRequestChunk.get("browserKey")));
224 String[] portletIds = StringUtil.split(
225 String.valueOf(pollerRequestChunk.get("portletIds")));
226 boolean initialRequest = GetterUtil.getBoolean(
227 String.valueOf(pollerRequestChunk.get("initialRequest")));
228 boolean startPolling = GetterUtil.getBoolean(
229 String.valueOf(pollerRequestChunk.get("startPolling")));
230
231 long userId = getUserId(companyId, userIdString);
232
233 if (userId == 0) {
234 return null;
235 }
236
237 return new PollerHeader(
238 userId, browserKey, portletIds, initialRequest, startPolling);
239 }
240
241 protected String getPollerRequest(HttpServletRequest request)
242 throws Exception {
243
244 String pollerRequest = ParamUtil.getString(request, "pollerRequest");
245
246 if (Validator.isNull(pollerRequest)) {
247 return null;
248 }
249
250 return StringUtil.replace(
251 pollerRequest,
252 new String[] {
253 StringPool.OPEN_CURLY_BRACE,
254 StringPool.CLOSE_CURLY_BRACE,
255 _ESCAPED_OPEN_CURLY_BRACE,
256 _ESCAPED_CLOSE_CURLY_BRACE
257 },
258 new String[] {
259 _OPEN_HASH_MAP_WRAPPER,
260 StringPool.DOUBLE_CLOSE_CURLY_BRACE,
261 StringPool.OPEN_CURLY_BRACE,
262 StringPool.CLOSE_CURLY_BRACE
263 });
264 }
265
266 protected long getUserId(long companyId, String userIdString) {
267 long userId = 0;
268
269 try {
270 Company company = CompanyLocalServiceUtil.getCompany(companyId);
271
272 userId = GetterUtil.getLong(
273 Encryptor.decrypt(company.getKeyObj(), userIdString));
274 }
275 catch (Exception e) {
276 _log.error(
277 "Invalid credentials for company id " + companyId +
278 " and user id " + userIdString);
279 }
280
281 return userId;
282 }
283
284 protected boolean isDoReceive(HttpServletRequest request)
285 throws Exception {
286
287 String path = GetterUtil.getString(request.getPathInfo());
288
289 if (path.endsWith("/receive")) {
290 return true;
291 }
292 else {
293 return false;
294 }
295 }
296
297 protected void process(
298 boolean doReceive, JSONArray pollerResponseChunksJSON,
299 Set<String> portletIdsWithChunks, PollerHeader pollerHeader,
300 String portletId, Map<String, String> parameterMap, String chunkId)
301 throws Exception {
302
303 PollerProcessor pollerProcessor =
304 PollerProcessorUtil.getPollerProcessor(portletId);
305
306 if (pollerProcessor == null) {
307 _log.error("Poller processor not found for portlet " + portletId);
308
309 return;
310 }
311
312 PollerRequest pollerRequest = new PollerRequest(
313 pollerHeader, portletId, parameterMap, chunkId);
314
315 if (doReceive) {
316 PollerResponse pollerResponse = new PollerResponse(
317 portletId, chunkId);
318
319 pollerProcessor.receive(pollerRequest, pollerResponse);
320
321 pollerResponseChunksJSON.put(pollerResponse.toJSONObject());
322 portletIdsWithChunks.add(portletId);
323 }
324 else {
325 pollerProcessor.send(pollerRequest);
326 }
327 }
328
329 private static final String _ESCAPED_CLOSE_CURLY_BRACE =
330 "[$CLOSE_CURLY_BRACE$]";
331
332 private static final String _ESCAPED_OPEN_CURLY_BRACE =
333 "[$OPEN_CURLY_BRACE$]";
334
335 private static final String _OPEN_HASH_MAP_WRAPPER =
336 "{\"javaClass\":\"java.util.HashMap\",\"map\":{";
337
338 private static Log _log = LogFactoryUtil.getLog(PollerServlet.class);
339
340 }