1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.handler.logging;
17
18 import org.jboss.netty.buffer.ChannelBuffer;
19 import org.jboss.netty.channel.ChannelDownstreamHandler;
20 import org.jboss.netty.channel.ChannelEvent;
21 import org.jboss.netty.channel.ChannelHandler;
22 import org.jboss.netty.channel.ChannelHandler.Sharable;
23 import org.jboss.netty.channel.ChannelHandlerContext;
24 import org.jboss.netty.channel.ChannelUpstreamHandler;
25 import org.jboss.netty.channel.ExceptionEvent;
26 import org.jboss.netty.channel.MessageEvent;
27 import org.jboss.netty.logging.InternalLogLevel;
28 import org.jboss.netty.logging.InternalLogger;
29 import org.jboss.netty.logging.InternalLoggerFactory;
30
31
32
33
34
35
36
37
38 @Sharable
39 public class LoggingHandler implements ChannelUpstreamHandler, ChannelDownstreamHandler {
40
41 private static final InternalLogLevel DEFAULT_LEVEL = InternalLogLevel.DEBUG;
42 private static final String NEWLINE = String.format("%n");
43
44 private static final String[] BYTE2HEX = new String[256];
45 private static final String[] HEXPADDING = new String[16];
46 private static final String[] BYTEPADDING = new String[16];
47 private static final char[] BYTE2CHAR = new char[256];
48
49 static {
50 int i;
51
52
53 for (i = 0; i < 10; i ++) {
54 StringBuilder buf = new StringBuilder(3);
55 buf.append(" 0");
56 buf.append(i);
57 BYTE2HEX[i] = buf.toString();
58 }
59 for (; i < 16; i ++) {
60 StringBuilder buf = new StringBuilder(3);
61 buf.append(" 0");
62 buf.append((char) ('a' + i - 10));
63 BYTE2HEX[i] = buf.toString();
64 }
65 for (; i < BYTE2HEX.length; i ++) {
66 StringBuilder buf = new StringBuilder(3);
67 buf.append(' ');
68 buf.append(Integer.toHexString(i));
69 BYTE2HEX[i] = buf.toString();
70 }
71
72
73 for (i = 0; i < HEXPADDING.length; i ++) {
74 int padding = HEXPADDING.length - i;
75 StringBuilder buf = new StringBuilder(padding * 3);
76 for (int j = 0; j < padding; j ++) {
77 buf.append(" ");
78 }
79 HEXPADDING[i] = buf.toString();
80 }
81
82
83 for (i = 0; i < BYTEPADDING.length; i ++) {
84 int padding = BYTEPADDING.length - i;
85 StringBuilder buf = new StringBuilder(padding);
86 for (int j = 0; j < padding; j ++) {
87 buf.append(' ');
88 }
89 BYTEPADDING[i] = buf.toString();
90 }
91
92
93 for (i = 0; i < BYTE2CHAR.length; i ++) {
94 if (i <= 0x1f || i >= 0x7f) {
95 BYTE2CHAR[i] = '.';
96 } else {
97 BYTE2CHAR[i] = (char) i;
98 }
99 }
100 }
101
102 private final InternalLogger logger;
103 private final InternalLogLevel level;
104 private final boolean hexDump;
105
106
107
108
109
110 public LoggingHandler() {
111 this(true);
112 }
113
114
115
116
117
118
119
120 public LoggingHandler(InternalLogLevel level) {
121 this(level, true);
122 }
123
124
125
126
127
128
129
130
131 public LoggingHandler(boolean hexDump) {
132 this(DEFAULT_LEVEL, hexDump);
133 }
134
135
136
137
138
139
140
141
142
143 public LoggingHandler(InternalLogLevel level, boolean hexDump) {
144 if (level == null) {
145 throw new NullPointerException("level");
146 }
147
148 logger = InternalLoggerFactory.getInstance(getClass());
149 this.level = level;
150 this.hexDump = hexDump;
151 }
152
153
154
155
156
157 public LoggingHandler(Class<?> clazz) {
158 this(clazz, true);
159 }
160
161
162
163
164
165
166
167 public LoggingHandler(Class<?> clazz, boolean hexDump) {
168 this(clazz, DEFAULT_LEVEL, hexDump);
169 }
170
171
172
173
174
175
176 public LoggingHandler(Class<?> clazz, InternalLogLevel level) {
177 this(clazz, level, true);
178 }
179
180
181
182
183
184
185
186
187 public LoggingHandler(Class<?> clazz, InternalLogLevel level, boolean hexDump) {
188 if (clazz == null) {
189 throw new NullPointerException("clazz");
190 }
191 if (level == null) {
192 throw new NullPointerException("level");
193 }
194 logger = InternalLoggerFactory.getInstance(clazz);
195 this.level = level;
196 this.hexDump = hexDump;
197 }
198
199
200
201
202
203 public LoggingHandler(String name) {
204 this(name, true);
205 }
206
207
208
209
210
211
212
213 public LoggingHandler(String name, boolean hexDump) {
214 this(name, DEFAULT_LEVEL, hexDump);
215 }
216
217
218
219
220
221
222
223
224 public LoggingHandler(String name, InternalLogLevel level, boolean hexDump) {
225 if (name == null) {
226 throw new NullPointerException("name");
227 }
228 if (level == null) {
229 throw new NullPointerException("level");
230 }
231 logger = InternalLoggerFactory.getInstance(name);
232 this.level = level;
233 this.hexDump = hexDump;
234 }
235
236
237
238
239
240 public InternalLogger getLogger() {
241 return logger;
242 }
243
244
245
246
247
248 public InternalLogLevel getLevel() {
249 return level;
250 }
251
252
253
254
255
256
257
258 public void log(ChannelEvent e) {
259 if (getLogger().isEnabled(level)) {
260 String msg = e.toString();
261
262
263 if (hexDump && e instanceof MessageEvent) {
264 MessageEvent me = (MessageEvent) e;
265 if (me.getMessage() instanceof ChannelBuffer) {
266 msg += formatBuffer((ChannelBuffer) me.getMessage());
267 }
268 }
269
270
271 if (e instanceof ExceptionEvent) {
272 getLogger().log(level, msg, ((ExceptionEvent) e).getCause());
273 } else {
274 getLogger().log(level, msg);
275 }
276 }
277 }
278
279 private static String formatBuffer(ChannelBuffer buf) {
280 int length = buf.readableBytes();
281 int rows = length / 16 + (length % 15 == 0? 0 : 1) + 4;
282 StringBuilder dump = new StringBuilder(rows * 80);
283
284 dump.append(
285 NEWLINE + " +-------------------------------------------------+" +
286 NEWLINE + " | 0 1 2 3 4 5 6 7 8 9 a b c d e f |" +
287 NEWLINE + "+--------+-------------------------------------------------+----------------+");
288
289 final int startIndex = buf.readerIndex();
290 final int endIndex = buf.writerIndex();
291
292 int i;
293 for (i = startIndex; i < endIndex; i ++) {
294 int relIdx = i - startIndex;
295 int relIdxMod16 = relIdx & 15;
296 if (relIdxMod16 == 0) {
297 dump.append(NEWLINE);
298 dump.append(Long.toHexString(relIdx & 0xFFFFFFFFL | 0x100000000L));
299 dump.setCharAt(dump.length() - 9, '|');
300 dump.append('|');
301 }
302 dump.append(BYTE2HEX[buf.getUnsignedByte(i)]);
303 if (relIdxMod16 == 15) {
304 dump.append(" |");
305 for (int j = i - 15; j <= i; j ++) {
306 dump.append(BYTE2CHAR[buf.getUnsignedByte(j)]);
307 }
308 dump.append('|');
309 }
310 }
311
312 if ((i - startIndex & 15) != 0) {
313 int remainder = length & 15;
314 dump.append(HEXPADDING[remainder]);
315 dump.append(" |");
316 for (int j = i - remainder; j < i; j ++) {
317 dump.append(BYTE2CHAR[buf.getUnsignedByte(j)]);
318 }
319 dump.append(BYTEPADDING[remainder]);
320 dump.append('|');
321 }
322
323 dump.append(
324 NEWLINE + "+--------+-------------------------------------------------+----------------+");
325
326 return dump.toString();
327 }
328
329 public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e)
330 throws Exception {
331 log(e);
332 ctx.sendUpstream(e);
333 }
334
335 public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e)
336 throws Exception {
337 log(e);
338 ctx.sendDownstream(e);
339 }
340 }