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.AbstractJaxbMojo;
24  import org.codehaus.mojo.jaxb2.shared.Validate;
25  import org.codehaus.mojo.jaxb2.shared.environment.AbstractLogAwareFacet;
26  
27  import java.util.ArrayList;
28  import java.util.List;
29  import java.util.logging.Handler;
30  import java.util.logging.Level;
31  import java.util.logging.Logger;
32  
33  /**
34   * EnvironmentFacet for replacing Handlers from Java Util Logging with a Maven Log.
35   * This is required as an environment facet for capturing log statements from tools
36   * that use the Java Util Logging system internally - such as the JDK SchemaGen tool.
37   *
38   * @author <a href="mailto:lj@jguru.se">Lennart J&ouml;relid</a>, jGuru Europe AB
39   * @since 2.1
40   */
41  public class LoggingHandlerEnvironmentFacet extends AbstractLogAwareFacet {
42  
43      /**
44       * Standard logger names/categories for the java.util.Logger.
45       */
46      public static final String[] DEFAULT_LOGGER_NAMES = new String[]{"com.sun", "javax.xml", "javax.tools"};
47  
48      // Internal state
49      private boolean restored;
50      private Logger rootLogger;
51      private Level originalRootLoggerLevel;
52      private List<Handler> originalHandlers;
53      private MavenLogHandler mavenLogHandler;
54  
55      private String logPrefix;
56      private String encoding;
57      private String[] loggerNamePrefixes;
58  
59      /**
60       * Creates a new JavaLoggingEnvironment, using the supplied variables to set up a MavenLogHandler.
61       * The MavenLogHandler is then assigned to the root logger.
62       *
63       * @param logPrefix          The prefix to use for the logger, indicating which tool is used by the log. Example: "XJC"
64       *                           or "SchemaGen".
65       * @param mavenLog           The active Maven Log.
66       * @param encoding           The configured encoding.
67       * @param loggerNamePrefixes The prefixes of the Logger names to be permitted logging.
68       */
69      public LoggingHandlerEnvironmentFacet(final String logPrefix,
70                                            final Log mavenLog,
71                                            final String encoding,
72                                            final String[] loggerNamePrefixes) {
73  
74          super(mavenLog);
75  
76          // Check sanity
77          Validate.notEmpty(encoding, "encoding");
78          Validate.notNull(loggerNamePrefixes, "loggerNamePrefixes");
79  
80          // Assign internal state
81          this.originalHandlers = new ArrayList<Handler>();
82          this.logPrefix = logPrefix;
83          rootLogger = Logger.getLogger("");
84          originalRootLoggerLevel = rootLogger.getLevel();
85          this.encoding = encoding;
86          this.loggerNamePrefixes = loggerNamePrefixes;
87      }
88  
89      /**
90       * {@inheritDoc}
91       * <p>Redirects JUL logging statements to the Maven Log.</p>
92       */
93      @Override
94      public void setup() {
95  
96          // Redirect the JUL Logging statements to the Maven Log.
97          rootLogger.setLevel(MavenLogHandler.getJavaUtilLoggingLevelFor(log));
98          this.mavenLogHandler = new MavenLogHandler(log, logPrefix, encoding, loggerNamePrefixes);
99  
100         for (Handler current : rootLogger.getHandlers()) {
101 
102             // Stash the original handlers from the RootLogger.
103             originalHandlers.add(current);
104 
105             // Remove the original handler from the RootLogger.
106             rootLogger.removeHandler(current);
107         }
108 
109         // Add the new Maven Log handler.
110         rootLogger.addHandler(this.mavenLogHandler);
111     }
112 
113     /**
114      * Restores the original root Logger state, including Level and Handlers.
115      */
116     public void restore() {
117 
118         if (!restored) {
119 
120             // Remove the extra Handler from the RootLogger
121             rootLogger.removeHandler(mavenLogHandler);
122 
123             // Restore the original state to the Root logger
124             rootLogger.setLevel(originalRootLoggerLevel);
125             for (Handler current : originalHandlers) {
126                 rootLogger.addHandler(current);
127             }
128 
129             // All done.
130             restored = true;
131         }
132     }
133 
134     /**
135      * Factory method creating a new LoggingHandlerEnvironmentFacet wrapping the supplied properties.
136      *
137      * @param mavenLog The active Maven Log.
138      * @param caller   The AbstractJaxbMojo subclass which invoked this LoggingHandlerEnvironmentFacet factory method.
139      * @param encoding The encoding used by the Maven Mojo subclass.
140      * @return A fully set up LoggingHandlerEnvironmentFacet
141      */
142     public static LoggingHandlerEnvironmentFacet create(final Log mavenLog,
143                                                         final Class<? extends AbstractJaxbMojo> caller,
144                                                         final String encoding) {
145 
146         // Check sanity
147         Validate.notNull(mavenLog, "mavenLog");
148         Validate.notNull(caller, "caller");
149         Validate.notEmpty(encoding, "encoding");
150 
151         // Find the standard log prefix for the tool in question.
152         final String logPrefix = caller.getClass().getCanonicalName().toUpperCase().contains("XJC")
153                 ? "XJC"
154                 : "SchemaGen";
155 
156         // All done.
157         return new LoggingHandlerEnvironmentFacet(logPrefix, mavenLog, encoding, DEFAULT_LOGGER_NAMES);
158     }
159 }