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 }