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.web.appender;
18  
19  import java.io.Serializable;
20  
21  import javax.servlet.ServletContext;
22  
23  import org.apache.logging.log4j.core.Filter;
24  import org.apache.logging.log4j.core.Layout;
25  import org.apache.logging.log4j.core.LogEvent;
26  import org.apache.logging.log4j.core.appender.AbstractAppender;
27  import org.apache.logging.log4j.core.config.Property;
28  import org.apache.logging.log4j.core.config.plugins.Plugin;
29  import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
30  import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
31  import org.apache.logging.log4j.core.layout.AbstractStringLayout;
32  import org.apache.logging.log4j.core.layout.PatternLayout;
33  import org.apache.logging.log4j.web.WebLoggerContextUtils;
34  
35  /**
36   * Logs using the ServletContext's log method
37   */
38  @Plugin(name = "Servlet", category = "Core", elementType = "appender", printObject = true)
39  public class ServletAppender extends AbstractAppender {
40  
41  	public static class Builder<B extends Builder<B>> extends AbstractAppender.Builder<B>
42  			implements org.apache.logging.log4j.core.util.Builder<ServletAppender> {
43  
44          @PluginBuilderAttribute
45          private boolean logThrowables;
46  
47  		@Override
48  		public ServletAppender build() {
49  			final String name = getName();
50  			if (name == null) {
51  				LOGGER.error("No name provided for ServletAppender");
52  			}
53  			final ServletContext servletContext = WebLoggerContextUtils.getServletContext();
54  			if (servletContext == null) {
55  				LOGGER.error("No servlet context is available");
56  				return null;
57  			}
58  			Layout<? extends Serializable> layout = getLayout();
59  			if (layout == null) {
60  				layout = PatternLayout.createDefaultLayout();
61  			} else if (!(layout instanceof AbstractStringLayout)) {
62  				LOGGER.error("Layout must be a StringLayout to log to ServletContext");
63  				return null;
64  			}
65  			return new ServletAppender(name, layout, getFilter(), servletContext, isIgnoreExceptions(), logThrowables);
66  		}
67  
68          /**
69           * Logs with {@link ServletContext#log(String, Throwable)} if true and with {@link ServletContext#log(String)} if false.
70           *
71           * @return whether to log a Throwable with the servlet context.
72           */
73          public boolean isLogThrowables() {
74              return logThrowables;
75          }
76  
77          /**
78           * Logs with {@link ServletContext#log(String, Throwable)} if true and with {@link ServletContext#log(String)} if false.
79           */
80          public void setLogThrowables(final boolean logThrowables) {
81              this.logThrowables = logThrowables;
82          }
83  
84  	}
85  
86      @PluginBuilderFactory
87      public static <B extends Builder<B>> B newBuilder() {
88          return new Builder<B>().asBuilder();
89      }
90  
91      private final ServletContext servletContext;
92      private final boolean logThrowables;
93  
94      private ServletAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
95              final ServletContext servletContext, final boolean ignoreExceptions, final boolean logThrowables) {
96          super(name, filter, layout, ignoreExceptions, Property.EMPTY_ARRAY);
97          this.servletContext = servletContext;
98          this.logThrowables = logThrowables;
99      }
100 
101     @Override
102     public void append(final LogEvent event) {
103         final String serialized = ((AbstractStringLayout) getLayout()).toSerializable(event);
104         if (logThrowables) {
105             servletContext.log(serialized, event.getThrown());
106         } else {
107             servletContext.log(serialized);
108         }
109     }
110 
111     /**
112      * Creates a Servlet Appender.
113      * @param layout The layout to use (required). Must extend {@link AbstractStringLayout}.
114      * @param filter The Filter or null.
115      * @param name The name of the Appender (required).
116      * @param ignoreExceptions If {@code true} (default) exceptions encountered when appending events are logged;
117      *                         otherwise they are propagated to the caller.
118      * @return The ServletAppender.
119      * @deprecated Use {@link #newBuilder()}.
120      */
121     @Deprecated
122     public static ServletAppender createAppender(final Layout<? extends Serializable> layout, final Filter filter,
123             final String name, final boolean ignoreExceptions) {
124         // @formatter:off
125     	return newBuilder().setFilter(filter).setIgnoreExceptions(ignoreExceptions).setLayout(layout).setName(name)
126     			.build();
127     	// @formatter:on
128     }
129 
130 }