001/** 002 * Copyright 2010-2014 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.common.util.log; 017 018import static org.kuali.common.util.base.Exceptions.illegalArgument; 019 020import java.util.ArrayList; 021import java.util.List; 022import java.util.Properties; 023 024import org.apache.commons.lang3.StringUtils; 025import org.kuali.common.util.Assert; 026import org.kuali.common.util.CollectionUtils; 027import org.kuali.common.util.KeyValue; 028import org.kuali.common.util.nullify.NullUtils; 029import org.kuali.common.util.obscure.DefaultObscurer; 030import org.kuali.common.util.obscure.Obscurer; 031import org.kuali.common.util.property.Constants; 032import org.slf4j.Logger; 033import org.slf4j.LoggerFactory; 034import org.springframework.util.PropertyPlaceholderHelper; 035 036public class LoggerUtils { 037 038 public static final Logger LOGGER_UTILS_LOGGER = Loggers.newLogger(); 039 private static final Obscurer DEFAULT_OBSCURER = new DefaultObscurer(); 040 private static final PropertyPlaceholderHelper HELPER = Constants.DEFAULT_PROPERTY_PLACEHOLDER_HELPER; 041 private static final Object[] EMPTY_OBJECT_ARRAY = {}; 042 043 /** 044 * <p> 045 * Convenience method for obtaining a logger (borrowed from the JBoss crew) 046 * </p> 047 * 048 * <pre> 049 * private static final Logger logger = LoggerUtils.make(); 050 * </pre> 051 */ 052 public static Logger make() { 053 Throwable throwable = new Throwable(); 054 StackTraceElement[] elements = throwable.getStackTrace(); 055 StackTraceElement directCaller = elements[1]; 056 return LoggerFactory.getLogger(directCaller.getClassName()); 057 } 058 059 public static String getLogMsg(List<String> includes, List<String> excludes) { 060 if (CollectionUtils.isEmpty(includes) && CollectionUtils.isEmpty(excludes)) { 061 return ""; 062 } 063 String includesCSV = StringUtils.trimToNull(CollectionUtils.getSpaceSeparatedCSV(includes)); 064 String excludesCSV = StringUtils.trimToNull(CollectionUtils.getSpaceSeparatedCSV(excludes)); 065 List<KeyValue> msgs = new ArrayList<KeyValue>(); 066 if (!StringUtils.isBlank(includesCSV)) { 067 msgs.add(new KeyValue("includes", includesCSV)); 068 } 069 if (!StringUtils.isBlank(excludesCSV)) { 070 msgs.add(new KeyValue("excludes", excludesCSV)); 071 } 072 StringBuilder sb = new StringBuilder(); 073 sb.append("["); 074 for (int i = 0; i < msgs.size(); i++) { 075 if (i != 0) { 076 sb.append(" "); 077 } 078 KeyValue msg = msgs.get(i); 079 sb.append(msg.getKey()); 080 sb.append(": "); 081 sb.append(msg.getValue()); 082 } 083 sb.append("]"); 084 return sb.toString(); 085 } 086 087 @Deprecated 088 public static String getLogMsg(org.kuali.common.util.StringFilter filter) { 089 Assert.notNull(filter, "filter is null"); 090 return getLogMsg(filter.getIncludes(), filter.getExcludes()); 091 } 092 093 @Deprecated 094 public static Object[] getLogMsgArgs(org.kuali.common.util.StringFilter filter) { 095 Assert.notNull(filter, "filter is null"); 096 String includes = CollectionUtils.getSpaceSeparatedCSV(filter.getIncludes()); 097 String excludes = CollectionUtils.getSpaceSeparatedCSV(filter.getExcludes()); 098 return new Object[] { includes, excludes }; 099 } 100 101 public static void log(LogMsg msg, Logger logger) { 102 Assert.notNull(logger, "logger is null"); 103 logMsg(msg.getMessage(), msg.getArgs(), logger, msg.getLevel()); 104 } 105 106 public static int[] getPadding(List<String> columns, List<Object[]> argsList) { 107 int[] padding = new int[columns.size()]; 108 for (int i = 0; i < padding.length; i++) { 109 padding[i] = Math.max(padding[i], columns.get(i).length()); 110 } 111 for (Object[] args : argsList) { 112 Assert.isTrue(columns.size() == args.length, "Column count must equals args.length"); 113 for (int i = 0; i < args.length; i++) { 114 padding[i] = Math.max(padding[i], args[i].toString().length()); 115 } 116 } 117 return padding; 118 } 119 120 public static String getHeader(List<String> columns, int[] padding, boolean leftAlign) { 121 StringBuilder sb = new StringBuilder(); 122 for (int i = 0; i < columns.size(); i++) { 123 if (i == 0) { 124 sb.append("|| "); 125 } else { 126 sb.append("| "); 127 } 128 if (leftAlign) { 129 sb.append(StringUtils.rightPad(columns.get(i), padding[i])); 130 } else { 131 sb.append(StringUtils.leftPad(columns.get(i), padding[i])); 132 } 133 if (i == columns.size() - 1) { 134 sb.append(" ||"); 135 } else { 136 sb.append(" |"); 137 } 138 } 139 return sb.toString(); 140 } 141 142 public static void updateArgsList(List<Object[]> argsList, int[] padding, boolean leftAlign) { 143 for (Object[] args : argsList) { 144 for (int i = 0; i < args.length; i++) { 145 if (leftAlign) { 146 args[i] = StringUtils.rightPad(args[i].toString(), padding[i]); 147 } else { 148 args[i] = StringUtils.leftPad(args[i].toString(), padding[i]); 149 } 150 } 151 } 152 } 153 154 public static void logTable(List<String> columns, List<Object[]> rows, Logger logger) { 155 logTable(columns, rows, LogTableContext.DEFAULT_LOGGER_LEVEL, logger, false); 156 } 157 158 public static void logTable(List<String> columns, List<Object[]> rows, LoggerLevel level, Logger logger) { 159 logTable(columns, rows, level, logger, false); 160 } 161 162 public static void logTable(List<String> columns, List<Object[]> rows, LoggerLevel level, Logger logger, boolean leftAlign) { 163 LogTableContext context = new LogTableContext(columns, rows, level, logger, leftAlign); 164 logTable(context); 165 } 166 167 public static void logTable(String title, List<String> columns, List<Object[]> rows) { 168 LogTableContext context = new LogTableContext(title, columns, rows); 169 logTable(context); 170 } 171 172 public static void logTable(List<String> columns, List<Object[]> rows) { 173 LogTableContext context = new LogTableContext(columns, rows); 174 logTable(context); 175 } 176 177 public static String getTable(LogTableContext context) { 178 Assert.notNull(context, "context is null"); 179 int[] padding = getPadding(context.getColumns(), context.getRows()); 180 int cols = context.getColumns().size(); 181 int rows = context.getRows().size(); 182 183 String header = getHeader(context.getColumns(), padding, context.isLeftAlign()); 184 updateArgsList(context.getRows(), padding, context.isLeftAlign()); 185 Properties properties = getProperties(context.getRows()); 186 String tableString = getTableString(rows, cols); 187 188 String resolved = HELPER.replacePlaceholders(tableString, properties); 189 190 return header + "\n" + resolved; 191 } 192 193 public static void logTable(LogTableContext context) { 194 String table = getTable(context); 195 int cols = context.getColumns().size(); 196 int rows = context.getRows().size(); 197 String defaultTitle = "Displaying a table with " + cols + " columns and " + rows + " rows\n\n"; 198 String title = StringUtils.equals(LogTableContext.NO_TITLE, context.getTitle()) ? defaultTitle : context.getTitle() + "\n\n"; 199 String msg = title + table; 200 logMsg(msg, context.getLogger(), context.getLevel()); 201 202 } 203 204 protected static String getTableString(int rows, int cols) { 205 StringBuilder sb = new StringBuilder(); 206 for (int row = 0; row < rows; row++) { 207 for (int col = 0; col < cols; col++) { 208 sb.append("${" + getPropertyKey(row, col) + "}"); 209 } 210 sb.append("\n"); 211 } 212 return sb.toString(); 213 } 214 215 protected static Properties getProperties(List<Object[]> rows) { 216 Properties properties = new Properties(); 217 for (int row = 0; row < rows.size(); row++) { 218 Object[] rowData = rows.get(row); 219 for (int col = 0; col < rowData.length; col++) { 220 String key = getPropertyKey(row, col); 221 StringBuilder sb = new StringBuilder(); 222 if (col == 0) { 223 sb.append("|| "); 224 } else { 225 sb.append("| "); 226 } 227 sb.append(rowData[col] + ""); 228 if (col == rowData.length - 1) { 229 sb.append(" ||"); 230 } else { 231 sb.append(" |"); 232 } 233 properties.setProperty(key, sb.toString()); 234 } 235 } 236 return properties; 237 } 238 239 protected static String getPropertyKey(int row, int col) { 240 return "log.table.row." + row + ".col." + col; 241 } 242 243 public static void logLines(String s, Logger logger, LoggerLevel level) { 244 if (s == null) { 245 return; 246 } 247 String[] lines = StringUtils.split(s, "\n"); 248 for (String line : lines) { 249 LoggerUtils.logMsg(line, logger, level); 250 } 251 } 252 253 public static final void log(String msg, List<Object> args, Logger logger, LoggerLevel level) { 254 switch (level) { 255 case DEBUG: 256 logger.debug(msg, args.toArray(EMPTY_OBJECT_ARRAY)); 257 return; 258 case TRACE: 259 logger.trace(msg, args.toArray(EMPTY_OBJECT_ARRAY)); 260 return; 261 case INFO: 262 logger.info(msg, args.toArray(EMPTY_OBJECT_ARRAY)); 263 return; 264 case WARN: 265 logger.warn(msg, args.toArray(EMPTY_OBJECT_ARRAY)); 266 return; 267 case ERROR: 268 logger.error(msg, args.toArray(EMPTY_OBJECT_ARRAY)); 269 return; 270 default: 271 throw illegalArgument("Logger level %s is unknown", level); 272 } 273 } 274 275 public static final void logMsg(String msg, Object[] args, Logger logger, LoggerLevel level) { 276 if (StringUtils.equals(LogMsg.NO_MSG, msg)) { 277 return; 278 } 279 switch (level) { 280 case DEBUG: 281 logger.debug(msg, args); 282 return; 283 case TRACE: 284 logger.trace(msg, args); 285 return; 286 case INFO: 287 logger.info(msg, args); 288 return; 289 case WARN: 290 logger.warn(msg, args); 291 return; 292 case ERROR: 293 logger.error(msg, args); 294 return; 295 default: 296 throw illegalArgument("Logger level %s is unknown", level); 297 } 298 } 299 300 public static final void logMsg(String msg, Logger logger, LoggerLevel level) { 301 logMsg(msg, null, logger, level); 302 } 303 304 public static final String getUsername(String username) { 305 return getNullAsNone(username); 306 } 307 308 public static final String getNullAsNone(String string) { 309 if (string == null) { 310 return NullUtils.NONE; 311 } else { 312 return string; 313 } 314 } 315 316 public static final String getPassword(String username, String password) { 317 return getPassword(username, password, DEFAULT_OBSCURER); 318 } 319 320 public static boolean isNullOrNone(String s) { 321 return NullUtils.isNullOrNone(s); 322 } 323 324 public static final String getPassword(String username, String password, Obscurer obscurer) { 325 if (isNullOrNone(password)) { 326 // There is no password, return NONE 327 return NullUtils.NONE; 328 } else if (StringUtils.equals(username, password)) { 329 // Not exactly high security, display the clear text value 330 return password; 331 } else { 332 // Otherwise obscure it 333 return obscurer.obscure(password); 334 } 335 } 336 337}