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.commons.net.io;
019
020 import java.io.FilterOutputStream;
021 import java.io.IOException;
022 import java.io.OutputStream;
023
024 /***
025 * This class wraps an output stream, replacing all occurrences
026 * of <CR><LF> (carriage return followed by a linefeed),
027 * which is the NETASCII standard for representing a newline, with the
028 * local line separator representation. You would use this class to
029 * implement ASCII file transfers requiring conversion from NETASCII.
030 * <p>
031 * Because of the translation process, a call to <code>flush()</code> will
032 * not flush the last byte written if that byte was a carriage
033 * return. A call to {@link #close close() }, however, will
034 * flush the carriage return.
035 * <p>
036 * <p>
037 * @author Daniel F. Savarese
038 ***/
039
040 public final class FromNetASCIIOutputStream extends FilterOutputStream
041 {
042 private boolean __lastWasCR;
043
044 /***
045 * Creates a FromNetASCIIOutputStream instance that wraps an existing
046 * OutputStream.
047 * <p>
048 * @param output The OutputStream to wrap.
049 ***/
050 public FromNetASCIIOutputStream(OutputStream output)
051 {
052 super(output);
053 __lastWasCR = false;
054 }
055
056
057 private void __write(int ch) throws IOException
058 {
059 switch (ch)
060 {
061 case '\r':
062 __lastWasCR = true;
063 // Don't write anything. We need to see if next one is linefeed
064 break;
065 case '\n':
066 if (__lastWasCR)
067 {
068 out.write(FromNetASCIIInputStream._lineSeparatorBytes);
069 __lastWasCR = false;
070 break;
071 }
072 __lastWasCR = false;
073 out.write('\n');
074 break;
075 default:
076 if (__lastWasCR)
077 {
078 out.write('\r');
079 __lastWasCR = false;
080 }
081 out.write(ch);
082 break;
083 }
084 }
085
086
087 /***
088 * Writes a byte to the stream. Note that a call to this method
089 * might not actually write a byte to the underlying stream until a
090 * subsequent character is written, from which it can be determined if
091 * a NETASCII line separator was encountered.
092 * This is transparent to the programmer and is only mentioned for
093 * completeness.
094 * <p>
095 * @param ch The byte to write.
096 * @exception IOException If an error occurs while writing to the underlying
097 * stream.
098 ***/
099 @Override
100 public synchronized void write(int ch)
101 throws IOException
102 {
103 if (FromNetASCIIInputStream._noConversionRequired)
104 {
105 out.write(ch);
106 return ;
107 }
108
109 __write(ch);
110 }
111
112
113 /***
114 * Writes a byte array to the stream.
115 * <p>
116 * @param buffer The byte array to write.
117 * @exception IOException If an error occurs while writing to the underlying
118 * stream.
119 ***/
120 @Override
121 public synchronized void write(byte buffer[])
122 throws IOException
123 {
124 write(buffer, 0, buffer.length);
125 }
126
127
128 /***
129 * Writes a number of bytes from a byte array to the stream starting from
130 * a given offset.
131 * <p>
132 * @param buffer The byte array to write.
133 * @param offset The offset into the array at which to start copying data.
134 * @param length The number of bytes to write.
135 * @exception IOException If an error occurs while writing to the underlying
136 * stream.
137 ***/
138 @Override
139 public synchronized void write(byte buffer[], int offset, int length)
140 throws IOException
141 {
142 if (FromNetASCIIInputStream._noConversionRequired)
143 {
144 // FilterOutputStream method is very slow.
145 //super.write(buffer, offset, length);
146 out.write(buffer, offset, length);
147 return ;
148 }
149
150 while (length-- > 0)
151 __write(buffer[offset++]);
152 }
153
154
155 /***
156 * Closes the stream, writing all pending data.
157 * <p>
158 * @exception IOException If an error occurs while closing the stream.
159 ***/
160 @Override
161 public synchronized void close()
162 throws IOException
163 {
164 if (FromNetASCIIInputStream._noConversionRequired)
165 {
166 super.close();
167 return ;
168 }
169
170 if (__lastWasCR)
171 out.write('\r');
172 super.close();
173 }
174 }