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