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      @Override
56      public void init(final FilterConfig filterConfig) throws ServletException {
57          context = filterConfig.getServletContext();
58          name = filterConfig.getInitParameter(CONTEXT_NAME);
59          URI configLocation = null;
60          String configLocn = filterConfig.getInitParameter(CONFIG_LOCATION);
61          if (configLocn != null) {
62              try {
63                  configLocation = new URI(configLocn);
64              } catch (Exception ex) {
65                  context.log("Unable to convert config location " + configLocn + " to a URI: " + ex.getMessage());
66              }
67          }
68  
69          if (name == null) {
70              throw new UnavailableException("A context-name attribute is required");
71          }
72          if (context.getAttribute(Log4jContextListener.LOG4J_CONTEXT_ATTRIBUTE) == null) {
73              LoggerContext ctx;
74              final LoggerContextFactory factory = LogManager.getFactory();
75              if (factory instanceof Log4jContextFactory) {
76                  final ContextSelector sel = ((Log4jContextFactory) factory).getSelector();
77                  if (sel instanceof NamedContextSelector) {
78                      selector = (NamedContextSelector) sel;
79                      ctx = selector.locateContext(name, configLocation);
80                  } else {
81                      return;
82                  }
83              } else {
84                  return;
85              }
86              context.setAttribute(Log4jContextListener.LOG4J_CONTEXT_ATTRIBUTE, ctx);
87              created = true;
88              context.log("Created context for " + name + " using " + ctx.getClass().getClassLoader());
89          }
90      }
91  
92      @Override
93      public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
94                           final FilterChain filterChain)
95          throws IOException, ServletException {
96          final LoggerContext ctx = (LoggerContext) context.getAttribute(Log4jContextListener.LOG4J_CONTEXT_ATTRIBUTE);
97          if (ctx != null) {
98              ContextAnchor.THREAD_CONTEXT.set(ctx);
99              try {
100                 filterChain.doFilter(servletRequest, servletResponse);
101             } finally {
102                 ContextAnchor.THREAD_CONTEXT.remove();
103             }
104         } else {
105             filterChain.doFilter(servletRequest, servletResponse);
106         }
107     }
108 
109     @Override
110     public void destroy() {
111         final LoggerContext ctx = (LoggerContext) context.getAttribute(Log4jContextListener.LOG4J_CONTEXT_ATTRIBUTE);
112         if (ctx != null && created) {
113             context.log("Removing context for " + name);
114             context.removeAttribute(Log4jContextListener.LOG4J_CONTEXT_ATTRIBUTE);
115             if (selector != null) {
116                 selector.removeContext(name);
117             }
118             ctx.stop();
119         }
120     }
121 }