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.appender;
18  
19  import java.io.Writer;
20  
21  import org.apache.logging.log4j.core.Filter;
22  import org.apache.logging.log4j.core.StringLayout;
23  import org.apache.logging.log4j.core.config.plugins.Plugin;
24  import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
25  import org.apache.logging.log4j.core.config.plugins.PluginFactory;
26  import org.apache.logging.log4j.core.layout.PatternLayout;
27  import org.apache.logging.log4j.core.util.CloseShieldWriter;
28  
29  /**
30   * Appends log events to a {@link Writer}.
31   */
32  @Plugin(name = "Writer", category = "Core", elementType = "appender", printObject = true)
33  public final class WriterAppender extends AbstractWriterAppender<WriterManager> {
34  
35      /**
36       * Builds WriterAppender instances.
37       */
38      public static class Builder implements org.apache.logging.log4j.core.util.Builder<WriterAppender> {
39  
40          private Filter filter;
41  
42          private boolean follow = false;
43  
44          private boolean ignoreExceptions = true;
45  
46          private StringLayout layout = PatternLayout.createDefaultLayout();
47  
48          private String name;
49  
50          private Writer target;
51  
52          @Override
53          public WriterAppender build() {
54              return new WriterAppender(name, layout, filter, getManager(target, follow, layout), ignoreExceptions);
55          }
56  
57          public Builder setFilter(final Filter aFilter) {
58              this.filter = aFilter;
59              return this;
60          }
61  
62          public Builder setFollow(final boolean shouldFollow) {
63              this.follow = shouldFollow;
64              return this;
65          }
66  
67          public Builder setIgnoreExceptions(final boolean shouldIgnoreExceptions) {
68              this.ignoreExceptions = shouldIgnoreExceptions;
69              return this;
70          }
71  
72          public Builder setLayout(final StringLayout aLayout) {
73              this.layout = aLayout;
74              return this;
75          }
76  
77          public Builder setName(final String aName) {
78              this.name = aName;
79              return this;
80          }
81  
82          public Builder setTarget(final Writer aTarget) {
83              this.target = aTarget;
84              return this;
85          }
86      }
87      /**
88       * Holds data to pass to factory method.
89       */
90      private static class FactoryData {
91          private final StringLayout layout;
92          private final String name;
93          private final Writer writer;
94  
95          /**
96           * Builds instances.
97           * 
98           * @param writer
99           *            The OutputStream.
100          * @param type
101          *            The name of the target.
102          * @param layout
103          *            A String layout
104          */
105         public FactoryData(final Writer writer, final String type, final StringLayout layout) {
106             this.writer = writer;
107             this.name = type;
108             this.layout = layout;
109         }
110     }
111 
112     private static class WriterManagerFactory implements ManagerFactory<WriterManager, FactoryData> {
113 
114         /**
115          * Creates a WriterManager.
116          * 
117          * @param name
118          *            The name of the entity to manage.
119          * @param data
120          *            The data required to create the entity.
121          * @return The WriterManager
122          */
123         @Override
124         public WriterManager createManager(final String name, final FactoryData data) {
125             return new WriterManager(data.writer, data.name, data.layout, true);
126         }
127     }
128 
129     private static WriterManagerFactory factory = new WriterManagerFactory();
130 
131     /**
132      * Creates a WriterAppender.
133      * 
134      * @param layout
135      *            The layout to use or null to get the default layout.
136      * @param filter
137      *            The Filter or null.
138      * @param target
139      *            The target Writer
140      * @param follow
141      *            If true will follow changes to the underlying output stream.
142      *            Use false as the default.
143      * @param name
144      *            The name of the Appender (required).
145      * @param ignore
146      *            If {@code "true"} (default) exceptions encountered when
147      *            appending events are logged; otherwise they are propagated to
148      *            the caller. Use true as the default.
149      * @return The ConsoleAppender.
150      */
151     @PluginFactory
152     public static WriterAppender createAppender(StringLayout layout, final Filter filter, final Writer target,
153             final String name, final boolean follow, final boolean ignore) {
154         if (name == null) {
155             LOGGER.error("No name provided for WriterAppender");
156             return null;
157         }
158         if (layout == null) {
159             layout = PatternLayout.createDefaultLayout();
160         }
161         return new WriterAppender(name, layout, filter, getManager(target, follow, layout), ignore);
162     }
163 
164     private static WriterManager getManager(final Writer target, final boolean follow, final StringLayout layout) {
165         final Writer writer = new CloseShieldWriter(target);
166         final String managerName = target.getClass().getName() + "@" + Integer.toHexString(target.hashCode()) + '.'
167                 + follow;
168         return WriterManager.getManager(managerName, new FactoryData(writer, managerName, layout), factory);
169     }
170 
171     @PluginBuilderFactory
172     public static Builder newBuilder() {
173         return new Builder();
174     }
175 
176     private WriterAppender(final String name, final StringLayout layout, final Filter filter,
177             final WriterManager manager, final boolean ignoreExceptions) {
178         super(name, layout, filter, ignoreExceptions, true, manager);
179     }
180 
181 }