View Javadoc

1   /*
2    LogUtils.java
3    Creation date : 29/10/2008
4    Copyright © Benjamin Croizet (graffity2199@yahoo.fr)
5   
6    This program is free software; you can redistribute it and/or
7    modify it under the terms of the GNU General Public License
8    or GNU Lesser General Public License as published by the
9    Free Software Foundation; either version 3 of the License,
10   or (at your option) any later version.
11  
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16  
17   You should have received copies of the GNU General Public License
18   and GNU Lesser General Public License along with this program;
19   if not, write to the Free Software Foundation, Inc.,
20   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21   http://www.fsf.org/licensing/licenses/gpl.html
22   http://www.gnu.org/licenses/lgpl.html
23   */
24  
25  package net.sourceforge.plantumldependency.common.utils.log;
26  
27  import static java.util.logging.LogManager.getLogManager;
28  import static java.util.regex.Matcher.quoteReplacement;
29  import static net.sourceforge.plantumldependency.common.constants.CharacterConstants.BACK_SLASH_CHAR;
30  import static net.sourceforge.plantumldependency.common.constants.CharacterConstants.LEFT_BRACES_CHAR;
31  import static net.sourceforge.plantumldependency.common.constants.CharacterConstants.RIGHT_BRACES_CHAR;
32  import static net.sourceforge.plantumldependency.common.constants.CommonConstants.BLANK_STRING;
33  import static net.sourceforge.plantumldependency.common.constants.log.ErrorConstants.MISSING_LOGGING_FILE_ERROR;
34  import static net.sourceforge.plantumldependency.common.utils.file.FileUtils.closeCloseable;
35  
36  import java.io.File;
37  import java.io.FileInputStream;
38  import java.io.IOException;
39  import java.io.InputStream;
40  import java.util.Enumeration;
41  import java.util.logging.Handler;
42  import java.util.logging.Level;
43  import java.util.logging.LogManager;
44  import java.util.logging.Logger;
45  
46  /**
47   * This class utilities containing useful methods which can be used with log message. For example,
48   * it can be used with log message where arguments are needed by building the string to log
49   * following passed arguments.
50   *
51   * @author Benjamin Croizet (<a href="mailto:graffity2199@yahoo.fr>graffity2199@yahoo.fr</a>)
52   * @since 1.3.0
53   * @version 1.3.0
54   */
55  public abstract class LogUtils {
56  
57      /**
58       * This method is the same of the {code String buildLogString(String logMessage, String[] args)}
59       * except that there is only one argument.
60       *
61       * @param logMessage
62       *            the generic log message as a {code String}. Arguments are described as {0}. Can't
63       *            be {code null}.
64       * @param args
65       *            the arguments as {code String} to replace in the log message. Can't be {code
66       *            null}.
67       * @return the final log message where generic argument have been replaced. For instance :<br>
68       *         - Log message : "Initializing {0} file...."<br>
69       *         - Arguments : "options.xml"<br>
70       *         will return "Initializing options.xml file...."
71       * @since 1.3.0
72       * @see #buildLogString(String, String[])
73       */
74      public static String buildLogString(final String logMessage, final Object args) {
75          assert logMessage != null : "logMessage is null";
76          assert args != null : "args is null";
77  
78          return buildLogString(logMessage, new String[] {args.toString()});
79      }
80  
81      /**
82       * This method is used to build the log string following the generic log message with passed
83       * arguments.
84       *
85       * @param logMessage
86       *            the generic log message as a {code String}. Arguments are described as {0}, {1},
87       *            {2} etc.... Can't be {code null}.
88       * @param args
89       *            the arguments as {code Object} to replace as {code String} in the log message. If
90       *            the arguments aren't enough, the arguments will be considered as empty and the log
91       *            message will be fill with a blank string instead. If the arguments are higher that
92       *            the number contained in the log message, the latest are ignored. Can be {null}, in
93       *            this case arguments will be filled with empty {code String}.
94       * @return the final log message where generic argument have been replaced. For instance :<br>
95       *         - Log message : "Initializing {0} file.... {1}"<br>
96       *         - Arguments : new String[] {"options.xml", "OK"}<br>
97       *         will return "Initializing options.xml file.... OK"
98       * @since 1.3.0
99       * @see #buildLogString(String, String[])
100      */
101     public static String buildLogString(final String logMessage, final Object[] args) {
102         assert logMessage != null : "logMessage is null";
103 
104         String[] str = null;
105 
106         if (args != null) {
107             str = new String[args.length];
108 
109             for (int i = 0; i < args.length; i++) {
110                 str[i] = args[i].toString();
111             }
112         }
113 
114         return buildLogString(logMessage, str);
115     }
116 
117     /**
118      * This method is the same of the {code String buildLogString(String logMessage, String[] args)}
119      * except that there is only one argument.
120      *
121      * @param logMessage
122      *            the generic log message as a {code String}. Arguments are described as {0}. Can't
123      *            be {code null}.
124      * @param args
125      *            the arguments as {code String} to replace in the log message. Can't be {null}.
126      * @return the final log message where generic argument have been replaced. For instance :<br>
127      *         - Log message : "Initializing {0} file...."<br>
128      *         - Arguments : "options.xml"<br>
129      *         will return "Initializing options.xml file...."
130      * @since 1.3.0
131      * @see #buildLogString(String, String[])
132      */
133     public static String buildLogString(final String logMessage, final String args) {
134         assert logMessage != null : "logMessage is null";
135         assert args != null : "args is null";
136 
137         return buildLogString(logMessage, new String[] {args});
138     }
139 
140     /**
141      * This method is used to build the log string following the generic log message with passed
142      * arguments.
143      *
144      * @param logMessage
145      *            the generic log message as a {code String}. Arguments are described as {0}, {1},
146      *            {2} etc.... Can't be {code null}.
147      * @param args
148      *            the arguments as {code String} to replace in the log message. If the arguments
149      *            aren't enough, the arguments will be considered as empty and the log message will
150      *            be fill with a blank string instead. If the arguments are higher that the number
151      *            contained in the log message, the latest are ignored. Can be {null}, in this case
152      *            arguments will be filled with empty {code String}.
153      * @return the final log message where generic argument have been replaced. For instance :<br>
154      *         - Log message : "Initializing {0} file.... {1}"<br>
155      *         - Arguments : new String[] {"options.xml", "OK"}<br>
156      *         will return "Initializing options.xml file.... OK"
157      * @since 1.3.0
158      */
159     public static String buildLogString(final String logMessage, final String[] args) {
160         assert logMessage != null : "logMessage is null";
161 
162         String result = logMessage;
163 
164         if (args == null || args.length == 0) {
165             int i = 0;
166             String tmp = result.replaceAll(
167                     BACK_SLASH_CHAR + LEFT_BRACES_CHAR + i + BACK_SLASH_CHAR + RIGHT_BRACES_CHAR, BLANK_STRING);
168             while (!tmp.equals(result)) {
169                 i++;
170                 result = tmp;
171                 tmp = result.replaceAll(BACK_SLASH_CHAR + LEFT_BRACES_CHAR + i + BACK_SLASH_CHAR + RIGHT_BRACES_CHAR,
172                         BLANK_STRING);
173             }
174         } else {
175             int i = 0;
176             String tmp = result.replaceAll(
177                     BACK_SLASH_CHAR + LEFT_BRACES_CHAR + i + BACK_SLASH_CHAR + RIGHT_BRACES_CHAR,
178                     quoteReplacement(args[i]));
179             while (!tmp.equals(result)) {
180                 i++;
181                 result = tmp;
182                 if (i >= args.length) {
183                     tmp = result.replaceAll(BACK_SLASH_CHAR + LEFT_BRACES_CHAR + i + BACK_SLASH_CHAR
184                             + RIGHT_BRACES_CHAR, BLANK_STRING);
185                 } else {
186                     tmp = result.replaceAll(BACK_SLASH_CHAR + LEFT_BRACES_CHAR + i + BACK_SLASH_CHAR
187                             + RIGHT_BRACES_CHAR, quoteReplacement(args[i]));
188                 }
189             }
190         }
191 
192         return result;
193     }
194 
195     /**
196      * Load logging properties from a resource present from the classloader of the specified class.
197      *
198      * @param fullResourcePath
199      *            the full resource path within classloader of the specified class to load logging
200      *            properties, mustn't be <code>null</code>.
201      * @param clazz
202      *            the {@link Class} to get the classloader from, mustn't be <code>null</code>.
203      * @throws IOException
204      *             if any exception occurs while reading the logging properties resource.
205      * @see ClassLoader#getResourceAsStream(String)
206      * @since 1.3.0
207      */
208     public static void readLoggerConfigurationFromResourceFromClassClassLoader(final String fullResourcePath,
209             final Class < ? > clazz) throws IOException {
210         readLoggerConfigurationFromResourceFromClassLoader(fullResourcePath, clazz.getClassLoader());
211     }
212 
213     /**
214      * Load logging properties from a resource present in the class path.
215      *
216      * @param fullResourcePath
217      *            the full resource path within the classloader to load logging properties, mustn't
218      *            be <code>null</code>.
219      * @param classLoader
220      *            the {@link ClassLoader} to load the resource from, mustn't be <code>null</code>.
221      * @throws IOException
222      *             if any exception occurs while reading the logging properties resource.
223      * @see ClassLoader#getResourceAsStream(String)
224      * @since 1.3.0
225      */
226     public static void readLoggerConfigurationFromResourceFromClassLoader(final String fullResourcePath,
227             final ClassLoader classLoader) throws IOException {
228         InputStream inputStream = null;
229         try {
230             inputStream = classLoader.getResourceAsStream(fullResourcePath);
231             if (inputStream != null) {
232                 readLoggerConfigurationFromResourceFromInputStream(inputStream);
233             } else {
234                 throw new IOException(buildLogString(MISSING_LOGGING_FILE_ERROR, fullResourcePath));
235             }
236         } finally {
237             closeCloseable(inputStream, fullResourcePath);
238         }
239     }
240 
241     /**
242      * Load logging properties from a resource present from the specified file.
243      *
244      * @param file
245      *            the {@link File} linked to the logging properties file, mustn't be
246      *            <code>null</code>.
247      * @throws IOException
248      *             if any exception occurs while reading the logging properties resource.
249      * @since 1.3.0
250      */
251     public static void readLoggerConfigurationFromResourceFromFile(final File file) throws IOException {
252         InputStream inputStream = null;
253         try {
254             inputStream = new FileInputStream(file);
255             readLoggerConfigurationFromResourceFromInputStream(inputStream);
256         } finally {
257             closeCloseable(inputStream, file);
258         }
259     }
260 
261     /**
262      * Load logging properties from a resource contained in the specified input stream.
263      *
264      * @param inputStream
265      *            the {@link InputStream} containing the properties logging file, mustn't be
266      *            <code>null</code>.
267      * @throws IOException
268      *             if any exception occurs while reading the logging properties input stream.
269      * @since 1.3.0
270      */
271     public static void readLoggerConfigurationFromResourceFromInputStream(final InputStream inputStream)
272             throws IOException {
273         final LogManager rootLogManager = getLogManager();
274         rootLogManager.readConfiguration(inputStream);
275     }
276 
277     /**
278      * Sets the specified log level to all log handlers.
279      *
280      * @param logLevel
281      *            the log {@link Level} to apply, mustn't be <code>null</code>.
282      * @since 1.3.0
283      */
284     public static void setLevelOfAllHandlers(final Level logLevel) {
285         final LogManager rootLogManager = getLogManager();
286         final Enumeration < String > loggerNames = rootLogManager.getLoggerNames();
287         while (loggerNames.hasMoreElements()) {
288             final String loggerName = loggerNames.nextElement();
289             final Logger logger = rootLogManager.getLogger(loggerName);
290             setLevelOfAllHandlers(logLevel, logger.getHandlers());
291         }
292     }
293 
294     /**
295      * Sets the specified log level to all log handlers.
296      *
297      * @param logLevel
298      *            the log {@link Level} to apply, mustn't be <code>null</code>.
299      * @param handlers
300      *            the array of {@link Handler} to apply the level, mustn't be <code>null</code>.
301      * @since 1.3.0
302      */
303     private static void setLevelOfAllHandlers(final Level logLevel, final Handler[] handlers) {
304         for (final Handler handler : handlers) {
305             handler.setLevel(logLevel);
306         }
307     }
308 
309     /**
310      * Sets the specified log level to all loggers.
311      *
312      * @param logLevel
313      *            the log {@link Level} to apply, mustn't be <code>null</code>.
314      * @since 1.3.0
315      */
316     public static void setLevelOfAllLoggers(final Level logLevel) {
317         final LogManager rootLogManager = getLogManager();
318         final Enumeration < String > loggerNames = rootLogManager.getLoggerNames();
319         while (loggerNames.hasMoreElements()) {
320             final String loggerName = loggerNames.nextElement();
321             final Logger logger = rootLogManager.getLogger(loggerName);
322             logger.setLevel(logLevel);
323         }
324     }
325 
326     /**
327      * Sets the specified log level to all loggers.
328      *
329      * @param logLevel
330      *            the log {@link Level} to apply, mustn't be <code>null</code>.
331      * @since 1.3.0
332      */
333     public static void setLevelOfAllLoggersAndHandlers(final Level logLevel) {
334         final LogManager rootLogManager = getLogManager();
335         final Enumeration < String > loggerNames = rootLogManager.getLoggerNames();
336         while (loggerNames.hasMoreElements()) {
337             final String loggerName = loggerNames.nextElement();
338             final Logger logger = rootLogManager.getLogger(loggerName);
339             logger.setLevel(logLevel);
340             setLevelOfAllHandlers(logLevel, logger.getHandlers());
341         }
342     }
343 
344     /**
345      * Private constructor to prevent from instantiation.
346      *
347      * @since 1.3.0
348      */
349     private LogUtils() {
350         super();
351     }
352 }