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.HttpUtil;
030 import com.liferay.portal.kernel.util.JavaConstants;
031 import com.liferay.portal.kernel.util.PropsKeys;
032 import com.liferay.portal.kernel.util.PropsUtil;
033 import com.liferay.portal.kernel.util.ServerDetector;
034 import com.liferay.portal.kernel.util.StringPool;
035 import com.liferay.portal.kernel.util.Validator;
036 import com.liferay.portal.kernel.util.WebKeys;
037
038 import java.io.IOException;
039
040 import javax.servlet.Filter;
041 import javax.servlet.FilterChain;
042 import javax.servlet.FilterConfig;
043 import javax.servlet.ServletContext;
044 import javax.servlet.ServletException;
045 import javax.servlet.ServletRequest;
046 import javax.servlet.ServletResponse;
047 import javax.servlet.http.HttpServletRequest;
048 import javax.servlet.http.HttpServletResponse;
049
050
055 public class InvokerFilter extends BasePortalLifecycle implements Filter {
056
057 @Override
058 public void destroy() {
059 portalDestroy();
060 }
061
062 @Override
063 public void doFilter(
064 ServletRequest servletRequest, ServletResponse servletResponse,
065 FilterChain filterChain)
066 throws IOException, ServletException {
067
068 HttpServletRequest request = (HttpServletRequest)servletRequest;
069
070 String uri = getURI(request);
071
072 request = handleNonSerializableRequest(request);
073
074 HttpServletResponse response = (HttpServletResponse)servletResponse;
075
076 if (ServletVersionDetector.is3_0()) {
077 response =
078 HttpOnlyCookieServletResponse.getHttpOnlyCookieServletResponse(
079 response);
080 }
081
082 response = secureResponseHeaders(request, response);
083
084 request.setAttribute(WebKeys.INVOKER_FILTER_URI, uri);
085
086 try {
087 InvokerFilterChain invokerFilterChain = getInvokerFilterChain(
088 request, uri, filterChain);
089
090 Thread currentThread = Thread.currentThread();
091
092 ClassLoader contextClassLoader =
093 currentThread.getContextClassLoader();
094
095 invokerFilterChain.setContextClassLoader(contextClassLoader);
096
097 invokerFilterChain.doFilter(request, response);
098 }
099 finally {
100 request.removeAttribute(WebKeys.INVOKER_FILTER_URI);
101 }
102 }
103
104 @Override
105 public void init(FilterConfig filterConfig) throws ServletException {
106 _filterConfig = filterConfig;
107
108 ServletContext servletContext = _filterConfig.getServletContext();
109
110 _contextPath = ContextPathUtil.getContextPath(servletContext);
111
112 boolean registerPortalLifecycle = GetterUtil.getBoolean(
113 _filterConfig.getInitParameter("register-portal-lifecycle"), true);
114
115 if (registerPortalLifecycle) {
116 registerPortalLifecycle();
117 }
118 else {
119 try {
120 doPortalInit();
121 }
122 catch (Exception e) {
123 _log.error(e, e);
124
125 throw new ServletException(e);
126 }
127 }
128 }
129
130 protected void clearFilterChainsCache() {
131 if (_filterChains != null) {
132 _filterChains.clear();
133 }
134 }
135
136 @Override
137 protected void doPortalDestroy() {
138 ServletContext servletContext = _filterConfig.getServletContext();
139
140 InvokerFilterHelper invokerFilterHelper =
141 (InvokerFilterHelper)servletContext.getAttribute(
142 InvokerFilterHelper.class.getName());
143
144 if (invokerFilterHelper != null) {
145 servletContext.removeAttribute(InvokerFilterHelper.class.getName());
146
147 invokerFilterHelper.destroy();
148 }
149 }
150
151 @Override
152 protected void doPortalInit() throws Exception {
153 _invokerFilterChainSize = GetterUtil.getInteger(
154 PropsUtil.get(PropsKeys.INVOKER_FILTER_CHAIN_SIZE));
155
156 if (_invokerFilterChainSize > 0) {
157 _filterChains = new ConcurrentLFUCache<String, InvokerFilterChain>(
158 _invokerFilterChainSize);
159 }
160
161 ServletContext servletContext = _filterConfig.getServletContext();
162
163 InvokerFilterHelper invokerFilterHelper =
164 (InvokerFilterHelper)servletContext.getAttribute(
165 InvokerFilterHelper.class.getName());
166
167 if (invokerFilterHelper == null) {
168 invokerFilterHelper = new InvokerFilterHelper();
169
170 invokerFilterHelper.init(_filterConfig);
171
172 servletContext.setAttribute(
173 InvokerFilterHelper.class.getName(), invokerFilterHelper);
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 HttpUtil.removePathParameters(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 final 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 }