001
014
015 package com.liferay.portal.kernel.servlet.filters.invoker;
016
017 import com.liferay.portal.kernel.cache.key.CacheKeyGenerator;
018 import com.liferay.portal.kernel.cache.key.CacheKeyGeneratorUtil;
019 import com.liferay.portal.kernel.concurrent.ConcurrentLFUCache;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.servlet.HttpOnlyCookieServletResponse;
023 import com.liferay.portal.kernel.servlet.NonSerializableObjectRequestWrapper;
024 import com.liferay.portal.kernel.servlet.SanitizedServletResponse;
025 import com.liferay.portal.kernel.servlet.ServletVersionDetector;
026 import com.liferay.portal.kernel.util.BasePortalLifecycle;
027 import com.liferay.portal.kernel.util.ContextPathUtil;
028 import com.liferay.portal.kernel.util.GetterUtil;
029 import com.liferay.portal.kernel.util.JavaConstants;
030 import com.liferay.portal.kernel.util.PropsKeys;
031 import com.liferay.portal.kernel.util.PropsUtil;
032 import com.liferay.portal.kernel.util.ServerDetector;
033 import com.liferay.portal.kernel.util.StringPool;
034 import com.liferay.portal.kernel.util.Validator;
035 import com.liferay.portal.kernel.util.WebKeys;
036
037 import java.io.IOException;
038
039 import javax.servlet.Filter;
040 import javax.servlet.FilterChain;
041 import javax.servlet.FilterConfig;
042 import javax.servlet.ServletContext;
043 import javax.servlet.ServletException;
044 import javax.servlet.ServletRequest;
045 import javax.servlet.ServletResponse;
046 import javax.servlet.http.HttpServletRequest;
047 import javax.servlet.http.HttpServletResponse;
048
049
054 public class InvokerFilter extends BasePortalLifecycle implements Filter {
055
056 @Override
057 public void destroy() {
058 portalDestroy();
059 }
060
061 @Override
062 public void doFilter(
063 ServletRequest servletRequest, ServletResponse servletResponse,
064 FilterChain filterChain)
065 throws IOException, ServletException {
066
067 HttpServletRequest request = (HttpServletRequest)servletRequest;
068
069 String uri = getURI(request);
070
071 request = handleNonSerializableRequest(request);
072
073 HttpServletResponse response = (HttpServletResponse)servletResponse;
074
075 if (ServletVersionDetector.is3_0()) {
076 response =
077 HttpOnlyCookieServletResponse.getHttpOnlyCookieServletResponse(
078 response);
079 }
080
081 response = secureResponseHeaders(request, response);
082
083 request.setAttribute(WebKeys.INVOKER_FILTER_URI, uri);
084
085 try {
086 InvokerFilterChain invokerFilterChain = getInvokerFilterChain(
087 request, uri, filterChain);
088
089 Thread currentThread = Thread.currentThread();
090
091 ClassLoader contextClassLoader =
092 currentThread.getContextClassLoader();
093
094 invokerFilterChain.setContextClassLoader(contextClassLoader);
095
096 invokerFilterChain.doFilter(request, response);
097 }
098 finally {
099 request.removeAttribute(WebKeys.INVOKER_FILTER_URI);
100 }
101 }
102
103 @Override
104 public void init(FilterConfig filterConfig) throws ServletException {
105 _filterConfig = filterConfig;
106
107 ServletContext servletContext = _filterConfig.getServletContext();
108
109 _contextPath = ContextPathUtil.getContextPath(servletContext);
110
111 boolean registerPortalLifecycle = GetterUtil.getBoolean(
112 _filterConfig.getInitParameter("register-portal-lifecycle"), true);
113
114 if (registerPortalLifecycle) {
115 registerPortalLifecycle();
116 }
117 else {
118 try {
119 doPortalInit();
120 }
121 catch (Exception e) {
122 _log.error(e, e);
123
124 throw new ServletException(e);
125 }
126 }
127 }
128
129 protected void clearFilterChainsCache() {
130 if (_filterChains != null) {
131 _filterChains.clear();
132 }
133 }
134
135 @Override
136 protected void doPortalDestroy() {
137 ServletContext servletContext = _filterConfig.getServletContext();
138
139 InvokerFilterHelper invokerFilterHelper =
140 (InvokerFilterHelper)servletContext.getAttribute(
141 InvokerFilterHelper.class.getName());
142
143 if (invokerFilterHelper != null) {
144 servletContext.removeAttribute(InvokerFilterHelper.class.getName());
145
146 invokerFilterHelper.destroy();
147 }
148 }
149
150 @Override
151 protected void doPortalInit() throws Exception {
152 _invokerFilterChainSize = GetterUtil.getInteger(
153 PropsUtil.get(PropsKeys.INVOKER_FILTER_CHAIN_SIZE));
154
155 if (_invokerFilterChainSize > 0) {
156 _filterChains = new ConcurrentLFUCache<String, InvokerFilterChain>(
157 _invokerFilterChainSize);
158 }
159
160 ServletContext servletContext = _filterConfig.getServletContext();
161
162 InvokerFilterHelper invokerFilterHelper =
163 (InvokerFilterHelper)servletContext.getAttribute(
164 InvokerFilterHelper.class.getName());
165
166 if (invokerFilterHelper == null) {
167 invokerFilterHelper = new InvokerFilterHelper();
168
169 servletContext.setAttribute(
170 InvokerFilterHelper.class.getName(), invokerFilterHelper);
171
172 invokerFilterHelper.readLiferayFilterWebXML(
173 servletContext, "/WEB-INF/liferay-web.xml");
174 }
175
176 _invokerFilterHelper = invokerFilterHelper;
177
178 _invokerFilterHelper.addInvokerFilter(this);
179
180 String dispatcher = GetterUtil.getString(
181 _filterConfig.getInitParameter("dispatcher"));
182
183 if (dispatcher.equals("ERROR")) {
184 _dispatcher = Dispatcher.ERROR;
185 }
186 else if (dispatcher.equals("FORWARD")) {
187 _dispatcher = Dispatcher.FORWARD;
188 }
189 else if (dispatcher.equals("INCLUDE")) {
190 _dispatcher = Dispatcher.INCLUDE;
191 }
192 else if (dispatcher.equals("REQUEST")) {
193 _dispatcher = Dispatcher.REQUEST;
194 }
195 else {
196 throw new IllegalArgumentException(
197 "Invalid dispatcher " + dispatcher);
198 }
199 }
200
201 protected InvokerFilterChain getInvokerFilterChain(
202 HttpServletRequest request, String uri, FilterChain filterChain) {
203
204 if (_filterChains == null) {
205 return _invokerFilterHelper.createInvokerFilterChain(
206 request, _dispatcher, uri, filterChain);
207 }
208
209 CacheKeyGenerator cacheKeyGenerator =
210 CacheKeyGeneratorUtil.getCacheKeyGenerator(
211 InvokerFilter.class.getName());
212
213 String key = String.valueOf(cacheKeyGenerator.getCacheKey(uri));
214
215 InvokerFilterChain invokerFilterChain = _filterChains.get(key);
216
217 if (invokerFilterChain == null) {
218 invokerFilterChain = _invokerFilterHelper.createInvokerFilterChain(
219 request, _dispatcher, uri, filterChain);
220
221 _filterChains.put(key, invokerFilterChain);
222 }
223
224 return invokerFilterChain.clone(filterChain);
225 }
226
227 protected String getURI(HttpServletRequest request) {
228 String uri = null;
229
230 if (_dispatcher == Dispatcher.ERROR) {
231 uri = (String)request.getAttribute(
232 JavaConstants.JAVAX_SERVLET_ERROR_REQUEST_URI);
233 }
234 else if (_dispatcher == Dispatcher.INCLUDE) {
235 uri = (String)request.getAttribute(
236 JavaConstants.JAVAX_SERVLET_INCLUDE_REQUEST_URI);
237 }
238 else {
239 uri = request.getRequestURI();
240 }
241
242 if (Validator.isNotNull(_contextPath) &&
243 !_contextPath.equals(StringPool.SLASH) &&
244 uri.startsWith(_contextPath)) {
245
246 uri = uri.substring(_contextPath.length());
247 }
248
249 return uri;
250 }
251
252 protected HttpServletRequest handleNonSerializableRequest(
253 HttpServletRequest request) {
254
255 if (ServerDetector.isWebLogic()) {
256 if (!NonSerializableObjectRequestWrapper.isWrapped(request)) {
257 request = new NonSerializableObjectRequestWrapper(request);
258 }
259 }
260
261 return request;
262 }
263
264 protected HttpServletResponse secureResponseHeaders(
265 HttpServletRequest request, HttpServletResponse response) {
266
267 if (!GetterUtil.getBoolean(
268 request.getAttribute(_SECURE_RESPONSE), true)) {
269
270 return response;
271 }
272
273 request.setAttribute(_SECURE_RESPONSE, Boolean.FALSE);
274
275 return SanitizedServletResponse.getSanitizedServletResponse(
276 request, response);
277 }
278
279 private static final String _SECURE_RESPONSE =
280 InvokerFilter.class.getName() + "SECURE_RESPONSE";
281
282 private static Log _log = LogFactoryUtil.getLog(InvokerFilter.class);
283
284 private String _contextPath;
285 private Dispatcher _dispatcher;
286 private ConcurrentLFUCache<String, InvokerFilterChain> _filterChains;
287 private FilterConfig _filterConfig;
288 private int _invokerFilterChainSize;
289 private InvokerFilterHelper _invokerFilterHelper;
290
291 }