001 /*
002 * Copyright 2001-2005 The Apache Software Foundation
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.apache.commons.net.io;
017
018 import java.io.FilterOutputStream;
019 import java.io.IOException;
020 import java.io.OutputStream;
021
022 /***
023 * This class wraps an output stream, replacing all occurrences
024 * of <CR><LF> (carriage return followed by a linefeed),
025 * which is the NETASCII standard for representing a newline, with the
026 * local line separator representation. You would use this class to
027 * implement ASCII file transfers requiring conversion from NETASCII.
028 * <p>
029 * Because of the translation process, a call to <code>flush()</code> will
030 * not flush the last byte written if that byte was a carriage
031 * return. A call to {@link #close close() }, however, will
032 * flush the carriage return.
033 * <p>
034 * <p>
035 * @author Daniel F. Savarese
036 ***/
037
038 public final class FromNetASCIIOutputStream extends FilterOutputStream
039 {
040 private boolean __lastWasCR;
041
042 /***
043 * Creates a FromNetASCIIOutputStream instance that wraps an existing
044 * OutputStream.
045 * <p>
046 * @param output The OutputStream to wrap.
047 ***/
048 public FromNetASCIIOutputStream(OutputStream output)
049 {
050 super(output);
051 __lastWasCR = false;
052 }
053
054
055 private void __write(int ch) throws IOException
056 {
057 switch (ch)
058 {
059 case '\r':
060 __lastWasCR = true;
061 // Don't write anything. We need to see if next one is linefeed
062 break;
063 case '\n':
064 if (__lastWasCR)
065 {
066 out.write(FromNetASCIIInputStream._lineSeparatorBytes);
067 __lastWasCR = false;
068 break;
069 }
070 __lastWasCR = false;
071 out.write('\n');
072 break;
073 default:
074 if (__lastWasCR)
075 {
076 out.write('\r');
077 __lastWasCR = false;
078 }
079 out.write(ch);
080 break;
081 }
082 }
083
084
085 /***
086 * Writes a byte to the stream. Note that a call to this method
087 * might not actually write a byte to the underlying stream until a
088 * subsequent character is written, from which it can be determined if
089 * a NETASCII line separator was encountered.
090 * This is transparent to the programmer and is only mentioned for
091 * completeness.
092 * <p>
093 * @param ch The byte to write.
094 * @exception IOException If an error occurs while writing to the underlying
095 * stream.
096 ***/
097 public synchronized void write(int ch)
098 throws IOException
099 {
100 if (FromNetASCIIInputStream._noConversionRequired)
101 {
102 out.write(ch);
103 return ;
104 }
105
106 __write(ch);
107 }
108
109
110 /***
111 * Writes a byte array to the stream.
112 * <p>
113 * @param buffer The byte array to write.
114 * @exception IOException If an error occurs while writing to the underlying
115 * stream.
116 ***/
117 public synchronized void write(byte buffer[])
118 throws IOException
119 {
120 write(buffer, 0, buffer.length);
121 }
122
123
124 /***
125 * Writes a number of bytes from a byte array to the stream starting from
126 * a given offset.
127 * <p>
128 * @param buffer The byte array to write.
129 * @param offset The offset into the array at which to start copying data.
130 * @param length The number of bytes to write.
131 * @exception IOException If an error occurs while writing to the underlying
132 * stream.
133 ***/
134 public synchronized void write(byte buffer[], int offset, int length)
135 throws IOException
136 {
137 if (FromNetASCIIInputStream._noConversionRequired)
138 {
139 // FilterOutputStream method is very slow.
140 //super.write(buffer, offset, length);
141 out.write(buffer, offset, length);
142 return ;
143 }
144
145 while (length-- > 0)
146 __write(buffer[offset++]);
147 }
148
149
150 /***
151 * Closes the stream, writing all pending data.
152 * <p>
153 * @exception IOException If an error occurs while closing the stream.
154 ***/
155 public synchronized void close()
156 throws IOException
157 {
158 if (FromNetASCIIInputStream._noConversionRequired)
159 {
160 super.close();
161 return ;
162 }
163
164 if (__lastWasCR)
165 out.write('\r');
166 super.close();
167 }
168 }