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
103 private final InternalLogger logger;
104 private final InternalLogLevel level;
105 private final boolean hexDump;
106
107
108
109
110
111 public LoggingHandler() {
112 this(true);
113 }
114
115
116
117
118
119
120
121 public LoggingHandler(InternalLogLevel level) {
122 this(level, true);
123 }
124
125
126
127
128
129
130
131
132 public LoggingHandler(boolean hexDump) {
133 this(DEFAULT_LEVEL, hexDump);
134 }
135
136
137
138
139
140
141
142
143
144 public LoggingHandler(InternalLogLevel level, boolean hexDump) {
145 if (level == null) {
146 throw new NullPointerException("level");
147 }
148
149 logger = InternalLoggerFactory.getInstance(getClass());
150 this.level = level;
151 this.hexDump = hexDump;
152 }
153
154
155
156
157
158 public LoggingHandler(Class<?> clazz) {
159 this(clazz, true);
160 }
161
162
163
164
165
166
167
168 public LoggingHandler(Class<?> clazz, boolean hexDump) {
169 this(clazz, DEFAULT_LEVEL, hexDump);
170 }
171
172
173
174
175
176
177 public LoggingHandler(Class<?> clazz, InternalLogLevel level) {
178 this(clazz, level, true);
179 }
180
181
182
183
184
185
186
187
188 public LoggingHandler(Class<?> clazz, InternalLogLevel level, boolean hexDump) {
189 if (clazz == null) {
190 throw new NullPointerException("clazz");
191 }
192 if (level == null) {
193 throw new NullPointerException("level");
194 }
195 logger = InternalLoggerFactory.getInstance(clazz);
196 this.level = level;
197 this.hexDump = hexDump;
198 }
199
200
201
202
203
204 public LoggingHandler(String name) {
205 this(name, true);
206 }
207
208
209
210
211
212
213
214 public LoggingHandler(String name, boolean hexDump) {
215 this(name, DEFAULT_LEVEL, hexDump);
216 }
217
218
219
220
221
222
223
224
225 public LoggingHandler(String name, InternalLogLevel level, boolean hexDump) {
226 if (name == null) {
227 throw new NullPointerException("name");
228 }
229 if (level == null) {
230 throw new NullPointerException("level");
231 }
232 logger = InternalLoggerFactory.getInstance(name);
233 this.level = level;
234 this.hexDump = hexDump;
235 }
236
237
238
239
240
241 public InternalLogger getLogger() {
242 return logger;
243 }
244
245
246
247
248
249 public InternalLogLevel getLevel() {
250 return level;
251 }
252
253
254
255
256
257
258
259 public void log(ChannelEvent e) {
260 if (getLogger().isEnabled(level)) {
261 String msg = e.toString();
262
263
264 if (hexDump && e instanceof MessageEvent) {
265 MessageEvent me = (MessageEvent) e;
266 if (me.getMessage() instanceof ChannelBuffer) {
267 msg += formatBuffer((ChannelBuffer) me.getMessage());
268 }
269 }
270
271
272 if (e instanceof ExceptionEvent) {
273 getLogger().log(level, msg, ((ExceptionEvent) e).getCause());
274 } else {
275 getLogger().log(level, msg);
276 }
277 }
278 }
279
280 private static String formatBuffer(ChannelBuffer buf) {
281 int length = buf.readableBytes();
282 int rows = length / 16 + (length % 15 == 0? 0 : 1) + 4;
283 StringBuilder dump = new StringBuilder(rows * 80);
284
285 dump.append(
286 NEWLINE + " +-------------------------------------------------+" +
287 NEWLINE + " | 0 1 2 3 4 5 6 7 8 9 a b c d e f |" +
288 NEWLINE + "+--------+-------------------------------------------------+----------------+");
289
290 final int startIndex = buf.readerIndex();
291 final int endIndex = buf.writerIndex();
292
293 int i;
294 for (i = startIndex; i < endIndex; i ++) {
295 int relIdx = i - startIndex;
296 int relIdxMod16 = relIdx & 15;
297 if (relIdxMod16 == 0) {
298 dump.append(NEWLINE);
299 dump.append(Long.toHexString(relIdx & 0xFFFFFFFFL | 0x100000000L));
300 dump.setCharAt(dump.length() - 9, '|');
301 dump.append('|');
302 }
303 dump.append(BYTE2HEX[buf.getUnsignedByte(i)]);
304 if (relIdxMod16 == 15) {
305 dump.append(" |");
306 for (int j = i - 15; j <= i; j ++) {
307 dump.append(BYTE2CHAR[buf.getUnsignedByte(j)]);
308 }
309 dump.append('|');
310 }
311 }
312
313 if ((i - startIndex & 15) != 0) {
314 int remainder = length & 15;
315 dump.append(HEXPADDING[remainder]);
316 dump.append(" |");
317 for (int j = i - remainder; j < i; j ++) {
318 dump.append(BYTE2CHAR[buf.getUnsignedByte(j)]);
319 }
320 dump.append(BYTEPADDING[remainder]);
321 dump.append('|');
322 }
323
324 dump.append(
325 NEWLINE + "+--------+-------------------------------------------------+----------------+");
326
327 return dump.toString();
328 }
329
330 public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e)
331 throws Exception {
332 log(e);
333 ctx.sendUpstream(e);
334 }
335
336 public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e)
337 throws Exception {
338 log(e);
339 ctx.sendDownstream(e);
340 }
341 }