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}