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.jul;
019
020import java.security.AccessController;
021import java.security.PrivilegedAction;
022import java.util.logging.Filter;
023import java.util.logging.Level;
024import java.util.logging.LogRecord;
025import java.util.logging.Logger;
026
027import org.apache.logging.log4j.message.Message;
028import org.apache.logging.log4j.message.MessageFactory;
029import org.apache.logging.log4j.spi.ExtendedLogger;
030
031/**
032 * Log4j API implementation of the JUL {@link Logger} class. <strong>Note that this implementation does
033 * <em>not</em> use the {@link java.util.logging.Handler} class.</strong> Instead, logging is delegated to the
034 * underlying Log4j {@link org.apache.logging.log4j.Logger} which may be implemented in one of many different ways.
035 * Consult the documentation for your Log4j Provider for more details.
036 * <p>Note that the methods {@link #getParent()} and {@link #setLevel(java.util.logging.Level)} are not supported by
037 * this implementation. If you need support for these methods, then you'll need to use log4j-core. The
038 * {@link #getParent()} method will not fail (thanks to JUL API limitations), but it won't necessarily be
039 * accurate!</p>
040 * <p>Also note that {@link #setParent(java.util.logging.Logger)} is explicitly unsupported. Parent loggers are
041 * determined using the syntax of the logger name; not through an arbitrary graph of loggers.</p>
042 *
043 * @since 2.1
044 */
045public class ApiLogger extends Logger {
046
047    private final WrappedLogger logger;
048    private static final String FQCN = ApiLogger.class.getName();
049
050    ApiLogger(final ExtendedLogger logger) {
051        super(logger.getName(), null);
052        final Level javaLevel = LevelTranslator.toJavaLevel(logger.getLevel());
053        // "java.util.logging.LoggingPermission" "control"
054        AccessController.doPrivileged(new PrivilegedAction<Object>() {
055            @Override
056            public Object run() {
057                ApiLogger.super.setLevel(javaLevel);
058                return null;
059            }
060        });
061        this.logger = new WrappedLogger(logger);
062    }
063
064    @Override
065    public void log(final LogRecord record) {
066        if (isFiltered(record)) {
067            return;
068        }
069        final org.apache.logging.log4j.Level level = LevelTranslator.toLevel(record.getLevel());
070        final Object[] parameters = record.getParameters();
071        final MessageFactory messageFactory = logger.getMessageFactory();
072        final Message message = parameters == null ?
073            messageFactory.newMessage(record.getMessage()) /* LOG4J2-1251: not formatted case */ :
074            messageFactory.newMessage(record.getMessage(), parameters);
075        final Throwable thrown = record.getThrown();
076        logger.logIfEnabled(FQCN, level, null, message, thrown);
077    }
078
079    // support for Logger.getFilter()/Logger.setFilter()
080    boolean isFiltered(final LogRecord logRecord) {
081        final Filter filter = getFilter();
082        return filter != null && !filter.isLoggable(logRecord);
083    }
084
085    @Override
086    public boolean isLoggable(final Level level) {
087        return logger.isEnabled(LevelTranslator.toLevel(level));
088    }
089
090    @Override
091    public String getName() {
092        return logger.getName();
093    }
094
095    @Override
096    public void setLevel(final Level newLevel) throws SecurityException {
097        throw new UnsupportedOperationException("Cannot set level through log4j-api");
098    }
099
100    /**
101     * Provides access to {@link Logger#setLevel(java.util.logging.Level)}. This method should only be used by child
102     * classes.
103     *
104     * @see Logger#setLevel(java.util.logging.Level)
105     */
106    protected void doSetLevel(final Level newLevel) throws SecurityException {
107        super.setLevel(newLevel);
108    }
109
110    /**
111     * Unsupported operation.
112     *
113     * @throws UnsupportedOperationException always
114     */
115    @Override
116    public void setParent(final Logger parent) {
117        throw new UnsupportedOperationException("Cannot set parent logger");
118    }
119
120    @Override
121    public void log(final Level level, final String msg) {
122        logger.log(LevelTranslator.toLevel(level), msg);
123    }
124
125    @Override
126    public void log(final Level level, final String msg, final Object param1) {
127        logger.log(LevelTranslator.toLevel(level), msg, param1);
128    }
129
130    @Override
131    public void log(final Level level, final String msg, final Object[] params) {
132        logger.log(LevelTranslator.toLevel(level), msg, params);
133    }
134
135    @Override
136    public void log(final Level level, final String msg, final Throwable thrown) {
137        logger.log(LevelTranslator.toLevel(level), msg, thrown);
138    }
139
140    @Override
141    public void logp(final Level level, final String sourceClass, final String sourceMethod, final String msg) {
142        log(level, msg);
143    }
144
145    @Override
146    public void logp(final Level level, final String sourceClass, final String sourceMethod, final String msg,
147                     final Object param1) {
148        log(level, msg, param1);
149    }
150
151    @Override
152    public void logp(final Level level, final String sourceClass, final String sourceMethod, final String msg,
153                     final Object[] params) {
154        log(level, msg, params);
155    }
156
157    @Override
158    public void logp(final Level level, final String sourceClass, final String sourceMethod, final String msg,
159                     final Throwable thrown) {
160        log(level, msg, thrown);
161    }
162
163    @Override
164    public void logrb(final Level level, final String sourceClass, final String sourceMethod, final String bundleName,
165                      final String msg) {
166        log(level, msg);
167    }
168
169    @Override
170    public void logrb(final Level level, final String sourceClass, final String sourceMethod, final String bundleName,
171                      final String msg, final Object param1) {
172        log(level, msg, param1);
173    }
174
175    @Override
176    public void logrb(final Level level, final String sourceClass, final String sourceMethod, final String bundleName,
177                      final String msg, final Object[] params) {
178        log(level, msg, params);
179    }
180
181    @Override
182    public void logrb(final Level level, final String sourceClass, final String sourceMethod, final String bundleName,
183                      final String msg, final Throwable thrown) {
184        log(level, msg, thrown);
185    }
186
187    @Override
188    public void entering(final String sourceClass, final String sourceMethod) {
189        logger.entry();
190    }
191
192    @Override
193    public void entering(final String sourceClass, final String sourceMethod, final Object param1) {
194        logger.entry(param1);
195    }
196
197    @Override
198    public void entering(final String sourceClass, final String sourceMethod, final Object[] params) {
199        logger.entry(params);
200    }
201
202    @Override
203    public void exiting(final String sourceClass, final String sourceMethod) {
204        logger.exit();
205    }
206
207    @Override
208    public void exiting(final String sourceClass, final String sourceMethod, final Object result) {
209        logger.exit(result);
210    }
211
212    @Override
213    public void throwing(final String sourceClass, final String sourceMethod, final Throwable thrown) {
214        logger.throwing(thrown);
215    }
216
217    @Override
218    public void severe(final String msg) {
219        logger.logIfEnabled(FQCN, org.apache.logging.log4j.Level.ERROR, null, msg);
220    }
221
222    @Override
223    public void warning(final String msg) {
224        logger.logIfEnabled(FQCN, org.apache.logging.log4j.Level.WARN, null, msg);
225    }
226
227    @Override
228    public void info(final String msg) {
229        logger.logIfEnabled(FQCN, org.apache.logging.log4j.Level.INFO, null, msg);
230    }
231
232    @Override
233    public void config(final String msg) {
234        logger.logIfEnabled(FQCN, LevelTranslator.CONFIG, null, msg);
235    }
236
237    @Override
238    public void fine(final String msg) {
239        logger.logIfEnabled(FQCN, org.apache.logging.log4j.Level.DEBUG, null, msg);
240    }
241
242    @Override
243    public void finer(final String msg) {
244        logger.logIfEnabled(FQCN, org.apache.logging.log4j.Level.TRACE, null, msg);
245    }
246
247    @Override
248    public void finest(final String msg) {
249        logger.logIfEnabled(FQCN, LevelTranslator.FINEST, null, msg);
250    }
251}