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.tools.ant.util;
019:
020: import java.io.InputStream;
021: import java.io.IOException;
022: import java.io.OutputStream;
023: import java.io.PrintStream;
024:
025: /**
026: * UUEncoding of an input stream placed into an outputstream.
027: * This class is meant to be a drop in replacement for
028: * sun.misc.UUEncoder, which was previously used by Ant.
029: * The uuencode algorithm code has been copied from the
030: * geronimo project.
031: **/
032:
033: public class UUEncoder {
034: protected static final int DEFAULT_MODE = 644;
035: private static final int MAX_CHARS_PER_LINE = 45;
036: private OutputStream out;
037: private String name;
038:
039: /**
040: * Constructor specifing a name for the encoded buffer, begin
041: * line will be:
042: * <pre>
043: * begin 644 [NAME]
044: * </pre>
045: * @param name the name of the encoded buffer.
046: */
047: public UUEncoder(String name) {
048: this .name = name;
049: }
050:
051: /**
052: * UUEncode bytes from the input stream, and write them as text characters
053: * to the output stream. This method will run until it exhausts the
054: * input stream.
055: * @param is the input stream.
056: * @param out the output stream.
057: * @throws IOException if there is an error.
058: */
059: public void encode(InputStream is, OutputStream out)
060: throws IOException {
061: this .out = out;
062: encodeBegin();
063: byte[] buffer = new byte[MAX_CHARS_PER_LINE * 100];
064: int count;
065: while ((count = is.read(buffer, 0, buffer.length)) != -1) {
066: int pos = 0;
067: while (count > 0) {
068: int num = count > MAX_CHARS_PER_LINE ? MAX_CHARS_PER_LINE
069: : count;
070: encodeLine(buffer, pos, num, out);
071: pos += num;
072: count -= num;
073: }
074: }
075: out.flush();
076: encodeEnd();
077: }
078:
079: /**
080: * Encode a string to the output.
081: */
082: private void encodeString(String n) throws IOException {
083: PrintStream writer = new PrintStream(out);
084: writer.print(n);
085: writer.flush();
086: }
087:
088: private void encodeBegin() throws IOException {
089: encodeString("begin " + DEFAULT_MODE + " " + name + "\n");
090: }
091:
092: private void encodeEnd() throws IOException {
093: encodeString(" \nend\n");
094: }
095:
096: /**
097: * Encode a single line of data (less than or equal to 45 characters).
098: *
099: * @param data The array of byte data.
100: * @param off The starting offset within the data.
101: * @param length Length of the data to encode.
102: * @param out The output stream the encoded data is written to.
103: *
104: * @exception IOException
105: */
106: private void encodeLine(byte[] data, int offset, int length,
107: OutputStream out) throws IOException {
108: // write out the number of characters encoded in this line.
109: out.write((byte) ((length & 0x3F) + ' '));
110: byte a;
111: byte b;
112: byte c;
113:
114: for (int i = 0; i < length;) {
115: // set the padding defaults
116: b = 1;
117: c = 1;
118: // get the next 3 bytes (if we have them)
119: a = data[offset + i++];
120: if (i < length) {
121: b = data[offset + i++];
122: if (i < length) {
123: c = data[offset + i++];
124: }
125: }
126:
127: byte d1 = (byte) (((a >>> 2) & 0x3F) + ' ');
128: byte d2 = (byte) ((((a << 4) & 0x30) | ((b >>> 4) & 0x0F)) + ' ');
129: byte d3 = (byte) ((((b << 2) & 0x3C) | ((c >>> 6) & 0x3)) + ' ');
130: byte d4 = (byte) ((c & 0x3F) + ' ');
131:
132: out.write(d1);
133: out.write(d2);
134: out.write(d3);
135: out.write(d4);
136: }
137:
138: // terminate with a linefeed alone
139: out.write('\n');
140: }
141: }
|