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