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