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 the integer value        
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 -&gt; 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 -@gt; 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      * @return the integer value
280      */
281     public static final int makeIntFromByte4(byte[] b) {
282         return makeIntFromByte4(b, 0);
283     }
284 
285     /**
286      * Reads an int from 4 bytes of the given array at the given offset.
287      * 
288      * @param b the byte array to read
289      * @param offset the offset at which to start
290      * @return the int value
291      */
292     public static final int makeIntFromByte4(byte[] b, int offset) {
293         return b[offset] << 24 | (b[offset + 1] & 0xff) << 16 | (b[offset + 2] & 0xff) << 8 | (b[offset + 3] & 0xff);
294     }
295 
296     /**
297      * Reads an int from 2 bytes of the given array at offset 0.
298      * 
299      * @param b the byte array to read
300      * @return the int value     
301      */
302     public static final int makeIntFromByte2(byte[] b) {
303         return makeIntFromByte2(b, 0);
304     }
305 
306     /**
307      * Reads an int from 2 bytes of the given array at the given offset.
308      * 
309      * @param b the byte array to read
310      * @param offset the offset at which to start
311      * @return the int value
312      */
313     public static final int makeIntFromByte2(byte[] b, int offset) {
314         return (b[offset] & 0xff) << 8 | (b[offset + 1] & 0xff);
315     }
316 
317     /**
318      * Returns true if the flag <code>testFlag</code> is set in the
319      * <code>flags</code> flagset.
320      * 
321      * @param flagSet the flagset to test
322      * @param testFlag the flag we search the presence of
323      * @return true if testFlag is present in the flagset, false otherwise.
324      */
325     public final static boolean isFlagSet(int flagSet, int testFlag) {
326         return (flagSet & testFlag) > 0;
327     }
328 }