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   */
    20  package org.apache.mina.proxy.utils;
    21
    22  import java.io.UnsupportedEncodingException;
    23
    24  /**
    25   * ByteUtilities.java - Byte manipulation functions.
    26   *
    27   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
    28   * @since MINA 2.0.0-M3
    29   */
    30  public class ByteUtilities {
    31
    32      /**
    33       * Returns the integer represented by up to 4 bytes in network byte order.
    34       *
    35       * @param buf the buffer to read the bytes from
    36       * @param start
    37       * @param count
    38       * @return
    39       */
    40      public static int networkByteOrderToInt(byte[] buf, int start, int count) {
    41          if (count > 4) {
    42              throw new IllegalArgumentException("Cannot handle more than 4 bytes");
    43          }
    44
    45          int result = 0;
    46
    47          for (int i = 0; i < count; i++) {
    48              result <<= 8;
    49              result |= (buf[start + i] & 0xff);
    50          }
    51
    52          return result;
    53      }
    54
    55      /**
    56       * Encodes an integer into up to 4 bytes in network byte order.
    57       *
    58       * @param num the int to convert to a byte array
    59       * @param count the number of reserved bytes for the write operation
    60       * @return the resulting byte array
    61       */
    62      public static byte[] intToNetworkByteOrder(int num, int count) {
    63          byte[] buf = new byte[count];
    64          intToNetworkByteOrder(num, buf, 0, count);
    65
    66          return buf;
    67      }
    68
    69      /**
    70       * Encodes an integer into up to 4 bytes in network byte order in the
    71       * supplied buffer starting at <code>start</code> offset and writing
    72       * <code>count</code> bytes.
    73       *
    74       * @param num the int to convert to a byte array
    75       * @param buf the buffer to write the bytes to
    76       * @param start the offset from beginning for the write operation
    77       * @param count the number of reserved bytes for the write operation
    78       */
    79      public static void intToNetworkByteOrder(int num, byte[] buf, int start, int count) {
    80          if (count > 4) {
    81              throw new IllegalArgumentException("Cannot handle more than 4 bytes");
    82          }
    83
    84          for (int i = count - 1; i >= 0; i--) {
    85              buf[start + i] = (byte) (num & 0xff);
    86              num >>>= 8;
    87          }
    88      }
    89
    90      /**
    91       * Write a 16 bit short as LITTLE_ENDIAN.
    92       *
    93       * @param v the short to write
    94       */
    95      public final static byte[] writeShort(short v) {
    96          return writeShort(v, new byte[2], 0);
    97      }
    98
    99      /**
    100      * Write a 16 bit short as LITTLE_ENDIAN to
    101      * the given array <code>b</code> at offset <code>offset</code>.
    102      *
    103      * @param v the short to write
    104      * @param b the byte array to write to
    105      * @param offset the offset at which to start writing in the array
    106      */
    107     public final static byte[] writeShort(short v, byte[] b, int offset) {
    108         b[offset] = (byte) v;
    109         b[offset + 1] = (byte) (v >> 8);
    110
    111         return b;
    112     }
    113
    114     /**
    115      * Write a 32 bit int as LITTLE_ENDIAN.
    116      *
    117      * @param v the int to write
    118      */
    119     public final static byte[] writeInt(int v) {
    120         return writeInt(v, new byte[4], 0);
    121     }
    122
    123     /**
    124      * Write a 32 bit int as LITTLE_ENDIAN to
    125      * the given array <code>b</code> at offset <code>offset</code>.
    126      *
    127      * @param v the int to write
    128      * @param b the byte array to write to
    129      * @param offset the offset at which to start writing in the array
    130      */
    131     public final static byte[] writeInt(int v, byte[] b, int offset) {
    132         b[offset] = (byte) v;
    133         b[offset + 1] = (byte) (v >> 8);
    134         b[offset + 2] = (byte) (v >> 16);
    135         b[offset + 3] = (byte) (v >> 24);
    136
    137         return b;
    138     }
    139
    140     /**
    141      * Invert the endianness of words (4 bytes) in the given byte array
    142      * starting at the given offset and repeating length/4 times.
    143      * eg: b0b1b2b3 -> b3b2b1b0
    144      *
    145      * @param b the byte array
    146      * @param offset the offset at which to change word start
    147      * @param length the number of bytes on which to operate
    148      * (should be a multiple of 4)
    149      */
    150     public final static void changeWordEndianess(byte[] b, int offset, int length) {
    151         byte tmp;
    152
    153         for (int i = offset; i < offset + length; i += 4) {
    154             tmp = b[i];
    155             b[i] = b[i + 3];
    156             b[i + 3] = tmp;
    157             tmp = b[i + 1];
    158             b[i + 1] = b[i + 2];
    159             b[i + 2] = tmp;
    160         }
    161     }
    162
    163     /**
    164      * Invert two bytes in the given byte array starting at the given
    165      * offset and repeating the inversion length/2 times.
    166      * eg: b0b1 -> b1b0
    167      *
    168      * @param b the byte array
    169      * @param offset the offset at which to change word start
    170      * @param length the number of bytes on which to operate
    171      * (should be a multiple of 2)
    172      */
    173     public final static void changeByteEndianess(byte[] b, int offset, int length) {
    174         byte tmp;
    175
    176         for (int i = offset; i < offset + length; i += 2) {
    177             tmp = b[i];
    178             b[i] = b[i + 1];
    179             b[i + 1] = tmp;
    180         }
    181     }
    182
    183     /**
    184      * Converts an OEM string as defined in NTLM protocol (eg ASCII charset)
    185      * to a byte array.
    186      *
    187      * @param s the string to convert
    188      * @return the result byte array
    189      * @throws UnsupportedEncodingException if the string is not an OEM string
    190      */
    191     public final static byte[] getOEMStringAsByteArray(String s) throws UnsupportedEncodingException {
    192         return s.getBytes("ASCII");
    193     }
    194
    195     /**
    196      * Converts an UTF-16LE string as defined in NTLM protocol to a byte array.
    197      *
    198      * @param s the string to convert
    199      * @return the result byte array
    200      * @throws UnsupportedEncodingException if the string is not an UTF-16LE string
    201      */
    202     public final static byte[] getUTFStringAsByteArray(String s) throws UnsupportedEncodingException {
    203         return s.getBytes("UTF-16LE");
    204     }
    205
    206     /**
    207      * Encodes the string to a byte array using UTF-16LE or the ASCII charset
    208      * in function of the <code>useUnicode</code> argument.
    209      *
    210      * @param s the string to encode
    211      * @param useUnicode if true then string is encoded to UTF-16LE
    212      * otherwise to ASCII
    213      * @return the encoded string as a byte array
    214      * @throws UnsupportedEncodingException if encoding fails
    215      */
    216     public final static byte[] encodeString(String s, boolean useUnicode) throws UnsupportedEncodingException {
    217         if (useUnicode) {
    218             return getUTFStringAsByteArray(s);
    219         }
    220
    221         return getOEMStringAsByteArray(s);
    222     }
    223
    224     /**
    225      * Returns a hexadecimal representation of the given byte array.
    226      *
    227      * @param bytes the array to output to an hex string
    228      * @return the hex representation as a string
    229      */
    230     public static String asHex(byte[] bytes) {
    231         return asHex(bytes, null);
    232     }
    233
    234     /**
    235      * Returns a hexadecimal representation of the given byte array.
    236      *
    237      * @param bytes the array to output to an hex string
    238      * @param separator the separator to use between each byte in the output
    239      * string. If null no char is inserted between each byte value.
    240      * @return the hex representation as a string
    241      */
    242     public static String asHex(byte[] bytes, String separator) {
    243         StringBuilder sb = new StringBuilder();
    244         for (int i = 0; i < bytes.length; i++) {
    245             String code = Integer.toHexString(bytes[i] & 0xFF);
    246             if ((bytes[i] & 0xFF) < 16) {
    247                 sb.append('0');
    248             }
    249
    250             sb.append(code);
    251
    252             if (separator != null && i < bytes.length - 1) {
    253                 sb.append(separator);
    254             }
    255         }
    256
    257         return sb.toString();
    258     }
    259
    260     /**
    261      * Converts a hex string representation to a byte array.
    262      *
    263      * @param hex the string holding the hex values
    264      * @return the resulting byte array
    265      */
    266     public static byte[] asByteArray(String hex) {
    267         byte[] bts = new byte[hex.length() / 2];
    268         for (int i = 0; i < bts.length; i++) {
    269             bts[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);
    270         }
    271
    272         return bts;
    273     }
    274
    275     /**
    276      * Reads an int from 4 bytes of the given array at offset 0.
    277      *
    278      * @param b the byte array to read
    279      * @param offset the offset at which to start
    280      * @return the int value
    281      */
    282     public static final int makeIntFromByte4(byte[] b) {
    283         return makeIntFromByte4(b, 0);
    284     }
    285
    286     /**
    287      * Reads an int from 4 bytes of the given array at the given offset.
    288      *
    289      * @param b the byte array to read
    290      * @param offset the offset at which to start
    291      * @return the int value
    292      */
    293     public static final int makeIntFromByte4(byte[] b, int offset) {
    294         return b[offset] << 24 | (b[offset + 1] & 0xff) << 16 | (b[offset + 2] & 0xff) << 8 | (b[offset + 3] & 0xff);
    295     }
    296
    297     /**
    298      * Reads an int from 2 bytes of the given array at offset 0.
    299      *
    300      * @param b the byte array to read
    301      * @return the int value
    302      */
    303     public static final int makeIntFromByte2(byte[] b) {
    304         return makeIntFromByte2(b, 0);
    305     }
    306
    307     /**
    308      * Reads an int from 2 bytes of the given array at the given offset.
    309      *
    310      * @param b the byte array to read
    311      * @param offset the offset at which to start
    312      * @return the int value
    313      */
    314     public static final int makeIntFromByte2(byte[] b, int offset) {
    315         return (b[offset] & 0xff) << 8 | (b[offset + 1] & 0xff);
    316     }
    317
    318     /**
    319      * Returns true if the flag <code>testFlag</code> is set in the
    320      * <code>flags</code> flagset.
    321      *
    322      * @param flagset the flagset to test
    323      * @param testFlag the flag we search the presence of
    324      * @return true if testFlag is present in the flagset, false otherwise.
    325      */
    326     public final static boolean isFlagSet(int flagSet, int testFlag) {
    327         return (flagSet & testFlag) > 0;
    328     }
    329 }