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