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 }