1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. 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.commons.net.io;
19
20 import java.io.FilterOutputStream;
21 import java.io.IOException;
22 import java.io.OutputStream;
23
24 /***
25 * This class wraps an output stream, replacing all occurrences
26 * of <CR><LF> (carriage return followed by a linefeed),
27 * which is the NETASCII standard for representing a newline, with the
28 * local line separator representation. You would use this class to
29 * implement ASCII file transfers requiring conversion from NETASCII.
30 * <p>
31 * Because of the translation process, a call to <code>flush()</code> will
32 * not flush the last byte written if that byte was a carriage
33 * return. A call to {@link #close close() }, however, will
34 * flush the carriage return.
35 * <p>
36 * <p>
37 * @author Daniel F. Savarese
38 ***/
39
40 public final class FromNetASCIIOutputStream extends FilterOutputStream
41 {
42 private boolean __lastWasCR;
43
44 /***
45 * Creates a FromNetASCIIOutputStream instance that wraps an existing
46 * OutputStream.
47 * <p>
48 * @param output The OutputStream to wrap.
49 ***/
50 public FromNetASCIIOutputStream(OutputStream output)
51 {
52 super(output);
53 __lastWasCR = false;
54 }
55
56
57 private void __write(int ch) throws IOException
58 {
59 switch (ch)
60 {
61 case '\r':
62 __lastWasCR = true;
63 // Don't write anything. We need to see if next one is linefeed
64 break;
65 case '\n':
66 if (__lastWasCR)
67 {
68 out.write(FromNetASCIIInputStream._lineSeparatorBytes);
69 __lastWasCR = false;
70 break;
71 }
72 __lastWasCR = false;
73 out.write('\n');
74 break;
75 default:
76 if (__lastWasCR)
77 {
78 out.write('\r');
79 __lastWasCR = false;
80 }
81 out.write(ch);
82 break;
83 }
84 }
85
86
87 /***
88 * Writes a byte to the stream. Note that a call to this method
89 * might not actually write a byte to the underlying stream until a
90 * subsequent character is written, from which it can be determined if
91 * a NETASCII line separator was encountered.
92 * This is transparent to the programmer and is only mentioned for
93 * completeness.
94 * <p>
95 * @param ch The byte to write.
96 * @exception IOException If an error occurs while writing to the underlying
97 * stream.
98 ***/
99 @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 }