001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.resiliency.spi.agent;
016    
017    import com.liferay.portal.kernel.io.AutoDeleteFileInputStream;
018    import com.liferay.portal.kernel.resiliency.spi.SPIUtil;
019    import com.liferay.portal.kernel.resiliency.spi.agent.annotation.Direction;
020    import com.liferay.portal.kernel.servlet.PersistentHttpServletRequestWrapper;
021    import com.liferay.portal.kernel.servlet.ServletInputStreamAdapter;
022    import com.liferay.portal.kernel.upload.FileItem;
023    import com.liferay.portal.kernel.upload.UploadServletRequest;
024    import com.liferay.portal.kernel.util.ArrayUtil;
025    import com.liferay.portal.kernel.util.ContentTypes;
026    import com.liferay.portal.kernel.util.CookieUtil;
027    import com.liferay.portal.kernel.util.FileUtil;
028    import com.liferay.portal.kernel.util.SetUtil;
029    import com.liferay.portal.kernel.util.StreamUtil;
030    import com.liferay.portal.kernel.util.StringBundler;
031    import com.liferay.portal.kernel.util.StringPool;
032    import com.liferay.portal.kernel.util.StringUtil;
033    import com.liferay.portal.model.Portlet;
034    import com.liferay.portal.theme.ThemeDisplay;
035    import com.liferay.portal.upload.UploadServletRequestImpl;
036    import com.liferay.portal.util.WebKeys;
037    
038    import java.io.File;
039    import java.io.FileOutputStream;
040    import java.io.IOException;
041    import java.io.Serializable;
042    
043    import java.util.Arrays;
044    import java.util.Collections;
045    import java.util.Enumeration;
046    import java.util.HashMap;
047    import java.util.List;
048    import java.util.Map;
049    import java.util.Set;
050    
051    import javax.servlet.ServletInputStream;
052    import javax.servlet.http.Cookie;
053    import javax.servlet.http.HttpServletRequest;
054    import javax.servlet.http.HttpServletRequestWrapper;
055    import javax.servlet.http.HttpSession;
056    
057    /**
058     * @author Shuyang Zhou
059     */
060    public class SPIAgentRequest extends SPIAgentSerializable {
061    
062            public static void populatePortletSessionAttributes(
063                    HttpServletRequest request, HttpSession session) {
064    
065                    if (!SPIUtil.isSPI()) {
066                            return;
067                    }
068    
069                    if (request.getAttribute(WebKeys.PORTLET_SESSION) != null) {
070                            return;
071                    }
072    
073                    SPIAgentRequest spiAgentRequest = (SPIAgentRequest)request.getAttribute(
074                            WebKeys.SPI_AGENT_REQUEST);
075    
076                    if (spiAgentRequest == null) {
077                            return;
078                    }
079    
080                    request.setAttribute(WebKeys.PORTLET_SESSION, session);
081    
082                    Map<String, Serializable> originalSessionAttributes =
083                            spiAgentRequest.originalSessionAttributes;
084    
085                    Map<String, Serializable> portletSessionAttributes =
086                            (Map<String, Serializable>)originalSessionAttributes.remove(
087                                    WebKeys.PORTLET_SESSION_ATTRIBUTES.concat(
088                                            spiAgentRequest.servletContextName));
089    
090                    Set<String> sessionAttributeNames = SetUtil.fromEnumeration(
091                            session.getAttributeNames());
092    
093                    if (portletSessionAttributes != null) {
094                            for (Map.Entry<String, Serializable> entry :
095                                            portletSessionAttributes.entrySet()) {
096    
097                                    session.setAttribute(entry.getKey(), entry.getValue());
098                            }
099    
100                            sessionAttributeNames.removeAll(portletSessionAttributes.keySet());
101                    }
102    
103                    for (String sessionAttributeName : sessionAttributeNames) {
104                            session.removeAttribute(sessionAttributeName);
105                    }
106            }
107    
108            public SPIAgentRequest(HttpServletRequest request) throws IOException {
109                    super(
110                            ((Portlet)request.getAttribute(
111                                    WebKeys.SPI_AGENT_PORTLET)).getContextName());
112    
113                    cookies = request.getCookies();
114                    distributedRequestAttributes = extractDistributedRequestAttributes(
115                            request, Direction.REQUEST);
116                    headerMap = extractRequestHeaders(request);
117                    parameterMap = request.getParameterMap();
118                    serverName = request.getServerName();
119                    serverPort = request.getServerPort();
120    
121                    String contentType = request.getContentType();
122    
123                    if ((contentType != null) &&
124                            contentType.startsWith(ContentTypes.MULTIPART)) {
125    
126                            HttpServletRequest currentRequest = request;
127    
128                            UploadServletRequest uploadServletRequest = null;
129    
130                            while (currentRequest instanceof HttpServletRequestWrapper) {
131                                    if (currentRequest instanceof UploadServletRequest) {
132                                            uploadServletRequest = (UploadServletRequest)currentRequest;
133    
134                                            break;
135                                    }
136    
137                                    HttpServletRequestWrapper httpServletRequestWrapper =
138                                            (HttpServletRequestWrapper)currentRequest;
139    
140                                    currentRequest =
141                                            (HttpServletRequest)httpServletRequestWrapper.getRequest();
142                            }
143    
144                            if (uploadServletRequest == null) {
145                                    this.contentType = contentType;
146    
147                                    requestBodyFile = FileUtil.createTempFile();
148    
149                                    FileOutputStream fileOutputStream = new FileOutputStream(
150                                            requestBodyFile);
151    
152                                    try {
153                                            StreamUtil.transfer(
154                                                    currentRequest.getInputStream(), fileOutputStream,
155                                                    false);
156                                    }
157                                    finally {
158                                            fileOutputStream.close();
159                                    }
160    
161                                    uploadServletRequest = new UploadServletRequestImpl(
162                                            new AgentHttpServletRequestWrapper(currentRequest));
163                            }
164    
165                            Map<String, FileItem[]> multipartParameterMap =
166                                    uploadServletRequest.getMultipartParameterMap();
167                            Map<String, List<String>> regularParameterMap =
168                                    uploadServletRequest.getRegularParameterMap();
169    
170                            if (!multipartParameterMap.isEmpty()) {
171                                    this.multipartParameterMap = multipartParameterMap;
172                            }
173    
174                            if (!regularParameterMap.isEmpty()) {
175                                    this.regularParameterMap = regularParameterMap;
176                            }
177                    }
178    
179                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
180                            WebKeys.THEME_DISPLAY);
181    
182                    if ((themeDisplay != null) && themeDisplay.isAjax()) {
183                            parameterMap = new HashMap<String, String[]>(parameterMap);
184    
185                            parameterMap.put(
186                                    "portalResiliencyPortletShowFooter",
187                                    new String[] {StringPool.FALSE});
188                    }
189    
190                    originalSessionAttributes = extractSessionAttributes(request);
191    
192                    captureThreadLocals();
193            }
194    
195            public Map<String, Serializable> getOriginalSessionAttributes() {
196                    return originalSessionAttributes;
197            }
198    
199            public HttpServletRequest populateRequest(HttpServletRequest request) {
200                    request = new AgentHttpServletRequestWrapper(request);
201    
202                    for (Map.Entry<String, Serializable> entry :
203                                    distributedRequestAttributes.entrySet()) {
204    
205                            request.setAttribute(entry.getKey(), entry.getValue());
206                    }
207    
208                    if ((multipartParameterMap != null) || (regularParameterMap != null)) {
209                            request = new UploadServletRequestImpl(
210                                    request, multipartParameterMap, regularParameterMap);
211                    }
212    
213                    restoreThreadLocals();
214    
215                    return request;
216            }
217    
218            public void populateSessionAttributes(HttpSession session) {
219                    for (Map.Entry<String, Serializable> entry :
220                                    originalSessionAttributes.entrySet()) {
221    
222                            session.setAttribute(entry.getKey(), entry.getValue());
223                    }
224            }
225    
226            @Override
227            public String toString() {
228                    int length = 20 + parameterMap.size() * 4;
229    
230                    if (cookies != null) {
231                            length += cookies.length * 2 - 1;
232                    }
233    
234                    StringBundler sb = new StringBundler(length);
235    
236                    sb.append("{contentType=");
237                    sb.append(contentType);
238                    sb.append(", cookies=[");
239    
240                    if (cookies != null) {
241                            for (Cookie cookie : cookies) {
242                                    sb.append(CookieUtil.toString(cookie));
243                                    sb.append(", ");
244                            }
245    
246                            sb.setIndex(sb.index() - 1);
247                    }
248    
249                    sb.append("], distributedRequestAttributes=");
250                    sb.append(distributedRequestAttributes);
251                    sb.append(", headerMap=");
252                    sb.append(headerMap);
253                    sb.append(", multipartParameterMap=");
254                    sb.append(multipartParameterMap);
255                    sb.append(", originalSessionAttributes=");
256                    sb.append(originalSessionAttributes);
257                    sb.append(", parameterMap={");
258    
259                    for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
260                            sb.append(entry.getKey());
261                            sb.append("=");
262                            sb.append(Arrays.toString(entry.getValue()));
263                            sb.append(", ");
264                    }
265    
266                    sb.setIndex(sb.index() - 1);
267    
268                    sb.append("}, regularParameterMap=");
269                    sb.append(regularParameterMap);
270                    sb.append(", requestBodyFile=");
271                    sb.append(requestBodyFile);
272                    sb.append(", serverName=");
273                    sb.append(serverName);
274                    sb.append(", serverPort=");
275                    sb.append(serverPort);
276                    sb.append("}");
277    
278                    return sb.toString();
279            }
280    
281            protected String contentType;
282            protected Cookie[] cookies;
283            protected Map<String, Serializable> distributedRequestAttributes;
284            protected Map<String, List<String>> headerMap;
285            protected Map<String, FileItem[]> multipartParameterMap;
286            protected Map<String, Serializable> originalSessionAttributes;
287            protected Map<String, String[]> parameterMap;
288            protected Map<String, List<String>> regularParameterMap;
289            protected File requestBodyFile;
290            protected String serverName;
291            protected int serverPort;
292    
293            protected class AgentHttpServletRequestWrapper
294                    extends PersistentHttpServletRequestWrapper {
295    
296                    public AgentHttpServletRequestWrapper(HttpServletRequest request) {
297                            super(request);
298                    }
299    
300                    @Override
301                    public int getContentLength() {
302                            if (requestBodyFile != null) {
303                                    return (int)requestBodyFile.length();
304                            }
305    
306                            return super.getContentLength();
307                    }
308    
309                    @Override
310                    public String getContentType() {
311                            if (contentType != null) {
312                                    return contentType;
313                            }
314    
315                            return super.getContentType();
316                    }
317    
318                    @Override
319                    public Cookie[] getCookies() {
320                            return cookies;
321                    }
322    
323                    @Override
324                    public String getHeader(String name) {
325                            List<String> values = headerMap.get(StringUtil.toLowerCase(name));
326    
327                            if ((values == null) || values.isEmpty()) {
328                                    return null;
329                            }
330    
331                            return values.get(0);
332                    }
333    
334                    @Override
335                    public Enumeration<String> getHeaderNames() {
336                            return Collections.enumeration(headerMap.keySet());
337                    }
338    
339                    @Override
340                    public Enumeration<String> getHeaders(String name) {
341                            List<String> values = headerMap.get(StringUtil.toLowerCase(name));
342    
343                            if (values == null) {
344                                    values = Collections.emptyList();
345                            }
346    
347                            return Collections.enumeration(values);
348                    }
349    
350                    @Override
351                    public ServletInputStream getInputStream() throws IOException {
352                            if (requestBodyFile != null) {
353                                    return new ServletInputStreamAdapter(
354                                            new AutoDeleteFileInputStream(requestBodyFile));
355                            }
356    
357                            return super.getInputStream();
358                    }
359    
360                    @Override
361                    public String getParameter(String name) {
362                            String[] values = parameterMap.get(name);
363    
364                            if (ArrayUtil.isNotEmpty(values)) {
365                                    return values[0];
366                            }
367                            else {
368                                    return null;
369                            }
370                    }
371    
372                    @Override
373                    public Map<String, String[]> getParameterMap() {
374                            return parameterMap;
375                    }
376    
377                    @Override
378                    public Enumeration<String> getParameterNames() {
379                            return Collections.enumeration(parameterMap.keySet());
380                    }
381    
382                    @Override
383                    public String[] getParameterValues(String name) {
384                            return parameterMap.get(name);
385                    }
386    
387                    @Override
388                    public String getServerName() {
389                            return serverName;
390                    }
391    
392                    @Override
393                    public int getServerPort() {
394                            return serverPort;
395                    }
396    
397            }
398    
399    }