1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
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  /**
62   * <a href="PollerServlet.java.html"><b><i>View Source</i></b></a>
63   *
64   * @author Brian Wing Shun Chan
65   *
66   */
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 = ParamUtil.getString(request, "pollerRequest");
99  
100         if (Validator.isNull(pollerRequest)) {
101             return null;
102         }
103 
104         pollerRequest = StringUtil.replace(
105             pollerRequest,
106             new String[] {
107                 StringPool.OPEN_CURLY_BRACE,
108                 StringPool.CLOSE_CURLY_BRACE,
109             },
110             new String[] {
111                 _OPEN_HASH_MAP_WRAPPER,
112                 StringPool.DOUBLE_CLOSE_CURLY_BRACE
113             });
114 
115         JSONArray pollerResponseChunksJSON = JSONFactoryUtil.createJSONArray();
116 
117         PollerHeader pollerHeader = null;
118 
119         Set<String> portletIdsWithChunks = new HashSet<String>();
120 
121         Map<String, Object>[] pollerRequestChunks =
122             (Map<String, Object>[])JSONFactoryUtil.deserialize(pollerRequest);
123 
124         for (int i = 0; i < pollerRequestChunks.length; i++) {
125             Map<String, Object> pollerRequestChunk = pollerRequestChunks[i];
126 
127             if (i == 0) {
128                 long companyId = GetterUtil.getLong(
129                     String.valueOf(pollerRequestChunk.get("companyId")));
130                 String userIdString = GetterUtil.getString(
131                     String.valueOf(pollerRequestChunk.get("userId")));
132                 long timestamp = GetterUtil.getLong(
133                     String.valueOf(pollerRequestChunk.get("timestamp")));
134                 long browserKey = GetterUtil.getLong(
135                     String.valueOf(pollerRequestChunk.get("browserKey")));
136                 boolean startPolling = GetterUtil.getBoolean(
137                     String.valueOf(pollerRequestChunk.get("startPolling")));
138                 String[] portletIds = StringUtil.split(
139                     String.valueOf(pollerRequestChunk.get("portletIds")));
140 
141                 long userId = getUserId(companyId, userIdString);
142 
143                 if (userId == 0) {
144                     return null;
145                 }
146 
147                 pollerHeader = new PollerHeader(
148                     userId, timestamp, browserKey, portletIds);
149 
150                 boolean suspendPolling = false;
151 
152                 if (startPolling) {
153                     BrowserTrackerLocalServiceUtil.updateBrowserTracker(
154                         userId, browserKey);
155                 }
156                 else {
157                     BrowserTracker browserTracker =
158                         BrowserTrackerLocalServiceUtil.getBrowserTracker(
159                             userId, browserKey);
160 
161                     if (browserTracker.getBrowserKey() != browserKey) {
162                         suspendPolling = true;
163                     }
164                 }
165 
166                 JSONObject pollerResponseChunkJSON =
167                     JSONFactoryUtil.createJSONObject();
168 
169                 pollerResponseChunkJSON.put("userId", userId);
170                 pollerResponseChunkJSON.put("timestamp", timestamp);
171                 pollerResponseChunkJSON.put("suspendPolling", suspendPolling);
172 
173                 pollerResponseChunksJSON.put(pollerResponseChunkJSON);
174             }
175             else {
176                 String portletId = (String)pollerRequestChunk.get("portletId");
177                 Map<String, Object> oldParameterMap =
178                     (Map<String, Object>)pollerRequestChunk.get("data");
179                 String chunkId = (String)pollerRequestChunk.get("chunkId");
180 
181                 Map<String, String> newParameterMap =
182                     new HashMap<String, String>();
183 
184                 for (Map.Entry<String, Object> entry :
185                         oldParameterMap.entrySet()) {
186 
187                     newParameterMap.put(
188                         entry.getKey(), String.valueOf(entry.getValue()));
189                 }
190 
191                 JSONObject pollerResponseChunkJSON = null;
192 
193                 try {
194                     pollerResponseChunkJSON = process(
195                         pollerHeader, portletId, newParameterMap, chunkId);
196                 }
197                 catch (Exception e) {
198                     _log.error(e, e);
199                 }
200 
201                 if (pollerResponseChunkJSON != null) {
202                     portletIdsWithChunks.add(portletId);
203 
204                     pollerResponseChunksJSON.put(pollerResponseChunkJSON);
205                 }
206             }
207         }
208 
209         for (String portletId : pollerHeader.getPortletIds()) {
210             if (portletIdsWithChunks.contains(portletId)) {
211                 continue;
212             }
213 
214             JSONObject pollerResponseChunkJSON = null;
215 
216             try {
217                 pollerResponseChunkJSON = process(
218                     pollerHeader, portletId, new HashMap<String, String>(),
219                     null);
220             }
221             catch (Exception e) {
222                 _log.error(e, e);
223             }
224 
225             if (pollerResponseChunkJSON != null) {
226                 pollerResponseChunksJSON.put(pollerResponseChunkJSON);
227             }
228         }
229 
230         return pollerResponseChunksJSON.toString();
231     }
232 
233     protected long getUserId(long companyId, String userIdString) {
234         long userId = 0;
235 
236         try {
237             Company company = CompanyLocalServiceUtil.getCompany(companyId);
238 
239             userId = GetterUtil.getLong(
240                 Encryptor.decrypt(company.getKeyObj(), userIdString));
241         }
242         catch (Exception e) {
243             _log.error(
244                 "Invalid credentials for company id " + companyId +
245                     " and user id " + userIdString);
246         }
247 
248         return userId;
249     }
250 
251     protected JSONObject process(
252             PollerHeader pollerHeader, String portletId,
253             Map<String, String> parameterMap, String chunkId)
254         throws Exception {
255 
256         PollerProcessor pollerProcessor =
257             PollerProcessorUtil.getPollerProcessor(portletId);
258 
259         if (pollerProcessor == null) {
260             _log.error("Poller processor not found for portlet " + portletId);
261 
262             return null;
263         }
264 
265         PollerRequest pollerRequest = new PollerRequest(
266             pollerHeader, portletId, parameterMap, chunkId);
267         PollerResponse pollerResponse = new PollerResponse(portletId, chunkId);
268 
269         pollerProcessor.process(pollerRequest, pollerResponse);
270 
271         return pollerResponse.toJSONObject();
272     }
273 
274     private static final String _OPEN_HASH_MAP_WRAPPER =
275         "{\"javaClass\":\"java.util.HashMap\",\"map\":{";
276 
277     private static Log _log = LogFactoryUtil.getLog(PollerServlet.class);
278 
279 }