1    
2    /* ====================================================================
3     * The Apache Software License, Version 1.1
4     *
5     * Copyright (c) 2002 The Apache Software Foundation.  All rights
6     * reserved.
7     *
8     * Redistribution and use in source and binary forms, with or without
9     * modification, are permitted provided that the following conditions
10    * are met:
11    *
12    * 1. Redistributions of source code must retain the above copyright
13    *    notice, this list of conditions and the following disclaimer.
14    *
15    * 2. Redistributions in binary form must reproduce the above copyright
16    *    notice, this list of conditions and the following disclaimer in
17    *    the documentation and/or other materials provided with the
18    *    distribution.
19    *
20    * 3. The end-user documentation included with the redistribution,
21    *    if any, must include the following acknowledgment:
22    *       "This product includes software developed by the
23    *        Apache Software Foundation (http://www.apache.org/)."
24    *    Alternately, this acknowledgment may appear in the software itself,
25    *    if and wherever such third-party acknowledgments normally appear.
26    *
27    * 4. The names "Apache" and "Apache Software Foundation" and
28    *    "Apache POI" must not be used to endorse or promote products
29    *    derived from this software without prior written permission. For
30    *    written permission, please contact apache@apache.org.
31    *
32    * 5. Products derived from this software may not be called "Apache",
33    *    "Apache POI", nor may "Apache" appear in their name, without
34    *    prior written permission of the Apache Software Foundation.
35    *
36    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39    * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40    * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41    * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43    * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45    * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47    * SUCH DAMAGE.
48    * ====================================================================
49    *
50    * This software consists of voluntary contributions made by many
51    * individuals on behalf of the Apache Software Foundation.  For more
52    * information on the Apache Software Foundation, please see
53    * <http://www.apache.org/>.
54    */
55   
56   package org.apache.poi.util;
57   
58   import java.io.*;
59   
60   /**
61    * dump data in hexadecimal format; derived from a HexDump utility I
62    * wrote in June 2001.
63    *
64    * @author Marc Johnson
65    * @author Glen Stampoultzis  (glens at apache.org)
66    */
67   
68   public class HexDump
69   {
70   
71       // all static methods, so no need for a public constructor
72       private HexDump()
73       {
74       }
75   
76       /**
77        * dump an array of bytes to an OutputStream
78        *
79        * @param data the byte array to be dumped
80        * @param offset its offset, whatever that might mean
81        * @param stream the OutputStream to which the data is to be
82        *               written
83        * @param index initial index into the byte array
84        *
85        * @exception IOException is thrown if anything goes wrong writing
86        *            the data to stream
87        * @exception ArrayIndexOutOfBoundsException if the index is
88        *            outside the data array's bounds
89        * @exception IllegalArgumentException if the output stream is
90        *            null
91        */
92   
93       public synchronized static void dump(final byte [] data, final long offset,
94                               final OutputStream stream, final int index)
95           throws IOException, ArrayIndexOutOfBoundsException,
96                   IllegalArgumentException
97       {
98           if ((index < 0) || (index >= data.length))
99           {
100              throw new ArrayIndexOutOfBoundsException(
101                  "illegal index: " + index + " into array of length "
102                  + data.length);
103          }
104          if (stream == null)
105          {
106              throw new IllegalArgumentException("cannot write to nullstream");
107          }
108          long         display_offset = offset + index;
109          StringBuffer buffer         = new StringBuffer(74);
110  
111          for (int j = index; j < data.length; j += 16)
112          {
113              int chars_read = data.length - j;
114  
115              if (chars_read > 16)
116              {
117                  chars_read = 16;
118              }
119              buffer.append(dump(display_offset)).append(' ');
120              for (int k = 0; k < 16; k++)
121              {
122                  if (k < chars_read)
123                  {
124                      buffer.append(dump(data[ k + j ]));
125                  }
126                  else
127                  {
128                      buffer.append("  ");
129                  }
130                  buffer.append(' ');
131              }
132              for (int k = 0; k < chars_read; k++)
133              {
134                  if ((data[ k + j ] >= ' ') && (data[ k + j ] < 127))
135                  {
136                      buffer.append(( char ) data[ k + j ]);
137                  }
138                  else
139                  {
140                      buffer.append('.');
141                  }
142              }
143              buffer.append(EOL);
144              stream.write(buffer.toString().getBytes());
145              stream.flush();
146              buffer.setLength(0);
147              display_offset += chars_read;
148          }
149      }
150  
151      public static final String        EOL         =
152          System.getProperty("line.separator");
153      private static final StringBuffer _lbuffer    = new StringBuffer(8);
154      private static final StringBuffer _cbuffer    = new StringBuffer(2);
155      private static final char         _hexcodes[] =
156      {
157          '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
158          'E', 'F'
159      };
160      private static final int          _shifts[]   =
161      {
162          28, 24, 20, 16, 12, 8, 4, 0
163      };
164  
165      private static StringBuffer dump(final long value)
166      {
167          _lbuffer.setLength(0);
168          for (int j = 0; j < 8; j++)
169          {
170              _lbuffer
171                  .append(_hexcodes[ (( int ) (value >> _shifts[ j ])) & 15 ]);
172          }
173          return _lbuffer;
174      }
175  
176      private static StringBuffer dump(final byte value)
177      {
178          _cbuffer.setLength(0);
179          for (int j = 0; j < 2; j++)
180          {
181              _cbuffer.append(_hexcodes[ (value >> _shifts[ j + 6 ]) & 15 ]);
182          }
183          return _cbuffer;
184      }
185  
186      /**
187       * Converts the parameter to a hex value.
188       *
189       * @param value     The value to convert
190       * @return          A String representing the array of bytes
191       */
192      public static String toHex(final byte[] value)
193      {
194          StringBuffer retVal = new StringBuffer();
195          retVal.append('[');
196          for(int x = 0; x < value.length; x++)
197          {
198              retVal.append(toHex(value[x]));
199              retVal.append(", ");
200          }
201          retVal.append(']');
202          return retVal.toString();
203      }
204      /**
205       * Converts the parameter to a hex value.
206       *
207       * @param value     The value to convert
208       * @return          The result right padded with 0
209       */
210      public static String toHex(final short value)
211      {
212          return toHex(value, 4);
213      }
214  
215      /**
216       * Converts the parameter to a hex value.
217       *
218       * @param value     The value to convert
219       * @return          The result right padded with 0
220       */
221      public static String toHex(final byte value)
222      {
223          return toHex(value, 2);
224      }
225  
226      /**
227       * Converts the parameter to a hex value.
228       *
229       * @param value     The value to convert
230       * @return          The result right padded with 0
231       */
232      public static String toHex(final int value)
233      {
234          return toHex(value, 8);
235      }
236  
237  
238      private static String toHex(final long value, final int digits)
239      {
240          StringBuffer result = new StringBuffer(digits);
241          for (int j = 0; j < digits; j++)
242          {
243              result.append( _hexcodes[ (int) ((value >> _shifts[ j + (8 - digits) ]) & 15)]);
244          }
245          return result.toString();
246      }
247  }
248