View Javadoc

1   /**
2    *
3    * Copyright 2003-2006 The Apache Software Foundation
4    *
5    *  Licensed under the Apache License, Version 2.0 (the "License");
6    *  you may not use this file except in compliance with the License.
7    *  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  
18  package org.apache.geronimo.mail.util;
19  
20  import java.io.IOException;
21  import java.io.OutputStream;
22  
23  public class XTextEncoder
24      implements Encoder
25  {
26      protected final byte[] encodingTable =
27          {
28              (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
29              (byte)'8', (byte)'9', (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F'
30          };
31  
32      /*
33       * set up the decoding table.
34       */
35      protected final byte[] decodingTable = new byte[128];
36  
37      protected void initialiseDecodingTable()
38      {
39          for (int i = 0; i < encodingTable.length; i++)
40          {
41              decodingTable[encodingTable[i]] = (byte)i;
42          }
43      }
44  
45      public XTextEncoder()
46      {
47          initialiseDecodingTable();
48      }
49  
50      /**
51       * encode the input data producing an XText output stream.
52       *
53       * @return the number of bytes produced.
54       */
55      public int encode(
56          byte[]                data,
57          int                    off,
58          int                    length,
59          OutputStream    out)
60          throws IOException
61      {
62          int bytesWritten = 0;
63  
64          for (int i = off; i < (off + length); i++)
65          {
66              int    v = data[i] & 0xff;
67              // character tha must be encoded?  Prefix with a '+' and encode in hex.
68              if (v < 33 || v > 126 || v == '+' || v == '+') {
69                  out.write((byte)'+');
70                  out.write(encodingTable[(v >>> 4)]);
71                  out.write(encodingTable[v & 0xf]);
72                  bytesWritten += 3;
73              }
74              else {
75                  // add unchanged.
76                  out.write((byte)v);
77                  bytesWritten++;
78              }
79          }
80  
81          return bytesWritten;
82      }
83  
84  
85      /**
86       * decode the xtext encoded byte data writing it to the given output stream
87       *
88       * @return the number of bytes produced.
89       */
90      public int decode(
91          byte[]                data,
92          int                    off,
93          int                    length,
94          OutputStream    out)
95          throws IOException
96      {
97          byte[]    bytes;
98          byte    b1, b2;
99          int        outLen = 0;
100 
101         int        end = off + length;
102 
103         int i = off;
104         while (i < end)
105         {
106             byte v = data[i++];
107             // a plus is a hex character marker, need to decode a hex value.
108             if (v == '+') {
109                 b1 = decodingTable[data[i++]];
110                 b2 = decodingTable[data[i++]];
111                 out.write((b1 << 4) | b2);
112             }
113             else {
114                 // copied over unchanged.
115                 out.write(v);
116             }
117             // always just one byte added
118             outLen++;
119         }
120 
121         return outLen;
122     }
123 
124     /**
125      * decode the xtext encoded String data writing it to the given output stream.
126      *
127      * @return the number of bytes produced.
128      */
129     public int decode(
130         String                data,
131         OutputStream    out)
132         throws IOException
133     {
134         byte[]    bytes;
135         byte    b1, b2, b3, b4;
136         int        length = 0;
137 
138         int        end = data.length();
139 
140         int i = 0;
141         while (i < end)
142         {
143             char v = data.charAt(i++);
144             if (v == '+') {
145                 b1 = decodingTable[data.charAt(i++)];
146                 b2 = decodingTable[data.charAt(i++)];
147 
148                 out.write((b1 << 4) | b2);
149             }
150             else {
151                 out.write((byte)v);
152             }
153             length++;
154         }
155 
156         return length;
157     }
158 }
159