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 }