View Javadoc

1   package it.imolinfo.jbi4cics.typemapping.cobol;
2   
3   /*******************************************************************************
4    *  Copyright (c) 2005, 2006 Imola Informatica.
5    *  All rights reserved. This program and the accompanying materials
6    *  are made available under the terms of the LGPL License v2.1
7    *  which accompanies this distribution, and is available at
8    *  http://www.gnu.org/licenses/lgpl.html
9    *******************************************************************************/
10       
11  
12  
13  import it.imolinfo.jbi4cics.Logger;
14  import it.imolinfo.jbi4cics.LoggerFactory;
15  import it.imolinfo.jbi4cics.jbi.Messages;
16  import java.io.BufferedInputStream;
17  import java.io.ByteArrayOutputStream;
18  import java.io.File;
19  import java.io.FileInputStream;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.OutputStream;
23  import java.io.PrintStream;
24  import java.text.DecimalFormat;
25  
26  
27  /**
28  * dump data in hexadecimal format; derived from a HexDump utility I
29  * wrote in June 2001.
30  *
31  * @author Marc Johnson
32  * @author Glen Stampoultzis  (glens at apache.org)
33  */
34  
35  public class HexDump {
36   
37   /**
38    * The logger for this class and its instances.
39    */
40   private static final Logger LOG
41           = LoggerFactory.getLogger(HexDump.class);
42   
43   /**
44    * The responsible to translate localized messages.
45    */
46   private static final Messages MESSAGES
47           = Messages.getMessages(HexDump.class);
48   
49   public static final String        EOL         =
50       System.getProperty("line.separator");
51  // private static final StringBuffer _lbuffer    = new StringBuffer(8);
52  // private static final StringBuffer _cbuffer    = new StringBuffer(2);
53   private static final char         HEXCODES[] =
54   {
55       '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
56       'E', 'F'
57   };
58   private static final int          SHIFTS[]   =
59   {
60       60, 56, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0
61   };
62  
63  
64   // all static methods, so no need for a public constructor
65   private HexDump()
66   {
67   }
68  
69   /**
70    * Dump an array of bytes to an OutputStream.
71    *
72    * @param data the byte array to be dumped
73    * @param offset its offset, whatever that might mean
74    * @param stream the OutputStream to which the data is to be
75    *               written
76    * @param index initial index into the byte array
77    * @param length number of characters to output
78    *
79    * @exception IOException is thrown if anything goes wrong writing
80    *            the data to stream
81    * @exception ArrayIndexOutOfBoundsException if the index is
82    *            outside the data array's bounds
83    * @exception IllegalArgumentException if the output stream is
84    *            null
85    */
86   public synchronized static void dump(final byte [] data, final long offset,
87                           final OutputStream stream, final int index, final int length)
88           throws IOException, ArrayIndexOutOfBoundsException,
89                   IllegalArgumentException
90   {
91       if (data.length == 0)
92       {
93           stream.write( ("No Data" + System.getProperty( "line.separator")).getBytes() );
94           stream.flush();
95           return;
96       }
97       if ((index < 0) || (index >= data.length))
98       {
99           LOG.error("CIC002112_Illegal_index", index, data.length);
100          throw new ArrayIndexOutOfBoundsException(MESSAGES.getString(
101                  "CIC002112_Illegal_index", index, data.length));
102      }
103      if (stream == null)
104      {
105          LOG.error("CIC002113_Cannot_write_nullstream");
106          throw new IllegalArgumentException(MESSAGES.getString(
107                  "CIC002113_Cannot_write_nullstream"));
108      }
109 
110      long         display_offset = offset + index;
111      StringBuffer buffer         = new StringBuffer(74);
112 
113 
114      int data_length = Math.min(data.length,index+length);
115      for (int j = index; j < data_length; j += 16)
116      {
117          int chars_read = data_length - j;
118 
119          if (chars_read > 16)
120          {
121              chars_read = 16;
122          }
123          buffer.append(
124                      dump(display_offset)
125                       ).append(' ');
126          for (int k = 0; k < 16; k++)
127          {
128              if (k < chars_read)
129              {
130                  buffer.append(dump(data[ k + j ]));
131              }
132              else
133              {
134                  buffer.append("  ");
135              }
136              buffer.append(' ');
137          }
138          for (int k = 0; k < chars_read; k++)
139          {
140              if ((data[ k + j ] >= ' ') && (data[ k + j ] < 127))
141              {
142                  buffer.append(( char ) data[ k + j ]);
143              }
144              else
145              {
146                  buffer.append('.');
147              }
148          }
149          buffer.append(EOL);
150          stream.write(buffer.toString().getBytes());
151          stream.flush();
152          buffer.setLength(0);
153          display_offset += chars_read;
154      }
155 
156  }
157 
158  /**
159   * Dump an array of bytes to an OutputStream.
160   *
161   * @param data the byte array to be dumped
162   * @param offset its offset, whatever that might mean
163   * @param stream the OutputStream to which the data is to be
164   *               written
165   * @param index initial index into the byte array
166   *
167   * @exception IOException is thrown if anything goes wrong writing
168   *            the data to stream
169   * @exception ArrayIndexOutOfBoundsException if the index is
170   *            outside the data array's bounds
171   * @exception IllegalArgumentException if the output stream is
172   *            null
173   */
174 
175  public synchronized static void dump(final byte [] data, final long offset,
176                          final OutputStream stream, final int index)
177      throws IOException, ArrayIndexOutOfBoundsException,
178              IllegalArgumentException
179  {
180      dump(data, offset, stream, index, data.length-index);
181  }
182 
183  /**
184   * Dump an array of bytes to a String.
185   *
186   * @param data the byte array to be dumped
187   * @param offset its offset, whatever that might mean
188   * @param index initial index into the byte array
189   *
190   * @throw ArrayIndexOutOfBoundsException if the index is
191   *            outside the data array's bounds
192   * @return output string
193   */
194  
195  public static String dump(final byte [] data, final long offset,
196                          final int index) {
197      StringBuffer buffer;
198      if ((index < 0) || (index >= data.length))
199      {
200          LOG.error("CIC002112_Illegal_index", index, data.length);
201          throw new ArrayIndexOutOfBoundsException(MESSAGES.getString(
202                  "CIC002112_Illegal_index", index, data.length));
203      }
204      long         display_offset = offset + index;
205      buffer         = new StringBuffer(74);
206 
207      for (int j = index; j < data.length; j += 16)
208      {
209          int chars_read = data.length - j;
210 
211          if (chars_read > 16)
212          {
213              chars_read = 16;
214          }
215          buffer.append(dump(display_offset)).append(' ');
216          for (int k = 0; k < 16; k++)
217          {
218              if (k < chars_read)
219              {
220                  buffer.append(dump(data[ k + j ]));
221              }
222              else
223              {
224                  buffer.append("  ");
225              }
226              buffer.append(' ');
227          }
228          for (int k = 0; k < chars_read; k++)
229          {
230              if ((data[ k + j ] >= ' ') && (data[ k + j ] < 127))
231              {
232                  buffer.append(( char ) data[ k + j ]);
233              }
234              else
235              {
236                  buffer.append('.');
237              }
238          }
239          buffer.append(EOL);
240          display_offset += chars_read;
241      }                 
242      return buffer.toString();
243  }
244  
245 
246  private static String dump(final long value)
247  {
248      StringBuffer buf = new StringBuffer();
249      buf.setLength(0);
250      for (int j = 0; j < 8; j++)
251      {
252          buf.append( HEXCODES[ (( int ) (value >> SHIFTS[ j + SHIFTS.length - 8 ])) & 15 ]);
253      }
254      return buf.toString();
255  }
256 
257  private static String dump(final byte value)
258  {
259      StringBuffer buf = new StringBuffer();
260      buf.setLength(0);
261      for (int j = 0; j < 2; j++)
262      {
263          buf.append(HEXCODES[ (value >> SHIFTS[ j + 6 ]) & 15 ]);
264      }
265      return buf.toString();
266  }
267 
268  /**
269   * Converts the parameter to a hex value.
270   *
271   * @param value     The value to convert
272   * @return          A String representing the array of bytes
273   */
274  public static String toHex(final byte[] value)
275  {
276      StringBuffer retVal = new StringBuffer();
277      retVal.append('[');
278      for(int x = 0; x < value.length; x++)
279      {
280          retVal.append("0x").append(toHex(value[x]));
281          if (value.length-x>1) {
282            retVal.append(", ");
283          }
284      }
285      retVal.append(']');
286      return retVal.toString();
287  }
288 
289  /**
290   * <p>Converts the parameter to a hex value breaking the results into
291   * lines.</p>
292   *
293   * @param value        The value to convert
294   * @param bytesPerLine The maximum number of bytes per line. The next byte
295   *                     will be written to a new line
296   * @return             A String representing the array of bytes
297   */
298  public static String toHex(final byte[] value, final int bytesPerLine)
299  {
300      final int digits =
301          (int) Math.round(Math.log(value.length) / Math.log(10) + 0.5);
302      final StringBuffer formatString = new StringBuffer();
303      for (int i = 0; i < digits; i++){
304          formatString.append('0');
305      }
306      formatString.append(": ");
307      final DecimalFormat format = new DecimalFormat(formatString.toString());
308      StringBuffer retVal = new StringBuffer();
309      retVal.append(format.format(0));
310      int i = -1;
311      for(int x = 0; x < value.length; x++)
312      {
313          if (++i == bytesPerLine)
314          {
315              retVal.append('\n');
316              retVal.append(format.format(x));
317              i = 0;
318          }
319          retVal.append(toHex(value[x]));
320          retVal.append(", ");
321      }
322      return retVal.toString();
323  }
324 
325  /**
326   * Converts the parameter to a hex value.
327   *
328   * @param value     The value to convert
329   * @return          The result right padded with 0
330   */
331  public static String toHex(final short value)
332  {
333      return toHex(value, 4);
334  }
335 
336  /**
337   * Converts the parameter to a hex value.
338   *
339   * @param value     The value to convert
340   * @return          The result right padded with 0
341   */
342  public static String toHex(final byte value)
343  {
344      return toHex(value, 2);
345  }
346 
347  /**
348   * Converts the parameter to a hex value.
349   *
350   * @param value     The value to convert
351   * @return          The result right padded with 0
352   */
353  public static String toHex(final int value)
354  {
355      return toHex(value, 8);
356  }
357 
358  /**
359   * Converts the parameter to a hex value.
360   *
361   * @param value     The value to convert
362   * @return          The result right padded with 0
363   */
364  public static String toHex(final long value)
365  {
366      return toHex(value, 16);
367  }
368 
369 
370  private static String toHex(final long value, final int digits)
371  {
372      StringBuffer result = new StringBuffer(digits);
373      for (int j = 0; j < digits; j++)
374      {
375          result.append( HEXCODES[ (int) ((value >> SHIFTS[ j + (16 - digits) ]) & 15)]);
376      }
377      return result.toString();
378  }
379 
380  /**
381   * Dumps <code>bytesToDump</code> bytes to an output stream.
382   *
383   * @param in          The stream to read from
384   * @param out         The output stream
385   * @param start       The index to use as the starting position for the left hand side label
386   * @param bytesToDump The number of bytes to output.  Use -1 to read until the end of file.
387   * @throws IOException The IO exception
388   */
389  public static void dump( InputStream in, PrintStream out, int start, int bytesToDump ) throws IOException
390  {
391      ByteArrayOutputStream buf = new ByteArrayOutputStream();
392      if (bytesToDump == -1)
393      {
394          int c = in.read();
395          while (c != -1)
396          {
397              buf.write(c);
398              c = in.read();
399          }
400      }
401      else
402      {
403          int bytesRemaining = bytesToDump;
404          while (bytesRemaining-- > 0)
405          {
406              int c = in.read();
407              if (c == -1){
408                  break;
409              }
410              else {
411                  buf.write(c);
412              }
413          }
414      }
415 
416      byte[] data = buf.toByteArray();
417      dump(data, 0, out, start, data.length);
418  }
419 
420  /**
421   * 
422   * @param args     The argoments
423   * @throws Exception    The exception
424   */
425  public static void main(String[] args) throws Exception {
426      File file = new File(args[0]);
427      InputStream in = new BufferedInputStream(new FileInputStream(file)); 
428      byte[] b = new byte[(int)file.length()];
429      in.read(b);
430      LOG.debug(HexDump.dump(b, 0, 0));
431      in.close();
432  }
433 }