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                                    filterEnabled = liferayFilter.isFilterEnabled(
086                                            request, response);
087                            }
088    
089                            if (filterEnabled) {
090                                    if (filter instanceof DirectCallFilter) {
091                                            try {
092                                                    processDirectCallFilter(filter, request, response);
093                                            }
094                                            catch (IOException ioe) {
095                                                    throw ioe;
096                                            }
097                                            catch (ServletException se) {
098                                                    throw se;
099                                            }
100                                            catch (Exception e) {
101                                                    throw new ServletException(e);
102                                            }
103                                    }
104                                    else {
105                                            processDoFilter(filter, request, response);
106                                    }
107                            }
108                            else {
109                                    if (_log.isDebugEnabled()) {
110                                            _log.debug("Skip disabled filter " + filter.getClass());
111                                    }
112    
113                                    doFilter(request, response);
114                            }
115                    }
116            }
117    
118            public void setContextClassLoader(ClassLoader contextClassLoader) {
119                    _contextClassLoader = contextClassLoader;
120            }
121    
122            protected void processDirectCallFilter(
123                            Filter filter, HttpServletRequest request,
124                            HttpServletResponse response)
125                    throws Exception {
126    
127                    if (filter instanceof WrapHttpServletRequestFilter) {
128                            if (_log.isDebugEnabled()) {
129                                    _log.debug("Wrap response with filter " + filter.getClass());
130                            }
131    
132                            WrapHttpServletRequestFilter wrapHttpServletRequestFilter =
133                                    (WrapHttpServletRequestFilter)filter;
134    
135                            request = wrapHttpServletRequestFilter.getWrappedHttpServletRequest(
136                                    request, response);
137                    }
138    
139                    if (filter instanceof WrapHttpServletResponseFilter) {
140                            if (_log.isDebugEnabled()) {
141                                    _log.debug("Wrap request with filter " + filter.getClass());
142                            }
143    
144                            WrapHttpServletResponseFilter wrapHttpServletResponseFilter =
145                                    (WrapHttpServletResponseFilter)filter;
146    
147                            response =
148                                    wrapHttpServletResponseFilter.getWrappedHttpServletResponse(
149                                            request, response);
150                    }
151    
152                    if (filter instanceof TryFinallyFilter) {
153                            TryFinallyFilter tryFinallyFilter = (TryFinallyFilter)filter;
154    
155                            Object object = null;
156    
157                            try {
158                                    if (_log.isDebugEnabled()) {
159                                            _log.debug("Invoke try for filter " + filter.getClass());
160                                    }
161    
162                                    object = tryFinallyFilter.doFilterTry(request, response);
163    
164                                    doFilter(request, response);
165                            }
166                            finally {
167                                    if (_log.isDebugEnabled()) {
168                                            _log.debug(
169                                                    "Invoke finally for filter " + filter.getClass());
170                                    }
171    
172                                    tryFinallyFilter.doFilterFinally(request, response, object);
173                            }
174                    }
175                    else if (filter instanceof TryFilter) {
176                            TryFilter tryFilter = (TryFilter)filter;
177    
178                            if (_log.isDebugEnabled()) {
179                                    _log.debug("Invoke try for filter " + filter.getClass());
180                            }
181    
182                            tryFilter.doFilterTry(request, response);
183    
184                            doFilter(request, response);
185                    }
186                    else {
187                            doFilter(request, response);
188                    }
189            }
190    
191            protected void processDoFilter(
192                            Filter filter, ServletRequest servletRequest,
193                            ServletResponse servletResponse)
194                    throws IOException, ServletException {
195    
196                    Thread currentThread = Thread.currentThread();
197    
198                    ClassLoader contextClassLoader = currentThread.getContextClassLoader();
199    
200                    currentThread.setContextClassLoader(_contextClassLoader);
201    
202                    try {
203                            filter.doFilter(servletRequest, servletResponse, this);
204                    }
205                    finally {
206                            currentThread.setContextClassLoader(contextClassLoader);
207                    }
208            }
209    
210            private static Log _log = LogFactoryUtil.getLog(InvokerFilterChain.class);
211    
212            private ClassLoader _contextClassLoader;
213            private FilterChain _filterChain;
214            private List<Filter> _filters;
215            private int _index;
216    
217    }