001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
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.util.CharPool;
020    import com.liferay.portal.kernel.util.GetterUtil;
021    import com.liferay.portal.kernel.util.StringPool;
022    import com.liferay.portal.kernel.util.Validator;
023    
024    import java.util.List;
025    import java.util.regex.Matcher;
026    import java.util.regex.Pattern;
027    
028    import javax.servlet.Filter;
029    import javax.servlet.FilterConfig;
030    import javax.servlet.http.HttpServletRequest;
031    
032    /**
033     * @author Mika Koivisto
034     * @author Brian Wing Shun Chan
035     */
036    public class FilterMapping {
037    
038            public FilterMapping(
039                    Filter filter, FilterConfig filterConfig, List<String> urlPatterns,
040                    List<String> dispatchers) {
041    
042                    _filter = filter;
043                    _urlPatterns = urlPatterns;
044    
045                    initFilterConfig(filterConfig);
046                    initDispatchers(dispatchers);
047            }
048    
049            public Filter getFilter() {
050                    return _filter;
051            }
052    
053            public boolean isMatch(
054                    HttpServletRequest request, Dispatcher dispatcher, String uri) {
055    
056                    if (!isMatchDispatcher(dispatcher)) {
057                            return false;
058                    }
059    
060                    boolean matchURLPattern = false;
061    
062                    for (String urlPattern : _urlPatterns) {
063                            if (isMatchURLPattern(uri, urlPattern)) {
064                                    matchURLPattern = true;
065    
066                                    break;
067                            }
068                    }
069    
070                    if (_log.isDebugEnabled()) {
071                            if (matchURLPattern) {
072                                    _log.debug(
073                                            _filter.getClass() + " has a pattern match with " + uri);
074                            }
075                            else {
076                                    _log.debug(
077                                            _filter.getClass() +
078                                                    " does not have a pattern match with " + uri);
079                            }
080                    }
081    
082                    if (!matchURLPattern) {
083                            return false;
084                    }
085    
086                    if (isMatchURLRegexPattern(request, uri)) {
087                            return true;
088                    }
089    
090                    return false;
091            }
092    
093            public boolean isMatchURLRegexPattern(
094                    HttpServletRequest request, String uri) {
095    
096                    String url = uri;
097    
098                    String queryString = request.getQueryString();
099    
100                    if (Validator.isNotNull(queryString)) {
101                            url = url.concat(StringPool.QUESTION).concat(queryString);
102                    }
103    
104                    boolean matchURLRegexPattern = true;
105    
106                    if (_urlRegexPattern != null) {
107                            Matcher matcher = _urlRegexPattern.matcher(url);
108    
109                            matchURLRegexPattern = matcher.find();
110                    }
111    
112                    if (matchURLRegexPattern && (_urlRegexIgnorePattern != null)) {
113                            Matcher matcher = _urlRegexIgnorePattern.matcher(url);
114    
115                            matchURLRegexPattern = !matcher.find();
116                    }
117    
118                    if (_log.isDebugEnabled()) {
119                            if (matchURLRegexPattern) {
120                                    _log.debug(
121                                            _filter.getClass() + " has a regex match with " + url);
122                            }
123                            else {
124                                    _log.debug(
125                                            _filter.getClass() + " does not have a regex match with " +
126                                                    url);
127                            }
128                    }
129    
130                    return matchURLRegexPattern;
131            }
132    
133            public void setFilter(Filter filter) {
134                    _filter = filter;
135            }
136    
137            protected void initDispatchers(List<String> dispatchers) {
138                    for (String dispatcher : dispatchers) {
139                            if (dispatcher.equals("ERROR")) {
140                                    _dispatcherError = true;
141                            }
142                            else if (dispatcher.equals("FORWARD")) {
143                                    _dispatcherForward = true;
144                            }
145                            else if (dispatcher.equals("INCLUDE")) {
146                                    _dispatcherInclude = true;
147                            }
148                            else if (dispatcher.equals("REQUEST")) {
149                                    _dispatcherRequest = true;
150                            }
151                            else {
152                                    throw new IllegalArgumentException(
153                                            "Invalid dispatcher " + dispatcher);
154                            }
155                    }
156    
157                    if (!_dispatcherError && !_dispatcherForward && !_dispatcherInclude &&
158                            !_dispatcherRequest) {
159    
160                            _dispatcherRequest = true;
161                    }
162            }
163    
164            protected void initFilterConfig(FilterConfig filterConfig) {
165                    String urlRegexPattern = GetterUtil.getString(
166                            filterConfig.getInitParameter("url-regex-pattern"));
167    
168                    if (Validator.isNotNull(urlRegexPattern)) {
169                            _urlRegexPattern = Pattern.compile(urlRegexPattern);
170                    }
171    
172                    String urlRegexIgnorePattern = GetterUtil.getString(
173                            filterConfig.getInitParameter("url-regex-ignore-pattern"));
174    
175                    if (Validator.isNotNull(urlRegexIgnorePattern)) {
176                            _urlRegexIgnorePattern = Pattern.compile(urlRegexIgnorePattern);
177                    }
178            }
179    
180            protected boolean isMatchDispatcher(Dispatcher dispatcher) {
181                    if (((dispatcher == Dispatcher.ERROR) && _dispatcherError) ||
182                            ((dispatcher == Dispatcher.FORWARD) && _dispatcherForward) ||
183                            ((dispatcher == Dispatcher.INCLUDE) && _dispatcherInclude) ||
184                            ((dispatcher == Dispatcher.REQUEST) && _dispatcherRequest)) {
185    
186                            return true;
187                    }
188                    else {
189                            return false;
190                    }
191            }
192    
193            protected boolean isMatchURLPattern(String uri, String urlPattern) {
194                    if (urlPattern.equals(uri)) {
195                            return true;
196                    }
197    
198                    if (urlPattern.equals(_SLASH_STAR)) {
199                            return true;
200                    }
201    
202                    if (urlPattern.endsWith(_SLASH_STAR)) {
203                            if (urlPattern.regionMatches(0, uri, 0, urlPattern.length() - 2)) {
204                                    if (uri.length() == (urlPattern.length() - 2)) {
205                                            return true;
206                                    }
207                                    else if (CharPool.SLASH ==
208                                                            uri.charAt(urlPattern.length() - 2)) {
209    
210                                            return true;
211                                    }
212                            }
213                    }
214                    else if (urlPattern.startsWith(_STAR_PERIOD)) {
215                            int slashPos = uri.lastIndexOf(CharPool.SLASH);
216                            int periodPos = uri.lastIndexOf(CharPool.PERIOD);
217    
218                            if ((slashPos >= 0) && (periodPos > slashPos) &&
219                                    (periodPos != (uri.length() - 1)) &&
220                                    ((uri.length() - periodPos) == (urlPattern.length() - 1))) {
221    
222                                    if (urlPattern.regionMatches(
223                                                    2, uri, periodPos + 1, urlPattern.length() - 2)) {
224    
225                                            return true;
226                                    }
227                            }
228                    }
229    
230                    return false;
231            }
232    
233            private static final String _SLASH_STAR = "/*";
234    
235            private static final String _STAR_PERIOD = "*.";
236    
237            private static Log _log = LogFactoryUtil.getLog(FilterMapping.class);
238    
239            private boolean _dispatcherError;
240            private boolean _dispatcherForward;
241            private boolean _dispatcherInclude;
242            private boolean _dispatcherRequest;
243            private Filter _filter;
244            private List<String> _urlPatterns;
245            private Pattern _urlRegexIgnorePattern;
246            private Pattern _urlRegexPattern;
247    
248    }