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 }