View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.mina.util;
20  
21  import java.nio.ByteBuffer;
22  
23  /**
24   * Utility class for smart dumping {@link ByteBuffer}
25   * 
26   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
27   */
28  public class ByteBufferDumper {
29      /** Hex chars */
30      private static final byte[] HEX_CHAR = new byte[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
31              'C', 'D', 'E', 'F' };
32  
33      /**
34       * Dump the content of the given ByteBuffer, up to a number of bytes. If the toAscii flag is set to
35       * <code>true</code>, this method will try to convert the bytes to a String
36       * 
37       * @param buffer The buffer to dump
38       * @param nbBytes The number of bytes to dump (-1 for all of them)
39       * @param toAscii If we want to write the message as a String
40       * @return A dump of this ByteBuffer
41       */
42      public static String dump(ByteBuffer buffer, int nbBytes, boolean toAscii) {
43          byte data[];
44          int start;
45          int size = Math.min(buffer.remaining(), nbBytes >= 0 ? nbBytes : Integer.MAX_VALUE);
46          int length = buffer.remaining();
47  
48          if (buffer.hasArray() && !buffer.isReadOnly()) {
49              start = buffer.position();
50              data = buffer.array();
51          } else {
52              data = new byte[size];
53  
54              int oldpos = buffer.position();
55              buffer.get(data);
56              buffer.position(oldpos);
57  
58              start = 0;
59              length = data.length;
60          }
61  
62          // is not ASCII printable ?
63          boolean binaryContent = false;
64  
65          if (toAscii) {
66              for (int i = start; i < start + size; i++) {
67                  byte b = data[i];
68  
69                  if (((b < 32) || (b > 126)) && (b != 13) && (b != 10)) {
70                      binaryContent = true;
71                      break;
72                  }
73              }
74          }
75  
76          if (!toAscii || binaryContent) {
77              StringBuilder out = new StringBuilder(size * 3 + 30);
78              out.append("ByteBuffer[len=").append(length).append(",bytes='");
79  
80              // fill the first
81              int byteValue = data[start] & 0xFF;
82              boolean isFirst = true;
83  
84              // and the others, too
85              for (int i = start; i < start + size; i++) {
86                  if (isFirst) {
87                      isFirst = false;
88                  } else {
89                      out.append(' ');
90                  }
91  
92                  byteValue = data[i] & 0xFF;
93                  out.append(new String(new byte[] { '0', 'x', HEX_CHAR[(byteValue & 0x00F0) >> 4],
94                          HEX_CHAR[byteValue & 0x000F] }));
95              }
96  
97              out.append("']");
98  
99              return out.toString();
100 
101         } else {
102             StringBuilder sb = new StringBuilder(size);
103             sb.append("ByteBuffer[len=").append(length).append(",str='").append(new String(data, start, size))
104                     .append("']");
105 
106             return sb.toString();
107         }
108     }
109 
110     /**
111      * Dumps the given buffer. If the buffer contains only ascii, it will write the buffer content as a String.
112      * 
113      * @param buffer The buffer to dump
114      * @return A string representing the buffer content
115      */
116     public static String dump(ByteBuffer buffer) {
117         return dump(buffer, -1, true);
118     }
119 
120     /**
121      * Dump a byte buffer remaining bytes as a hex-decimal string. The current buffer position will remain unchanged.
122      * 
123      * @param buffer the buffer to dump
124      * @return a hex string
125      */
126     public static String toHex(ByteBuffer buffer) {
127         StringBuilder out = new StringBuilder(buffer.remaining() * 2);
128         int pos = buffer.position();
129         while (buffer.hasRemaining()) {
130             int byteValue = buffer.get() & 0xFF;
131             out.append((char) (HEX_CHAR[(byteValue & 0x00F0) >> 4]))
132                     .append((char) ((HEX_CHAR[byteValue & 0x000F]) - 0));
133         }
134         buffer.position(pos);
135         return out.toString();
136     }
137 
138     public static ByteBuffer fromHexString(String hex) {
139         if (hex.length() % 2 != 0) {
140             throw new IllegalArgumentException("the hexa-decimal string length cannot be odd");
141         }
142         int size = hex.length() / 2;
143         ByteBuffer res = ByteBuffer.allocate(size);
144 
145         for (int i = 0; i < size; i++) {
146             int b = ((Character.digit(hex.charAt(i * 2), 16) << 4) | (Character.digit(hex.charAt(i * 2 + 1), 16)));
147             res.put((byte) b);
148         }
149 
150         res.flip();
151         return res;
152     }
153 }