View Javadoc
1   package org.codehaus.mojo.jaxb2.shared.environment.logging;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.plugin.logging.Log;
23  import org.codehaus.mojo.jaxb2.shared.Validate;
24  
25  import java.io.UnsupportedEncodingException;
26  import java.util.Arrays;
27  import java.util.List;
28  import java.util.logging.Filter;
29  import java.util.logging.Handler;
30  import java.util.logging.Level;
31  import java.util.logging.LogRecord;
32  import java.util.logging.SimpleFormatter;
33  
34  /**
35   * Handler implementation which delegates its actual logging to an internal Maven log.
36   * This is required to capture logging statements from tools that use the Java Util Logging
37   * system internally - such as the JDK SchemaGen tool.
38   *
39   * @author <a href="mailto:lj@jguru.se">Lennart J&ouml;relid</a>, jGuru Europe AB
40   * @since 2.0
41   */
42  public class MavenLogHandler extends Handler {
43  
44      // Internal state
45      private Log log;
46      private String prefix;
47  
48      /**
49       * Creates a new MavenLogHandler which adapts a {@link Handler} to emit log messages onto a Maven Log.
50       *
51       * @param log                       The Maven Log to emit log messages to.
52       * @param prefix                    An optional prefix used to prefix any log message.
53       * @param encoding                  The encoding which should be used.
54       * @param acceptedLogRecordPrefixes A non-null list of prefixes holding LogRecord logger names for
55       *                                  permitted/accepted LogRecords.
56       */
57      public MavenLogHandler(final Log log,
58                             final String prefix,
59                             final String encoding,
60                             final String[] acceptedLogRecordPrefixes) {
61  
62          // Check sanity
63          Validate.notNull(log, "log");
64          Validate.notNull(prefix, "prefix");
65          Validate.notEmpty(encoding, "encoding");
66  
67          // Assign internal state
68          this.log = log;
69          this.prefix = prefix.isEmpty() ? "" : "[" + prefix + "]: ";
70  
71          setFormatter(new SimpleFormatter());
72          setLevel(getJavaUtilLoggingLevelFor(log));
73          try {
74              setEncoding(encoding);
75          } catch (UnsupportedEncodingException e) {
76              log.error("Could not use encoding '" + encoding + "'", e);
77          }
78  
79          if (acceptedLogRecordPrefixes != null && acceptedLogRecordPrefixes.length > 0) {
80              setFilter(getLoggingFilter(acceptedLogRecordPrefixes));
81          }
82      }
83  
84      /**
85       * {@inheritDoc}
86       */
87      @Override
88      public void publish(final LogRecord record) {
89  
90          if (this.isLoggable(record)) {
91  
92              final Level level = record.getLevel();
93              final String message = prefix + getFormatter().format(record);
94  
95              if (Level.SEVERE.equals(level)) {
96                  log.error(message);
97              } else if (Level.WARNING.equals(level)) {
98                  log.warn(message);
99              } else if (Level.INFO.equals(level)) {
100                 log.info(message);
101             } else {
102                 log.debug(message);
103             }
104         }
105     }
106 
107     /**
108      * {@inheritDoc}
109      */
110     @Override
111     public void flush() {
112         // Do nothing.
113     }
114 
115     /**
116      * {@inheritDoc}
117      */
118     @Override
119     public void close() throws SecurityException {
120         // Do nothing.
121     }
122 
123     /**
124      * Retrieves the JUL Level matching the supplied Maven Log.
125      *
126      * @param mavenLog A non-null Maven Log.
127      * @return The Corresponding JUL Level.
128      */
129     public static Level getJavaUtilLoggingLevelFor(final Log mavenLog) {
130 
131         // Check sanity
132         Validate.notNull(mavenLog, "mavenLog");
133 
134         Level toReturn = Level.SEVERE;
135 
136         if (mavenLog.isDebugEnabled()) {
137             toReturn = Level.FINER;
138         } else if (mavenLog.isInfoEnabled()) {
139             toReturn = Level.INFO;
140         } else if (mavenLog.isWarnEnabled()) {
141             toReturn = Level.WARNING;
142         }
143 
144         // All Done.
145         return toReturn;
146     }
147 
148     /**
149      * Retrieves a java.util.Logging filter used to ensure that only LogRecords whose
150      * logger names start with any of the required prefixes are logged.
151      *
152      * @param requiredPrefixes A non-null list of prefixes to be matched with the LogRecord logger names.
153      * @return A java.util.logging Filter that only permits logging LogRecords whose
154      * logger names start with any of the required prefixes.
155      */
156     public static Filter getLoggingFilter(final String... requiredPrefixes) {
157 
158         // Check sanity
159         Validate.notNull(requiredPrefixes, "requiredPrefixes");
160 
161         // All done.
162         return new Filter() {
163 
164             // Internal state
165             private List<String> requiredPrefs = Arrays.asList(requiredPrefixes);
166 
167             @Override
168             public boolean isLoggable(final LogRecord record) {
169 
170                 final String loggerName = record.getLoggerName();
171                 for (String current : requiredPrefs) {
172                     if (loggerName.startsWith(current)) {
173                         return true;
174                     }
175                 }
176 
177                 // No matches found.
178                 return false;
179             }
180         };
181     }
182 }