001    /**
002     * Copyright (c) 2000-present 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.servlet;
016    
017    import com.liferay.portal.kernel.servlet.PersistentHttpServletRequestWrapper;
018    import com.liferay.portal.kernel.util.AutoResetThreadLocal;
019    import com.liferay.portal.kernel.util.WebKeys;
020    
021    import java.io.Closeable;
022    
023    import java.util.ArrayList;
024    import java.util.Collections;
025    import java.util.Enumeration;
026    import java.util.List;
027    import java.util.Locale;
028    import java.util.concurrent.locks.Lock;
029    
030    import javax.servlet.RequestDispatcher;
031    import javax.servlet.ServletRequest;
032    import javax.servlet.ServletRequestWrapper;
033    import javax.servlet.http.HttpServletRequest;
034    import javax.servlet.http.HttpSession;
035    
036    /**
037     * @author Shuyang Zhou
038     */
039    public class ThreadLocalFacadeHttpServletRequestWrapper
040            extends PersistentHttpServletRequestWrapper implements Closeable {
041    
042            public ThreadLocalFacadeHttpServletRequestWrapper(
043                    ServletRequestWrapper servletRequestWrapper,
044                    HttpServletRequest httpServletRequest) {
045    
046                    super(httpServletRequest);
047    
048                    _servletRequestWrapper = servletRequestWrapper;
049    
050                    _nextHttpServletRequestThreadLocal.set(httpServletRequest);
051    
052                    _locales = new ArrayList<>();
053    
054                    Enumeration<Locale> enumeration = httpServletRequest.getLocales();
055    
056                    while (enumeration.hasMoreElements()) {
057                            _locales.add(enumeration.nextElement());
058                    }
059            }
060    
061            @Override
062            public void close() {
063                    if (_servletRequestWrapper != null) {
064                            HttpServletRequest nextHttpServletRequest =
065                                    _nextHttpServletRequestThreadLocal.get();
066    
067                            _servletRequestWrapper.setRequest(nextHttpServletRequest);
068                    }
069            }
070    
071            @Override
072            public Object getAttribute(String name) {
073                    ServletRequest servletRequest = getRequest();
074    
075                    return servletRequest.getAttribute(name);
076            }
077    
078            @Override
079            public Enumeration<String> getAttributeNames() {
080                    ServletRequest servletRequest = getRequest();
081    
082                    Lock lock = (Lock)servletRequest.getAttribute(
083                            WebKeys.PARALLEL_RENDERING_MERGE_LOCK);
084    
085                    if (lock != null) {
086                            lock.lock();
087                    }
088    
089                    try {
090                            return servletRequest.getAttributeNames();
091                    }
092                    finally {
093                            if (lock != null) {
094                                    lock.unlock();
095                            }
096                    }
097            }
098    
099            @Override
100            public Enumeration<Locale> getLocales() {
101                    return Collections.enumeration(_locales);
102            }
103    
104            @Override
105            public ServletRequest getRequest() {
106                    return _nextHttpServletRequestThreadLocal.get();
107            }
108    
109            @Override
110            public RequestDispatcher getRequestDispatcher(String uri) {
111                    ServletRequest servletRequest = getRequest();
112    
113                    return servletRequest.getRequestDispatcher(uri);
114            }
115    
116            @Override
117            public HttpSession getSession() {
118                    return getSession(true);
119            }
120    
121            @Override
122            public HttpSession getSession(boolean create) {
123                    HttpServletRequest httpServletRequest =
124                            (HttpServletRequest)getRequest();
125    
126                    HttpSession httpSession = httpServletRequest.getSession(false);
127    
128                    if (!create || (httpSession != null)) {
129                            return httpSession;
130                    }
131    
132                    synchronized (httpServletRequest.getServletContext()) {
133                            return httpServletRequest.getSession(true);
134                    }
135            }
136    
137            @Override
138            public void removeAttribute(String name) {
139                    ServletRequest servletRequest = getRequest();
140    
141                    servletRequest.removeAttribute(name);
142            }
143    
144            @Override
145            public void setAttribute(String name, Object o) {
146                    ServletRequest servletRequest = getRequest();
147    
148                    servletRequest.setAttribute(name, o);
149            }
150    
151            @Override
152            public void setRequest(ServletRequest servletRequest) {
153                    _nextHttpServletRequestThreadLocal.set(
154                            (HttpServletRequest)servletRequest);
155            }
156    
157            private static final ThreadLocal<HttpServletRequest>
158                    _nextHttpServletRequestThreadLocal =
159                            new AutoResetThreadLocal<HttpServletRequest>(
160                                    ThreadLocalFacadeHttpServletRequestWrapper.class +
161                                            "._nextHttpServletRequestThreadLocal") {
162    
163                                    @Override
164                                    protected HttpServletRequest copy(
165                                            HttpServletRequest httpServletRequest) {
166    
167                                            return httpServletRequest;
168                                    }
169    
170                            };
171    
172            private final List<Locale> _locales;
173            private final ServletRequestWrapper _servletRequestWrapper;
174    
175    }