View Javadoc

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   ***/
38  
39  public final class FromNetASCIIOutputStream extends FilterOutputStream
40  {
41      private boolean __lastWasCR;
42  
43      /***
44       * Creates a FromNetASCIIOutputStream instance that wraps an existing
45       * OutputStream.
46       * <p>
47       * @param output  The OutputStream to wrap.
48       ***/
49      public FromNetASCIIOutputStream(OutputStream output)
50      {
51          super(output);
52          __lastWasCR = false;
53      }
54  
55  
56      private void __write(int ch) throws IOException
57      {
58          switch (ch)
59          {
60          case '\r':
61              __lastWasCR = true;
62              // Don't write anything.  We need to see if next one is linefeed
63              break;
64          case '\n':
65              if (__lastWasCR)
66              {
67                  out.write(FromNetASCIIInputStream._lineSeparatorBytes);
68                  __lastWasCR = false;
69                  break;
70              }
71              __lastWasCR = false;
72              out.write('\n');
73              break;
74          default:
75              if (__lastWasCR)
76              {
77                  out.write('\r');
78                  __lastWasCR = false;
79              }
80              out.write(ch);
81              break;
82          }
83      }
84  
85  
86      /***
87       * Writes a byte to the stream.    Note that a call to this method
88       * might not actually write a byte to the underlying stream until a
89       * subsequent character is written, from which it can be determined if
90       * a NETASCII line separator was encountered.
91       * This is transparent to the programmer and is only mentioned for
92       * completeness.
93       * <p>
94       * @param ch The byte to write.
95       * @exception IOException If an error occurs while writing to the underlying
96       *            stream.
97       ***/
98      @Override
99      public synchronized void write(int ch)
100     throws IOException
101     {
102         if (FromNetASCIIInputStream._noConversionRequired)
103         {
104             out.write(ch);
105             return ;
106         }
107 
108         __write(ch);
109     }
110 
111 
112     /***
113      * Writes a byte array to the stream.
114      * <p>
115      * @param buffer  The byte array to write.
116      * @exception IOException If an error occurs while writing to the underlying
117      *            stream.
118      ***/
119     @Override
120     public synchronized void write(byte buffer[])
121     throws IOException
122     {
123         write(buffer, 0, buffer.length);
124     }
125 
126 
127     /***
128      * Writes a number of bytes from a byte array to the stream starting from
129      * a given offset.
130      * <p>
131      * @param buffer  The byte array to write.
132      * @param offset  The offset into the array at which to start copying data.
133      * @param length  The number of bytes to write.
134      * @exception IOException If an error occurs while writing to the underlying
135      *            stream.
136      ***/
137     @Override
138     public synchronized void write(byte buffer[], int offset, int length)
139     throws IOException
140     {
141         if (FromNetASCIIInputStream._noConversionRequired)
142         {
143             // FilterOutputStream method is very slow.
144             //super.write(buffer, offset, length);
145             out.write(buffer, offset, length);
146             return ;
147         }
148 
149         while (length-- > 0) {
150             __write(buffer[offset++]);
151         }
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         }
173         super.close();
174     }
175 }