Clover coverage report - Maven Clover report
Coverage timestamp: Sun Aug 20 2006 04:01:04 PDT
file stats: LOC: 241   Methods: 6
NCLOC: 113   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
UUEncoder.java 72.7% 91.9% 83.3% 87.3%
coverage coverage
 1    /**
 2    *
 3    * Copyright 2003-2004 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    import java.io.UnsupportedEncodingException;
 23   
 24    public class UUEncoder implements Encoder {
 25   
 26    // this is the maximum number of chars allowed per line, since we have to include a uuencoded length at
 27    // the start of each line.
 28    static private final int MAX_CHARS_PER_LINE = 45;
 29   
 30   
 31  10 public UUEncoder()
 32    {
 33    }
 34   
 35    /**
 36    * encode the input data producing a UUEncoded output stream.
 37    *
 38    * @param data The array of byte data.
 39    * @param off The starting offset within the data.
 40    * @param length Length of the data to encode.
 41    * @param out The output stream the encoded data is written to.
 42    *
 43    * @return the number of bytes produced.
 44    */
 45  15 public int encode(byte[] data, int off, int length, OutputStream out) throws IOException
 46    {
 47  15 int byteCount = 0;
 48   
 49  15 while (true) {
 50    // keep writing complete lines until we've exhausted the data.
 51  30 if (length > MAX_CHARS_PER_LINE) {
 52    // encode another line and adjust the length and position
 53  15 byteCount += encodeLine(data, off, MAX_CHARS_PER_LINE, out);
 54  15 length -= MAX_CHARS_PER_LINE;
 55  15 off += MAX_CHARS_PER_LINE;
 56    }
 57    else {
 58    // last line. Encode the partial and quit
 59  15 byteCount += encodeLine(data, off, MAX_CHARS_PER_LINE, out);
 60  15 break;
 61    }
 62    }
 63  15 return byteCount;
 64    }
 65   
 66   
 67    /**
 68    * Encode a single line of data (less than or equal to 45 characters).
 69    *
 70    * @param data The array of byte data.
 71    * @param off The starting offset within the data.
 72    * @param length Length of the data to encode.
 73    * @param out The output stream the encoded data is written to.
 74    *
 75    * @return The number of bytes written to the output stream.
 76    * @exception IOException
 77    */
 78  30 private int encodeLine(byte[] data, int offset, int length, OutputStream out) throws IOException {
 79    // write out the number of characters encoded in this line.
 80  30 out.write((byte)((length & 0x3F) + ' '));
 81  30 byte a;
 82  30 byte b;
 83  30 byte c;
 84   
 85    // count the bytes written...we add 2, one for the length and 1 for the linend terminator.
 86  30 int bytesWritten = 2;
 87   
 88  30 for (int i = 0; i < length;) {
 89    // set the padding defauls
 90  450 b = 1;
 91  450 c = 1;
 92    // get the next 3 bytes (if we have them)
 93  450 a = data[offset + i++];
 94  450 if (i < length) {
 95  450 b = data[offset + i++];
 96  450 if (i < length) {
 97  450 c = data[offset + i++];
 98    }
 99    }
 100   
 101  450 byte d1 = (byte)(((a >>> 2) & 0x3F) + ' ');
 102  450 byte d2 = (byte)(((( a << 4) & 0x30) | ((b >>> 4) & 0x0F)) + ' ');
 103  450 byte d3 = (byte)((((b << 2) & 0x3C) | ((c >>> 6) & 0x3)) + ' ');
 104  450 byte d4 = (byte)((c & 0x3F) + ' ');
 105   
 106  450 out.write(d1);
 107  450 out.write(d2);
 108  450 out.write(d3);
 109  450 out.write(d4);
 110   
 111  450 bytesWritten += 4;
 112    }
 113   
 114    // terminate with a linefeed alone
 115  30 out.write('\n');
 116   
 117  30 return bytesWritten;
 118    }
 119   
 120   
 121    /**
 122    * decode the uuencoded byte data writing it to the given output stream
 123    *
 124    * @param data The array of byte data to decode.
 125    * @param off Starting offset within the array.
 126    * @param length The length of data to encode.
 127    * @param out The output stream used to return the decoded data.
 128    *
 129    * @return the number of bytes produced.
 130    * @exception IOException
 131    */
 132  30 public int decode(byte[] data, int off, int length, OutputStream out) throws IOException
 133    {
 134  30 int bytesWritten = 0;
 135   
 136  30 while (length > 0) {
 137  30 int lineOffset = off;
 138   
 139    // scan forward looking for a EOL terminator for the next line of data.
 140  30 while (length > 0 && data[off] != '\n') {
 141  1830 off++;
 142  1830 length--;
 143    }
 144   
 145    // go decode this line of data
 146  30 bytesWritten += decodeLine(data, lineOffset, off - lineOffset, out);
 147   
 148    // the offset was left pointing at the EOL character, so step over that one before
 149    // scanning again.
 150  30 off++;
 151  30 length--;
 152    }
 153  30 return bytesWritten;
 154    }
 155   
 156   
 157    /**
 158    * decode a single line of uuencoded byte data writing it to the given output stream
 159    *
 160    * @param data The array of byte data to decode.
 161    * @param off Starting offset within the array.
 162    * @param length The length of data to decode (length does NOT include the terminating new line).
 163    * @param out The output stream used to return the decoded data.
 164    *
 165    * @return the number of bytes produced.
 166    * @exception IOException
 167    */
 168  30 private int decodeLine(byte[] data, int off, int length, OutputStream out) throws IOException {
 169  30 int count = data[off++];
 170   
 171    // obtain and validate the count
 172  30 if (count < ' ') {
 173  0 throw new IOException("Invalid UUEncode line length");
 174    }
 175   
 176  30 count = (count - ' ') & 0x3F;
 177   
 178    // get the rounded count of characters that should have been used to encode this. The + 1 is for the
 179    // length encoded at the beginning
 180  30 int requiredLength = (((count * 8) + 5) / 6) + 1;
 181  30 if (length < requiredLength) {
 182  0 throw new IOException("UUEncoded data and length do not match");
 183    }
 184   
 185  30 int bytesWritten = 0;
 186    // now decode the bytes.
 187  30 while (bytesWritten < count) {
 188    // even one byte of data requires two bytes to encode, so we should have that.
 189  450 byte a = (byte)((data[off++] - ' ') & 0x3F);
 190  450 byte b = (byte)((data[off++] - ' ') & 0x3F);
 191  450 byte c = 0;
 192  450 byte d = 0;
 193   
 194    // do the first byte
 195  450 byte first = (byte)(((a << 2) & 0xFC) | ((b >>> 4) & 3));
 196  450 out.write(first);
 197  450 bytesWritten++;
 198   
 199    // still have more bytes to decode? do the second byte of the second. That requires
 200    // a third byte from the data.
 201  450 if (bytesWritten < count) {
 202  450 c = (byte)((data[off++] - ' ') & 0x3F);
 203  450 byte second = (byte)(((b << 4) & 0xF0) | ((c >>> 2) & 0x0F));
 204  450 out.write(second);
 205  450 bytesWritten++;
 206   
 207    // need the third one?
 208  450 if (bytesWritten < count) {
 209  450 d = (byte)((data[off++] - ' ') & 0x3F);
 210  450 byte third = (byte)(((c << 6) & 0xC0) | (d & 0x3F));
 211  450 out.write(third);
 212  450 bytesWritten++;
 213    }
 214    }
 215    }
 216  30 return bytesWritten;
 217    }
 218   
 219   
 220    /**
 221    * decode the UUEncoded String data writing it to the given output stream.
 222    *
 223    * @param data The String data to decode.
 224    * @param out The output stream to write the decoded data to.
 225    *
 226    * @return the number of bytes produced.
 227    * @exception IOException
 228    */
 229  0 public int decode(String data, OutputStream out) throws IOException
 230    {
 231  0 try {
 232    // just get the byte data and decode.
 233  0 byte[] bytes = data.getBytes("US-ASCII");
 234  0 return decode(bytes, 0, bytes.length, out);
 235    } catch (UnsupportedEncodingException e) {
 236  0 throw new IOException("Invalid UUEncoding");
 237    }
 238    }
 239    }
 240   
 241