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.geronimo.mail.util;
21  
22  import java.io.IOException;
23  import java.io.OutputStream;
24  
25  public class HexEncoder
26      implements Encoder
27  {
28      protected final byte[] encodingTable =
29          {
30              (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
31              (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'
32          };
33  
34      /*
35       * set up the decoding table.
36       */
37      protected final byte[] decodingTable = new byte[128];
38  
39      protected void initialiseDecodingTable()
40      {
41          for (int i = 0; i < encodingTable.length; i++)
42          {
43              decodingTable[encodingTable[i]] = (byte)i;
44          }
45  
46          decodingTable['A'] = decodingTable['a'];
47          decodingTable['B'] = decodingTable['b'];
48          decodingTable['C'] = decodingTable['c'];
49          decodingTable['D'] = decodingTable['d'];
50          decodingTable['E'] = decodingTable['e'];
51          decodingTable['F'] = decodingTable['f'];
52      }
53  
54      public HexEncoder()
55      {
56          initialiseDecodingTable();
57      }
58  
59      /**
60       * encode the input data producing a Hex output stream.
61       *
62       * @return the number of bytes produced.
63       */
64      public int encode(
65          byte[]                data,
66          int                    off,
67          int                    length,
68          OutputStream    out)
69          throws IOException
70      {
71          for (int i = off; i < (off + length); i++)
72          {
73              int    v = data[i] & 0xff;
74  
75              out.write(encodingTable[(v >>> 4)]);
76              out.write(encodingTable[v & 0xf]);
77          }
78  
79          return length * 2;
80      }
81  
82      private boolean ignore(
83          char    c)
84      {
85          return (c == '\n' || c =='\r' || c == '\t' || c == ' ');
86      }
87  
88      /**
89       * decode the Hex encoded byte data writing it to the given output stream,
90       * whitespace characters will be ignored.
91       *
92       * @return the number of bytes produced.
93       */
94      public int decode(
95          byte[]                data,
96          int                    off,
97          int                    length,
98          OutputStream    out)
99          throws IOException
100     {
101         byte[]    bytes;
102         byte    b1, b2;
103         int        outLen = 0;
104 
105         int        end = off + length;
106 
107         while (end > 0)
108         {
109             if (!ignore((char)data[end - 1]))
110             {
111                 break;
112             }
113 
114             end--;
115         }
116 
117         int i = off;
118         while (i < end)
119         {
120             while (i < end && ignore((char)data[i]))
121             {
122                 i++;
123             }
124 
125             b1 = decodingTable[data[i++]];
126 
127             while (i < end && ignore((char)data[i]))
128             {
129                 i++;
130             }
131 
132             b2 = decodingTable[data[i++]];
133 
134             out.write((b1 << 4) | b2);
135 
136             outLen++;
137         }
138 
139         return outLen;
140     }
141 
142     /**
143      * decode the Hex encoded String data writing it to the given output stream,
144      * whitespace characters will be ignored.
145      *
146      * @return the number of bytes produced.
147      */
148     public int decode(
149         String                data,
150         OutputStream    out)
151         throws IOException
152     {
153         byte[]    bytes;
154         byte    b1, b2, b3, b4;
155         int        length = 0;
156 
157         int        end = data.length();
158 
159         while (end > 0)
160         {
161             if (!ignore(data.charAt(end - 1)))
162             {
163                 break;
164             }
165 
166             end--;
167         }
168 
169         int i = 0;
170         while (i < end)
171         {
172             while (i < end && ignore(data.charAt(i)))
173             {
174                 i++;
175             }
176 
177             b1 = decodingTable[data.charAt(i++)];
178 
179             while (i < end && ignore(data.charAt(i)))
180             {
181                 i++;
182             }
183 
184             b2 = decodingTable[data.charAt(i++)];
185 
186             out.write((b1 << 4) | b2);
187 
188             length++;
189         }
190 
191         return length;
192     }
193 }