001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    
019    package org.apache.hadoop.lib.servlet;
020    
021    import org.apache.hadoop.classification.InterfaceAudience;
022    import org.slf4j.MDC;
023    
024    import javax.servlet.Filter;
025    import javax.servlet.FilterChain;
026    import javax.servlet.FilterConfig;
027    import javax.servlet.ServletException;
028    import javax.servlet.ServletRequest;
029    import javax.servlet.ServletResponse;
030    import javax.servlet.http.HttpServletRequest;
031    import java.io.IOException;
032    import java.security.Principal;
033    
034    /**
035     * Filter that sets request contextual information for the slf4j MDC.
036     * <p/>
037     * It sets the following values:
038     * <ul>
039     * <li>hostname: if the {@link HostnameFilter} is present and configured
040     * before this filter</li>
041     * <li>user: the <code>HttpServletRequest.getUserPrincipal().getName()</code></li>
042     * <li>method: the HTTP method fo the request (GET, POST, ...)</li>
043     * <li>path: the path of the request URL</li>
044     * </ul>
045     */
046    @InterfaceAudience.Private
047    public class MDCFilter implements Filter {
048    
049      /**
050       * Initializes the filter.
051       * <p/>
052       * This implementation is a NOP.
053       *
054       * @param config filter configuration.
055       *
056       * @throws ServletException thrown if the filter could not be initialized.
057       */
058      @Override
059      public void init(FilterConfig config) throws ServletException {
060      }
061    
062      /**
063       * Sets the slf4j <code>MDC</code> and delegates the request to the chain.
064       *
065       * @param request servlet request.
066       * @param response servlet response.
067       * @param chain filter chain.
068       *
069       * @throws IOException thrown if an IO error occurrs.
070       * @throws ServletException thrown if a servet error occurrs.
071       */
072      @Override
073      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
074        throws IOException, ServletException {
075        try {
076          MDC.clear();
077          String hostname = HostnameFilter.get();
078          if (hostname != null) {
079            MDC.put("hostname", HostnameFilter.get());
080          }
081          Principal principal = ((HttpServletRequest) request).getUserPrincipal();
082          String user = (principal != null) ? principal.getName() : null;
083          if (user != null) {
084            MDC.put("user", user);
085          }
086          MDC.put("method", ((HttpServletRequest) request).getMethod());
087          MDC.put("path", ((HttpServletRequest) request).getPathInfo());
088          chain.doFilter(request, response);
089        } finally {
090          MDC.clear();
091        }
092      }
093    
094      /**
095       * Destroys the filter.
096       * <p/>
097       * This implementation is a NOP.
098       */
099      @Override
100      public void destroy() {
101      }
102    }
103