View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  package org.apache.logging.log4j.core.web;
18  
19  import org.apache.logging.log4j.LogManager;
20  import org.apache.logging.log4j.core.impl.ContextAnchor;
21  import org.apache.logging.log4j.core.impl.Log4jContextFactory;
22  import org.apache.logging.log4j.core.selector.ContextSelector;
23  import org.apache.logging.log4j.core.LoggerContext;
24  import org.apache.logging.log4j.core.selector.NamedContextSelector;
25  import org.apache.logging.log4j.spi.LoggerContextFactory;
26  
27  import javax.servlet.Filter;
28  import javax.servlet.FilterChain;
29  import javax.servlet.FilterConfig;
30  import javax.servlet.ServletContext;
31  import javax.servlet.ServletException;
32  import javax.servlet.ServletRequest;
33  import javax.servlet.ServletResponse;
34  import javax.servlet.UnavailableException;
35  import java.io.IOException;
36  import java.net.URI;
37  
38  /**
39   * ServletFilter than may be used to set up a LoggerContext for each web application.
40   */
41  public class JNDIContextFilter implements Filter {
42      /**
43       * The Filter init parameter that defines the name of the LoggerContext.
44       */
45      public static final String CONTEXT_NAME = "context-name";
46      /**
47       * The Filter init parameter that defines the configuration location for the LoggerContext.
48       */
49      public static final String CONFIG_LOCATION = "config-location";
50      private ServletContext context;
51      private boolean created = false;
52      private String name;
53      private NamedContextSelector selector = null;
54  
55      public void init(final FilterConfig filterConfig) throws ServletException {
56          context = filterConfig.getServletContext();
57          name = filterConfig.getInitParameter(CONTEXT_NAME);
58          URI configLocation = null;
59          String configLocn = filterConfig.getInitParameter(CONFIG_LOCATION);
60          if (configLocn != null) {
61              try {
62                  configLocation = new URI(configLocn);
63              } catch (Exception ex) {
64                  context.log("Unable to convert config location " + configLocn + " to a URI: " + ex.getMessage());
65              }
66          }
67  
68          if (name == null) {
69              throw new UnavailableException("A context-name attribute is required");
70          }
71          if (context.getAttribute(Log4jContextListener.LOG4J_CONTEXT_ATTRIBUTE) == null) {
72              LoggerContext ctx;
73              final LoggerContextFactory factory = LogManager.getFactory();
74              if (factory instanceof Log4jContextFactory) {
75                  final ContextSelector sel = ((Log4jContextFactory) factory).getSelector();
76                  if (sel instanceof NamedContextSelector) {
77                      selector = (NamedContextSelector) sel;
78                      ctx = selector.locateContext(name, configLocation);
79                  } else {
80                      return;
81                  }
82              } else {
83                  return;
84              }
85              context.setAttribute(Log4jContextListener.LOG4J_CONTEXT_ATTRIBUTE, ctx);
86              created = true;
87              context.log("Created context for " + name + " using " + ctx.getClass().getClassLoader());
88          }
89      }
90  
91      public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
92                           final FilterChain filterChain)
93          throws IOException, ServletException {
94          final LoggerContext ctx = (LoggerContext) context.getAttribute(Log4jContextListener.LOG4J_CONTEXT_ATTRIBUTE);
95          if (ctx != null) {
96              ContextAnchor.THREAD_CONTEXT.set(ctx);
97              try {
98                  filterChain.doFilter(servletRequest, servletResponse);
99              } finally {
100                 ContextAnchor.THREAD_CONTEXT.remove();
101             }
102         } else {
103             filterChain.doFilter(servletRequest, servletResponse);
104         }
105     }
106 
107     public void destroy() {
108         final LoggerContext ctx = (LoggerContext) context.getAttribute(Log4jContextListener.LOG4J_CONTEXT_ATTRIBUTE);
109         if (ctx != null && created) {
110             context.log("Removing context for " + name);
111             context.removeAttribute(Log4jContextListener.LOG4J_CONTEXT_ATTRIBUTE);
112             if (selector != null) {
113                 selector.removeContext(name);
114             }
115             ctx.stop();
116         }
117     }
118 }