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 = new HttpOnlyCookieServletResponse(response);
077 }
078
079 response = secureResponseHeaders(request, response);
080
081 request.setAttribute(WebKeys.INVOKER_FILTER_URI, uri);
082
083 try {
084 InvokerFilterChain invokerFilterChain = getInvokerFilterChain(
085 request, uri, filterChain);
086
087 Thread currentThread = Thread.currentThread();
088
089 ClassLoader contextClassLoader =
090 currentThread.getContextClassLoader();
091
092 invokerFilterChain.setContextClassLoader(contextClassLoader);
093
094 invokerFilterChain.doFilter(request, response);
095 }
096 finally {
097 request.removeAttribute(WebKeys.INVOKER_FILTER_URI);
098 }
099 }
100
101 @Override
102 public void init(FilterConfig filterConfig) throws ServletException {
103 _filterConfig = filterConfig;
104
105 ServletContext servletContext = _filterConfig.getServletContext();
106
107 _contextPath = ContextPathUtil.getContextPath(servletContext);
108
109 boolean registerPortalLifecycle = GetterUtil.getBoolean(
110 _filterConfig.getInitParameter("register-portal-lifecycle"), true);
111
112 if (registerPortalLifecycle) {
113 registerPortalLifecycle();
114 }
115 else {
116 try {
117 doPortalInit();
118 }
119 catch (Exception e) {
120 _log.error(e, e);
121
122 throw new ServletException(e);
123 }
124 }
125 }
126
127 protected void clearFilterChainsCache() {
128 if (_filterChains != null) {
129 _filterChains.clear();
130 }
131 }
132
133 @Override
134 protected void doPortalDestroy() {
135 ServletContext servletContext = _filterConfig.getServletContext();
136
137 InvokerFilterHelper invokerFilterHelper =
138 (InvokerFilterHelper)servletContext.getAttribute(
139 InvokerFilterHelper.class.getName());
140
141 if (invokerFilterHelper != null) {
142 servletContext.removeAttribute(InvokerFilterHelper.class.getName());
143
144 invokerFilterHelper.destroy();
145 }
146 }
147
148 @Override
149 protected void doPortalInit() throws Exception {
150 _invokerFilterChainSize = GetterUtil.getInteger(
151 PropsUtil.get(PropsKeys.INVOKER_FILTER_CHAIN_SIZE));
152
153 if (_invokerFilterChainSize > 0) {
154 _filterChains = new ConcurrentLFUCache<String, InvokerFilterChain>(
155 _invokerFilterChainSize);
156 }
157
158 ServletContext servletContext = _filterConfig.getServletContext();
159
160 InvokerFilterHelper invokerFilterHelper =
161 (InvokerFilterHelper)servletContext.getAttribute(
162 InvokerFilterHelper.class.getName());
163
164 if (invokerFilterHelper == null) {
165 invokerFilterHelper = new InvokerFilterHelper();
166
167 servletContext.setAttribute(
168 InvokerFilterHelper.class.getName(), invokerFilterHelper);
169
170 invokerFilterHelper.readLiferayFilterWebXML(
171 servletContext, "/WEB-INF/liferay-web.xml");
172 }
173
174 _invokerFilterHelper = invokerFilterHelper;
175
176 _invokerFilterHelper.addInvokerFilter(this);
177
178 String dispatcher = GetterUtil.getString(
179 _filterConfig.getInitParameter("dispatcher"));
180
181 if (dispatcher.equals("ERROR")) {
182 _dispatcher = Dispatcher.ERROR;
183 }
184 else if (dispatcher.equals("FORWARD")) {
185 _dispatcher = Dispatcher.FORWARD;
186 }
187 else if (dispatcher.equals("INCLUDE")) {
188 _dispatcher = Dispatcher.INCLUDE;
189 }
190 else if (dispatcher.equals("REQUEST")) {
191 _dispatcher = Dispatcher.REQUEST;
192 }
193 else {
194 throw new IllegalArgumentException(
195 "Invalid dispatcher " + dispatcher);
196 }
197 }
198
199 protected InvokerFilterChain getInvokerFilterChain(
200 HttpServletRequest request, String uri, FilterChain filterChain) {
201
202 if (_filterChains == null) {
203 return _invokerFilterHelper.createInvokerFilterChain(
204 request, _dispatcher, uri, filterChain);
205 }
206
207 CacheKeyGenerator cacheKeyGenerator =
208 CacheKeyGeneratorUtil.getCacheKeyGenerator(
209 InvokerFilter.class.getName());
210
211 String key = String.valueOf(cacheKeyGenerator.getCacheKey(uri));
212
213 InvokerFilterChain invokerFilterChain = _filterChains.get(key);
214
215 if (invokerFilterChain == null) {
216 invokerFilterChain = _invokerFilterHelper.createInvokerFilterChain(
217 request, _dispatcher, uri, filterChain);
218
219 _filterChains.put(key, invokerFilterChain);
220 }
221
222 return invokerFilterChain.clone(filterChain);
223 }
224
225 protected String getURI(HttpServletRequest request) {
226 String uri = null;
227
228 if (_dispatcher == Dispatcher.ERROR) {
229 uri = (String)request.getAttribute(
230 JavaConstants.JAVAX_SERVLET_ERROR_REQUEST_URI);
231 }
232 else if (_dispatcher == Dispatcher.INCLUDE) {
233 uri = (String)request.getAttribute(
234 JavaConstants.JAVAX_SERVLET_INCLUDE_REQUEST_URI);
235 }
236 else {
237 uri = request.getRequestURI();
238 }
239
240 if (Validator.isNotNull(_contextPath) &&
241 !_contextPath.equals(StringPool.SLASH) &&
242 uri.startsWith(_contextPath)) {
243
244 uri = uri.substring(_contextPath.length());
245 }
246
247 return uri;
248 }
249
250 protected HttpServletRequest handleNonSerializableRequest(
251 HttpServletRequest request) {
252
253 if (ServerDetector.isWebLogic()) {
254 if (!NonSerializableObjectRequestWrapper.isWrapped(request)) {
255 request = new NonSerializableObjectRequestWrapper(request);
256 }
257 }
258
259 return request;
260 }
261
262 protected HttpServletResponse secureResponseHeaders(
263 HttpServletRequest request, HttpServletResponse response) {
264
265 if (!GetterUtil.getBoolean(
266 request.getAttribute(_SECURE_RESPONSE), true)) {
267
268 return response;
269 }
270
271 request.setAttribute(_SECURE_RESPONSE, Boolean.FALSE);
272
273 return SanitizedServletResponse.getSanitizedServletResponse(
274 request, response);
275 }
276
277 private static final String _SECURE_RESPONSE =
278 InvokerFilter.class.getName() + "SECURE_RESPONSE";
279
280 private static Log _log = LogFactoryUtil.getLog(InvokerFilter.class);
281
282 private String _contextPath;
283 private Dispatcher _dispatcher;
284 private ConcurrentLFUCache<String, InvokerFilterChain> _filterChains;
285 private FilterConfig _filterConfig;
286 private int _invokerFilterChainSize;
287 private InvokerFilterHelper _invokerFilterHelper;
288
289 }