001 /** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one or more 004 * contributor license agreements. See the NOTICE file distributed with 005 * this work for additional information regarding copyright ownership. 006 * The ASF licenses this file to You under the Apache License, Version 2.0 007 * (the "License"); you may not use this file except in compliance with 008 * the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019 package org.apache.geronimo.util.encoders; 020 021 import java.io.IOException; 022 import java.io.OutputStream; 023 024 public class HexEncoder 025 implements Encoder 026 { 027 protected final byte[] encodingTable = 028 { 029 (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', 030 (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f' 031 }; 032 033 /* 034 * set up the decoding table. 035 */ 036 protected final byte[] decodingTable = new byte[128]; 037 038 protected void initialiseDecodingTable() 039 { 040 for (int i = 0; i < encodingTable.length; i++) 041 { 042 decodingTable[encodingTable[i]] = (byte)i; 043 } 044 045 decodingTable['A'] = decodingTable['a']; 046 decodingTable['B'] = decodingTable['b']; 047 decodingTable['C'] = decodingTable['c']; 048 decodingTable['D'] = decodingTable['d']; 049 decodingTable['E'] = decodingTable['e']; 050 decodingTable['F'] = decodingTable['f']; 051 } 052 053 public HexEncoder() 054 { 055 initialiseDecodingTable(); 056 } 057 058 /** 059 * encode the input data producing a Hex output stream. 060 * 061 * @return the number of bytes produced. 062 */ 063 public int encode( 064 byte[] data, 065 int off, 066 int length, 067 OutputStream out) 068 throws IOException 069 { 070 for (int i = off; i < (off + length); i++) 071 { 072 int v = data[i] & 0xff; 073 074 out.write(encodingTable[(v >>> 4)]); 075 out.write(encodingTable[v & 0xf]); 076 } 077 078 return length * 2; 079 } 080 081 private boolean ignore( 082 char c) 083 { 084 return (c == '\n' || c =='\r' || c == '\t' || c == ' '); 085 } 086 087 /** 088 * decode the Hex encoded byte data writing it to the given output stream, 089 * whitespace characters will be ignored. 090 * 091 * @return the number of bytes produced. 092 */ 093 public int decode( 094 byte[] data, 095 int off, 096 int length, 097 OutputStream out) 098 throws IOException 099 { 100 byte[] bytes; 101 byte b1, b2; 102 int outLen = 0; 103 104 int end = off + length; 105 106 while (end > 0) 107 { 108 if (!ignore((char)data[end - 1])) 109 { 110 break; 111 } 112 113 end--; 114 } 115 116 int i = off; 117 while (i < end) 118 { 119 while (i < end && ignore((char)data[i])) 120 { 121 i++; 122 } 123 124 b1 = decodingTable[data[i++]]; 125 126 while (i < end && ignore((char)data[i])) 127 { 128 i++; 129 } 130 131 b2 = decodingTable[data[i++]]; 132 133 out.write((b1 << 4) | b2); 134 135 outLen++; 136 } 137 138 return outLen; 139 } 140 141 /** 142 * decode the Hex encoded String data writing it to the given output stream, 143 * whitespace characters will be ignored. 144 * 145 * @return the number of bytes produced. 146 */ 147 public int decode( 148 String data, 149 OutputStream out) 150 throws IOException 151 { 152 byte[] bytes; 153 byte b1, b2, b3, b4; 154 int length = 0; 155 156 int end = data.length(); 157 158 while (end > 0) 159 { 160 if (!ignore(data.charAt(end - 1))) 161 { 162 break; 163 } 164 165 end--; 166 } 167 168 int i = 0; 169 while (i < end) 170 { 171 while (i < end && ignore(data.charAt(i))) 172 { 173 i++; 174 } 175 176 b1 = decodingTable[data.charAt(i++)]; 177 178 while (i < end && ignore(data.charAt(i))) 179 { 180 i++; 181 } 182 183 b2 = decodingTable[data.charAt(i++)]; 184 185 out.write((b1 << 4) | b2); 186 187 length++; 188 } 189 190 return length; 191 } 192 }