001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017
018package org.apache.logging.log4j.core.tools;
019
020import java.io.PrintStream;
021import java.util.ArrayList;
022import java.util.Arrays;
023import java.util.List;
024
025/**
026 * Generates source code for custom or extended logger wrappers.
027 * <p>
028 * Usage:
029 * <p>
030 * To generate source code for an extended logger that adds custom log levels to the existing ones: <br>
031 * {@code java org.apache.logging.log4j.core.tools.Generate$ExtendedLogger <logger.class.name> <CUSTOMLEVEL>=<WEIGHT>
032 * [CUSTOMLEVEL2=WEIGHT2 [CUSTOMLEVEL3=WEIGHT3] ...]}
033 * <p>
034 * Example of creating an extended logger:<br>
035 * {@code java org.apache.logging.log4j.core.tools.Generate$ExtendedLogger com.mycomp.ExtLogger DIAG=350 NOTICE=450
036 * VERBOSE=550}
037 * <p>
038 * To generate source code for a custom logger that replaces the existing log levels with custom ones: <br>
039 * {@code java org.apache.logging.log4j.core.tools.Generate$CustomLogger <logger.class.name> <CUSTOMLEVEL>=<WEIGHT>
040 * [CUSTOMLEVEL2=WEIGHT2 [CUSTOMLEVEL3=WEIGHT3] ...]}
041 * <p>
042 * Example of creating a custom logger:<br>
043 * {@code java org.apache.logging.log4j.core.tools.Generate$CustomLogger com.mycomp.MyLogger DEFCON1=350 DEFCON2=450
044 * DEFCON3=550}
045 */
046public final class Generate {
047    // Implementation note:
048    // The generated code is in the user's namespace which has its own versioning scheme, so
049    // any @since tags in the generated code deliberately mention "Log4j-2.x" rather than just the log4j version number.
050
051    static final String PACKAGE_DECLARATION = "package %s;%n%n";
052
053    static enum Type {
054        CUSTOM {
055            @Override
056            String imports() {
057                //@formatter:off
058                return "" 
059                        + "import java.io.Serializable;%n" 
060                        + "import org.apache.logging.log4j.Level;%n" 
061                        + "import org.apache.logging.log4j.LogManager;%n" 
062                        + "import org.apache.logging.log4j.Logger;%n" 
063                        + "import org.apache.logging.log4j.Marker;%n" 
064                        + "import org.apache.logging.log4j.message.Message;%n" 
065                        + "import org.apache.logging.log4j.message.MessageFactory;%n" 
066                        + "import org.apache.logging.log4j.spi.AbstractLogger;%n" 
067                        + "import org.apache.logging.log4j.spi.ExtendedLoggerWrapper;%n" 
068                        + "import org.apache.logging.log4j.util.MessageSupplier;%n" 
069                        + "import org.apache.logging.log4j.util.Supplier;%n"
070                        + "%n";
071                //@formatter:on
072            }
073
074            @Override
075            String declaration() {
076                //@formatter:off
077                return "" 
078                        + "/**%n" 
079                        + " * Custom Logger interface with convenience methods for%n" 
080                        + " * %s%n" 
081                        + " * <p>Compatible with Log4j 2.6 or higher.</p>%n" 
082                        + " */%n" 
083                        + "public final class %s implements Serializable {%n" 
084                        + "    private static final long serialVersionUID = " + System.nanoTime() + "L;%n" 
085                        + "    private final ExtendedLoggerWrapper logger;%n" 
086                        + "%n";
087                //@formatter:on
088            }
089
090            @Override
091            String constructor() {
092                //@formatter:off
093                return "" 
094                        + "%n" 
095                        + "    private %s(final Logger logger) {%n" 
096                        + "        this.logger = new ExtendedLoggerWrapper((AbstractLogger) logger, logger.getName(), "
097                        + "logger.getMessageFactory());%n" 
098                        + "    }%n";
099                //@formatter:on
100            }
101
102            @Override
103            Class<?> generator() {
104                return CustomLogger.class;
105            }
106        },
107        EXTEND {
108            @Override
109            String imports() {
110                //@formatter:off
111                return "" 
112                        + "import org.apache.logging.log4j.Level;%n" 
113                        + "import org.apache.logging.log4j.LogManager;%n" 
114                        + "import org.apache.logging.log4j.Logger;%n" 
115                        + "import org.apache.logging.log4j.Marker;%n" 
116                        + "import org.apache.logging.log4j.message.Message;%n" 
117                        + "import org.apache.logging.log4j.message.MessageFactory;%n" 
118                        + "import org.apache.logging.log4j.spi.AbstractLogger;%n" 
119                        + "import org.apache.logging.log4j.spi.ExtendedLoggerWrapper;%n" 
120                        + "import org.apache.logging.log4j.util.MessageSupplier;%n" 
121                        + "import org.apache.logging.log4j.util.Supplier;%n"
122                        + "%n";
123                //@formatter:on
124            }
125
126            @Override
127            String declaration() {
128                //@formatter:off
129                return "" 
130                        + "/**%n" 
131                        + " * Extended Logger interface with convenience methods for%n" 
132                        + " * %s%n" 
133                        + " * <p>Compatible with Log4j 2.6 or higher.</p>%n" 
134                        + " */%n" 
135                        + "public final class %s extends ExtendedLoggerWrapper {%n" 
136                        + "    private static final long serialVersionUID = " + System.nanoTime() + "L;%n" 
137                        + "    private final ExtendedLoggerWrapper logger;%n" 
138                        + "%n";
139                //@formatter:on
140            }
141
142            @Override
143            String constructor() {
144                //@formatter:off
145                return "" 
146                        + "%n" 
147                        + "    private %s(final Logger logger) {%n" 
148                        + "        super((AbstractLogger) logger, logger.getName(), logger.getMessageFactory());%n" 
149                        + "        this.logger = this;%n" 
150                        + "    }%n";
151                //@formatter:on
152            }
153
154            @Override
155            Class<?> generator() {
156                return ExtendedLogger.class;
157            }
158        };
159        abstract String imports();
160
161        abstract String declaration();
162
163        abstract String constructor();
164
165        abstract Class<?> generator();
166    }
167
168    static final String FQCN_FIELD = "" 
169            + "    private static final String FQCN = %s.class.getName();%n";
170
171    static final String LEVEL_FIELD = "" 
172            + "    private static final Level %s = Level.forName(\"%s\", %d);%n";
173
174    static final String FACTORY_METHODS = "" 
175            //@formatter:off
176            + "%n" 
177            + "    /**%n" 
178            + "     * Returns a custom Logger with the name of the calling class.%n" 
179            + "     * %n" 
180            + "     * @return The custom Logger for the calling class.%n" 
181            + "     */%n" 
182            + "    public static CLASSNAME create() {%n" 
183            + "        final Logger wrapped = LogManager.getLogger();%n" 
184            + "        return new CLASSNAME(wrapped);%n" 
185            + "    }%n" 
186            + "%n" 
187            + "    /**%n" 
188            + "     * Returns a custom Logger using the fully qualified name of the Class as%n" 
189            + "     * the Logger name.%n" 
190            + "     * %n" 
191            + "     * @param loggerName The Class whose name should be used as the Logger name.%n" 
192            + "     *            If null it will default to the calling class.%n" 
193            + "     * @return The custom Logger.%n" 
194            + "     */%n" 
195            + "    public static CLASSNAME create(final Class<?> loggerName) {%n" 
196            + "        final Logger wrapped = LogManager.getLogger(loggerName);%n" 
197            + "        return new CLASSNAME(wrapped);%n" 
198            + "    }%n" 
199            + "%n" 
200            + "    /**%n" 
201            + "     * Returns a custom Logger using the fully qualified name of the Class as%n" 
202            + "     * the Logger name.%n" 
203            + "     * %n" 
204            + "     * @param loggerName The Class whose name should be used as the Logger name.%n" 
205            + "     *            If null it will default to the calling class.%n" 
206            + "     * @param messageFactory The message factory is used only when creating a%n" 
207            + "     *            logger, subsequent use does not change the logger but will log%n" 
208            + "     *            a warning if mismatched.%n" 
209            + "     * @return The custom Logger.%n" 
210            + "     */%n" 
211            + "    public static CLASSNAME create(final Class<?> loggerName, final MessageFactory" 
212            + " messageFactory) {%n" 
213            + "        final Logger wrapped = LogManager.getLogger(loggerName, messageFactory);%n" 
214            + "        return new CLASSNAME(wrapped);%n" 
215            + "    }%n" 
216            + "%n" 
217            + "    /**%n" 
218            + "     * Returns a custom Logger using the fully qualified class name of the value%n" 
219            + "     * as the Logger name.%n" 
220            + "     * %n" 
221            + "     * @param value The value whose class name should be used as the Logger%n" 
222            + "     *            name. If null the name of the calling class will be used as%n" 
223            + "     *            the logger name.%n" 
224            + "     * @return The custom Logger.%n" 
225            + "     */%n" 
226            + "    public static CLASSNAME create(final Object value) {%n" 
227            + "        final Logger wrapped = LogManager.getLogger(value);%n" 
228            + "        return new CLASSNAME(wrapped);%n" 
229            + "    }%n" 
230            + "%n" 
231            + "    /**%n" 
232            + "     * Returns a custom Logger using the fully qualified class name of the value%n" 
233            + "     * as the Logger name.%n" 
234            + "     * %n" 
235            + "     * @param value The value whose class name should be used as the Logger%n" 
236            + "     *            name. If null the name of the calling class will be used as%n" 
237            + "     *            the logger name.%n" 
238            + "     * @param messageFactory The message factory is used only when creating a%n" 
239            + "     *            logger, subsequent use does not change the logger but will log%n" 
240            + "     *            a warning if mismatched.%n" 
241            + "     * @return The custom Logger.%n" 
242            + "     */%n" 
243            + "    public static CLASSNAME create(final Object value, final MessageFactory messageFactory) {%n" 
244            + "        final Logger wrapped = LogManager.getLogger(value, messageFactory);%n" 
245            + "        return new CLASSNAME(wrapped);%n" 
246            + "    }%n" 
247            + "%n" 
248            + "    /**%n" 
249            + "     * Returns a custom Logger with the specified name.%n" 
250            + "     * %n" 
251            + "     * @param name The logger name. If null the name of the calling class will%n" 
252            + "     *            be used.%n" 
253            + "     * @return The custom Logger.%n" 
254            + "     */%n" 
255            + "    public static CLASSNAME create(final String name) {%n" 
256            + "        final Logger wrapped = LogManager.getLogger(name);%n" 
257            + "        return new CLASSNAME(wrapped);%n" 
258            + "    }%n" 
259            + "%n" 
260            + "    /**%n" 
261            + "     * Returns a custom Logger with the specified name.%n" 
262            + "     * %n" 
263            + "     * @param name The logger name. If null the name of the calling class will%n" 
264            + "     *            be used.%n" 
265            + "     * @param messageFactory The message factory is used only when creating a%n" 
266            + "     *            logger, subsequent use does not change the logger but will log%n" 
267            + "     *            a warning if mismatched.%n" 
268            + "     * @return The custom Logger.%n" 
269            + "     */%n" 
270            + "    public static CLASSNAME create(final String name, final MessageFactory messageFactory) {%n" 
271            + "        final Logger wrapped = LogManager.getLogger(name, messageFactory);%n" 
272            + "        return new CLASSNAME(wrapped);%n" 
273            + "    }%n";
274            //@formatter:on
275
276    static final String METHODS = "" 
277            //@formatter:off
278            + "%n" 
279            + "    /**%n" 
280            + "     * Logs a message with the specific Marker at the {@code CUSTOM_LEVEL} level.%n" 
281            + "     * %n" 
282            + "     * @param marker the marker data specific to this log statement%n" 
283            + "     * @param msg the message string to be logged%n" 
284            + "     */%n" 
285            + "    public void methodName(final Marker marker, final Message msg) {%n" 
286            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, msg, (Throwable) null);%n" 
287            + "    }%n" 
288            + "%n" 
289            + "    /**%n" 
290            + "     * Logs a message with the specific Marker at the {@code CUSTOM_LEVEL} level.%n" 
291            + "     * %n" 
292            + "     * @param marker the marker data specific to this log statement%n" 
293            + "     * @param msg the message string to be logged%n" 
294            + "     * @param t A Throwable or null.%n" 
295            + "     */%n" 
296            + "    public void methodName(final Marker marker, final Message msg, final Throwable t) {%n" 
297            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, msg, t);%n" 
298            + "    }%n" 
299            + "%n" 
300            + "    /**%n" 
301            + "     * Logs a message object with the {@code CUSTOM_LEVEL} level.%n" 
302            + "     * %n" 
303            + "     * @param marker the marker data specific to this log statement%n" 
304            + "     * @param message the message object to log.%n" 
305            + "     */%n" 
306            + "    public void methodName(final Marker marker, final Object message) {%n" 
307            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, (Throwable) null);%n" 
308            + "    }%n" 
309            + "%n" 
310            + "    /**%n" 
311            + "     * Logs a message CharSequence with the {@code CUSTOM_LEVEL} level.%n" 
312            + "     * %n" 
313            + "     * @param marker the marker data specific to this log statement%n" 
314            + "     * @param message the message CharSequence to log.%n" 
315            + "     * @since Log4j-2.6%n" 
316            + "     */%n" 
317            + "    public void methodName(final Marker marker, final CharSequence message) {%n" 
318            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, (Throwable) null);%n" 
319            + "    }%n" 
320            + "%n" 
321            + "    /**%n" 
322            + "     * Logs a message at the {@code CUSTOM_LEVEL} level including the stack trace of%n" 
323            + "     * the {@link Throwable} {@code t} passed as parameter.%n" 
324            + "     * %n" 
325            + "     * @param marker the marker data specific to this log statement%n" 
326            + "     * @param message the message to log.%n" 
327            + "     * @param t the exception to log, including its stack trace.%n" 
328            + "     */%n" 
329            + "    public void methodName(final Marker marker, final Object message, final Throwable t) {%n" 
330            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, t);%n" 
331            + "    }%n" 
332            + "%n" 
333            + "    /**%n" 
334            + "     * Logs a message at the {@code CUSTOM_LEVEL} level including the stack trace of%n" 
335            + "     * the {@link Throwable} {@code t} passed as parameter.%n" 
336            + "     * %n" 
337            + "     * @param marker the marker data specific to this log statement%n" 
338            + "     * @param message the CharSequence to log.%n" 
339            + "     * @param t the exception to log, including its stack trace.%n" 
340            + "     * @since Log4j-2.6%n" 
341            + "     */%n" 
342            + "    public void methodName(final Marker marker, final CharSequence message, final Throwable t) {%n" 
343            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, t);%n" 
344            + "    }%n" 
345            + "%n" 
346            + "    /**%n" 
347            + "     * Logs a message object with the {@code CUSTOM_LEVEL} level.%n" 
348            + "     * %n" 
349            + "     * @param marker the marker data specific to this log statement%n" 
350            + "     * @param message the message object to log.%n" 
351            + "     */%n" 
352            + "    public void methodName(final Marker marker, final String message) {%n" 
353            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, (Throwable) null);%n" 
354            + "    }%n" 
355            + "%n" 
356            + "    /**%n" 
357            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
358            + "     * %n" 
359            + "     * @param marker the marker data specific to this log statement%n" 
360            + "     * @param message the message to log; the format depends on the message factory.%n" 
361            + "     * @param params parameters to the message.%n" 
362            + "     * @see #getMessageFactory()%n" 
363            + "     */%n" 
364            + "    public void methodName(final Marker marker, final String message, final Object... params) {%n" 
365            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, params);%n" 
366            + "    }%n" 
367            + "%n" 
368            + "    /**%n" 
369            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
370            + "     * %n" 
371            + "     * @param marker the marker data specific to this log statement%n" 
372            + "     * @param message the message to log; the format depends on the message factory.%n" 
373            + "     * @param p0 parameter to the message.%n" 
374            + "     * @see #getMessageFactory()%n" 
375            + "     * @since Log4j-2.6%n" 
376            + "     */%n" 
377            + "    public void methodName(final Marker marker, final String message, final Object p0) {%n" 
378            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, p0);%n" 
379            + "    }%n" 
380            + "%n" 
381            + "    /**%n" 
382            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
383            + "     * %n" 
384            + "     * @param marker the marker data specific to this log statement%n" 
385            + "     * @param message the message to log; the format depends on the message factory.%n" 
386            + "     * @param p0 parameter to the message.%n" 
387            + "     * @param p1 parameter to the message.%n" 
388            + "     * @see #getMessageFactory()%n" 
389            + "     * @since Log4j-2.6%n" 
390            + "     */%n" 
391            + "    public void methodName(final Marker marker, final String message, final Object p0, " 
392            + "final Object p1) {%n"
393            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, p0, p1);%n" 
394            + "    }%n" 
395            + "%n" 
396            + "    /**%n" 
397            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
398            + "     * %n" 
399            + "     * @param marker the marker data specific to this log statement%n" 
400            + "     * @param message the message to log; the format depends on the message factory.%n" 
401            + "     * @param p0 parameter to the message.%n" 
402            + "     * @param p1 parameter to the message.%n" 
403            + "     * @param p2 parameter to the message.%n" 
404            + "     * @see #getMessageFactory()%n" 
405            + "     * @since Log4j-2.6%n" 
406            + "     */%n" 
407            + "    public void methodName(final Marker marker, final String message, final Object p0, " 
408            + "final Object p1, final Object p2) {%n" 
409            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, p0, p1, p2);%n" 
410            + "    }%n" 
411            + "%n" 
412            + "    /**%n" 
413            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
414            + "     * %n" 
415            + "     * @param marker the marker data specific to this log statement%n" 
416            + "     * @param message the message to log; the format depends on the message factory.%n" 
417            + "     * @param p0 parameter to the message.%n" 
418            + "     * @param p1 parameter to the message.%n" 
419            + "     * @param p2 parameter to the message.%n" 
420            + "     * @param p3 parameter to the message.%n" 
421            + "     * @see #getMessageFactory()%n" 
422            + "     * @since Log4j-2.6%n" 
423            + "     */%n" 
424            + "    public void methodName(final Marker marker, final String message, final Object p0, " 
425            + "final Object p1, final Object p2,%n" 
426            + "            final Object p3) {%n" 
427            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, p0, p1, p2, p3);%n" 
428            + "    }%n" 
429            + "%n" 
430            + "    /**%n" 
431            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
432            + "     * %n" 
433            + "     * @param marker the marker data specific to this log statement%n" 
434            + "     * @param message the message to log; the format depends on the message factory.%n" 
435            + "     * @param p0 parameter to the message.%n" 
436            + "     * @param p1 parameter to the message.%n" 
437            + "     * @param p2 parameter to the message.%n" 
438            + "     * @param p3 parameter to the message.%n" 
439            + "     * @param p4 parameter to the message.%n" 
440            + "     * @see #getMessageFactory()%n" 
441            + "     * @since Log4j-2.6%n" 
442            + "     */%n" 
443            + "    public void methodName(final Marker marker, final String message, final Object p0, " 
444            + "final Object p1, final Object p2,%n" 
445            + "            final Object p3, final Object p4) {%n" 
446            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, p0, p1, p2, p3, p4);%n" 
447            + "    }%n" 
448            + "%n" 
449            + "    /**%n" 
450            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
451            + "     * %n" 
452            + "     * @param marker the marker data specific to this log statement%n" 
453            + "     * @param message the message to log; the format depends on the message factory.%n" 
454            + "     * @param p0 parameter to the message.%n" 
455            + "     * @param p1 parameter to the message.%n" 
456            + "     * @param p2 parameter to the message.%n" 
457            + "     * @param p3 parameter to the message.%n" 
458            + "     * @param p4 parameter to the message.%n" 
459            + "     * @param p5 parameter to the message.%n" 
460            + "     * @see #getMessageFactory()%n" 
461            + "     * @since Log4j-2.6%n" 
462            + "     */%n" 
463            + "    public void methodName(final Marker marker, final String message, final Object p0, " 
464            + "final Object p1, final Object p2,%n" 
465            + "            final Object p3, final Object p4, final Object p5) {%n" 
466            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, p0, p1, p2, p3, p4, p5);%n" 
467            + "    }%n" 
468            + "%n" 
469            + "    /**%n" 
470            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
471            + "     * %n" 
472            + "     * @param marker the marker data specific to this log statement%n" 
473            + "     * @param message the message to log; the format depends on the message factory.%n" 
474            + "     * @param p0 parameter to the message.%n" 
475            + "     * @param p1 parameter to the message.%n" 
476            + "     * @param p2 parameter to the message.%n" 
477            + "     * @param p3 parameter to the message.%n" 
478            + "     * @param p4 parameter to the message.%n" 
479            + "     * @param p5 parameter to the message.%n" 
480            + "     * @param p6 parameter to the message.%n" 
481            + "     * @see #getMessageFactory()%n" 
482            + "     * @since Log4j-2.6%n" 
483            + "     */%n" 
484            + "    public void methodName(final Marker marker, final String message, final Object p0, " 
485            + "final Object p1, final Object p2,%n" 
486            + "            final Object p3, final Object p4, final Object p5, final Object p6) {%n" 
487            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, p0, p1, p2, p3, p4, p5, p6);%n" 
488            + "    }%n" 
489            + "%n" 
490            + "    /**%n" 
491            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
492            + "     * %n" 
493            + "     * @param marker the marker data specific to this log statement%n" 
494            + "     * @param message the message to log; the format depends on the message factory.%n" 
495            + "     * @param p0 parameter to the message.%n" 
496            + "     * @param p1 parameter to the message.%n" 
497            + "     * @param p2 parameter to the message.%n" 
498            + "     * @param p3 parameter to the message.%n" 
499            + "     * @param p4 parameter to the message.%n" 
500            + "     * @param p5 parameter to the message.%n" 
501            + "     * @param p6 parameter to the message.%n" 
502            + "     * @param p7 parameter to the message.%n" 
503            + "     * @see #getMessageFactory()%n" 
504            + "     * @since Log4j-2.6%n" 
505            + "     */%n" 
506            + "    public void methodName(final Marker marker, final String message, final Object p0, " 
507            + "final Object p1, final Object p2,%n" 
508            + "            final Object p3, final Object p4, final Object p5, final Object p6,%n" 
509            + "            final Object p7) {%n" 
510            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, p0, p1, p2, p3, p4, p5, p6, p7);%n" 
511            + "    }%n" 
512            + "%n" 
513            + "    /**%n" 
514            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
515            + "     * %n" 
516            + "     * @param marker the marker data specific to this log statement%n" 
517            + "     * @param message the message to log; the format depends on the message factory.%n" 
518            + "     * @param p0 parameter to the message.%n" 
519            + "     * @param p1 parameter to the message.%n" 
520            + "     * @param p2 parameter to the message.%n" 
521            + "     * @param p3 parameter to the message.%n" 
522            + "     * @param p4 parameter to the message.%n" 
523            + "     * @param p5 parameter to the message.%n" 
524            + "     * @param p6 parameter to the message.%n" 
525            + "     * @param p7 parameter to the message.%n" 
526            + "     * @param p8 parameter to the message.%n" 
527            + "     * @see #getMessageFactory()%n" 
528            + "     * @since Log4j-2.6%n" 
529            + "     */%n" 
530            + "    public void methodName(final Marker marker, final String message, final Object p0, " 
531            + "final Object p1, final Object p2,%n" 
532            + "            final Object p3, final Object p4, final Object p5, final Object p6,%n" 
533            + "            final Object p7, final Object p8) {%n" 
534            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, p0, p1, p2, p3, p4, p5, p6, p7, " 
535            + "p8);%n" 
536            + "    }%n" 
537            + "%n" 
538            + "    /**%n" 
539            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
540            + "     * %n" 
541            + "     * @param marker the marker data specific to this log statement%n" 
542            + "     * @param message the message to log; the format depends on the message factory.%n" 
543            + "     * @param p0 parameter to the message.%n" 
544            + "     * @param p1 parameter to the message.%n" 
545            + "     * @param p2 parameter to the message.%n" 
546            + "     * @param p3 parameter to the message.%n" 
547            + "     * @param p4 parameter to the message.%n" 
548            + "     * @param p5 parameter to the message.%n" 
549            + "     * @param p6 parameter to the message.%n" 
550            + "     * @param p7 parameter to the message.%n" 
551            + "     * @param p8 parameter to the message.%n" 
552            + "     * @param p9 parameter to the message.%n" 
553            + "     * @see #getMessageFactory()%n" 
554            + "     * @since Log4j-2.6%n" 
555            + "     */%n" 
556            + "    public void methodName(final Marker marker, final String message, final Object p0, " 
557            + "final Object p1, final Object p2,%n" 
558            + "            final Object p3, final Object p4, final Object p5, final Object p6,%n" 
559            + "            final Object p7, final Object p8, final Object p9) {%n" 
560            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, p0, p1, p2, p3, p4, p5, p6, p7, " 
561            + "p8, p9);%n" 
562            + "    }%n" 
563            + "%n" 
564            + "    /**%n" 
565            + "     * Logs a message at the {@code CUSTOM_LEVEL} level including the stack trace of%n" 
566            + "     * the {@link Throwable} {@code t} passed as parameter.%n" 
567            + "     * %n" 
568            + "     * @param marker the marker data specific to this log statement%n" 
569            + "     * @param message the message to log.%n" 
570            + "     * @param t the exception to log, including its stack trace.%n" 
571            + "     */%n" 
572            + "    public void methodName(final Marker marker, final String message, final Throwable t) {%n" 
573            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, t);%n" 
574            + "    }%n" 
575            + "%n" 
576            + "    /**%n" 
577            + "     * Logs the specified Message at the {@code CUSTOM_LEVEL} level.%n" 
578            + "     * %n" 
579            + "     * @param msg the message string to be logged%n" 
580            + "     */%n" 
581            + "    public void methodName(final Message msg) {%n" 
582            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, msg, (Throwable) null);%n" 
583            + "    }%n" 
584            + "%n" 
585            + "    /**%n" 
586            + "     * Logs the specified Message at the {@code CUSTOM_LEVEL} level.%n" 
587            + "     * %n" 
588            + "     * @param msg the message string to be logged%n" 
589            + "     * @param t A Throwable or null.%n" 
590            + "     */%n" 
591            + "    public void methodName(final Message msg, final Throwable t) {%n" 
592            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, msg, t);%n" 
593            + "    }%n" 
594            + "%n" 
595            + "    /**%n" 
596            + "     * Logs a message object with the {@code CUSTOM_LEVEL} level.%n" 
597            + "     * %n" 
598            + "     * @param message the message object to log.%n" 
599            + "     */%n" 
600            + "    public void methodName(final Object message) {%n" 
601            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, (Throwable) null);%n" 
602            + "    }%n" 
603            + "%n" 
604            + "    /**%n" 
605            + "     * Logs a message at the {@code CUSTOM_LEVEL} level including the stack trace of%n" 
606            + "     * the {@link Throwable} {@code t} passed as parameter.%n" 
607            + "     * %n" 
608            + "     * @param message the message to log.%n" 
609            + "     * @param t the exception to log, including its stack trace.%n" 
610            + "     */%n" 
611            + "    public void methodName(final Object message, final Throwable t) {%n" 
612            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, t);%n" 
613            + "    }%n" 
614            + "%n" 
615            + "    /**%n" 
616            + "     * Logs a message CharSequence with the {@code CUSTOM_LEVEL} level.%n" 
617            + "     * %n" 
618            + "     * @param message the message CharSequence to log.%n" 
619            + "     * @since Log4j-2.6%n" 
620            + "     */%n" 
621            + "    public void methodName(final CharSequence message) {%n" 
622            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, (Throwable) null);%n" 
623            + "    }%n" 
624            + "%n" 
625            + "    /**%n" 
626            + "     * Logs a CharSequence at the {@code CUSTOM_LEVEL} level including the stack trace of%n" 
627            + "     * the {@link Throwable} {@code t} passed as parameter.%n" 
628            + "     * %n" 
629            + "     * @param message the CharSequence to log.%n" 
630            + "     * @param t the exception to log, including its stack trace.%n" 
631            + "     * @since Log4j-2.6%n" 
632            + "     */%n" 
633            + "    public void methodName(final CharSequence message, final Throwable t) {%n" 
634            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, t);%n" 
635            + "    }%n" 
636            + "%n" 
637            + "    /**%n" 
638            + "     * Logs a message object with the {@code CUSTOM_LEVEL} level.%n" 
639            + "     * %n" 
640            + "     * @param message the message object to log.%n" 
641            + "     */%n" 
642            + "    public void methodName(final String message) {%n" 
643            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, (Throwable) null);%n" 
644            + "    }%n" 
645            + "%n" 
646            + "    /**%n" 
647            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
648            + "     * %n" 
649            + "     * @param message the message to log; the format depends on the message factory.%n"
650            + "     * @param params parameters to the message.%n" 
651            + "     * @see #getMessageFactory()%n" 
652            + "     */%n" 
653            + "    public void methodName(final String message, final Object... params) {%n" 
654            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, params);%n" 
655            + "    }%n" 
656            + "%n" 
657            + "    /**%n" 
658            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
659            + "     * %n" 
660            + "     * @param message the message to log; the format depends on the message factory.%n" 
661            + "     * @param p0 parameter to the message.%n" 
662            + "     * @see #getMessageFactory()%n" 
663            + "     * @since Log4j-2.6%n" 
664            + "     */%n" 
665            + "    public void methodName(final String message, final Object p0) {%n" 
666            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, p0);%n" 
667            + "    }%n" 
668            + "%n" 
669            + "    /**%n" 
670            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
671            + "     * %n" 
672            + "     * @param message the message to log; the format depends on the message factory.%n" 
673            + "     * @param p0 parameter to the message.%n" 
674            + "     * @param p1 parameter to the message.%n" 
675            + "     * @see #getMessageFactory()%n" 
676            + "     * @since Log4j-2.6%n" 
677            + "     */%n" 
678            + "    public void methodName(final String message, final Object p0, " 
679            + "final Object p1) {%n" 
680            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, p0, p1);%n" 
681            + "    }%n" 
682            + "%n" 
683            + "    /**%n" 
684            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
685            + "     * %n" 
686            + "     * @param message the message to log; the format depends on the message factory.%n" 
687            + "     * @param p0 parameter to the message.%n" 
688            + "     * @param p1 parameter to the message.%n" 
689            + "     * @param p2 parameter to the message.%n" 
690            + "     * @see #getMessageFactory()%n" 
691            + "     * @since Log4j-2.6%n" 
692            + "     */%n" 
693            + "    public void methodName(final String message, final Object p0, " 
694            + "final Object p1, final Object p2) {%n" 
695            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, p0, p1, p2);%n" 
696            + "    }%n" 
697            + "%n" 
698            + "    /**%n" 
699            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
700            + "     * %n" 
701            + "     * @param message the message to log; the format depends on the message factory.%n" 
702            + "     * @param p0 parameter to the message.%n" 
703            + "     * @param p1 parameter to the message.%n" 
704            + "     * @param p2 parameter to the message.%n" 
705            + "     * @param p3 parameter to the message.%n" 
706            + "     * @see #getMessageFactory()%n" 
707            + "     * @since Log4j-2.6%n" 
708            + "     */%n" 
709            + "    public void methodName(final String message, final Object p0, " 
710            + "final Object p1, final Object p2,%n" 
711            + "            final Object p3) {%n" 
712            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, p0, p1, p2, p3);%n" 
713            + "    }%n" 
714            + "%n" 
715            + "    /**%n" 
716            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
717            + "     * %n" 
718            + "     * @param message the message to log; the format depends on the message factory.%n" 
719            + "     * @param p0 parameter to the message.%n" 
720            + "     * @param p1 parameter to the message.%n" 
721            + "     * @param p2 parameter to the message.%n" 
722            + "     * @param p3 parameter to the message.%n" 
723            + "     * @param p4 parameter to the message.%n" 
724            + "     * @see #getMessageFactory()%n" 
725            + "     * @since Log4j-2.6%n" 
726            + "     */%n" 
727            + "    public void methodName(final String message, final Object p0, " 
728            + "final Object p1, final Object p2,%n" 
729            + "            final Object p3, final Object p4) {%n" 
730            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, p0, p1, p2, p3, p4);%n" 
731            + "    }%n" 
732            + "%n" 
733            + "    /**%n" 
734            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
735            + "     * %n" 
736            + "     * @param message the message to log; the format depends on the message factory.%n" 
737            + "     * @param p0 parameter to the message.%n" 
738            + "     * @param p1 parameter to the message.%n" 
739            + "     * @param p2 parameter to the message.%n" 
740            + "     * @param p3 parameter to the message.%n" 
741            + "     * @param p4 parameter to the message.%n" 
742            + "     * @param p5 parameter to the message.%n" 
743            + "     * @see #getMessageFactory()%n" 
744            + "     * @since Log4j-2.6%n" 
745            + "     */%n" 
746            + "    public void methodName(final String message, final Object p0, " 
747            + "final Object p1, final Object p2,%n" 
748            + "            final Object p3, final Object p4, final Object p5) {%n" 
749            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, p0, p1, p2, p3, p4, p5);%n" 
750            + "    }%n" 
751            + "%n" 
752            + "    /**%n" 
753            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
754            + "     * %n" 
755            + "     * @param message the message to log; the format depends on the message factory.%n" 
756            + "     * @param p0 parameter to the message.%n" 
757            + "     * @param p1 parameter to the message.%n" 
758            + "     * @param p2 parameter to the message.%n" 
759            + "     * @param p3 parameter to the message.%n" 
760            + "     * @param p4 parameter to the message.%n" 
761            + "     * @param p5 parameter to the message.%n" 
762            + "     * @param p6 parameter to the message.%n" 
763            + "     * @see #getMessageFactory()%n" 
764            + "     * @since Log4j-2.6%n" 
765            + "     */%n" 
766            + "    public void methodName(final String message, final Object p0, " 
767            + "final Object p1, final Object p2,%n" 
768            + "            final Object p3, final Object p4, final Object p5, final Object p6) {%n" 
769            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, p0, p1, p2, p3, p4, p5, p6);%n" 
770            + "    }%n" 
771            + "%n" 
772            + "    /**%n" 
773            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
774            + "     * %n" 
775            + "     * @param message the message to log; the format depends on the message factory.%n" 
776            + "     * @param p0 parameter to the message.%n" 
777            + "     * @param p1 parameter to the message.%n" 
778            + "     * @param p2 parameter to the message.%n" 
779            + "     * @param p3 parameter to the message.%n" 
780            + "     * @param p4 parameter to the message.%n" 
781            + "     * @param p5 parameter to the message.%n" 
782            + "     * @param p6 parameter to the message.%n" 
783            + "     * @param p7 parameter to the message.%n" 
784            + "     * @see #getMessageFactory()%n" 
785            + "     * @since Log4j-2.6%n" 
786            + "     */%n" 
787            + "    public void methodName(final String message, final Object p0, " 
788            + "final Object p1, final Object p2,%n" 
789            + "            final Object p3, final Object p4, final Object p5, final Object p6,%n" 
790            + "            final Object p7) {%n" 
791            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, p0, p1, p2, p3, p4, p5, p6, p7);%n" 
792            + "    }%n" 
793            + "%n" 
794            + "    /**%n" 
795            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
796            + "     * %n" 
797            + "     * @param message the message to log; the format depends on the message factory.%n" 
798            + "     * @param p0 parameter to the message.%n" 
799            + "     * @param p1 parameter to the message.%n" 
800            + "     * @param p2 parameter to the message.%n" 
801            + "     * @param p3 parameter to the message.%n" 
802            + "     * @param p4 parameter to the message.%n" 
803            + "     * @param p5 parameter to the message.%n" 
804            + "     * @param p6 parameter to the message.%n" 
805            + "     * @param p7 parameter to the message.%n" 
806            + "     * @param p8 parameter to the message.%n" 
807            + "     * @see #getMessageFactory()%n" 
808            + "     * @since Log4j-2.6%n" 
809            + "     */%n" 
810            + "    public void methodName(final String message, final Object p0, " 
811            + "final Object p1, final Object p2,%n" 
812            + "            final Object p3, final Object p4, final Object p5, final Object p6,%n" 
813            + "            final Object p7, final Object p8) {%n" 
814            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, p0, p1, p2, p3, p4, p5, p6, p7, " 
815            + "p8);%n" 
816            + "    }%n" 
817            + "%n" 
818            + "    /**%n" 
819            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" 
820            + "     * %n" 
821            + "     * @param message the message to log; the format depends on the message factory.%n" 
822            + "     * @param p0 parameter to the message.%n" 
823            + "     * @param p1 parameter to the message.%n" 
824            + "     * @param p2 parameter to the message.%n" 
825            + "     * @param p3 parameter to the message.%n" 
826            + "     * @param p4 parameter to the message.%n" 
827            + "     * @param p5 parameter to the message.%n" 
828            + "     * @param p6 parameter to the message.%n" 
829            + "     * @param p7 parameter to the message.%n" 
830            + "     * @param p8 parameter to the message.%n" 
831            + "     * @param p9 parameter to the message.%n" 
832            + "     * @see #getMessageFactory()%n" 
833            + "     * @since Log4j-2.6%n" 
834            + "     */%n" 
835            + "    public void methodName(final String message, final Object p0, " 
836            + "final Object p1, final Object p2,%n" 
837            + "            final Object p3, final Object p4, final Object p5, final Object p6,%n" 
838            + "            final Object p7, final Object p8, final Object p9) {%n" 
839            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, p0, p1, p2, p3, p4, p5, p6, p7, " 
840            + "p8, p9);%n" 
841            + "    }%n" 
842            + "%n" 
843            + "    /**%n" 
844            + "     * Logs a message at the {@code CUSTOM_LEVEL} level including the stack trace of%n" 
845            + "     * the {@link Throwable} {@code t} passed as parameter.%n" 
846            + "     * %n" 
847            + "     * @param message the message to log.%n" 
848            + "     * @param t the exception to log, including its stack trace.%n" 
849            + "     */%n" 
850            + "    public void methodName(final String message, final Throwable t) {%n" 
851            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, t);%n" 
852            + "    }%n"
853            + "%n" 
854            + "    /**%n" 
855            + "     * Logs a message which is only to be constructed if the logging level is the {@code CUSTOM_LEVEL}"
856            + "level.%n" 
857            + "     *%n" 
858            + "     * @param msgSupplier A function, which when called, produces the desired log message;%n" 
859            + "     *            the format depends on the message factory.%n" 
860            + "     * @since Log4j-2.4%n" 
861            + "     */%n" 
862            + "    public void methodName(final Supplier<?> msgSupplier) {%n" 
863            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, msgSupplier, (Throwable) null);%n" 
864            + "    }%n" 
865            + "%n" 
866            + "    /**%n" 
867            + "     * Logs a message (only to be constructed if the logging level is the {@code CUSTOM_LEVEL}%n" 
868            + "     * level) including the stack trace of the {@link Throwable} <code>t</code> passed as parameter.%n"
869            + "     *%n" 
870            + "     * @param msgSupplier A function, which when called, produces the desired log message;%n" 
871            + "     *            the format depends on the message factory.%n" 
872            + "     * @param t the exception to log, including its stack trace.%n" 
873            + "     * @since Log4j-2.4%n" 
874            + "     */%n" 
875            + "    public void methodName(final Supplier<?> msgSupplier, final Throwable t) {%n" 
876            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, msgSupplier, t);%n" 
877            + "    }%n" 
878            + "%n" 
879            + "    /**%n" 
880            + "     * Logs a message which is only to be constructed if the logging level is the%n" 
881            + "     * {@code CUSTOM_LEVEL} level with the specified Marker.%n" 
882            + "     *%n" 
883            + "     * @param marker the marker data specific to this log statement%n" 
884            + "     * @param msgSupplier A function, which when called, produces the desired log message;%n" 
885            + "     *            the format depends on the message factory.%n" 
886            + "     * @since Log4j-2.4%n" 
887            + "     */%n" 
888            + "    public void methodName(final Marker marker, final Supplier<?> msgSupplier) {%n" 
889            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, msgSupplier, (Throwable) null);%n" 
890            + "    }%n" 
891            + "%n" 
892            + "    /**%n" 
893            + "     * Logs a message with parameters which are only to be constructed if the logging level is the%n" 
894            + "     * {@code CUSTOM_LEVEL} level.%n" 
895            + "     *%n" 
896            + "     * @param marker the marker data specific to this log statement%n" 
897            + "     * @param message the message to log; the format depends on the message factory.%n" 
898            + "     * @param paramSuppliers An array of functions, which when called, produce the desired log" 
899            + " message parameters.%n" 
900            + "     * @since Log4j-2.4%n" 
901            + "     */%n" 
902            + "    public void methodName(final Marker marker, final String message, final Supplier<?>..." 
903            + " paramSuppliers) {%n" 
904            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, paramSuppliers);%n" 
905            + "    }%n" 
906            + "%n" 
907            + "    /**%n" 
908            + "     * Logs a message (only to be constructed if the logging level is the {@code CUSTOM_LEVEL}%n" 
909            + "     * level) with the specified Marker and including the stack trace of the {@link Throwable}%n" 
910            + "     * <code>t</code> passed as parameter.%n"
911            + "     *%n" 
912            + "     * @param marker the marker data specific to this log statement%n" 
913            + "     * @param msgSupplier A function, which when called, produces the desired log message;%n" 
914            + "     *            the format depends on the message factory.%n" 
915            + "     * @param t A Throwable or null.%n" 
916            + "     * @since Log4j-2.4%n" 
917            + "     */%n" 
918            + "    public void methodName(final Marker marker, final Supplier<?> msgSupplier, final Throwable t) {%n" 
919            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, msgSupplier, t);%n" 
920            + "    }%n" 
921            + "%n" 
922            + "    /**%n" 
923            + "     * Logs a message with parameters which are only to be constructed if the logging level is%n" 
924            + "     * the {@code CUSTOM_LEVEL} level.%n" 
925            + "     *%n" 
926            + "     * @param message the message to log; the format depends on the message factory.%n" 
927            + "     * @param paramSuppliers An array of functions, which when called, produce the desired log" 
928            + " message parameters.%n" 
929            + "     * @since Log4j-2.4%n" 
930            + "     */%n" 
931            + "    public void methodName(final String message, final Supplier<?>... paramSuppliers) {%n" 
932            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, paramSuppliers);%n" 
933            + "    }%n" 
934            + "%n" 
935            + "    /**%n" 
936            + "     * Logs a message which is only to be constructed if the logging level is the%n" 
937            + "     * {@code CUSTOM_LEVEL} level with the specified Marker. The {@code MessageSupplier} may or may%n" 
938            + "     * not use the {@link MessageFactory} to construct the {@code Message}.%n" 
939            + "     *%n" 
940            + "     * @param marker the marker data specific to this log statement%n" 
941            + "     * @param msgSupplier A function, which when called, produces the desired log message.%n" 
942            + "     * @since Log4j-2.4%n" 
943            + "     */%n" 
944            + "    public void methodName(final Marker marker, final MessageSupplier msgSupplier) {%n" 
945            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, msgSupplier, (Throwable) null);%n" 
946            + "    }%n" 
947            + "%n" 
948            + "    /**%n" 
949            + "     * Logs a message (only to be constructed if the logging level is the {@code CUSTOM_LEVEL}%n" 
950            + "     * level) with the specified Marker and including the stack trace of the {@link Throwable}%n" 
951            + "     * <code>t</code> passed as parameter. The {@code MessageSupplier} may or may not use the%n" 
952            + "     * {@link MessageFactory} to construct the {@code Message}.%n"
953            + "     *%n" 
954            + "     * @param marker the marker data specific to this log statement%n" 
955            + "     * @param msgSupplier A function, which when called, produces the desired log message.%n" 
956            + "     * @param t A Throwable or null.%n" 
957            + "     * @since Log4j-2.4%n" 
958            + "     */%n" 
959            + "    public void methodName(final Marker marker, final MessageSupplier msgSupplier, final " 
960            + "Throwable t) {%n" 
961            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, msgSupplier, t);%n" 
962            + "    }%n" 
963            + "%n" 
964            + "    /**%n" 
965            + "     * Logs a message which is only to be constructed if the logging level is the%n" 
966            + "     * {@code CUSTOM_LEVEL} level. The {@code MessageSupplier} may or may not use the%n" 
967            + "     * {@link MessageFactory} to construct the {@code Message}.%n"
968            + "     *%n" 
969            + "     * @param msgSupplier A function, which when called, produces the desired log message.%n" 
970            + "     * @since Log4j-2.4%n" 
971            + "     */%n" 
972            + "    public void methodName(final MessageSupplier msgSupplier) {%n" 
973            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, msgSupplier, (Throwable) null);%n" 
974            + "    }%n" 
975            + "%n" 
976            + "    /**%n" 
977            + "     * Logs a message (only to be constructed if the logging level is the {@code CUSTOM_LEVEL}%n" 
978            + "     * level) including the stack trace of the {@link Throwable} <code>t</code> passed as parameter.%n"
979            + "     * The {@code MessageSupplier} may or may not use the {@link MessageFactory} to construct the%n" 
980            + "     * {@code Message}.%n"
981            + "     *%n" 
982            + "     * @param msgSupplier A function, which when called, produces the desired log message.%n" 
983            + "     * @param t the exception to log, including its stack trace.%n" 
984            + "     * @since Log4j-2.4%n" 
985            + "     */%n" 
986            + "    public void methodName(final MessageSupplier msgSupplier, final Throwable t) {%n" 
987            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, msgSupplier, t);%n" 
988            + "    }%n";
989            //@formatter:on
990
991    private Generate() {
992    }
993
994    /**
995     * Generates source code for custom logger wrappers that only provide convenience methods for the specified custom
996     * levels, not for the standard built-in levels.
997     */
998    public static final class CustomLogger {
999        /**
1000         * Generates source code for custom logger wrappers that only provide convenience methods for the specified
1001         * custom levels, not for the standard built-in levels.
1002         *
1003         * @param args className of the custom logger to generate, followed by a NAME=intLevel pair for each custom log
1004         *            level to generate convenience methods for
1005         */
1006        public static void main(final String[] args) {
1007            generate(args, Type.CUSTOM);
1008        }
1009
1010        private CustomLogger() {
1011        }
1012    }
1013
1014    /**
1015     * Generates source code for extended logger wrappers that provide convenience methods for the specified custom
1016     * levels, and by extending {@code org.apache.logging.log4j.spi.ExtendedLoggerWrapper}, inherit the convenience
1017     * methods for the built-in levels provided by the {@code Logger} interface.
1018     */
1019    public static final class ExtendedLogger {
1020        /**
1021         * Generates source code for extended logger wrappers that provide convenience methods for the specified custom
1022         * levels.
1023         *
1024         * @param args className of the custom logger to generate, followed by a NAME=intLevel pair for each custom log
1025         *            level to generate convenience methods for
1026         */
1027        public static void main(final String[] args) {
1028            generate(args, Type.EXTEND);
1029        }
1030
1031        private ExtendedLogger() {
1032        }
1033    }
1034
1035    static class LevelInfo {
1036        final String name;
1037        final int intLevel;
1038
1039        LevelInfo(final String description) {
1040            final String[] parts = description.split("=");
1041            name = parts[0];
1042            intLevel = Integer.parseInt(parts[1]);
1043        }
1044
1045        public static List<LevelInfo> parse(final List<String> values, final Class<?> generator) {
1046            final List<LevelInfo> result = new ArrayList<>(values.size());
1047            for (int i = 0; i < values.size(); i++) {
1048                try {
1049                    result.add(new LevelInfo(values.get(i)));
1050                } catch (final Exception ex) {
1051                    System.err.println("Cannot parse custom level '" + values.get(i) + "': " + ex.toString());
1052                    usage(System.err, generator);
1053                    System.exit(-1);
1054                }
1055            }
1056            return result;
1057        }
1058    }
1059
1060    private static void generate(final String[] args, final Type type) {
1061        generate(args, type, System.out);
1062    }
1063
1064    static void generate(final String[] args, final Type type, final PrintStream printStream) {
1065        if (!validate(args)) {
1066            usage(printStream, type.generator());
1067            System.exit(-1);
1068        }
1069        final List<String> values = new ArrayList<>(Arrays.asList(args));
1070        final String classFQN = values.remove(0);
1071        final List<LevelInfo> levels = LevelInfo.parse(values, type.generator());
1072        printStream.println(generateSource(classFQN, levels, type));
1073    }
1074
1075    static boolean validate(final String[] args) {
1076        if (args.length < 2) {
1077            return false;
1078        }
1079        return true;
1080    }
1081
1082    private static void usage(final PrintStream out, final Class<?> generator) {
1083        out.println("Usage: java " + generator.getName() + " className LEVEL1=intLevel1 [LEVEL2=intLevel2...]");
1084        out.println("       Where className is the fully qualified class name of the custom/extended logger");
1085        out.println("       to generate, followed by a space-separated list of custom log levels.");
1086        out.println("       For each custom log level, specify NAME=intLevel (without spaces).");
1087    }
1088
1089    static String generateSource(final String classNameFQN, final List<LevelInfo> levels, final Type type) {
1090        final StringBuilder sb = new StringBuilder(10000 * levels.size());
1091        final int lastDot = classNameFQN.lastIndexOf('.');
1092        final String pkg = classNameFQN.substring(0, lastDot >= 0 ? lastDot : 0);
1093        if (!pkg.isEmpty()) {
1094            sb.append(String.format(PACKAGE_DECLARATION, pkg));
1095        }
1096        sb.append(String.format(type.imports(), ""));
1097        final String className = classNameFQN.substring(classNameFQN.lastIndexOf('.') + 1);
1098        final String javadocDescr = javadocDescription(levels);
1099        sb.append(String.format(type.declaration(), javadocDescr, className));
1100        sb.append(String.format(FQCN_FIELD, className));
1101        for (final LevelInfo level : levels) {
1102            sb.append(String.format(LEVEL_FIELD, level.name, level.name, level.intLevel));
1103        }
1104        sb.append(String.format(type.constructor(), className));
1105        sb.append(String.format(FACTORY_METHODS.replaceAll("CLASSNAME", className), ""));
1106        for (final LevelInfo level : levels) {
1107            final String methodName = camelCase(level.name);
1108            final String phase1 = METHODS.replaceAll("CUSTOM_LEVEL", level.name);
1109            final String phase2 = phase1.replaceAll("methodName", methodName);
1110            sb.append(String.format(phase2, ""));
1111        }
1112
1113        sb.append('}');
1114        sb.append(System.getProperty("line.separator"));
1115        return sb.toString();
1116    }
1117
1118    static String javadocDescription(final List<LevelInfo> levels) {
1119        if (levels.size() == 1) {
1120            return "the " + levels.get(0).name + " custom log level.";
1121        }
1122        final StringBuilder sb = new StringBuilder(512);
1123        sb.append("the ");
1124        String sep = "";
1125        for (int i = 0; i < levels.size(); i++) {
1126            sb.append(sep);
1127            sb.append(levels.get(i).name);
1128            sep = (i == levels.size() - 2) ? " and " : ", ";
1129        }
1130        sb.append(" custom log levels.");
1131        return sb.toString();
1132    }
1133
1134    static String camelCase(final String customLevel) {
1135        final StringBuilder sb = new StringBuilder(customLevel.length());
1136        boolean lower = true;
1137        for (final char ch : customLevel.toCharArray()) {
1138            if (ch == '_') {
1139                lower = false;
1140                continue;
1141            }
1142            sb.append(lower ? Character.toLowerCase(ch) : Character.toUpperCase(ch));
1143            lower = true;
1144        }
1145        return sb.toString();
1146    }
1147}