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