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.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.servlet.LiferayFilter;
020    import com.liferay.portal.kernel.servlet.PortletServlet;
021    import com.liferay.portal.kernel.util.InstanceFactory;
022    import com.liferay.portal.kernel.util.Validator;
023    import com.liferay.portal.kernel.xml.Document;
024    import com.liferay.portal.kernel.xml.Element;
025    import com.liferay.portal.kernel.xml.SAXReaderUtil;
026    
027    import java.io.InputStream;
028    
029    import java.util.ArrayList;
030    import java.util.HashMap;
031    import java.util.List;
032    import java.util.Map;
033    import java.util.concurrent.CopyOnWriteArrayList;
034    
035    import javax.servlet.Filter;
036    import javax.servlet.FilterChain;
037    import javax.servlet.FilterConfig;
038    import javax.servlet.ServletContext;
039    import javax.servlet.ServletException;
040    import javax.servlet.http.HttpServletRequest;
041    
042    /**
043     * @author Mika Koivisto
044     * @author Brian Wing Shun Chan
045     */
046    public class InvokerFilterHelper {
047    
048            public void destroy() {
049                    for (Map.Entry<String, Filter> entry : _filters.entrySet()) {
050                            Filter filter = entry.getValue();
051    
052                            try {
053                                    filter.destroy();
054                            }
055                            catch (Exception e) {
056                                    _log.error(e, e);
057                            }
058                    }
059    
060                    _filterConfigs.clear();
061                    _filterMappings.clear();
062                    _filters.clear();
063    
064                    for (InvokerFilter invokerFilter : _invokerFilters) {
065                            invokerFilter.clearFilterChainsCache();
066                    }
067            }
068    
069            public Filter getFilter(String filterName) {
070                    return _filters.get(filterName);
071            }
072    
073            public FilterConfig getFilterConfig(String filterName) {
074                    return _filterConfigs.get(filterName);
075            }
076    
077            public void init(FilterConfig filterConfig) throws ServletException {
078                    try {
079                            ServletContext servletContext = filterConfig.getServletContext();
080    
081                            readLiferayFilterWebXML(servletContext, "/WEB-INF/liferay-web.xml");
082                    }
083                    catch (Exception e) {
084                            _log.error(e, e);
085    
086                            throw new ServletException(e);
087                    }
088            }
089    
090            public Filter registerFilter(String filterName, Filter filter) {
091                    Filter previousFilter = _filters.put(filterName, filter);
092    
093                    if (previousFilter != null) {
094                            for (FilterMapping filterMapping : _filterMappings) {
095                                    if (filterMapping.getFilter() == previousFilter) {
096                                            if (filter != null) {
097                                                    filterMapping.setFilter(filter);
098                                            }
099                                            else {
100                                                    _filterMappings.remove(filterMapping);
101                                                    _filterConfigs.remove(filterName);
102                                            }
103                                    }
104                            }
105                    }
106    
107                    for (InvokerFilter invokerFilter : _invokerFilters) {
108                            invokerFilter.clearFilterChainsCache();
109                    }
110    
111                    return previousFilter;
112            }
113    
114            public void registerFilterMapping(
115                    FilterMapping filterMapping, String filterName, boolean after) {
116    
117                    int i = 0;
118    
119                    if (Validator.isNotNull(filterName)) {
120                            Filter filter = _filters.get(filterName);
121    
122                            if (filter != null) {
123                                    for (; i < _filterMappings.size(); i++) {
124                                            FilterMapping currentFilterMapping = _filterMappings.get(i);
125    
126                                            if (currentFilterMapping.getFilter() == filter) {
127                                                    break;
128                                            }
129                                    }
130                            }
131                    }
132    
133                    if (after) {
134                            i++;
135                    }
136    
137                    _filterMappings.add(i, filterMapping);
138    
139                    for (InvokerFilter invokerFilter : _invokerFilters) {
140                            invokerFilter.clearFilterChainsCache();
141                    }
142            }
143    
144            public void unregisterFilterMapping(FilterMapping filterMapping) {
145                    _filterMappings.remove(filterMapping);
146    
147                    for (InvokerFilter invokerFilter : _invokerFilters) {
148                            invokerFilter.clearFilterChainsCache();
149                    }
150            }
151    
152            protected void addInvokerFilter(InvokerFilter invokerFilter) {
153                    _invokerFilters.add(invokerFilter);
154            }
155    
156            protected InvokerFilterChain createInvokerFilterChain(
157                    HttpServletRequest request, Dispatcher dispatcher, String uri,
158                    FilterChain filterChain) {
159    
160                    InvokerFilterChain invokerFilterChain = new InvokerFilterChain(
161                            filterChain);
162    
163                    for (FilterMapping filterMapping : _filterMappings) {
164                            if (filterMapping.isMatch(request, dispatcher, uri)) {
165                                    Filter filter = filterMapping.getFilter();
166    
167                                    invokerFilterChain.addFilter(filter);
168                            }
169                    }
170    
171                    return invokerFilterChain;
172            }
173    
174            protected void initFilter(
175                            ServletContext servletContext, String filterName,
176                            String filterClassName, Map<String, String> initParameterMap)
177                    throws Exception {
178    
179                    ClassLoader contextClassLoader =
180                            (ClassLoader)servletContext.getAttribute(
181                                    PortletServlet.PORTLET_CLASS_LOADER);
182    
183                    if (contextClassLoader == null) {
184                            Thread currentThread = Thread.currentThread();
185    
186                            contextClassLoader = currentThread.getContextClassLoader();
187                    }
188    
189                    Filter filter = (Filter)InstanceFactory.newInstance(
190                            contextClassLoader, filterClassName);
191    
192                    FilterConfig filterConfig = new InvokerFilterConfig(
193                            servletContext, filterName, initParameterMap);
194    
195                    filter.init(filterConfig);
196    
197                    boolean filterEnabled = true;
198    
199                    if (filter instanceof LiferayFilter) {
200                            LiferayFilter liferayFilter = (LiferayFilter)filter;
201    
202                            filterEnabled = liferayFilter.isFilterEnabled();
203                    }
204    
205                    if (filterEnabled) {
206                            _filterConfigs.put(filterName, filterConfig);
207                            _filters.put(filterName, filter);
208                    }
209                    else {
210                            if (_log.isDebugEnabled()) {
211                                    _log.debug("Removing disabled filter " + filter.getClass());
212                            }
213                    }
214            }
215    
216            protected void initFilterMapping(
217                    String filterName, List<String> urlPatterns, List<String> dispatchers) {
218    
219                    Filter filter = _filters.get(filterName);
220    
221                    if (filter == null) {
222                            return;
223                    }
224    
225                    FilterConfig filterConfig = _filterConfigs.get(filterName);
226    
227                    if (filterConfig == null) {
228                            return;
229                    }
230    
231                    FilterMapping filterMapping = new FilterMapping(
232                            filter, filterConfig, urlPatterns, dispatchers);
233    
234                    _filterMappings.add(filterMapping);
235            }
236    
237            protected void readLiferayFilterWebXML(
238                            ServletContext servletContext, String path)
239                    throws Exception {
240    
241                    InputStream inputStream = servletContext.getResourceAsStream(path);
242    
243                    if (inputStream == null) {
244                            return;
245                    }
246    
247                    Document document = SAXReaderUtil.read(inputStream, true);
248    
249                    Element rootElement = document.getRootElement();
250    
251                    List<Element> filterElements = rootElement.elements("filter");
252    
253                    for (Element filterElement : filterElements) {
254                            String filterName = filterElement.elementText("filter-name");
255                            String filterClassName = filterElement.elementText("filter-class");
256    
257                            Map<String, String> initParameterMap =
258                                    new HashMap<String, String>();
259    
260                            List<Element> initParamElements = filterElement.elements(
261                                    "init-param");
262    
263                            for (Element initParamElement : initParamElements) {
264                                    String name = initParamElement.elementText("param-name");
265                                    String value = initParamElement.elementText("param-value");
266    
267                                    initParameterMap.put(name, value);
268                            }
269    
270                            initFilter(
271                                    servletContext, filterName, filterClassName, initParameterMap);
272                    }
273    
274                    List<Element> filterMappingElements = rootElement.elements(
275                            "filter-mapping");
276    
277                    for (Element filterMappingElement : filterMappingElements) {
278                            String filterName = filterMappingElement.elementText("filter-name");
279    
280                            List<String> urlPatterns = new ArrayList<String>();
281    
282                            List<Element> urlPatternElements = filterMappingElement.elements(
283                                    "url-pattern");
284    
285                            for (Element urlPatternElement : urlPatternElements) {
286                                    urlPatterns.add(urlPatternElement.getTextTrim());
287                            }
288    
289                            List<String> dispatchers = new ArrayList<String>(4);
290    
291                            List<Element> dispatcherElements = filterMappingElement.elements(
292                                    "dispatcher");
293    
294                            for (Element dispatcherElement : dispatcherElements) {
295                                    String dispatcher =
296                                            dispatcherElement.getTextTrim().toUpperCase();
297    
298                                    dispatchers.add(dispatcher);
299                            }
300    
301                            initFilterMapping(filterName, urlPatterns, dispatchers);
302                    }
303            }
304    
305            private static Log _log = LogFactoryUtil.getLog(InvokerFilter.class);
306    
307            private Map<String, FilterConfig> _filterConfigs =
308                    new HashMap<String, FilterConfig>();
309            private List<FilterMapping> _filterMappings =
310                    new CopyOnWriteArrayList<FilterMapping>();
311            private Map<String, Filter> _filters = new HashMap<String, Filter>();
312            private List<InvokerFilter> _invokerFilters =
313                    new ArrayList<InvokerFilter>();
314    
315    }