/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 1997-2013 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html * or packager/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at packager/legal/LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" * exception as provided by Oracle in the GPL Version 2 section of the License * file that accompanied this code. * * Modifications: * If applicable, add the following below the License Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyright [year] [name of copyright owner]" * * Contributor(s): * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. * * * This file incorporates work covered by the following copyright and * permission notice: * * Copyright 2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.catalina.core; import org.apache.catalina.Globals; import org.apache.catalina.security.SecurityUtil; import org.apache.catalina.util.InstanceSupport; import org.glassfish.logging.annotation.LogMessageInfo; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.security.Principal; import java.security.PrivilegedActionException; import java.util.ResourceBundle; import java.util.logging.Logger; import static org.apache.catalina.InstanceEvent.EventType.AFTER_FILTER_EVENT; import static org.apache.catalina.InstanceEvent.EventType.BEFORE_FILTER_EVENT; /** * Implementation of <code>javax.servlet.FilterChain</code> used to manage * the execution of a set of filters for a particular request. When the * set of defined filters has all been executed, the next call to * <code>doFilter()</code> will execute the servlet's <code>service()</code> * method itself. * * @author Craig R. McClanahan * @version $Revision: 1.6 $ $Date: 2006/11/21 17:39:39 $ */ final class ApplicationFilterChain implements FilterChain { private static final Logger log = StandardServer.log; private static final ResourceBundle rb = log.getResourceBundle(); @LogMessageInfo( message = "Filter execution threw an exception", level = "WARNING" ) public static final String FILTER_EXECUTION_EXCEPTION = "AS-WEB-CORE-00097"; // -------------------------------------------------------------- Constants public static final int INCREMENT = 10; // ----------------------------------------------------------- Constructors /** * Construct a new chain instance with no defined filters. */ public ApplicationFilterChain() { super(); } // ----------------------------------------------------- Instance Variables /** * Filters. */ private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0]; /** * The int which is used to maintain the current position * in the filter chain. */ private int pos = 0; /** * The int which gives the current number of filters in the chain. */ private int n = 0; /** * The servlet instance to be executed by this chain. */ private Servlet servlet = null; /** * The wrapper around the servlet instance to be executed by this chain. */ private StandardWrapper wrapper = null; /** * Static class array used when the SecurityManager is turned on and * <code>doFilter</code is invoked. */ private static Class<?>[] classType = new Class[]{ServletRequest.class, ServletResponse.class, FilterChain.class}; /** * Static class array used when the SecurityManager is turned on and * <code>service</code is invoked. */ /* IASRI 4665318 private static Class<?>[] classTypeUsedInService = new Class[]{ ServletRequest.class, ServletResponse.class}; */ // ---------------------------------------------------- FilterChain Methods /** * Invoke the next filter in this chain, passing the specified request * and response. If there are no more filters in this chain, invoke * the <code>service()</code> method of the servlet itself. * * @param request The servlet request we are processing * @param response The servlet response we are creating * * @exception IOException if an input/output error occurs * @exception ServletException if a servlet exception occurs */ public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if (Globals.IS_SECURITY_ENABLED) { final ServletRequest req = request; final ServletResponse res = response; try { java.security.AccessController.doPrivileged( new java.security.PrivilegedExceptionAction<Void>() { public Void run() throws ServletException, IOException { internalDoFilter(req,res); return null; } } ); } catch( PrivilegedActionException pe) { Exception e = pe.getException(); if (e instanceof ServletException) throw (ServletException) e; else if (e instanceof IOException) throw (IOException) e; else if (e instanceof RuntimeException) throw (RuntimeException) e; else throw new ServletException(e.getMessage(), e); } } else { internalDoFilter(request,response); } } private void internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if (wrapper == null) { throw new IllegalStateException("Missing wrapper"); } InstanceSupport support = wrapper.getInstanceSupport(); // Call the next filter if there is one if (pos < n) { ApplicationFilterConfig filterConfig = filters[pos++]; if (!filterConfig.isAsyncSupported()) { RequestFacadeHelper reqFacHelper = RequestFacadeHelper.getInstance(request); if (reqFacHelper != null) { reqFacHelper.disableAsyncSupport(); } } Filter filter = null; try { filter = filterConfig.getFilter(); support.fireInstanceEvent(BEFORE_FILTER_EVENT, filter, request, response); if( SecurityUtil.isPackageProtectionEnabled() ) { final ServletRequest req = request; final ServletResponse res = response; Principal principal = ((HttpServletRequest) req).getUserPrincipal(); Object[] filterType = new Object[3]; filterType[0] = req; filterType[1] = res; filterType[2] = this; SecurityUtil.doAsPrivilege ("doFilter", filter, classType, filterType, principal); } else { filter.doFilter(request, response, this); } support.fireInstanceEvent(AFTER_FILTER_EVENT, filter, request, response); } catch (IOException e) { if (filter != null) support.fireInstanceEvent(AFTER_FILTER_EVENT, filter, request, response, e); throw e; } catch (ServletException e) { if (filter != null) support.fireInstanceEvent(AFTER_FILTER_EVENT, filter, request, response, e); throw e; } catch (RuntimeException e) { if (filter != null) support.fireInstanceEvent(AFTER_FILTER_EVENT, filter, request, response, e); throw e; } catch (Throwable e) { if (filter != null) support.fireInstanceEvent(AFTER_FILTER_EVENT, filter, request, response, e); throw new ServletException (rb.getString(FILTER_EXECUTION_EXCEPTION), e); } return; } // We fell off the end of the chain -- call the servlet instance /* IASRI 4665318 try { support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT, servlet, request, response); if ((request instanceof HttpServletRequest) && (response instanceof HttpServletResponse)) { // START SJS WS 7.0 6236329 //if( System.getSecurityManager() != null) { if ( SecurityUtil.executeUnderSubjectDoAs() ){ // END OF SJS WS 7.0 6236329 final ServletRequest req = request; final ServletResponse res = response; Principal principal = ((HttpServletRequest) req).getUserPrincipal(); Object[] serviceType = new Object[2]; serviceType[0] = req; serviceType[1] = res; SecurityUtil.doAsPrivilege("service", servlet, classTypeUsedInService, serviceType, principal); serviceType = null; } else { servlet.service((HttpServletRequest) request, (HttpServletResponse) response); } } else { servlet.service(request, response); } support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response); } catch (IOException e) { support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e); throw e; } catch (ServletException e) { support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e); throw e; } catch (RuntimeException e) { support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e); throw e; } catch (Throwable e) { support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e); throw new ServletException (sm.getString("filterChain.servlet"), e); //filterChain.servlet=PWC1244: Servlet execution threw an exception } */ // START IASRI 4665318 wrapper.service(request, response, servlet); // END IASRI 4665318 } // -------------------------------------------------------- Package Methods /** * Add a filter to the set of filters that will be executed in this chain. * * @param filterConfig The FilterConfig for the servlet to be executed */ void addFilter(ApplicationFilterConfig filterConfig) { if (n == filters.length) { ApplicationFilterConfig[] newFilters = new ApplicationFilterConfig[n + INCREMENT]; System.arraycopy(filters, 0, newFilters, 0, n); filters = newFilters; } filters[n++] = filterConfig; } /** * Release references to the filters and wrapper executed by this chain. */ void release() { n = 0; pos = 0; servlet = null; wrapper = null; } /** * Sets the Servlet instance that will be executed at the end of this * Filter chain. * * @param servlet the Servlet instance that will be executed at the end * of this Filter chain. */ void setServlet(Servlet servlet) { this.servlet = servlet; } /** * Sets the wrapper of the Servlet that will be executed at the end of * this Filter chain. * * @param wrapper the wrapper of the Servlet that will be executed at * the end of this Filter chain. */ void setWrapper(StandardWrapper wrapper) { this.wrapper = wrapper; } }