001/* 002 GRANITE DATA SERVICES 003 Copyright (C) 2011 GRANITE DATA SERVICES S.A.S. 004 005 This file is part of Granite Data Services. 006 007 Granite Data Services is free software; you can redistribute it and/or modify 008 it under the terms of the GNU Library General Public License as published by 009 the Free Software Foundation; either version 2 of the License, or (at your 010 option) any later version. 011 012 Granite Data Services is distributed in the hope that it will be useful, but 013 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License 015 for more details. 016 017 You should have received a copy of the GNU Library General Public License 018 along with this library; if not, see <http://www.gnu.org/licenses/>. 019*/ 020 021package org.granite.logging; 022 023import java.lang.reflect.Array; 024import java.util.ArrayList; 025import java.util.Arrays; 026import java.util.Calendar; 027import java.util.Collection; 028import java.util.Date; 029import java.util.Formattable; 030import java.util.HashMap; 031import java.util.List; 032import java.util.Map; 033 034/** 035 * @author Franck WOLFF 036 */ 037public class DefaultLoggingFormatter implements LoggingFormatter { 038 039 private static final int MAX_COLLECTION_ITEMS = 100; 040 041 private final int maxItems; 042 043 public DefaultLoggingFormatter() { 044 this(MAX_COLLECTION_ITEMS); 045 } 046 047 public DefaultLoggingFormatter(int maxItems) { 048 this.maxItems = maxItems; 049 } 050 051 public String format(String message, Object... args) { 052 try { 053 for (int i = 0; i < args.length; i++) 054 args[i] = convert(args[i]); 055 056 return String.format(message, args); 057 } catch (Exception e) { 058 try { 059 return "[FORMATTER ERROR] \"" + message + "\"(" + Arrays.toString(args) + ") - " + e; 060 } catch (Exception f) { 061 return "[FORMATTER ERROR] \"" + message + "\"(" + f + ") - " + e; 062 } 063 } 064 } 065 066 protected Object convert(Object o) { 067 if (o == null || 068 o instanceof Formattable || 069 o instanceof Number || 070 o instanceof Character || 071 o instanceof Boolean || 072 o instanceof Date || 073 o instanceof Calendar) 074 return o; 075 076 try { 077 if (o instanceof String) { 078 o = new StringBuilder().append('"').append(o).append('"').toString(); 079 } 080 else if (o.getClass().isArray()) { 081 Class<?> type = o.getClass().getComponentType(); 082 083 if (maxItems < 0) { 084 if (type.isPrimitive()) { 085 if (type == Byte.TYPE) 086 return Arrays.toString((byte[])o); 087 if (type == Character.TYPE) 088 return Arrays.toString((char[])o); 089 if (type == Integer.TYPE) 090 return Arrays.toString((int[])o); 091 if (type == Double.TYPE) 092 return Arrays.toString((double[])o); 093 if (type == Long.TYPE) 094 return Arrays.toString((long[])o); 095 if (type == Float.TYPE) 096 return Arrays.toString((float[])o); 097 if (type == Short.TYPE) 098 return Arrays.toString((short[])o); 099 if (type == Boolean.TYPE) 100 return Arrays.toString((boolean[])o); 101 return "[Array of unknown primitive type: " + type + "]"; // Should never append... 102 } 103 return Arrays.toString((Object[])o); 104 } 105 106 final int max = Math.min(maxItems, Array.getLength(o)); 107 List<Object> list = new ArrayList<Object>(max); 108 109 for (int i = 0; i < max; i++) 110 list.add(Array.get(o, i)); 111 if (max < Array.getLength(o)) 112 list.add("(first " + max + '/' + Array.getLength(o) + " elements only...)"); 113 114 o = list; 115 } 116 else if (o instanceof Collection<?> && maxItems >= 0) { 117 118 Collection<?> coll = (Collection<?>)o; 119 final int max = Math.min(maxItems, coll.size()); 120 List<Object> list = new ArrayList<Object>(max); 121 122 int i = 0; 123 for (Object item : coll) { 124 if (i >= max) { 125 list.add("(first " + max + '/' + coll.size() + " elements only...)"); 126 break; 127 } 128 list.add(item); 129 i++; 130 } 131 132 o = list; 133 } 134 else if (o instanceof Map<?, ?> && maxItems >= 0) { 135 Map<?, ?> map = (Map<?, ?>)o; 136 final int max = Math.min(maxItems, map.size()); 137 Map<Object, Object> copy = new HashMap<Object, Object>(max); 138 139 int i = 0; 140 for (Map.Entry<?, ?> item : map.entrySet()) { 141 if (i >= max) { 142 copy.put("(first " + max + '/' + map.size() + " elements only...)", "..."); 143 break; 144 } 145 copy.put(item.getKey(), item.getValue()); 146 i++; 147 } 148 149 o = copy; 150 } 151 else { 152 o = o.toString(); 153 } 154 155 return o; 156 } catch (Exception e) { 157 return o.getClass().getName() + " (exception: " + e.toString() + ")"; 158 } 159 } 160}