KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > drda > DssTrace


1 /*
2
3    Derby - Class org.apache.derby.impl.drda.DssTrace
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to You under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21 package org.apache.derby.impl.drda;
22
23 // Generic process and error tracing encapsulation.
24
// This class also traces a DRDA communications buffer.
25
// The value of the hex bytes are traced along with
26
// the ascii and ebcdic translations.
27
public class DssTrace
28 {
29   // This class was implemented using character arrays to translate bytes
30
// into ascii and ebcdic. The goal was to be able to quickly index into the
31
// arrays to find the characters. Char arrays instead of strings were used as
32
// much as possible in an attempt to help speed up performance.
33
private static final String JavaDoc LIST_SEPARATOR = " # ";
34
35   // trace representation for a java null.
36
private static final String JavaDoc NULL_VALUE = "null";
37
38   // An array of characters used to translate bytes to ascii.
39
// The position in the array corresponds to the hex value of the
40
// character
41
private static final char asciiChar [] = {
42     // 0 1 2 3 4 5 6 7 8 9 A B C D E F
43
'.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.', //0
44
'.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.', //1
45
' ','!','"','#','$','%','&','\'','(',')','*','+',',','-','.','/', //2
46
'0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?', //3
47
'@','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O', //4
48
'P','Q','R','S','T','U','V','W','X','Y','Z','[','\\',']','^','_', //5
49
'`','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o', //6
50
'p','q','r','s','t','u','v','w','x','y','z','{','|','}','~','.', //7
51
'.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.', //8
52
'.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.', //9
53
'.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.', //A
54
'.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.', //B
55
'.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.', //C
56
'.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.', //D
57
'.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.', //E
58
'.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.' //F
59
};
60
61
62   // This mapping table associates a codepoint to a String describing the codepoint.
63
// This is needed because the trace prints the
64
// first codepoint in send and receive buffers.
65
// This could be final but there is no need to create the mapping
66
// if tracing isn't used. So... this array will only be created when
67
// the com buffer trace is started. Note this ref is not protected
68
// by final and care must be taken if it's value needs to change.
69
private static CodePointNameTable codePointNameTable = null;
70
71   // This column position header is used to mark offsets into the trace.
72
private static final String JavaDoc colPosHeader =
73   " 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF 0123456789ABCDEF";
74
75   // An array of characters used to translate bytes to ebcdic.
76
// The position in the array corresponds to the hex value of the
77
// character.
78
private static final char ebcdicChar[] = {
79     // 0 1 2 3 4 5 6 7 8 9 A B C D E F
80
'.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.', //0
81
'.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.', //1
82
'.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.', //2
83
'.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.', //3
84
' ','.','.','.','.','.','.','.','.','.','.','.','<','(','+','|', //4
85
'&','.','.','.','.','.','.','.','.','.','!','$','*',')',';','.', //5
86
'-','/','.','.','.','.','.','.','.','.','|',',','%','_','>','?', //6
87
'.','.','.','.','.','.','.','.','.','`',':','#','@','\'','=','"', //7
88
'.','a','b','c','d','e','f','g','h','i','.','.','.','.','.','.', //8
89
'.','j','k','l','m','n','o','p','q','r','.','.','.','.','.','.', //9
90
'.','~','s','t','u','v','w','x','y','z','.','.','.','.','.','.', //A
91
'.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.', //B
92
'{','A','B','C','D','E','F','G','H','I','.','.','.','.','.','.', //C
93
'}','J','K','L','M','N','O','P','Q','R','.','.','.','.','.','.', //D
94
'\\','.','S','T','U','V','W','X','Y','Z','.','.','.','.','.','.', //E
95
'0','1','2','3','4','5','6','7','8','9','.','.','.','.','.','.' //F
96
};
97
98
99   // An array of characters representing hex numbers.
100
private static final char hexDigit [] = {
101     '0','1','2','3','4','5','6','7',
102     '8','9','A','B','C','D','E','F'
103   };
104
105
106   // A PrintWriter is used in printing the trace.
107
private java.io.PrintWriter JavaDoc comBufferWriter = null;
108
109
110   // The receive header comes befor bytes which would be read from
111
// a Stream.
112
private static final String JavaDoc receiveHeader =
113   " RECEIVE BUFFER: (ASCII) (EBCDIC)";
114
115
116   // The send header comes before bytes which would be written to
117
// a Stream.
118
private static final String JavaDoc sendHeader =
119   " SEND BUFFER: (ASCII) (EBCDIC)";
120
121
122   // The space character is defined for convience.
123
private static final char spaceChar = ' ';
124
125
126   // This boolean indicates if the trace is on.
127
// It has been declared private now but may be made public at
128
// a later time.
129
private boolean comBufferTraceOn = false;
130
131
132   // The comBufferSync is an object used for serialization.
133
// This separate object is used because this trace code may
134
// get eventually placed into another class which performs
135
// method entry and exit tracing. Since each trace may be writing
136
// to different logs, separate objects will be used to perform the
137
// synchronization.
138
private Boolean JavaDoc comBufferSync = new Boolean JavaDoc (true);
139
140
141   // The zero character is defined for convinience.
142
private static final char zeroChar = '0';
143
144   // The recevie constant is used to indicate that the bytes were read to a Stream.
145
// It indicates to this class that a receive header should be used.
146
protected static final int TYPE_TRACE_RECEIVE = 2;
147
148   // The send constant is used to indicate that the bytes were written to
149
// a Stream. It indicates to this class that a send header should be used.
150
protected static final int TYPE_TRACE_SEND = 1;
151
152   // Query if trace is on.
153
// This is currently needed since the comBufferTrcOn flag is private.
154
protected boolean isComBufferTraceOn()
155   {
156     // The trace flag indicates if tracing is on.
157
return comBufferTraceOn;
158   }
159
160   // Start the communications buffer trace.
161
// The name of the file to place the trace is passed to this method.
162
// After calling this method, calls to isComBufferTraceOn() will return true.
163
protected void startComBufferTrace (String JavaDoc fileName)
164   {
165     synchronized (comBufferSync) {
166       try {
167         // Only start the trace if it is off.
168
if (comBufferTraceOn == false) {
169           // The writer will be buffered for effeciency.
170
comBufferWriter = new java.io.PrintWriter JavaDoc (new java.io.BufferedWriter JavaDoc (new java.io.FileWriter JavaDoc (fileName), 4096));
171           // Turn on the trace flag.
172
comBufferTraceOn = true;
173           // initialize the codepoint name table if it is null.
174
// this is done here so that the CodePointName objects
175
// aren't created if the trace isn't used (save some memory).
176
// this process should only be done once
177
// since after the table is created the ref will
178
// no longer be null.
179
if (DssTrace.codePointNameTable == null) {
180             codePointNameTable = new CodePointNameTable();
181           }
182         }
183       }
184       catch (java.io.IOException JavaDoc e) {
185         // The IOException is currently ignored. Handling should be added.
186
}
187     }
188   }
189
190   // Stop the communications buffer trace.
191
// The trace file is flushed and closed. After calling this method,
192
// calls to isComBufferTraceOn () will return false.
193
protected void stopComBufferTrace ()
194   {
195     synchronized (comBufferSync) {
196       // Only stop the trace if it is actually on.
197
if (comBufferTraceOn == true) {
198         // Turn of the trace flag.
199
comBufferTraceOn = false;
200         // Flush and close the writer used for tracing.
201
comBufferWriter.flush();
202         comBufferWriter.close();
203       }
204     }
205   }
206
207   // Write the communication buffer data to the trace.
208
// The data is passed in via a byte array. The start and length of the data is given.
209
// The type is needed to indicate if the data is part of the send or receive buffer.
210
// The class name, method name, and trcPt number are also written to the trace.
211
// Not much checking is performed on the parameters. This is done to help performance.
212
protected void writeComBufferData (byte[] buff,
213                                          int offset,
214                                          int len,
215                                          int type,
216                                          String JavaDoc className,
217                                          String JavaDoc methodName,
218                                          int trcPt)
219   {
220     // why don't we synchronize the method!!!
221

222     // Grab the lock to make sure another thread doesn't try to
223
// write data or close the writer.
224
synchronized (comBufferSync) {
225
226       // Only take action if the trace is on.
227
if (comBufferTraceOn) {
228
229         // Obtain an instance of the Calendar so a timestamp can be written.
230
// this call seems to slow things down a bit.
231
java.util.Calendar JavaDoc time = java.util.Calendar.getInstance();
232
233         // Print the timestamp, class name, method name, thread name, and tracepoint.
234
comBufferWriter.println (" (" +
235                                  time.get (java.util.Calendar.YEAR) +
236                                  "." +
237                                  (time.get (java.util.Calendar.MONTH) + 1) +
238                                  "." +
239                                  time.get (java.util.Calendar.DAY_OF_MONTH) +
240                                  " " +
241                                  time.get (java.util.Calendar.HOUR_OF_DAY) +
242                                  ":" +
243                                  time.get (java.util.Calendar.MINUTE) +
244                                  ":" +
245                                  time.get (java.util.Calendar.SECOND) +
246                                  ") " +
247                                  className +
248                                  " " +
249                                  methodName +
250                                  " " +
251                                  Thread.currentThread().getName() +
252                                  " " +
253                                  trcPt);
254
255         // A newline is added for formatting.
256
comBufferWriter.println();
257
258         // The data will only be written if there is a non-zero positive length.
259
if (len != 0) {
260           String JavaDoc codePointName = null;
261           // If the length <= 10, lookup the first codepoint so it's name can be printed???
262
if (len >= 10) {
263             // Get the int value of the two byte unsigned codepoint.
264
int codePoint = getCodePoint (buff, offset+8);
265             codePointName = codePointNameTable.lookup (codePoint);
266           }
267
268           if (codePointName == null) {
269             // codePointName was still null so either < 10 bytes were given or
270
// the codepoint wasn't found in the table. Just print the plain send header.
271
comBufferWriter.println (getHeader (type));
272           }
273           else {
274             // codePointName isn't null so the name of the codepoint will be printed.
275
printHeaderWithCodePointName (codePointName, type);
276           }
277
278           // Print the col position header in the trace.
279
comBufferWriter.println (colPosHeader);
280
281           // A char array will be used to translate the bytes to their character
282
// representations along with ascii and ebcdic representations.
283
char trcDump[] = new char[77];
284
285           // bCounter, aCounter, eCounter are offsets used to help position the characters
286
short bCounter = 7;
287           short aCounter = 43;
288           short eCounter = 61;
289
290           // The lines will be counted starting at zero. This is hard coded since we are
291
// at the beginning.
292
trcDump[0] = DssTrace.zeroChar;
293           trcDump[1] = DssTrace.zeroChar;
294           trcDump[2] = DssTrace.zeroChar;
295           trcDump[3] = DssTrace.zeroChar;
296
297           // The 0's are already in the trace so bump the line counter up a row.
298
int lineCounter = 0x10;
299
300           // Make sure the character array has all blanks in it.
301
// Some of these blanks will be replaced later with values.
302
// The 0's were not wrote over.
303
for (int j = 4; j < 77; j++) {
304             trcDump[j] = DssTrace.spaceChar;
305           }
306
307           // i will maintain the position in the byte array to be traced.
308
int i = 0;
309
310           do {
311             // Get the unsigned value of the byte.
312
// int num = b[off++] & 0xff;
313
int num = (buff[offset] < 0)? buff[offset] + 256 : buff[offset]; // jev
314
offset++;
315             i++;
316             // Place the characters representing the bytes in the array.
317
trcDump[bCounter++] = DssTrace.hexDigit[((num >>> 4) & 0xf)];
318             trcDump[bCounter++] = DssTrace.hexDigit[(num & 0xf)];
319
320             // Place the ascii and ebcdc representations in the array.
321
trcDump[aCounter++] = DssTrace.asciiChar[num];
322             trcDump[eCounter++] = DssTrace.ebcdicChar[num];
323
324             if (((i%8) == 0)) {
325               if (((i%16) == 0)) {
326                 // Print the array each time 16 bytes are processed.
327
comBufferWriter.println (trcDump);
328                 if (i != len) {
329                   // Not yet at the end of the byte array.
330
if ((len - i) < 16) {
331                     // This is the last line so blank it all out.
332
// This keeps the last line looking pretty in case
333
// < 16 bytes remain.
334
for (int j = 0; j < trcDump.length; j++) {
335                       trcDump[j] = DssTrace.spaceChar;
336                     }
337                   }
338                   // Reset the counters.
339
bCounter = 0;
340                   aCounter = 43;
341                   eCounter = 61;
342                   // Reset the lineCounter if it starts to get too large.
343
if (lineCounter == 0xfff0) {
344                     lineCounter = 0;
345                   }
346                   // Place the characters representing the line counter in the array.
347
trcDump[bCounter++] = DssTrace.hexDigit[((lineCounter >>> 12) & 0xf)];
348                   trcDump[bCounter++] = DssTrace.hexDigit[((lineCounter >>> 8) & 0xf)];
349                   trcDump[bCounter++] = DssTrace.hexDigit[((lineCounter >>> 4) & 0xf)];
350                   trcDump[bCounter++] = DssTrace.hexDigit[(lineCounter & 0xf)];
351                   bCounter += 3;
352                   // Bump up the line counter.
353
lineCounter += 0x10;
354                 }
355               }
356               else {
357                 // 8 bytes were processed so move the counter to adjust for
358
// spaces between the columns of bytes.
359
bCounter += 2;
360               }
361             }
362             // do this until we all the data has been traced.
363
} while (i < len);
364
365           // print the last line and add some blank lines to make it easier to read.
366
if (len % 16 != 0) {
367             comBufferWriter.println (trcDump);
368           }
369           comBufferWriter.println();
370           comBufferWriter.println();
371         }
372         // Flush the writer.
373
comBufferWriter.flush();
374       }
375     }
376   }
377
378   // Gets the int value of the two byte unsigned codepoint.
379
private static int getCodePoint (byte[] buff, int offset)
380   {
381     return ((buff[offset++] & 0xff) << 8) +
382       ((buff[offset] & 0xff) << 0);
383   }
384
385   private static String JavaDoc getHeader (int type)
386   {
387     switch (type) {
388     case DssTrace.TYPE_TRACE_SEND:
389       return DssTrace.sendHeader;
390     case DssTrace.TYPE_TRACE_RECEIVE:
391       return DssTrace.receiveHeader;
392     default:
393       // throw new !!!
394
return null;
395     }
396   }
397
398   private static int getStartPosition (int type)
399   {
400     switch (type) {
401     case DssTrace.TYPE_TRACE_SEND:
402       return 20; // This is right after 'SEND BUFFER: '.
403
case DssTrace.TYPE_TRACE_RECEIVE:
404       return 23; // This is right after 'RECEIVE BUFFER: '.
405
default:
406       // throw new !!!
407
return 0;
408     }
409   }
410
411   private void printHeaderWithCodePointName (String JavaDoc codePointName, int type)
412   {
413     // Create a char array so some of the characters
414
// can be replaced with the name of the codepoint.
415
char headerArray[] = DssTrace.getHeader(type).toCharArray();
416
417     // At most, 16 character name will be used. This is so
418
// the headers on top of the ascii and ebcdic rows aren't shifted.
419
int replaceLen = (codePointName.length() < 17) ? codePointName.length() : 16;
420
421     int offset = getStartPosition (type);
422     for (int i = 0; i < replaceLen; i++) {
423       headerArray[offset++] = codePointName.charAt (i); // make sure charAt() starts at 0!!!
424
}
425     comBufferWriter.println (headerArray);
426   }
427
428 }
429
Popular Tags