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.servlet.DirectCallFilter;
020    import com.liferay.portal.kernel.servlet.LiferayFilter;
021    import com.liferay.portal.kernel.servlet.TryFilter;
022    import com.liferay.portal.kernel.servlet.TryFinallyFilter;
023    import com.liferay.portal.kernel.servlet.WrapHttpServletRequestFilter;
024    import com.liferay.portal.kernel.servlet.WrapHttpServletResponseFilter;
025    
026    import java.io.IOException;
027    
028    import java.util.ArrayList;
029    import java.util.List;
030    
031    import javax.servlet.Filter;
032    import javax.servlet.FilterChain;
033    import javax.servlet.ServletException;
034    import javax.servlet.ServletRequest;
035    import javax.servlet.ServletResponse;
036    import javax.servlet.http.HttpServletRequest;
037    import javax.servlet.http.HttpServletResponse;
038    
039    /**
040     * @author Mika Koivisto
041     * @author Brian Wing Shun Chan
042     * @author Shuyang Zhou
043     */
044    public class InvokerFilterChain implements FilterChain {
045    
046            public InvokerFilterChain(FilterChain filterChain) {
047                    _filterChain = filterChain;
048            }
049    
050            public void addFilter(Filter filter) {
051                    if (_filters == null) {
052                            _filters = new ArrayList<Filter>();
053                    }
054    
055                    _filters.add(filter);
056            }
057    
058            public InvokerFilterChain clone(FilterChain filterChain) {
059                    InvokerFilterChain invokerFilterChain = new InvokerFilterChain(
060                            filterChain);
061    
062                    invokerFilterChain._filters = _filters;
063    
064                    return invokerFilterChain;
065            }
066    
067            public void doFilter(
068                            ServletRequest servletRequest, ServletResponse servletResponse)
069                    throws IOException, ServletException {
070    
071                    if ((_filters == null) || (_index >= _filters.size())) {
072                            _filterChain.doFilter(servletRequest, servletResponse);
073                    }
074                    else {
075                            HttpServletRequest request = (HttpServletRequest)servletRequest;
076                            HttpServletResponse response = (HttpServletResponse)servletResponse;
077    
078                            Filter filter = _filters.get(_index++);
079    
080                            boolean filterEnabled = true;
081    
082                            if (filter instanceof LiferayFilter) {
083                                    LiferayFilter liferayFilter = (LiferayFilter)filter;
084    
085                                    if (!liferayFilter.isFilterEnabled() ||
086                                            !liferayFilter.isFilterEnabled(request, response)) {
087    
088                                            filterEnabled = false;
089                                    }
090                            }
091    
092                            if (filterEnabled) {
093                                    if (filter instanceof DirectCallFilter) {
094                                            try {
095                                                    processDirectCallFilter(filter, request, response);
096                                            }
097                                            catch (IOException ioe) {
098                                                    throw ioe;
099                                            }
100                                            catch (ServletException se) {
101                                                    throw se;
102                                            }
103                                            catch (Exception e) {
104                                                    throw new ServletException(e);
105                                            }
106                                    }
107                                    else {
108                                            processDoFilter(filter, request, response);
109                                    }
110                            }
111                            else {
112                                    if (_log.isDebugEnabled()) {
113                                            _log.debug("Skip disabled filter " + filter.getClass());
114                                    }
115    
116                                    doFilter(request, response);
117                            }
118                    }
119            }
120    
121            public void setContextClassLoader(ClassLoader contextClassLoader) {
122                    _contextClassLoader = contextClassLoader;
123            }
124    
125            protected void processDirectCallFilter(
126                            Filter filter, HttpServletRequest request,
127                            HttpServletResponse response)
128                    throws Exception {
129    
130                    if (filter instanceof WrapHttpServletRequestFilter) {
131                            if (_log.isDebugEnabled()) {
132                                    _log.debug("Wrap response with filter " + filter.getClass());
133                            }
134    
135                            WrapHttpServletRequestFilter wrapHttpServletRequestFilter =
136                                    (WrapHttpServletRequestFilter)filter;
137    
138                            request = wrapHttpServletRequestFilter.getWrappedHttpServletRequest(
139                                    request, response);
140                    }
141    
142                    if (filter instanceof WrapHttpServletResponseFilter) {
143                            if (_log.isDebugEnabled()) {
144                                    _log.debug("Wrap request with filter " + filter.getClass());
145                            }
146    
147                            WrapHttpServletResponseFilter wrapHttpServletResponseFilter =
148                                    (WrapHttpServletResponseFilter)filter;
149    
150                            response =
151                                    wrapHttpServletResponseFilter.getWrappedHttpServletResponse(
152                                            request, response);
153                    }
154    
155                    if (filter instanceof TryFinallyFilter) {
156                            TryFinallyFilter tryFinallyFilter = (TryFinallyFilter)filter;
157    
158                            Object object = null;
159    
160                            try {
161                                    if (_log.isDebugEnabled()) {
162                                            _log.debug("Invoke try for filter " + filter.getClass());
163                                    }
164    
165                                    object = tryFinallyFilter.doFilterTry(request, response);
166    
167                                    doFilter(request, response);
168                            }
169                            finally {
170                                    if (_log.isDebugEnabled()) {
171                                            _log.debug(
172                                                    "Invoke finally for filter " + filter.getClass());
173                                    }
174    
175                                    tryFinallyFilter.doFilterFinally(request, response, object);
176                            }
177                    }
178                    else if (filter instanceof TryFilter) {
179                            TryFilter tryFilter = (TryFilter)filter;
180    
181                            if (_log.isDebugEnabled()) {
182                                    _log.debug("Invoke try for filter " + filter.getClass());
183                            }
184    
185                            tryFilter.doFilterTry(request, response);
186    
187                            doFilter(request, response);
188                    }
189                    else {
190                            doFilter(request, response);
191                    }
192            }
193    
194            protected void processDoFilter(
195                            Filter filter, ServletRequest servletRequest,
196                            ServletResponse servletResponse)
197                    throws IOException, ServletException {
198    
199                    Thread currentThread = Thread.currentThread();
200    
201                    ClassLoader contextClassLoader = currentThread.getContextClassLoader();
202    
203                    currentThread.setContextClassLoader(_contextClassLoader);
204    
205                    try {
206                            filter.doFilter(servletRequest, servletResponse, this);
207                    }
208                    finally {
209                            currentThread.setContextClassLoader(contextClassLoader);
210                    }
211            }
212    
213            private static Log _log = LogFactoryUtil.getLog(InvokerFilterChain.class);
214    
215            private ClassLoader _contextClassLoader;
216            private FilterChain _filterChain;
217            private List<Filter> _filters;
218            private int _index;
219    
220    }