View Javadoc
1   /*
2    * Copyright (c) 2012-2022, jcabi.com
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met: 1) Redistributions of source code must retain the above
8    * copyright notice, this list of conditions and the following
9    * disclaimer. 2) Redistributions in binary form must reproduce the above
10   * copyright notice, this list of conditions and the following
11   * disclaimer in the documentation and/or other materials provided
12   * with the distribution. 3) Neither the name of the jcabi.com nor
13   * the names of its contributors may be used to endorse or promote
14   * products derived from this software without specific prior written
15   * permission.
16   *
17   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
19   * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21   * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28   * OF THE POSSIBILITY OF SUCH DAMAGE.
29   */
30  package com.jcabi.slf4j;
31  
32  import lombok.EqualsAndHashCode;
33  import lombok.ToString;
34  import org.apache.maven.plugin.logging.Log;
35  import org.slf4j.Marker;
36  import org.slf4j.event.Level;
37  import org.slf4j.helpers.FormattingTuple;
38  import org.slf4j.helpers.LegacyAbstractLogger;
39  import org.slf4j.helpers.MessageFormatter;
40  
41  /**
42   * Implementation of {@link org.slf4j.Logger} transforming SLF4J messages
43   * to Maven log messages.
44   *
45   * <p>The class has too many methods, but
46   * we can't do anything with this since the parent class requires
47   * us to implement them all.
48   *
49   * <p>The class is thread-safe.
50   *
51   * @since 0.1.6
52   * @see <a href="http://www.slf4j.org/faq.html#slf4j_compatible">SLF4J FAQ</a>
53   */
54  @ToString
55  @EqualsAndHashCode(callSuper = false)
56  @SuppressWarnings("PMD.TooManyMethods")
57  final class Slf4jAdapter extends LegacyAbstractLogger {
58  
59      /**
60       * Serialization ID.
61       */
62      public static final long serialVersionUID = 0x12C0976798AB5439L;
63  
64      /**
65       * The log to use.
66       */
67      @SuppressWarnings("PMD.ProperLogger")
68      private final transient Log mlog;
69  
70      /**
71       * The name of the log.
72       */
73      private final transient String label;
74  
75      /**
76       * Public ctor.
77       * @param log The log to use
78       * @param name The label of the logger
79       */
80      Slf4jAdapter(final Log log, final String name) {
81          super();
82          this.mlog = log;
83          this.label = name;
84      }
85  
86      @Override
87      public String getName() {
88          return this.getClass().getName();
89      }
90  
91      @Override
92      public boolean isTraceEnabled() {
93          return false;
94      }
95  
96      @Override
97      public void trace(final String msg) {
98          this.mlog.debug(this.decorate(msg));
99      }
100 
101     @Override
102     public void trace(final String format, final Object arg) {
103         this.mlog.debug(this.decorate(Slf4jAdapter.format(format, arg)));
104     }
105 
106     @Override
107     public void trace(final String format, final Object first,
108         final Object second) {
109         this.mlog.debug(this.decorate(Slf4jAdapter.format(format, first, second)));
110     }
111 
112     @Override
113     public void trace(final String format, final Object... array) {
114         this.mlog.debug(this.decorate(Slf4jAdapter.format(format, array)));
115     }
116 
117     @Override
118     public void trace(final String msg, final Throwable thr) {
119         this.mlog.debug(this.decorate(msg), thr);
120     }
121 
122     @Override
123     public boolean isDebugEnabled() {
124         return this.mlog.isDebugEnabled();
125     }
126 
127     @Override
128     public void debug(final String msg) {
129         this.mlog.debug(this.decorate(msg));
130     }
131 
132     @Override
133     public void debug(final String format, final Object arg) {
134         this.mlog.debug(this.decorate(Slf4jAdapter.format(format, arg)));
135     }
136 
137     @Override
138     public void debug(final String format, final Object first,
139         final Object second) {
140         this.mlog.debug(this.decorate(Slf4jAdapter.format(format, first, second)));
141     }
142 
143     @Override
144     public void debug(final String format, final Object... array) {
145         this.mlog.debug(this.decorate(Slf4jAdapter.format(format, array)));
146     }
147 
148     @Override
149     public void debug(final String msg, final Throwable thr) {
150         this.mlog.debug(this.decorate(msg), thr);
151     }
152 
153     @Override
154     public boolean isInfoEnabled() {
155         return true;
156     }
157 
158     @Override
159     public void info(final String msg) {
160         this.mlog.info(msg);
161     }
162 
163     @Override
164     public void info(final String format, final Object arg) {
165         this.mlog.info(Slf4jAdapter.format(format, arg));
166     }
167 
168     @Override
169     public void info(final String format, final Object first,
170         final Object second) {
171         this.mlog.info(Slf4jAdapter.format(format, first, second));
172     }
173 
174     @Override
175     public void info(final String format, final Object... array) {
176         this.mlog.info(Slf4jAdapter.format(format, array));
177     }
178 
179     @Override
180     public void info(final String msg, final Throwable thr) {
181         this.mlog.info(msg, thr);
182     }
183 
184     @Override
185     public boolean isWarnEnabled() {
186         return true;
187     }
188 
189     @Override
190     public void warn(final String msg) {
191         this.mlog.warn(msg);
192     }
193 
194     @Override
195     public void warn(final String format, final Object arg) {
196         this.mlog.warn(Slf4jAdapter.format(format, arg));
197     }
198 
199     @Override
200     public void warn(final String format, final Object... array) {
201         this.mlog.warn(Slf4jAdapter.format(format, array));
202     }
203 
204     @Override
205     public void warn(final String format, final Object first,
206         final Object second) {
207         this.mlog.warn(Slf4jAdapter.format(format, first, second));
208     }
209 
210     @Override
211     public void warn(final String msg, final Throwable thr) {
212         this.mlog.warn(msg, thr);
213     }
214 
215     @Override
216     public boolean isErrorEnabled() {
217         return true;
218     }
219 
220     @Override
221     public void error(final String msg) {
222         this.mlog.error(msg);
223     }
224 
225     @Override
226     public void error(final String format, final Object arg) {
227         this.mlog.error(Slf4jAdapter.format(format, arg));
228     }
229 
230     @Override
231     public void error(final String format, final Object first,
232         final Object second) {
233         this.mlog.error(Slf4jAdapter.format(format, first, second));
234     }
235 
236     @Override
237     public void error(final String format, final Object... array) {
238         this.mlog.error(Slf4jAdapter.format(format, array));
239     }
240 
241     @Override
242     public void error(final String msg, final Throwable thr) {
243         this.mlog.error(msg, thr);
244     }
245 
246     @Override
247     public String getFullyQualifiedCallerName() {
248         return "jcabi-maven-slf4j";
249     }
250 
251     @Override
252     public void handleNormalizedLoggingCall(final Level level, final Marker marker,
253         final String msg, final Object[] arguments, final Throwable throwable) {
254         throw new UnsupportedOperationException("we should not reach this point ever");
255     }
256 
257     /**
258      * Format with one object.
259      * @param format Format to use
260      * @param arg One argument
261      * @return The message
262      */
263     private static String format(final String format, final Object arg) {
264         final FormattingTuple tuple =
265             MessageFormatter.format(format, arg);
266         return tuple.getMessage();
267     }
268 
269     /**
270      * Format with two objects.
271      * @param format Format to use
272      * @param first First argument
273      * @param second Second argument
274      * @return The message
275      */
276     private static String format(final String format, final Object first,
277         final Object second) {
278         final FormattingTuple tuple =
279             MessageFormatter.format(format, first, second);
280         return tuple.getMessage();
281     }
282 
283     /**
284      * Format with array.
285      * @param format Format to use
286      * @param array List of arguments
287      * @return The message
288      */
289     private static String format(final String format, final Object... array) {
290         final FormattingTuple tuple =
291             MessageFormatter.format(format, array);
292         return tuple.getMessage();
293     }
294 
295     /**
296      * Decorate a message with a label prefix.
297      * @param msg The text to decorate
298      * @return The message decorated
299      */
300     private String decorate(final String msg) {
301         return String.format(
302             "%s %s: %s",
303             Thread.currentThread().getName(),
304             this.label,
305             msg
306         );
307     }
308 
309 }