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