001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.kernel.servlet.filters.invoker;
016    
017    import com.liferay.portal.kernel.concurrent.ConcurrentLRUCache;
018    import com.liferay.portal.kernel.util.BasePortalLifecycle;
019    import com.liferay.portal.kernel.util.GetterUtil;
020    import com.liferay.portal.kernel.util.JavaConstants;
021    import com.liferay.portal.kernel.util.PropsKeys;
022    import com.liferay.portal.kernel.util.PropsUtil;
023    import com.liferay.portal.kernel.util.StringPool;
024    import com.liferay.portal.kernel.util.Validator;
025    import com.liferay.portal.kernel.util.WebKeys;
026    
027    import java.io.IOException;
028    
029    import javax.servlet.Filter;
030    import javax.servlet.FilterChain;
031    import javax.servlet.FilterConfig;
032    import javax.servlet.ServletContext;
033    import javax.servlet.ServletException;
034    import javax.servlet.ServletRequest;
035    import javax.servlet.ServletResponse;
036    import javax.servlet.http.HttpServletRequest;
037    
038    /**
039     * @author Mika Koivisto
040     * @author Brian Wing Shun Chan
041     */
042    public class InvokerFilter extends BasePortalLifecycle implements Filter {
043    
044            public void destroy() {
045                    portalDestroy();
046            }
047    
048            public void doFilter(
049                            ServletRequest servletRequest, ServletResponse servletResponse,
050                            FilterChain filterChain)
051                    throws IOException, ServletException {
052    
053                    HttpServletRequest request = (HttpServletRequest)servletRequest;
054    
055                    String uri = getURI(request);
056    
057                    request.setAttribute(WebKeys.INVOKER_FILTER_URI, uri);
058    
059                    InvokerFilterChain invokerFilterChain = getInvokerFilterChain(
060                            request, uri, filterChain);
061    
062                    Thread currentThread = Thread.currentThread();
063    
064                    ClassLoader contextClassLoader = currentThread.getContextClassLoader();
065    
066                    invokerFilterChain.setContextClassLoader(contextClassLoader);
067    
068                    invokerFilterChain.doFilter(servletRequest, servletResponse);
069            }
070    
071            public void init(FilterConfig filterConfig) {
072                    _filterConfig = filterConfig;
073    
074                    registerPortalLifecycle();
075            }
076    
077            protected void clearFilterChainsCache() {
078                    if (_filterChains != null) {
079                            _filterChains.clear();
080                    }
081            }
082    
083            @Override
084            protected void doPortalDestroy() {
085                    ServletContext servletContext = _filterConfig.getServletContext();
086    
087                    InvokerFilterHelper invokerFilterHelper =
088                            (InvokerFilterHelper)servletContext.getAttribute(
089                                    InvokerFilterHelper.class.getName());
090    
091                    if (invokerFilterHelper != null) {
092                            servletContext.removeAttribute(InvokerFilterHelper.class.getName());
093    
094                            _invokerFilterHelper.destroy();
095                    }
096            }
097    
098            @Override
099            protected void doPortalInit() throws Exception {
100                    _invokerFilterChainSize = GetterUtil.getInteger(
101                            PropsUtil.get(PropsKeys.INVOKER_FILTER_CHAIN_SIZE));
102    
103                    if (_invokerFilterChainSize > 0) {
104                            _filterChains = new ConcurrentLRUCache<Integer, InvokerFilterChain>(
105                                    _invokerFilterChainSize);
106                    }
107    
108                    ServletContext servletContext = _filterConfig.getServletContext();
109    
110                    InvokerFilterHelper invokerFilterHelper =
111                            (InvokerFilterHelper)servletContext.getAttribute(
112                                    InvokerFilterHelper.class.getName());
113    
114                    if (invokerFilterHelper == null) {
115                            invokerFilterHelper = new InvokerFilterHelper();
116    
117                            invokerFilterHelper.readLiferayFilterWebXML(
118                                    servletContext, "/WEB-INF/liferay-web.xml");
119    
120                            servletContext.setAttribute(
121                                    InvokerFilterHelper.class.getName(), invokerFilterHelper);
122                    }
123    
124                    _invokerFilterHelper = invokerFilterHelper;
125    
126                    _invokerFilterHelper.addInvokerFilter(this);
127    
128                    String dispatcher = GetterUtil.getString(
129                            _filterConfig.getInitParameter("dispatcher"));
130    
131                    if (dispatcher.equals("ERROR")) {
132                            _dispatcher = Dispatcher.ERROR;
133                    }
134                    else if (dispatcher.equals("FORWARD")) {
135                            _dispatcher = Dispatcher.FORWARD;
136                    }
137                    else if (dispatcher.equals("INCLUDE")) {
138                            _dispatcher = Dispatcher.INCLUDE;
139                    }
140                    else if (dispatcher.equals("REQUEST")) {
141                            _dispatcher = Dispatcher.REQUEST;
142                    }
143                    else {
144                            throw new IllegalArgumentException(
145                                    "Invalid dispatcher " + dispatcher);
146                    }
147            }
148    
149            protected InvokerFilterChain getInvokerFilterChain(
150                    HttpServletRequest request, String uri, FilterChain filterChain) {
151    
152                    if (_filterChains == null) {
153                            return _invokerFilterHelper.createInvokerFilterChain(
154                                    request, _dispatcher, uri, filterChain);
155                    }
156    
157                    Integer key = uri.hashCode();
158    
159                    InvokerFilterChain invokerFilterChain = _filterChains.get(key);
160    
161                    if (invokerFilterChain == null) {
162                            invokerFilterChain = _invokerFilterHelper.createInvokerFilterChain(
163                                    request, _dispatcher, uri, filterChain);
164    
165                            _filterChains.put(key, invokerFilterChain);
166                    }
167    
168                    return invokerFilterChain.clone(filterChain);
169            }
170    
171            protected String getURI(HttpServletRequest request) {
172                    String uri = null;
173    
174                    if (_dispatcher == Dispatcher.ERROR) {
175                            uri = (String)request.getAttribute(
176                                    JavaConstants.JAVAX_SERVLET_ERROR_REQUEST_URI);
177                    }
178                    else if (_dispatcher == Dispatcher.INCLUDE) {
179                            uri = (String)request.getAttribute(
180                                    JavaConstants.JAVAX_SERVLET_INCLUDE_REQUEST_URI);
181                    }
182                    else {
183                            uri = request.getRequestURI();
184                    }
185    
186                    String contextPath = request.getContextPath();
187    
188                    if (Validator.isNotNull(contextPath) &&
189                            !contextPath.equals(StringPool.SLASH) &&
190                            uri.startsWith(contextPath)) {
191    
192                            uri = uri.substring(contextPath.length());
193                    }
194    
195                    return uri;
196            }
197    
198            private Dispatcher _dispatcher;
199            private ConcurrentLRUCache<Integer, InvokerFilterChain> _filterChains;
200            private FilterConfig _filterConfig;
201            private int _invokerFilterChainSize;
202            private InvokerFilterHelper _invokerFilterHelper;
203    
204    }