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
018package org.apache.commons.net.io;
019
020import java.io.FilterOutputStream;
021import java.io.IOException;
022import java.io.OutputStream;
023
024/***
025 * This class wraps an output stream, replacing all singly occurring
026 * <LF> (linefeed) characters with <CR><LF> (carriage return
027 * followed by linefeed), which is the NETASCII standard for representing
028 * a newline.
029 * You would use this class to implement ASCII file transfers requiring
030 * conversion to NETASCII.
031 *
032 *
033 ***/
034
035public final class ToNetASCIIOutputStream extends FilterOutputStream
036{
037    private boolean __lastWasCR;
038
039    /***
040     * Creates a ToNetASCIIOutputStream instance that wraps an existing
041     * OutputStream.
042     *
043     * @param output  The OutputStream to wrap.
044     ***/
045    public ToNetASCIIOutputStream(OutputStream output)
046    {
047        super(output);
048        __lastWasCR = false;
049    }
050
051
052    /***
053     * Writes a byte to the stream.    Note that a call to this method
054     * may result in multiple writes to the underlying input stream in order
055     * to convert naked newlines to NETASCII line separators.
056     * This is transparent to the programmer and is only mentioned for
057     * completeness.
058     *
059     * @param ch The byte to write.
060     * @throws IOException If an error occurs while writing to the underlying
061     *            stream.
062     ***/
063    @Override
064    public synchronized void write(int ch)
065    throws IOException
066    {
067        switch (ch)
068        {
069        case '\r':
070            __lastWasCR = true;
071            out.write('\r');
072            return ;
073        case '\n':
074            if (!__lastWasCR) {
075                out.write('\r');
076            }
077            //$FALL-THROUGH$
078        default:
079            __lastWasCR = false;
080            out.write(ch);
081            return ;
082        }
083    }
084
085
086    /***
087     * Writes a byte array to the stream.
088     *
089     * @param buffer  The byte array to write.
090     * @throws IOException If an error occurs while writing to the underlying
091     *            stream.
092     ***/
093    @Override
094    public synchronized void write(byte buffer[])
095    throws IOException
096    {
097        write(buffer, 0, buffer.length);
098    }
099
100
101    /***
102     * Writes a number of bytes from a byte array to the stream starting from
103     * a given offset.
104     *
105     * @param buffer  The byte array to write.
106     * @param offset  The offset into the array at which to start copying data.
107     * @param length  The number of bytes to write.
108     * @throws IOException If an error occurs while writing to the underlying
109     *            stream.
110     ***/
111    @Override
112    public synchronized void write(byte buffer[], int offset, int length)
113    throws IOException
114    {
115        while (length-- > 0) {
116            write(buffer[offset++]);
117        }
118    }
119
120}