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 InvokerFilter() {
045                    if (_INVOKER_FILTER_CHAIN_SIZE > 0) {
046                            _filterChains = new ConcurrentLRUCache<Integer, InvokerFilterChain>(
047                                    _INVOKER_FILTER_CHAIN_SIZE);
048                    }
049            }
050    
051            public void destroy() {
052                    portalDestroy();
053            }
054    
055            public void doFilter(
056                            ServletRequest servletRequest, ServletResponse servletResponse,
057                            FilterChain filterChain)
058                    throws IOException, ServletException {
059    
060                    HttpServletRequest request = (HttpServletRequest)servletRequest;
061    
062                    String uri = getURI(request);
063    
064                    request.setAttribute(WebKeys.INVOKER_FILTER_URI, uri);
065    
066                    InvokerFilterChain invokerFilterChain = getInvokerFilterChain(
067                            request, uri, filterChain);
068    
069                    Thread currentThread = Thread.currentThread();
070    
071                    ClassLoader contextClassLoader = currentThread.getContextClassLoader();
072    
073                    invokerFilterChain.setContextClassLoader(contextClassLoader);
074    
075                    invokerFilterChain.doFilter(servletRequest, servletResponse);
076            }
077    
078            public void init(FilterConfig filterConfig) {
079                    _filterConfig = filterConfig;
080    
081                    registerPortalLifecycle();
082            }
083    
084            protected void clearFilterChainsCache() {
085                    if (_filterChains != null) {
086                            _filterChains.clear();
087                    }
088            }
089    
090            @Override
091            protected void doPortalDestroy() {
092                    ServletContext servletContext = _filterConfig.getServletContext();
093    
094                    InvokerFilterHelper invokerFilterHelper =
095                            (InvokerFilterHelper)servletContext.getAttribute(
096                                    InvokerFilterHelper.class.getName());
097    
098                    if (invokerFilterHelper != null) {
099                            servletContext.removeAttribute(InvokerFilterHelper.class.getName());
100    
101                            _invokerFilterHelper.destroy();
102                    }
103            }
104    
105            @Override
106            protected void doPortalInit() throws Exception {
107                    ServletContext servletContext = _filterConfig.getServletContext();
108    
109                    InvokerFilterHelper invokerFilterHelper =
110                            (InvokerFilterHelper)servletContext.getAttribute(
111                                    InvokerFilterHelper.class.getName());
112    
113                    if (invokerFilterHelper == null) {
114                            invokerFilterHelper = new InvokerFilterHelper();
115    
116                            invokerFilterHelper.readLiferayFilterWebXML(
117                                    servletContext, "/WEB-INF/liferay-web.xml");
118    
119                            servletContext.setAttribute(
120                                    InvokerFilterHelper.class.getName(), invokerFilterHelper);
121                    }
122    
123                    _invokerFilterHelper = invokerFilterHelper;
124    
125                    _invokerFilterHelper.addInvokerFilter(this);
126    
127                    String dispatcher = GetterUtil.getString(
128                            _filterConfig.getInitParameter("dispatcher"));
129    
130                    if (dispatcher.equals("ERROR")) {
131                            _dispatcher = Dispatcher.ERROR;
132                    }
133                    else if (dispatcher.equals("FORWARD")) {
134                            _dispatcher = Dispatcher.FORWARD;
135                    }
136                    else if (dispatcher.equals("INCLUDE")) {
137                            _dispatcher = Dispatcher.INCLUDE;
138                    }
139                    else if (dispatcher.equals("REQUEST")) {
140                            _dispatcher = Dispatcher.REQUEST;
141                    }
142                    else {
143                            throw new IllegalArgumentException(
144                                    "Invalid dispatcher " + dispatcher);
145                    }
146            }
147    
148            protected InvokerFilterChain getInvokerFilterChain(
149                    HttpServletRequest request, String uri, FilterChain filterChain) {
150    
151                    if (_filterChains == null) {
152                            return _invokerFilterHelper.createInvokerFilterChain(
153                                    request, _dispatcher, uri, filterChain);
154                    }
155    
156                    Integer key = uri.hashCode();
157    
158                    InvokerFilterChain invokerFilterChain = _filterChains.get(key);
159    
160                    if (invokerFilterChain == null) {
161                            invokerFilterChain = _invokerFilterHelper.createInvokerFilterChain(
162                                    request, _dispatcher, uri, filterChain);
163    
164                            _filterChains.put(key, invokerFilterChain);
165                    }
166    
167                    return invokerFilterChain.clone(filterChain);
168            }
169    
170            protected String getURI(HttpServletRequest request) {
171                    String uri = null;
172    
173                    if (_dispatcher == Dispatcher.ERROR) {
174                            uri = (String)request.getAttribute(
175                                    JavaConstants.JAVAX_SERVLET_ERROR_REQUEST_URI);
176                    }
177                    else if (_dispatcher == Dispatcher.INCLUDE) {
178                            uri = (String)request.getAttribute(
179                                    JavaConstants.JAVAX_SERVLET_INCLUDE_REQUEST_URI);
180                    }
181                    else {
182                            uri = request.getRequestURI();
183                    }
184    
185                    String contextPath = request.getContextPath();
186    
187                    if (Validator.isNotNull(contextPath) &&
188                            !contextPath.equals(StringPool.SLASH) &&
189                            uri.startsWith(contextPath)) {
190    
191                            uri = uri.substring(contextPath.length());
192                    }
193    
194                    return uri;
195            }
196    
197            private static final int _INVOKER_FILTER_CHAIN_SIZE = GetterUtil.getInteger(
198                    PropsUtil.get(PropsKeys.INVOKER_FILTER_CHAIN_SIZE));
199    
200            private Dispatcher _dispatcher;
201            private ConcurrentLRUCache<Integer, InvokerFilterChain> _filterChains;
202            private FilterConfig _filterConfig;
203            private InvokerFilterHelper _invokerFilterHelper;
204    
205    }