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.agent.annotation.Direction;
019    import com.liferay.portal.kernel.servlet.PersistentHttpServletRequestWrapper;
020    import com.liferay.portal.kernel.servlet.ServletInputStreamAdapter;
021    import com.liferay.portal.kernel.upload.FileItem;
022    import com.liferay.portal.kernel.upload.UploadServletRequest;
023    import com.liferay.portal.kernel.util.ArrayUtil;
024    import com.liferay.portal.kernel.util.ContentTypes;
025    import com.liferay.portal.kernel.util.CookieUtil;
026    import com.liferay.portal.kernel.util.FileUtil;
027    import com.liferay.portal.kernel.util.StreamUtil;
028    import com.liferay.portal.kernel.util.StringBundler;
029    import com.liferay.portal.kernel.util.StringPool;
030    import com.liferay.portal.kernel.util.StringUtil;
031    import com.liferay.portal.theme.ThemeDisplay;
032    import com.liferay.portal.upload.UploadServletRequestImpl;
033    import com.liferay.portal.util.WebKeys;
034    
035    import java.io.File;
036    import java.io.FileOutputStream;
037    import java.io.IOException;
038    import java.io.Serializable;
039    
040    import java.util.Arrays;
041    import java.util.Collections;
042    import java.util.Enumeration;
043    import java.util.HashMap;
044    import java.util.List;
045    import java.util.Map;
046    
047    import javax.servlet.ServletInputStream;
048    import javax.servlet.http.Cookie;
049    import javax.servlet.http.HttpServletRequest;
050    import javax.servlet.http.HttpServletRequestWrapper;
051    import javax.servlet.http.HttpSession;
052    
053    /**
054     * @author Shuyang Zhou
055     */
056    public class SPIAgentRequest extends SPIAgentSerializable {
057    
058            public SPIAgentRequest(HttpServletRequest request) throws IOException {
059                    cookies = request.getCookies();
060                    distributedRequestAttributes = extractDistributedRequestAttributes(
061                            request, Direction.REQUEST);
062                    headerMap = extractRequestHeaders(request);
063                    parameterMap = request.getParameterMap();
064                    serverName = request.getServerName();
065                    serverPort = request.getServerPort();
066    
067                    String contentType = request.getContentType();
068    
069                    if ((contentType != null) &&
070                            contentType.startsWith(ContentTypes.MULTIPART)) {
071    
072                            HttpServletRequest currentRequest = request;
073    
074                            UploadServletRequest uploadServletRequest = null;
075    
076                            while (currentRequest instanceof HttpServletRequestWrapper) {
077                                    if (currentRequest instanceof UploadServletRequest) {
078                                            uploadServletRequest = (UploadServletRequest)currentRequest;
079    
080                                            break;
081                                    }
082    
083                                    HttpServletRequestWrapper httpServletRequestWrapper =
084                                            (HttpServletRequestWrapper)currentRequest;
085    
086                                    currentRequest =
087                                            (HttpServletRequest)httpServletRequestWrapper.getRequest();
088                            }
089    
090                            if (uploadServletRequest == null) {
091                                    this.contentType = contentType;
092    
093                                    requestBodyFile = FileUtil.createTempFile();
094    
095                                    FileOutputStream fileOutputStream = new FileOutputStream(
096                                            requestBodyFile);
097    
098                                    try {
099                                            StreamUtil.transfer(
100                                                    currentRequest.getInputStream(), fileOutputStream,
101                                                    false);
102                                    }
103                                    finally {
104                                            fileOutputStream.close();
105                                    }
106    
107                                    uploadServletRequest = new UploadServletRequestImpl(
108                                            new AgentHttpServletRequestWrapper(currentRequest));
109                            }
110    
111                            Map<String, FileItem[]> multipartParameterMap =
112                                    uploadServletRequest.getMultipartParameterMap();
113                            Map<String, List<String>> regularParameterMap =
114                                    uploadServletRequest.getRegularParameterMap();
115    
116                            if (!multipartParameterMap.isEmpty()) {
117                                    this.multipartParameterMap = multipartParameterMap;
118                            }
119    
120                            if (!regularParameterMap.isEmpty()) {
121                                    this.regularParameterMap = regularParameterMap;
122                            }
123                    }
124    
125                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
126                            WebKeys.THEME_DISPLAY);
127    
128                    if ((themeDisplay != null) && themeDisplay.isAjax()) {
129                            parameterMap = new HashMap<String, String[]>(parameterMap);
130    
131                            parameterMap.put(
132                                    "portalResiliencyPortletShowFooter",
133                                    new String[] {StringPool.FALSE});
134                    }
135    
136                    HttpSession session = request.getSession();
137    
138                    originalSessionAttributes = extractSessionAttributes(session);
139    
140                    captureThreadLocals();
141            }
142    
143            public Map<String, Serializable> getOriginalSessionAttributes() {
144                    return originalSessionAttributes;
145            }
146    
147            public HttpServletRequest populateRequest(HttpServletRequest request) {
148                    request = new AgentHttpServletRequestWrapper(request);
149    
150                    for (Map.Entry<String, Serializable> entry :
151                                    distributedRequestAttributes.entrySet()) {
152    
153                            request.setAttribute(entry.getKey(), entry.getValue());
154                    }
155    
156                    if ((multipartParameterMap != null) || (regularParameterMap != null)) {
157                            request = new UploadServletRequestImpl(
158                                    request, multipartParameterMap, regularParameterMap);
159                    }
160    
161                    restoreThreadLocals();
162    
163                    return request;
164            }
165    
166            public void populateSessionAttributes(HttpSession httpSession) {
167                    for (Map.Entry<String, Serializable> entry :
168                                    originalSessionAttributes.entrySet()) {
169    
170                            httpSession.setAttribute(entry.getKey(), entry.getValue());
171                    }
172            }
173    
174            @Override
175            public String toString() {
176                    int length = 20 + parameterMap.size() * 4;
177    
178                    if (cookies != null) {
179                            length += cookies.length * 2 - 1;
180                    }
181    
182                    StringBundler sb = new StringBundler(length);
183    
184                    sb.append("{contentType=");
185                    sb.append(contentType);
186                    sb.append(", cookies=[");
187    
188                    if (cookies != null) {
189                            for (Cookie cookie : cookies) {
190                                    sb.append(CookieUtil.toString(cookie));
191                                    sb.append(", ");
192                            }
193    
194                            sb.setIndex(sb.index() - 1);
195                    }
196    
197                    sb.append("], distributedRequestAttributes=");
198                    sb.append(distributedRequestAttributes);
199                    sb.append(", headerMap=");
200                    sb.append(headerMap);
201                    sb.append(", multipartParameterMap=");
202                    sb.append(multipartParameterMap);
203                    sb.append(", originalSessionAttributes=");
204                    sb.append(originalSessionAttributes);
205                    sb.append(", parameterMap={");
206    
207                    for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
208                            sb.append(entry.getKey());
209                            sb.append("=");
210                            sb.append(Arrays.toString(entry.getValue()));
211                            sb.append(", ");
212                    }
213    
214                    sb.setIndex(sb.index() - 1);
215    
216                    sb.append("}, regularParameterMap=");
217                    sb.append(regularParameterMap);
218                    sb.append(", requestBodyFile=");
219                    sb.append(requestBodyFile);
220                    sb.append(", serverName=");
221                    sb.append(serverName);
222                    sb.append(", serverPort=");
223                    sb.append(serverPort);
224                    sb.append("}");
225    
226                    return sb.toString();
227            }
228    
229            protected String contentType;
230            protected Cookie[] cookies;
231            protected Map<String, Serializable> distributedRequestAttributes;
232            protected Map<String, List<String>> headerMap;
233            protected Map<String, FileItem[]> multipartParameterMap;
234            protected Map<String, Serializable> originalSessionAttributes;
235            protected Map<String, String[]> parameterMap;
236            protected Map<String, List<String>> regularParameterMap;
237            protected File requestBodyFile;
238            protected String serverName;
239            protected int serverPort;
240    
241            protected class AgentHttpServletRequestWrapper
242                    extends PersistentHttpServletRequestWrapper {
243    
244                    public AgentHttpServletRequestWrapper(HttpServletRequest request) {
245                            super(request);
246                    }
247    
248                    @Override
249                    public int getContentLength() {
250                            if (requestBodyFile != null) {
251                                    return (int)requestBodyFile.length();
252                            }
253    
254                            return super.getContentLength();
255                    }
256    
257                    @Override
258                    public String getContentType() {
259                            if (contentType != null) {
260                                    return contentType;
261                            }
262    
263                            return super.getContentType();
264                    }
265    
266                    @Override
267                    public Cookie[] getCookies() {
268                            return cookies;
269                    }
270    
271                    @Override
272                    public String getHeader(String name) {
273                            List<String> values = headerMap.get(StringUtil.toLowerCase(name));
274    
275                            if ((values == null) || values.isEmpty()) {
276                                    return null;
277                            }
278    
279                            return values.get(0);
280                    }
281    
282                    @Override
283                    public Enumeration<String> getHeaderNames() {
284                            return Collections.enumeration(headerMap.keySet());
285                    }
286    
287                    @Override
288                    public Enumeration<String> getHeaders(String name) {
289                            List<String> values = headerMap.get(StringUtil.toLowerCase(name));
290    
291                            if (values == null) {
292                                    values = Collections.emptyList();
293                            }
294    
295                            return Collections.enumeration(values);
296                    }
297    
298                    @Override
299                    public ServletInputStream getInputStream() throws IOException {
300                            if (requestBodyFile != null) {
301                                    return new ServletInputStreamAdapter(
302                                            new AutoDeleteFileInputStream(requestBodyFile));
303                            }
304    
305                            return super.getInputStream();
306                    }
307    
308                    @Override
309                    public String getParameter(String name) {
310                            String[] values = parameterMap.get(name);
311    
312                            if (ArrayUtil.isNotEmpty(values)) {
313                                    return values[0];
314                            }
315                            else {
316                                    return null;
317                            }
318                    }
319    
320                    @Override
321                    public Map<String, String[]> getParameterMap() {
322                            return parameterMap;
323                    }
324    
325                    @Override
326                    public Enumeration<String> getParameterNames() {
327                            return Collections.enumeration(parameterMap.keySet());
328                    }
329    
330                    @Override
331                    public String[] getParameterValues(String name) {
332                            return parameterMap.get(name);
333                    }
334    
335                    @Override
336                    public String getServerName() {
337                            return serverName;
338                    }
339    
340                    @Override
341                    public int getServerPort() {
342                            return serverPort;
343                    }
344    
345            }
346    
347    }