001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.commons.weaver.maven;
020
021import java.text.MessageFormat;
022import java.util.ArrayList;
023import java.util.List;
024import java.util.ResourceBundle;
025import java.util.logging.Handler;
026import java.util.logging.Level;
027import java.util.logging.LogManager;
028import java.util.logging.LogRecord;
029import java.util.logging.Logger;
030
031import org.apache.commons.lang3.ArrayUtils;
032import org.apache.maven.plugin.MojoExecutionException;
033import org.apache.maven.plugin.logging.Log;
034
035/**
036 * This class redirects calls to java.util Logging to Mojo logging.
037 */
038public class JavaLoggingToMojoLoggingRedirector {
039    private final List<Handler> removedHandlers = new ArrayList<Handler>();
040
041    /**
042     * The Maven mojo logger to delegate messages to.
043     */
044    private final Log mojoLogger;
045
046    private JDKLogHandler activeHandler;
047
048    /**
049     * @param mojoLogger
050     *            the Maven mojo logger to delegate messages to.
051     */
052    public JavaLoggingToMojoLoggingRedirector(final Log mojoLogger) {
053        this.mojoLogger = mojoLogger;
054    }
055
056    /**
057     * Activates this feature.
058     * @throws MojoExecutionException in the event of failure
059     */
060    public void activate() throws MojoExecutionException {
061        try {
062            final Logger rootLogger = LogManager.getLogManager().getLogger("");
063            // remove old handlers
064            for (final Handler handler : rootLogger.getHandlers()) {
065                rootLogger.removeHandler(handler);
066                removedHandlers.add(handler);
067            }
068            if (removedHandlers.isEmpty()) {
069                throw new MojoExecutionException("could not remove any handler. aborting.");
070            }
071
072            // add our own
073            activeHandler = new JDKLogHandler();
074            activeHandler.setLevel(Level.ALL);
075            rootLogger.setLevel(Level.ALL);
076
077            rootLogger.addHandler(activeHandler);
078        } catch (Exception exc) {
079            throw new MojoExecutionException("failed to activate the jul logging redirector", exc);
080        }
081    }
082
083    /**
084     * Deactivate the redirection and put the original Handlers back in place
085     * again.
086     */
087    public void deactivate() {
088        final Logger rootLogger = LogManager.getLogManager().getLogger("");
089        // remove old handlers
090        for (final Handler handler : rootLogger.getHandlers()) {
091            if (handler == activeHandler) {
092                rootLogger.removeHandler(handler);
093            }
094        }
095
096        for (final Handler oldHandler : removedHandlers) {
097            rootLogger.addHandler(oldHandler);
098        }
099    }
100
101    private class JDKLogHandler extends Handler {
102
103        @Override
104        public void publish(final LogRecord record) {
105            final Throwable exception = record.getThrown();
106            final Level level = record.getLevel();
107            if (level == Level.SEVERE && mojoLogger.isErrorEnabled()) {
108                if (exception == null) {
109                    mojoLogger.error(getMessage(record));
110                } else {
111                    mojoLogger.error(getMessage(record), exception);
112                }
113            } else if (level == Level.WARNING && mojoLogger.isWarnEnabled()) {
114                if (exception == null) {
115                    mojoLogger.warn(getMessage(record));
116                } else {
117                    mojoLogger.warn(getMessage(record), exception);
118                }
119            } else if (level == Level.INFO && mojoLogger.isInfoEnabled()) {
120                if (exception == null) {
121                    mojoLogger.info(getMessage(record));
122                } else {
123                    mojoLogger.info(getMessage(record), exception);
124                }
125            } else if (mojoLogger.isDebugEnabled()) {
126                if (exception == null) {
127                    mojoLogger.debug(getMessage(record));
128                } else {
129                    mojoLogger.debug(getMessage(record), exception);
130                }
131            }
132        }
133
134        private String getMessage(final LogRecord record) {
135            final ResourceBundle bundle = record.getResourceBundle();
136            final Object[] params = record.getParameters();
137            final String message;
138            if (bundle != null && bundle.containsKey(record.getMessage())) {
139                // todo: cannot enforce Locale.ENGLISH here
140                message = bundle.getString(record.getMessage());
141            } else {
142                message = record.getMessage();
143            }
144            if (ArrayUtils.isNotEmpty(params)) {
145                return new MessageFormat(message).format(params);
146            }
147            return message;
148        }
149
150        @Override
151        public void flush() {
152            // nothing to do
153        }
154
155        @Override
156        public void close() {
157            // nothing to do
158        }
159
160    }
161
162}