/* | |
* Licensed to the Apache Software Foundation (ASF) under one or more | |
* contributor license agreements. See the NOTICE file distributed with | |
* this work for additional information regarding copyright ownership. | |
* The ASF licenses this file to you under the Apache License, Version 2.0 | |
* (the "License"); you may not use this file except in compliance with | |
* the License. You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package org.apache.myfaces.test.mock; | |
import java.io.UnsupportedEncodingException; | |
/** | |
* Hex encoder and decoder. The charset used for certain operation can be set, the default is set in | |
* {@link #DEFAULT_CHARSET_NAME} | |
* | |
* @since 1.0.0 | |
* @author Apache Software Foundation | |
* @version $Id: Hex.java 801639 2009-08-06 13:15:10Z niallp $ | |
*/ | |
class _Hex | |
{ | |
/** | |
* Default charset name is {@link CharEncoding#UTF_8} | |
*/ | |
public static final String DEFAULT_CHARSET_NAME = "UTF-8"; | |
/** | |
* Used to build output as Hex | |
*/ | |
private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5', | |
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; | |
/** | |
* Used to build output as Hex | |
*/ | |
private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', | |
'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; | |
/** | |
* Converts an array of characters representing hexadecimal values into an array of bytes of those same values. The | |
* returned array will be half the length of the passed array, as it takes two characters to represent any given | |
* byte. An exception is thrown if the passed char array has an odd number of elements. | |
* | |
* @param data | |
* An array of characters containing hexadecimal digits | |
* @return A byte array containing binary data decoded from the supplied char array. | |
* @throws DecoderException | |
* Thrown if an odd number or illegal of characters is supplied | |
*/ | |
public static byte[] decodeHex(char[] data) throws Exception | |
{ | |
int len = data.length; | |
if ((len & 0x01) != 0) | |
{ | |
throw new Exception("Odd number of characters."); | |
} | |
byte[] out = new byte[len >> 1]; | |
// two characters form the hex value. | |
for (int i = 0, j = 0; j < len; i++) | |
{ | |
int f = toDigit(data[j], j) << 4; | |
j++; | |
f = f | toDigit(data[j], j); | |
j++; | |
out[i] = (byte) (f & 0xFF); | |
} | |
return out; | |
} | |
/** | |
* Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order. | |
* The returned array will be double the length of the passed array, as it takes two characters to represent any | |
* given byte. | |
* | |
* @param data | |
* a byte[] to convert to Hex characters | |
* @return A char[] containing hexadecimal characters | |
*/ | |
public static char[] encodeHex(byte[] data) | |
{ | |
return encodeHex(data, true); | |
} | |
/** | |
* Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order. | |
* The returned array will be double the length of the passed array, as it takes two characters to represent any | |
* given byte. | |
* | |
* @param data | |
* a byte[] to convert to Hex characters | |
* @param toLowerCase | |
* <code>true</code> converts to lowercase, <code>false</code> to uppercase | |
* @return A char[] containing hexadecimal characters | |
*/ | |
public static char[] encodeHex(byte[] data, boolean toLowerCase) | |
{ | |
return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); | |
} | |
/** | |
* Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order. | |
* The returned array will be double the length of the passed array, as it takes two characters to represent any | |
* given byte. | |
* | |
* @param data | |
* a byte[] to convert to Hex characters | |
* @param toDigits | |
* the output alphabet | |
* @return A char[] containing hexadecimal characters | |
*/ | |
protected static char[] encodeHex(byte[] data, char[] toDigits) | |
{ | |
int l = data.length; | |
char[] out = new char[l << 1]; | |
// two characters form the hex value. | |
for (int i = 0, j = 0; i < l; i++) | |
{ | |
out[j++] = toDigits[(0xF0 & data[i]) >>> 4]; | |
out[j++] = toDigits[0x0F & data[i]]; | |
} | |
return out; | |
} | |
/** | |
* Converts an array of bytes into a String representing the hexadecimal values of each byte in order. The returned | |
* String will be double the length of the passed array, as it takes two characters to represent any given byte. | |
* | |
* @param data | |
* a byte[] to convert to Hex characters | |
* @return A String containing hexadecimal characters | |
*/ | |
public static String encodeHexString(byte[] data) | |
{ | |
return new String(encodeHex(data)); | |
} | |
/** | |
* Converts a hexadecimal character to an integer. | |
* | |
* @param ch | |
* A character to convert to an integer digit | |
* @param index | |
* The index of the character in the source | |
* @return An integer | |
* @throws DecoderException | |
* Thrown if ch is an illegal hex character | |
*/ | |
protected static int toDigit(char ch, int index) throws Exception | |
{ | |
int digit = Character.digit(ch, 16); | |
if (digit == -1) | |
{ | |
throw new Exception("Illegal hexadecimal charcter " + ch | |
+ " at index " + index); | |
} | |
return digit; | |
} | |
private final String charsetName; | |
/** | |
* Creates a new codec with the default charset name {@link #DEFAULT_CHARSET_NAME} | |
*/ | |
public _Hex() | |
{ | |
// use default encoding | |
this.charsetName = DEFAULT_CHARSET_NAME; | |
} | |
/** | |
* Creates a new codec with the given charset name. | |
* | |
* @param csName | |
* the charset name. | |
*/ | |
public _Hex(String csName) | |
{ | |
this.charsetName = csName; | |
} | |
/** | |
* Converts an array of character bytes representing hexadecimal values into an array of bytes of those same values. | |
* The returned array will be half the length of the passed array, as it takes two characters to represent any given | |
* byte. An exception is thrown if the passed char array has an odd number of elements. | |
* | |
* @param array | |
* An array of character bytes containing hexadecimal digits | |
* @return A byte array containing binary data decoded from the supplied byte array (representing characters). | |
* @throws DecoderException | |
* Thrown if an odd number of characters is supplied to this function | |
* @see #decodeHex(char[]) | |
*/ | |
public byte[] decode(byte[] array) throws Exception | |
{ | |
try | |
{ | |
return decodeHex(new String(array, getCharsetName()).toCharArray()); | |
} | |
catch (UnsupportedEncodingException e) | |
{ | |
throw new Exception(e.getMessage(), e); | |
} | |
} | |
/** | |
* Converts a String or an array of character bytes representing hexadecimal values into an array of bytes of those | |
* same values. The returned array will be half the length of the passed String or array, as it takes two characters | |
* to represent any given byte. An exception is thrown if the passed char array has an odd number of elements. | |
* | |
* @param object | |
* A String or, an array of character bytes containing hexadecimal digits | |
* @return A byte array containing binary data decoded from the supplied byte array (representing characters). | |
* @throws DecoderException | |
* Thrown if an odd number of characters is supplied to this function or the object is not a String or | |
* char[] | |
* @see #decodeHex(char[]) | |
*/ | |
public Object decode(Object object) throws Exception | |
{ | |
try | |
{ | |
char[] charArray = object instanceof String ? ((String) object) | |
.toCharArray() : (char[]) object; | |
return decodeHex(charArray); | |
} | |
catch (ClassCastException e) | |
{ | |
throw new Exception(e.getMessage(), e); | |
} | |
} | |
/** | |
* Converts an array of bytes into an array of bytes for the characters representing the hexadecimal values of each | |
* byte in order. The returned array will be double the length of the passed array, as it takes two characters to | |
* represent any given byte. | |
* <p> | |
* The conversion from hexadecimal characters to the returned bytes is performed with the charset named by | |
* {@link #getCharsetName()}. | |
* </p> | |
* | |
* @param array | |
* a byte[] to convert to Hex characters | |
* @return A byte[] containing the bytes of the hexadecimal characters | |
* @throws IllegalStateException | |
* if the charsetName is invalid. This API throws {@link IllegalStateException} instead of | |
* {@link UnsupportedEncodingException} for backward compatibility. | |
* @see #encodeHex(byte[]) | |
*/ | |
public byte[] encode(byte[] array) | |
{ | |
return getBytesUnchecked(encodeHexString(array), getCharsetName()); | |
} | |
private static byte[] getBytesUnchecked(String string, String charsetName) | |
{ | |
if (string == null) | |
{ | |
return null; | |
} | |
try | |
{ | |
return string.getBytes(charsetName); | |
} | |
catch (UnsupportedEncodingException e) | |
{ | |
throw new IllegalStateException(charsetName, e); | |
} | |
} | |
/** | |
* Converts a String or an array of bytes into an array of characters representing the hexadecimal values of each | |
* byte in order. The returned array will be double the length of the passed String or array, as it takes two | |
* characters to represent any given byte. | |
* <p> | |
* The conversion from hexadecimal characters to bytes to be encoded to performed with the charset named by | |
* {@link #getCharsetName()}. | |
* </p> | |
* | |
* @param object | |
* a String, or byte[] to convert to Hex characters | |
* @return A char[] containing hexadecimal characters | |
* @throws EncoderException | |
* Thrown if the given object is not a String or byte[] | |
* @see #encodeHex(byte[]) | |
*/ | |
public Object encode(Object object) throws Exception | |
{ | |
try | |
{ | |
byte[] byteArray = object instanceof String ? ((String) object) | |
.getBytes(getCharsetName()) : (byte[]) object; | |
return encodeHex(byteArray); | |
} | |
catch (ClassCastException e) | |
{ | |
throw new Exception(e.getMessage(), e); | |
} | |
catch (UnsupportedEncodingException e) | |
{ | |
throw new Exception(e.getMessage(), e); | |
} | |
} | |
/** | |
* Gets the charset name. | |
* | |
* @return the charset name. | |
*/ | |
public String getCharsetName() | |
{ | |
return this.charsetName; | |
} | |
/** | |
* Returns a string representation of the object, which includes the charset name. | |
* | |
* @return a string representation of the object. | |
*/ | |
public String toString() | |
{ | |
return super.toString() + "[charsetName=" + this.charsetName + "]"; | |
} | |
} |